1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import android.animation.AnimatorInflater;
20 import android.animation.StateListAnimator;
21 import android.annotation.CallSuper;
22 import android.annotation.ColorInt;
23 import android.annotation.DrawableRes;
24 import android.annotation.FloatRange;
25 import android.annotation.IdRes;
26 import android.annotation.IntDef;
27 import android.annotation.LayoutRes;
28 import android.annotation.NonNull;
29 import android.annotation.Nullable;
30 import android.annotation.Size;
31 import android.annotation.UiThread;
32 import android.content.ClipData;
33 import android.content.Context;
34 import android.content.ContextWrapper;
35 import android.content.Intent;
36 import android.content.res.ColorStateList;
37 import android.content.res.Configuration;
38 import android.content.res.Resources;
39 import android.content.res.TypedArray;
40 import android.graphics.Bitmap;
41 import android.graphics.Canvas;
42 import android.graphics.Insets;
43 import android.graphics.Interpolator;
44 import android.graphics.LinearGradient;
45 import android.graphics.Matrix;
46 import android.graphics.Outline;
47 import android.graphics.Paint;
48 import android.graphics.PixelFormat;
49 import android.graphics.Point;
50 import android.graphics.PorterDuff;
51 import android.graphics.PorterDuffXfermode;
52 import android.graphics.Rect;
53 import android.graphics.RectF;
54 import android.graphics.Region;
55 import android.graphics.Shader;
56 import android.graphics.drawable.ColorDrawable;
57 import android.graphics.drawable.Drawable;
58 import android.hardware.display.DisplayManagerGlobal;
59 import android.os.Build.VERSION_CODES;
60 import android.os.Bundle;
61 import android.os.Handler;
62 import android.os.IBinder;
63 import android.os.Parcel;
64 import android.os.Parcelable;
65 import android.os.RemoteException;
66 import android.os.SystemClock;
67 import android.os.SystemProperties;
68 import android.os.Trace;
69 import android.text.TextUtils;
70 import android.util.AttributeSet;
71 import android.util.FloatProperty;
72 import android.util.LayoutDirection;
73 import android.util.Log;
74 import android.util.LongSparseLongArray;
75 import android.util.Pools.SynchronizedPool;
76 import android.util.Property;
77 import android.util.SparseArray;
78 import android.util.StateSet;
79 import android.util.SuperNotCalledException;
80 import android.util.TypedValue;
81 import android.view.ContextMenu.ContextMenuInfo;
82 import android.view.AccessibilityIterators.TextSegmentIterator;
83 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
84 import android.view.AccessibilityIterators.WordTextSegmentIterator;
85 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
86 import android.view.accessibility.AccessibilityEvent;
87 import android.view.accessibility.AccessibilityEventSource;
88 import android.view.accessibility.AccessibilityManager;
89 import android.view.accessibility.AccessibilityNodeInfo;
90 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
91 import android.view.accessibility.AccessibilityNodeProvider;
92 import android.view.animation.Animation;
93 import android.view.animation.AnimationUtils;
94 import android.view.animation.Transformation;
95 import android.view.inputmethod.EditorInfo;
96 import android.view.inputmethod.InputConnection;
97 import android.view.inputmethod.InputMethodManager;
98 import android.widget.Checkable;
99 import android.widget.FrameLayout;
100 import android.widget.ScrollBarDrawable;
101 
102 import static android.os.Build.VERSION_CODES.*;
103 import static java.lang.Math.max;
104 
105 import com.android.internal.R;
106 import com.android.internal.util.Predicate;
107 import com.android.internal.view.menu.MenuBuilder;
108 import com.google.android.collect.Lists;
109 import com.google.android.collect.Maps;
110 
111 import java.lang.annotation.Retention;
112 import java.lang.annotation.RetentionPolicy;
113 import java.lang.ref.WeakReference;
114 import java.lang.reflect.Field;
115 import java.lang.reflect.InvocationTargetException;
116 import java.lang.reflect.Method;
117 import java.lang.reflect.Modifier;
118 import java.util.ArrayList;
119 import java.util.Arrays;
120 import java.util.Collections;
121 import java.util.HashMap;
122 import java.util.List;
123 import java.util.Locale;
124 import java.util.Map;
125 import java.util.concurrent.CopyOnWriteArrayList;
126 import java.util.concurrent.atomic.AtomicInteger;
127 
128 /**
129  * <p>
130  * This class represents the basic building block for user interface components. A View
131  * occupies a rectangular area on the screen and is responsible for drawing and
132  * event handling. View is the base class for <em>widgets</em>, which are
133  * used to create interactive UI components (buttons, text fields, etc.). The
134  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
135  * are invisible containers that hold other Views (or other ViewGroups) and define
136  * their layout properties.
137  * </p>
138  *
139  * <div class="special reference">
140  * <h3>Developer Guides</h3>
141  * <p>For information about using this class to develop your application's user interface,
142  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
143  * </div>
144  *
145  * <a name="Using"></a>
146  * <h3>Using Views</h3>
147  * <p>
148  * All of the views in a window are arranged in a single tree. You can add views
149  * either from code or by specifying a tree of views in one or more XML layout
150  * files. There are many specialized subclasses of views that act as controls or
151  * are capable of displaying text, images, or other content.
152  * </p>
153  * <p>
154  * Once you have created a tree of views, there are typically a few types of
155  * common operations you may wish to perform:
156  * <ul>
157  * <li><strong>Set properties:</strong> for example setting the text of a
158  * {@link android.widget.TextView}. The available properties and the methods
159  * that set them will vary among the different subclasses of views. Note that
160  * properties that are known at build time can be set in the XML layout
161  * files.</li>
162  * <li><strong>Set focus:</strong> The framework will handled moving focus in
163  * response to user input. To force focus to a specific view, call
164  * {@link #requestFocus}.</li>
165  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
166  * that will be notified when something interesting happens to the view. For
167  * example, all views will let you set a listener to be notified when the view
168  * gains or loses focus. You can register such a listener using
169  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
170  * Other view subclasses offer more specialized listeners. For example, a Button
171  * exposes a listener to notify clients when the button is clicked.</li>
172  * <li><strong>Set visibility:</strong> You can hide or show views using
173  * {@link #setVisibility(int)}.</li>
174  * </ul>
175  * </p>
176  * <p><em>
177  * Note: The Android framework is responsible for measuring, laying out and
178  * drawing views. You should not call methods that perform these actions on
179  * views yourself unless you are actually implementing a
180  * {@link android.view.ViewGroup}.
181  * </em></p>
182  *
183  * <a name="Lifecycle"></a>
184  * <h3>Implementing a Custom View</h3>
185  *
186  * <p>
187  * To implement a custom view, you will usually begin by providing overrides for
188  * some of the standard methods that the framework calls on all views. You do
189  * not need to override all of these methods. In fact, you can start by just
190  * overriding {@link #onDraw(android.graphics.Canvas)}.
191  * <table border="2" width="85%" align="center" cellpadding="5">
192  *     <thead>
193  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
194  *     </thead>
195  *
196  *     <tbody>
197  *     <tr>
198  *         <td rowspan="2">Creation</td>
199  *         <td>Constructors</td>
200  *         <td>There is a form of the constructor that are called when the view
201  *         is created from code and a form that is called when the view is
202  *         inflated from a layout file. The second form should parse and apply
203  *         any attributes defined in the layout file.
204  *         </td>
205  *     </tr>
206  *     <tr>
207  *         <td><code>{@link #onFinishInflate()}</code></td>
208  *         <td>Called after a view and all of its children has been inflated
209  *         from XML.</td>
210  *     </tr>
211  *
212  *     <tr>
213  *         <td rowspan="3">Layout</td>
214  *         <td><code>{@link #onMeasure(int, int)}</code></td>
215  *         <td>Called to determine the size requirements for this view and all
216  *         of its children.
217  *         </td>
218  *     </tr>
219  *     <tr>
220  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
221  *         <td>Called when this view should assign a size and position to all
222  *         of its children.
223  *         </td>
224  *     </tr>
225  *     <tr>
226  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
227  *         <td>Called when the size of this view has changed.
228  *         </td>
229  *     </tr>
230  *
231  *     <tr>
232  *         <td>Drawing</td>
233  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
234  *         <td>Called when the view should render its content.
235  *         </td>
236  *     </tr>
237  *
238  *     <tr>
239  *         <td rowspan="4">Event processing</td>
240  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
241  *         <td>Called when a new hardware key event occurs.
242  *         </td>
243  *     </tr>
244  *     <tr>
245  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
246  *         <td>Called when a hardware key up event occurs.
247  *         </td>
248  *     </tr>
249  *     <tr>
250  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
251  *         <td>Called when a trackball motion event occurs.
252  *         </td>
253  *     </tr>
254  *     <tr>
255  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
256  *         <td>Called when a touch screen motion event occurs.
257  *         </td>
258  *     </tr>
259  *
260  *     <tr>
261  *         <td rowspan="2">Focus</td>
262  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
263  *         <td>Called when the view gains or loses focus.
264  *         </td>
265  *     </tr>
266  *
267  *     <tr>
268  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
269  *         <td>Called when the window containing the view gains or loses focus.
270  *         </td>
271  *     </tr>
272  *
273  *     <tr>
274  *         <td rowspan="3">Attaching</td>
275  *         <td><code>{@link #onAttachedToWindow()}</code></td>
276  *         <td>Called when the view is attached to a window.
277  *         </td>
278  *     </tr>
279  *
280  *     <tr>
281  *         <td><code>{@link #onDetachedFromWindow}</code></td>
282  *         <td>Called when the view is detached from its window.
283  *         </td>
284  *     </tr>
285  *
286  *     <tr>
287  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
288  *         <td>Called when the visibility of the window containing the view
289  *         has changed.
290  *         </td>
291  *     </tr>
292  *     </tbody>
293  *
294  * </table>
295  * </p>
296  *
297  * <a name="IDs"></a>
298  * <h3>IDs</h3>
299  * Views may have an integer id associated with them. These ids are typically
300  * assigned in the layout XML files, and are used to find specific views within
301  * the view tree. A common pattern is to:
302  * <ul>
303  * <li>Define a Button in the layout file and assign it a unique ID.
304  * <pre>
305  * &lt;Button
306  *     android:id="@+id/my_button"
307  *     android:layout_width="wrap_content"
308  *     android:layout_height="wrap_content"
309  *     android:text="@string/my_button_text"/&gt;
310  * </pre></li>
311  * <li>From the onCreate method of an Activity, find the Button
312  * <pre class="prettyprint">
313  *      Button myButton = (Button) findViewById(R.id.my_button);
314  * </pre></li>
315  * </ul>
316  * <p>
317  * View IDs need not be unique throughout the tree, but it is good practice to
318  * ensure that they are at least unique within the part of the tree you are
319  * searching.
320  * </p>
321  *
322  * <a name="Position"></a>
323  * <h3>Position</h3>
324  * <p>
325  * The geometry of a view is that of a rectangle. A view has a location,
326  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
327  * two dimensions, expressed as a width and a height. The unit for location
328  * and dimensions is the pixel.
329  * </p>
330  *
331  * <p>
332  * It is possible to retrieve the location of a view by invoking the methods
333  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
334  * coordinate of the rectangle representing the view. The latter returns the
335  * top, or Y, coordinate of the rectangle representing the view. These methods
336  * both return the location of the view relative to its parent. For instance,
337  * when getLeft() returns 20, that means the view is located 20 pixels to the
338  * right of the left edge of its direct parent.
339  * </p>
340  *
341  * <p>
342  * In addition, several convenience methods are offered to avoid unnecessary
343  * computations, namely {@link #getRight()} and {@link #getBottom()}.
344  * These methods return the coordinates of the right and bottom edges of the
345  * rectangle representing the view. For instance, calling {@link #getRight()}
346  * is similar to the following computation: <code>getLeft() + getWidth()</code>
347  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
348  * </p>
349  *
350  * <a name="SizePaddingMargins"></a>
351  * <h3>Size, padding and margins</h3>
352  * <p>
353  * The size of a view is expressed with a width and a height. A view actually
354  * possess two pairs of width and height values.
355  * </p>
356  *
357  * <p>
358  * The first pair is known as <em>measured width</em> and
359  * <em>measured height</em>. These dimensions define how big a view wants to be
360  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
361  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
362  * and {@link #getMeasuredHeight()}.
363  * </p>
364  *
365  * <p>
366  * The second pair is simply known as <em>width</em> and <em>height</em>, or
367  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
368  * dimensions define the actual size of the view on screen, at drawing time and
369  * after layout. These values may, but do not have to, be different from the
370  * measured width and height. The width and height can be obtained by calling
371  * {@link #getWidth()} and {@link #getHeight()}.
372  * </p>
373  *
374  * <p>
375  * To measure its dimensions, a view takes into account its padding. The padding
376  * is expressed in pixels for the left, top, right and bottom parts of the view.
377  * Padding can be used to offset the content of the view by a specific amount of
378  * pixels. For instance, a left padding of 2 will push the view's content by
379  * 2 pixels to the right of the left edge. Padding can be set using the
380  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
381  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
382  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
383  * {@link #getPaddingEnd()}.
384  * </p>
385  *
386  * <p>
387  * Even though a view can define a padding, it does not provide any support for
388  * margins. However, view groups provide such a support. Refer to
389  * {@link android.view.ViewGroup} and
390  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
391  * </p>
392  *
393  * <a name="Layout"></a>
394  * <h3>Layout</h3>
395  * <p>
396  * Layout is a two pass process: a measure pass and a layout pass. The measuring
397  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
398  * of the view tree. Each view pushes dimension specifications down the tree
399  * during the recursion. At the end of the measure pass, every view has stored
400  * its measurements. The second pass happens in
401  * {@link #layout(int,int,int,int)} and is also top-down. During
402  * this pass each parent is responsible for positioning all of its children
403  * using the sizes computed in the measure pass.
404  * </p>
405  *
406  * <p>
407  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
408  * {@link #getMeasuredHeight()} values must be set, along with those for all of
409  * that view's descendants. A view's measured width and measured height values
410  * must respect the constraints imposed by the view's parents. This guarantees
411  * that at the end of the measure pass, all parents accept all of their
412  * children's measurements. A parent view may call measure() more than once on
413  * its children. For example, the parent may measure each child once with
414  * unspecified dimensions to find out how big they want to be, then call
415  * measure() on them again with actual numbers if the sum of all the children's
416  * unconstrained sizes is too big or too small.
417  * </p>
418  *
419  * <p>
420  * The measure pass uses two classes to communicate dimensions. The
421  * {@link MeasureSpec} class is used by views to tell their parents how they
422  * want to be measured and positioned. The base LayoutParams class just
423  * describes how big the view wants to be for both width and height. For each
424  * dimension, it can specify one of:
425  * <ul>
426  * <li> an exact number
427  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
428  * (minus padding)
429  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
430  * enclose its content (plus padding).
431  * </ul>
432  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
433  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
434  * an X and Y value.
435  * </p>
436  *
437  * <p>
438  * MeasureSpecs are used to push requirements down the tree from parent to
439  * child. A MeasureSpec can be in one of three modes:
440  * <ul>
441  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
442  * of a child view. For example, a LinearLayout may call measure() on its child
443  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
444  * tall the child view wants to be given a width of 240 pixels.
445  * <li>EXACTLY: This is used by the parent to impose an exact size on the
446  * child. The child must use this size, and guarantee that all of its
447  * descendants will fit within this size.
448  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
449  * child. The child must guarantee that it and all of its descendants will fit
450  * within this size.
451  * </ul>
452  * </p>
453  *
454  * <p>
455  * To initiate a layout, call {@link #requestLayout}. This method is typically
456  * called by a view on itself when it believes that is can no longer fit within
457  * its current bounds.
458  * </p>
459  *
460  * <a name="Drawing"></a>
461  * <h3>Drawing</h3>
462  * <p>
463  * Drawing is handled by walking the tree and recording the drawing commands of
464  * any View that needs to update. After this, the drawing commands of the
465  * entire tree are issued to screen, clipped to the newly damaged area.
466  * </p>
467  *
468  * <p>
469  * The tree is largely recorded and drawn in order, with parents drawn before
470  * (i.e., behind) their children, with siblings drawn in the order they appear
471  * in the tree. If you set a background drawable for a View, then the View will
472  * draw it before calling back to its <code>onDraw()</code> method. The child
473  * drawing order can be overridden with
474  * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
475  * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
476  * </p>
477  *
478  * <p>
479  * To force a view to draw, call {@link #invalidate()}.
480  * </p>
481  *
482  * <a name="EventHandlingThreading"></a>
483  * <h3>Event Handling and Threading</h3>
484  * <p>
485  * The basic cycle of a view is as follows:
486  * <ol>
487  * <li>An event comes in and is dispatched to the appropriate view. The view
488  * handles the event and notifies any listeners.</li>
489  * <li>If in the course of processing the event, the view's bounds may need
490  * to be changed, the view will call {@link #requestLayout()}.</li>
491  * <li>Similarly, if in the course of processing the event the view's appearance
492  * may need to be changed, the view will call {@link #invalidate()}.</li>
493  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
494  * the framework will take care of measuring, laying out, and drawing the tree
495  * as appropriate.</li>
496  * </ol>
497  * </p>
498  *
499  * <p><em>Note: The entire view tree is single threaded. You must always be on
500  * the UI thread when calling any method on any view.</em>
501  * If you are doing work on other threads and want to update the state of a view
502  * from that thread, you should use a {@link Handler}.
503  * </p>
504  *
505  * <a name="FocusHandling"></a>
506  * <h3>Focus Handling</h3>
507  * <p>
508  * The framework will handle routine focus movement in response to user input.
509  * This includes changing the focus as views are removed or hidden, or as new
510  * views become available. Views indicate their willingness to take focus
511  * through the {@link #isFocusable} method. To change whether a view can take
512  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
513  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
514  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
515  * </p>
516  * <p>
517  * Focus movement is based on an algorithm which finds the nearest neighbor in a
518  * given direction. In rare cases, the default algorithm may not match the
519  * intended behavior of the developer. In these situations, you can provide
520  * explicit overrides by using these XML attributes in the layout file:
521  * <pre>
522  * nextFocusDown
523  * nextFocusLeft
524  * nextFocusRight
525  * nextFocusUp
526  * </pre>
527  * </p>
528  *
529  *
530  * <p>
531  * To get a particular view to take focus, call {@link #requestFocus()}.
532  * </p>
533  *
534  * <a name="TouchMode"></a>
535  * <h3>Touch Mode</h3>
536  * <p>
537  * When a user is navigating a user interface via directional keys such as a D-pad, it is
538  * necessary to give focus to actionable items such as buttons so the user can see
539  * what will take input.  If the device has touch capabilities, however, and the user
540  * begins interacting with the interface by touching it, it is no longer necessary to
541  * always highlight, or give focus to, a particular view.  This motivates a mode
542  * for interaction named 'touch mode'.
543  * </p>
544  * <p>
545  * For a touch capable device, once the user touches the screen, the device
546  * will enter touch mode.  From this point onward, only views for which
547  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
548  * Other views that are touchable, like buttons, will not take focus when touched; they will
549  * only fire the on click listeners.
550  * </p>
551  * <p>
552  * Any time a user hits a directional key, such as a D-pad direction, the view device will
553  * exit touch mode, and find a view to take focus, so that the user may resume interacting
554  * with the user interface without touching the screen again.
555  * </p>
556  * <p>
557  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
558  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
559  * </p>
560  *
561  * <a name="Scrolling"></a>
562  * <h3>Scrolling</h3>
563  * <p>
564  * The framework provides basic support for views that wish to internally
565  * scroll their content. This includes keeping track of the X and Y scroll
566  * offset as well as mechanisms for drawing scrollbars. See
567  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
568  * {@link #awakenScrollBars()} for more details.
569  * </p>
570  *
571  * <a name="Tags"></a>
572  * <h3>Tags</h3>
573  * <p>
574  * Unlike IDs, tags are not used to identify views. Tags are essentially an
575  * extra piece of information that can be associated with a view. They are most
576  * often used as a convenience to store data related to views in the views
577  * themselves rather than by putting them in a separate structure.
578  * </p>
579  *
580  * <a name="Properties"></a>
581  * <h3>Properties</h3>
582  * <p>
583  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
584  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
585  * available both in the {@link Property} form as well as in similarly-named setter/getter
586  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
587  * be used to set persistent state associated with these rendering-related properties on the view.
588  * The properties and methods can also be used in conjunction with
589  * {@link android.animation.Animator Animator}-based animations, described more in the
590  * <a href="#Animation">Animation</a> section.
591  * </p>
592  *
593  * <a name="Animation"></a>
594  * <h3>Animation</h3>
595  * <p>
596  * Starting with Android 3.0, the preferred way of animating views is to use the
597  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
598  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
599  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
600  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
601  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
602  * makes animating these View properties particularly easy and efficient.
603  * </p>
604  * <p>
605  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
606  * You can attach an {@link Animation} object to a view using
607  * {@link #setAnimation(Animation)} or
608  * {@link #startAnimation(Animation)}. The animation can alter the scale,
609  * rotation, translation and alpha of a view over time. If the animation is
610  * attached to a view that has children, the animation will affect the entire
611  * subtree rooted by that node. When an animation is started, the framework will
612  * take care of redrawing the appropriate views until the animation completes.
613  * </p>
614  *
615  * <a name="Security"></a>
616  * <h3>Security</h3>
617  * <p>
618  * Sometimes it is essential that an application be able to verify that an action
619  * is being performed with the full knowledge and consent of the user, such as
620  * granting a permission request, making a purchase or clicking on an advertisement.
621  * Unfortunately, a malicious application could try to spoof the user into
622  * performing these actions, unaware, by concealing the intended purpose of the view.
623  * As a remedy, the framework offers a touch filtering mechanism that can be used to
624  * improve the security of views that provide access to sensitive functionality.
625  * </p><p>
626  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
627  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
628  * will discard touches that are received whenever the view's window is obscured by
629  * another visible window.  As a result, the view will not receive touches whenever a
630  * toast, dialog or other window appears above the view's window.
631  * </p><p>
632  * For more fine-grained control over security, consider overriding the
633  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
634  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
635  * </p>
636  *
637  * @attr ref android.R.styleable#View_alpha
638  * @attr ref android.R.styleable#View_background
639  * @attr ref android.R.styleable#View_clickable
640  * @attr ref android.R.styleable#View_contentDescription
641  * @attr ref android.R.styleable#View_drawingCacheQuality
642  * @attr ref android.R.styleable#View_duplicateParentState
643  * @attr ref android.R.styleable#View_id
644  * @attr ref android.R.styleable#View_requiresFadingEdge
645  * @attr ref android.R.styleable#View_fadeScrollbars
646  * @attr ref android.R.styleable#View_fadingEdgeLength
647  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
648  * @attr ref android.R.styleable#View_fitsSystemWindows
649  * @attr ref android.R.styleable#View_isScrollContainer
650  * @attr ref android.R.styleable#View_focusable
651  * @attr ref android.R.styleable#View_focusableInTouchMode
652  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
653  * @attr ref android.R.styleable#View_keepScreenOn
654  * @attr ref android.R.styleable#View_layerType
655  * @attr ref android.R.styleable#View_layoutDirection
656  * @attr ref android.R.styleable#View_longClickable
657  * @attr ref android.R.styleable#View_minHeight
658  * @attr ref android.R.styleable#View_minWidth
659  * @attr ref android.R.styleable#View_nextFocusDown
660  * @attr ref android.R.styleable#View_nextFocusLeft
661  * @attr ref android.R.styleable#View_nextFocusRight
662  * @attr ref android.R.styleable#View_nextFocusUp
663  * @attr ref android.R.styleable#View_onClick
664  * @attr ref android.R.styleable#View_padding
665  * @attr ref android.R.styleable#View_paddingBottom
666  * @attr ref android.R.styleable#View_paddingLeft
667  * @attr ref android.R.styleable#View_paddingRight
668  * @attr ref android.R.styleable#View_paddingTop
669  * @attr ref android.R.styleable#View_paddingStart
670  * @attr ref android.R.styleable#View_paddingEnd
671  * @attr ref android.R.styleable#View_saveEnabled
672  * @attr ref android.R.styleable#View_rotation
673  * @attr ref android.R.styleable#View_rotationX
674  * @attr ref android.R.styleable#View_rotationY
675  * @attr ref android.R.styleable#View_scaleX
676  * @attr ref android.R.styleable#View_scaleY
677  * @attr ref android.R.styleable#View_scrollX
678  * @attr ref android.R.styleable#View_scrollY
679  * @attr ref android.R.styleable#View_scrollbarSize
680  * @attr ref android.R.styleable#View_scrollbarStyle
681  * @attr ref android.R.styleable#View_scrollbars
682  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
683  * @attr ref android.R.styleable#View_scrollbarFadeDuration
684  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
685  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
686  * @attr ref android.R.styleable#View_scrollbarThumbVertical
687  * @attr ref android.R.styleable#View_scrollbarTrackVertical
688  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
689  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
690  * @attr ref android.R.styleable#View_stateListAnimator
691  * @attr ref android.R.styleable#View_transitionName
692  * @attr ref android.R.styleable#View_soundEffectsEnabled
693  * @attr ref android.R.styleable#View_tag
694  * @attr ref android.R.styleable#View_textAlignment
695  * @attr ref android.R.styleable#View_textDirection
696  * @attr ref android.R.styleable#View_transformPivotX
697  * @attr ref android.R.styleable#View_transformPivotY
698  * @attr ref android.R.styleable#View_translationX
699  * @attr ref android.R.styleable#View_translationY
700  * @attr ref android.R.styleable#View_translationZ
701  * @attr ref android.R.styleable#View_visibility
702  *
703  * @see android.view.ViewGroup
704  */
705 @UiThread
706 public class View implements Drawable.Callback, KeyEvent.Callback,
707         AccessibilityEventSource {
708     private static final boolean DBG = false;
709 
710     /**
711      * The logging tag used by this class with android.util.Log.
712      */
713     protected static final String VIEW_LOG_TAG = "View";
714 
715     /**
716      * When set to true, apps will draw debugging information about their layouts.
717      *
718      * @hide
719      */
720     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
721 
722     /**
723      * When set to true, this view will save its attribute data.
724      *
725      * @hide
726      */
727     public static boolean mDebugViewAttributes = false;
728 
729     /**
730      * Used to mark a View that has no ID.
731      */
732     public static final int NO_ID = -1;
733 
734     /**
735      * Signals that compatibility booleans have been initialized according to
736      * target SDK versions.
737      */
738     private static boolean sCompatibilityDone = false;
739 
740     /**
741      * Use the old (broken) way of building MeasureSpecs.
742      */
743     private static boolean sUseBrokenMakeMeasureSpec = false;
744 
745     /**
746      * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
747      */
748     static boolean sUseZeroUnspecifiedMeasureSpec = false;
749 
750     /**
751      * Ignore any optimizations using the measure cache.
752      */
753     private static boolean sIgnoreMeasureCache = false;
754 
755     /**
756      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
757      * calling setFlags.
758      */
759     private static final int NOT_FOCUSABLE = 0x00000000;
760 
761     /**
762      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
763      * setFlags.
764      */
765     private static final int FOCUSABLE = 0x00000001;
766 
767     /**
768      * Mask for use with setFlags indicating bits used for focus.
769      */
770     private static final int FOCUSABLE_MASK = 0x00000001;
771 
772     /**
773      * This view will adjust its padding to fit sytem windows (e.g. status bar)
774      */
775     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
776 
777     /** @hide */
778     @IntDef({VISIBLE, INVISIBLE, GONE})
779     @Retention(RetentionPolicy.SOURCE)
780     public @interface Visibility {}
781 
782     /**
783      * This view is visible.
784      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
785      * android:visibility}.
786      */
787     public static final int VISIBLE = 0x00000000;
788 
789     /**
790      * This view is invisible, but it still takes up space for layout purposes.
791      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
792      * android:visibility}.
793      */
794     public static final int INVISIBLE = 0x00000004;
795 
796     /**
797      * This view is invisible, and it doesn't take any space for layout
798      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
799      * android:visibility}.
800      */
801     public static final int GONE = 0x00000008;
802 
803     /**
804      * Mask for use with setFlags indicating bits used for visibility.
805      * {@hide}
806      */
807     static final int VISIBILITY_MASK = 0x0000000C;
808 
809     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
810 
811     /**
812      * This view is enabled. Interpretation varies by subclass.
813      * Use with ENABLED_MASK when calling setFlags.
814      * {@hide}
815      */
816     static final int ENABLED = 0x00000000;
817 
818     /**
819      * This view is disabled. Interpretation varies by subclass.
820      * Use with ENABLED_MASK when calling setFlags.
821      * {@hide}
822      */
823     static final int DISABLED = 0x00000020;
824 
825    /**
826     * Mask for use with setFlags indicating bits used for indicating whether
827     * this view is enabled
828     * {@hide}
829     */
830     static final int ENABLED_MASK = 0x00000020;
831 
832     /**
833      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
834      * called and further optimizations will be performed. It is okay to have
835      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
836      * {@hide}
837      */
838     static final int WILL_NOT_DRAW = 0x00000080;
839 
840     /**
841      * Mask for use with setFlags indicating bits used for indicating whether
842      * this view is will draw
843      * {@hide}
844      */
845     static final int DRAW_MASK = 0x00000080;
846 
847     /**
848      * <p>This view doesn't show scrollbars.</p>
849      * {@hide}
850      */
851     static final int SCROLLBARS_NONE = 0x00000000;
852 
853     /**
854      * <p>This view shows horizontal scrollbars.</p>
855      * {@hide}
856      */
857     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
858 
859     /**
860      * <p>This view shows vertical scrollbars.</p>
861      * {@hide}
862      */
863     static final int SCROLLBARS_VERTICAL = 0x00000200;
864 
865     /**
866      * <p>Mask for use with setFlags indicating bits used for indicating which
867      * scrollbars are enabled.</p>
868      * {@hide}
869      */
870     static final int SCROLLBARS_MASK = 0x00000300;
871 
872     /**
873      * Indicates that the view should filter touches when its window is obscured.
874      * Refer to the class comments for more information about this security feature.
875      * {@hide}
876      */
877     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
878 
879     /**
880      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
881      * that they are optional and should be skipped if the window has
882      * requested system UI flags that ignore those insets for layout.
883      */
884     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
885 
886     /**
887      * <p>This view doesn't show fading edges.</p>
888      * {@hide}
889      */
890     static final int FADING_EDGE_NONE = 0x00000000;
891 
892     /**
893      * <p>This view shows horizontal fading edges.</p>
894      * {@hide}
895      */
896     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
897 
898     /**
899      * <p>This view shows vertical fading edges.</p>
900      * {@hide}
901      */
902     static final int FADING_EDGE_VERTICAL = 0x00002000;
903 
904     /**
905      * <p>Mask for use with setFlags indicating bits used for indicating which
906      * fading edges are enabled.</p>
907      * {@hide}
908      */
909     static final int FADING_EDGE_MASK = 0x00003000;
910 
911     /**
912      * <p>Indicates this view can be clicked. When clickable, a View reacts
913      * to clicks by notifying the OnClickListener.<p>
914      * {@hide}
915      */
916     static final int CLICKABLE = 0x00004000;
917 
918     /**
919      * <p>Indicates this view is caching its drawing into a bitmap.</p>
920      * {@hide}
921      */
922     static final int DRAWING_CACHE_ENABLED = 0x00008000;
923 
924     /**
925      * <p>Indicates that no icicle should be saved for this view.<p>
926      * {@hide}
927      */
928     static final int SAVE_DISABLED = 0x000010000;
929 
930     /**
931      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
932      * property.</p>
933      * {@hide}
934      */
935     static final int SAVE_DISABLED_MASK = 0x000010000;
936 
937     /**
938      * <p>Indicates that no drawing cache should ever be created for this view.<p>
939      * {@hide}
940      */
941     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
942 
943     /**
944      * <p>Indicates this view can take / keep focus when int touch mode.</p>
945      * {@hide}
946      */
947     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
948 
949     /** @hide */
950     @Retention(RetentionPolicy.SOURCE)
951     @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
952     public @interface DrawingCacheQuality {}
953 
954     /**
955      * <p>Enables low quality mode for the drawing cache.</p>
956      */
957     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
958 
959     /**
960      * <p>Enables high quality mode for the drawing cache.</p>
961      */
962     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
963 
964     /**
965      * <p>Enables automatic quality mode for the drawing cache.</p>
966      */
967     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
968 
969     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
970             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
971     };
972 
973     /**
974      * <p>Mask for use with setFlags indicating bits used for the cache
975      * quality property.</p>
976      * {@hide}
977      */
978     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
979 
980     /**
981      * <p>
982      * Indicates this view can be long clicked. When long clickable, a View
983      * reacts to long clicks by notifying the OnLongClickListener or showing a
984      * context menu.
985      * </p>
986      * {@hide}
987      */
988     static final int LONG_CLICKABLE = 0x00200000;
989 
990     /**
991      * <p>Indicates that this view gets its drawable states from its direct parent
992      * and ignores its original internal states.</p>
993      *
994      * @hide
995      */
996     static final int DUPLICATE_PARENT_STATE = 0x00400000;
997 
998     /**
999      * <p>
1000      * Indicates this view can be context clicked. When context clickable, a View reacts to a
1001      * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1002      * OnContextClickListener.
1003      * </p>
1004      * {@hide}
1005      */
1006     static final int CONTEXT_CLICKABLE = 0x00800000;
1007 
1008 
1009     /** @hide */
1010     @IntDef({
1011         SCROLLBARS_INSIDE_OVERLAY,
1012         SCROLLBARS_INSIDE_INSET,
1013         SCROLLBARS_OUTSIDE_OVERLAY,
1014         SCROLLBARS_OUTSIDE_INSET
1015     })
1016     @Retention(RetentionPolicy.SOURCE)
1017     public @interface ScrollBarStyle {}
1018 
1019     /**
1020      * The scrollbar style to display the scrollbars inside the content area,
1021      * without increasing the padding. The scrollbars will be overlaid with
1022      * translucency on the view's content.
1023      */
1024     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1025 
1026     /**
1027      * The scrollbar style to display the scrollbars inside the padded area,
1028      * increasing the padding of the view. The scrollbars will not overlap the
1029      * content area of the view.
1030      */
1031     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1032 
1033     /**
1034      * The scrollbar style to display the scrollbars at the edge of the view,
1035      * without increasing the padding. The scrollbars will be overlaid with
1036      * translucency.
1037      */
1038     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1039 
1040     /**
1041      * The scrollbar style to display the scrollbars at the edge of the view,
1042      * increasing the padding of the view. The scrollbars will only overlap the
1043      * background, if any.
1044      */
1045     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1046 
1047     /**
1048      * Mask to check if the scrollbar style is overlay or inset.
1049      * {@hide}
1050      */
1051     static final int SCROLLBARS_INSET_MASK = 0x01000000;
1052 
1053     /**
1054      * Mask to check if the scrollbar style is inside or outside.
1055      * {@hide}
1056      */
1057     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1058 
1059     /**
1060      * Mask for scrollbar style.
1061      * {@hide}
1062      */
1063     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1064 
1065     /**
1066      * View flag indicating that the screen should remain on while the
1067      * window containing this view is visible to the user.  This effectively
1068      * takes care of automatically setting the WindowManager's
1069      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1070      */
1071     public static final int KEEP_SCREEN_ON = 0x04000000;
1072 
1073     /**
1074      * View flag indicating whether this view should have sound effects enabled
1075      * for events such as clicking and touching.
1076      */
1077     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1078 
1079     /**
1080      * View flag indicating whether this view should have haptic feedback
1081      * enabled for events such as long presses.
1082      */
1083     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1084 
1085     /**
1086      * <p>Indicates that the view hierarchy should stop saving state when
1087      * it reaches this view.  If state saving is initiated immediately at
1088      * the view, it will be allowed.
1089      * {@hide}
1090      */
1091     static final int PARENT_SAVE_DISABLED = 0x20000000;
1092 
1093     /**
1094      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1095      * {@hide}
1096      */
1097     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1098 
1099     /** @hide */
1100     @IntDef(flag = true,
1101             value = {
1102                 FOCUSABLES_ALL,
1103                 FOCUSABLES_TOUCH_MODE
1104             })
1105     @Retention(RetentionPolicy.SOURCE)
1106     public @interface FocusableMode {}
1107 
1108     /**
1109      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1110      * should add all focusable Views regardless if they are focusable in touch mode.
1111      */
1112     public static final int FOCUSABLES_ALL = 0x00000000;
1113 
1114     /**
1115      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1116      * should add only Views focusable in touch mode.
1117      */
1118     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1119 
1120     /** @hide */
1121     @IntDef({
1122             FOCUS_BACKWARD,
1123             FOCUS_FORWARD,
1124             FOCUS_LEFT,
1125             FOCUS_UP,
1126             FOCUS_RIGHT,
1127             FOCUS_DOWN
1128     })
1129     @Retention(RetentionPolicy.SOURCE)
1130     public @interface FocusDirection {}
1131 
1132     /** @hide */
1133     @IntDef({
1134             FOCUS_LEFT,
1135             FOCUS_UP,
1136             FOCUS_RIGHT,
1137             FOCUS_DOWN
1138     })
1139     @Retention(RetentionPolicy.SOURCE)
1140     public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1141 
1142     /**
1143      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1144      * item.
1145      */
1146     public static final int FOCUS_BACKWARD = 0x00000001;
1147 
1148     /**
1149      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1150      * item.
1151      */
1152     public static final int FOCUS_FORWARD = 0x00000002;
1153 
1154     /**
1155      * Use with {@link #focusSearch(int)}. Move focus to the left.
1156      */
1157     public static final int FOCUS_LEFT = 0x00000011;
1158 
1159     /**
1160      * Use with {@link #focusSearch(int)}. Move focus up.
1161      */
1162     public static final int FOCUS_UP = 0x00000021;
1163 
1164     /**
1165      * Use with {@link #focusSearch(int)}. Move focus to the right.
1166      */
1167     public static final int FOCUS_RIGHT = 0x00000042;
1168 
1169     /**
1170      * Use with {@link #focusSearch(int)}. Move focus down.
1171      */
1172     public static final int FOCUS_DOWN = 0x00000082;
1173 
1174     /**
1175      * Bits of {@link #getMeasuredWidthAndState()} and
1176      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1177      */
1178     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1179 
1180     /**
1181      * Bits of {@link #getMeasuredWidthAndState()} and
1182      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1183      */
1184     public static final int MEASURED_STATE_MASK = 0xff000000;
1185 
1186     /**
1187      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1188      * for functions that combine both width and height into a single int,
1189      * such as {@link #getMeasuredState()} and the childState argument of
1190      * {@link #resolveSizeAndState(int, int, int)}.
1191      */
1192     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1193 
1194     /**
1195      * Bit of {@link #getMeasuredWidthAndState()} and
1196      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1197      * is smaller that the space the view would like to have.
1198      */
1199     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1200 
1201     /**
1202      * Base View state sets
1203      */
1204     // Singles
1205     /**
1206      * Indicates the view has no states set. States are used with
1207      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1208      * view depending on its state.
1209      *
1210      * @see android.graphics.drawable.Drawable
1211      * @see #getDrawableState()
1212      */
1213     protected static final int[] EMPTY_STATE_SET;
1214     /**
1215      * Indicates the view is enabled. States are used with
1216      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1217      * view depending on its state.
1218      *
1219      * @see android.graphics.drawable.Drawable
1220      * @see #getDrawableState()
1221      */
1222     protected static final int[] ENABLED_STATE_SET;
1223     /**
1224      * Indicates the view is focused. States are used with
1225      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1226      * view depending on its state.
1227      *
1228      * @see android.graphics.drawable.Drawable
1229      * @see #getDrawableState()
1230      */
1231     protected static final int[] FOCUSED_STATE_SET;
1232     /**
1233      * Indicates the view is selected. States are used with
1234      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1235      * view depending on its state.
1236      *
1237      * @see android.graphics.drawable.Drawable
1238      * @see #getDrawableState()
1239      */
1240     protected static final int[] SELECTED_STATE_SET;
1241     /**
1242      * Indicates the view is pressed. States are used with
1243      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1244      * view depending on its state.
1245      *
1246      * @see android.graphics.drawable.Drawable
1247      * @see #getDrawableState()
1248      */
1249     protected static final int[] PRESSED_STATE_SET;
1250     /**
1251      * Indicates the view's window has focus. States are used with
1252      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1253      * view depending on its state.
1254      *
1255      * @see android.graphics.drawable.Drawable
1256      * @see #getDrawableState()
1257      */
1258     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1259     // Doubles
1260     /**
1261      * Indicates the view is enabled and has the focus.
1262      *
1263      * @see #ENABLED_STATE_SET
1264      * @see #FOCUSED_STATE_SET
1265      */
1266     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1267     /**
1268      * Indicates the view is enabled and selected.
1269      *
1270      * @see #ENABLED_STATE_SET
1271      * @see #SELECTED_STATE_SET
1272      */
1273     protected static final int[] ENABLED_SELECTED_STATE_SET;
1274     /**
1275      * Indicates the view is enabled and that its window has focus.
1276      *
1277      * @see #ENABLED_STATE_SET
1278      * @see #WINDOW_FOCUSED_STATE_SET
1279      */
1280     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1281     /**
1282      * Indicates the view is focused and selected.
1283      *
1284      * @see #FOCUSED_STATE_SET
1285      * @see #SELECTED_STATE_SET
1286      */
1287     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1288     /**
1289      * Indicates the view has the focus and that its window has the focus.
1290      *
1291      * @see #FOCUSED_STATE_SET
1292      * @see #WINDOW_FOCUSED_STATE_SET
1293      */
1294     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1295     /**
1296      * Indicates the view is selected and that its window has the focus.
1297      *
1298      * @see #SELECTED_STATE_SET
1299      * @see #WINDOW_FOCUSED_STATE_SET
1300      */
1301     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1302     // Triples
1303     /**
1304      * Indicates the view is enabled, focused and selected.
1305      *
1306      * @see #ENABLED_STATE_SET
1307      * @see #FOCUSED_STATE_SET
1308      * @see #SELECTED_STATE_SET
1309      */
1310     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1311     /**
1312      * Indicates the view is enabled, focused and its window has the focus.
1313      *
1314      * @see #ENABLED_STATE_SET
1315      * @see #FOCUSED_STATE_SET
1316      * @see #WINDOW_FOCUSED_STATE_SET
1317      */
1318     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1319     /**
1320      * Indicates the view is enabled, selected and its window has the focus.
1321      *
1322      * @see #ENABLED_STATE_SET
1323      * @see #SELECTED_STATE_SET
1324      * @see #WINDOW_FOCUSED_STATE_SET
1325      */
1326     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1327     /**
1328      * Indicates the view is focused, selected and its window has the focus.
1329      *
1330      * @see #FOCUSED_STATE_SET
1331      * @see #SELECTED_STATE_SET
1332      * @see #WINDOW_FOCUSED_STATE_SET
1333      */
1334     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1335     /**
1336      * Indicates the view is enabled, focused, selected and its window
1337      * has the focus.
1338      *
1339      * @see #ENABLED_STATE_SET
1340      * @see #FOCUSED_STATE_SET
1341      * @see #SELECTED_STATE_SET
1342      * @see #WINDOW_FOCUSED_STATE_SET
1343      */
1344     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1345     /**
1346      * Indicates the view is pressed and its window has the focus.
1347      *
1348      * @see #PRESSED_STATE_SET
1349      * @see #WINDOW_FOCUSED_STATE_SET
1350      */
1351     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1352     /**
1353      * Indicates the view is pressed and selected.
1354      *
1355      * @see #PRESSED_STATE_SET
1356      * @see #SELECTED_STATE_SET
1357      */
1358     protected static final int[] PRESSED_SELECTED_STATE_SET;
1359     /**
1360      * Indicates the view is pressed, selected and its window has the focus.
1361      *
1362      * @see #PRESSED_STATE_SET
1363      * @see #SELECTED_STATE_SET
1364      * @see #WINDOW_FOCUSED_STATE_SET
1365      */
1366     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1367     /**
1368      * Indicates the view is pressed and focused.
1369      *
1370      * @see #PRESSED_STATE_SET
1371      * @see #FOCUSED_STATE_SET
1372      */
1373     protected static final int[] PRESSED_FOCUSED_STATE_SET;
1374     /**
1375      * Indicates the view is pressed, focused and its window has the focus.
1376      *
1377      * @see #PRESSED_STATE_SET
1378      * @see #FOCUSED_STATE_SET
1379      * @see #WINDOW_FOCUSED_STATE_SET
1380      */
1381     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1382     /**
1383      * Indicates the view is pressed, focused and selected.
1384      *
1385      * @see #PRESSED_STATE_SET
1386      * @see #SELECTED_STATE_SET
1387      * @see #FOCUSED_STATE_SET
1388      */
1389     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1390     /**
1391      * Indicates the view is pressed, focused, selected and its window has the focus.
1392      *
1393      * @see #PRESSED_STATE_SET
1394      * @see #FOCUSED_STATE_SET
1395      * @see #SELECTED_STATE_SET
1396      * @see #WINDOW_FOCUSED_STATE_SET
1397      */
1398     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1399     /**
1400      * Indicates the view is pressed and enabled.
1401      *
1402      * @see #PRESSED_STATE_SET
1403      * @see #ENABLED_STATE_SET
1404      */
1405     protected static final int[] PRESSED_ENABLED_STATE_SET;
1406     /**
1407      * Indicates the view is pressed, enabled and its window has the focus.
1408      *
1409      * @see #PRESSED_STATE_SET
1410      * @see #ENABLED_STATE_SET
1411      * @see #WINDOW_FOCUSED_STATE_SET
1412      */
1413     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1414     /**
1415      * Indicates the view is pressed, enabled and selected.
1416      *
1417      * @see #PRESSED_STATE_SET
1418      * @see #ENABLED_STATE_SET
1419      * @see #SELECTED_STATE_SET
1420      */
1421     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1422     /**
1423      * Indicates the view is pressed, enabled, selected and its window has the
1424      * focus.
1425      *
1426      * @see #PRESSED_STATE_SET
1427      * @see #ENABLED_STATE_SET
1428      * @see #SELECTED_STATE_SET
1429      * @see #WINDOW_FOCUSED_STATE_SET
1430      */
1431     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1432     /**
1433      * Indicates the view is pressed, enabled and focused.
1434      *
1435      * @see #PRESSED_STATE_SET
1436      * @see #ENABLED_STATE_SET
1437      * @see #FOCUSED_STATE_SET
1438      */
1439     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1440     /**
1441      * Indicates the view is pressed, enabled, focused and its window has the
1442      * focus.
1443      *
1444      * @see #PRESSED_STATE_SET
1445      * @see #ENABLED_STATE_SET
1446      * @see #FOCUSED_STATE_SET
1447      * @see #WINDOW_FOCUSED_STATE_SET
1448      */
1449     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1450     /**
1451      * Indicates the view is pressed, enabled, focused and selected.
1452      *
1453      * @see #PRESSED_STATE_SET
1454      * @see #ENABLED_STATE_SET
1455      * @see #SELECTED_STATE_SET
1456      * @see #FOCUSED_STATE_SET
1457      */
1458     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1459     /**
1460      * Indicates the view is pressed, enabled, focused, selected and its window
1461      * has the focus.
1462      *
1463      * @see #PRESSED_STATE_SET
1464      * @see #ENABLED_STATE_SET
1465      * @see #SELECTED_STATE_SET
1466      * @see #FOCUSED_STATE_SET
1467      * @see #WINDOW_FOCUSED_STATE_SET
1468      */
1469     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1470 
1471     static {
1472         EMPTY_STATE_SET = StateSet.get(0);
1473 
1474         WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1475 
1476         SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1477         SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1478                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1479 
1480         FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1481         FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1482                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1483         FOCUSED_SELECTED_STATE_SET = StateSet.get(
1484                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1485         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1486                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1487                         | StateSet.VIEW_STATE_FOCUSED);
1488 
1489         ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1490         ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1491                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1492         ENABLED_SELECTED_STATE_SET = StateSet.get(
1493                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1494         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1495                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1496                         | StateSet.VIEW_STATE_ENABLED);
1497         ENABLED_FOCUSED_STATE_SET = StateSet.get(
1498                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1499         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1500                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1501                         | StateSet.VIEW_STATE_ENABLED);
1502         ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1503                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1504                         | StateSet.VIEW_STATE_ENABLED);
1505         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1506                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1507                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1508 
1509         PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1510         PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1511                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1512         PRESSED_SELECTED_STATE_SET = StateSet.get(
1513                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1514         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1515                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1516                         | StateSet.VIEW_STATE_PRESSED);
1517         PRESSED_FOCUSED_STATE_SET = StateSet.get(
1518                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1519         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1520                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1521                         | StateSet.VIEW_STATE_PRESSED);
1522         PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1523                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1524                         | StateSet.VIEW_STATE_PRESSED);
1525         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1526                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1527                         | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1528         PRESSED_ENABLED_STATE_SET = StateSet.get(
1529                 StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1530         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1531                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1532                         | StateSet.VIEW_STATE_PRESSED);
1533         PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1534                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1535                         | StateSet.VIEW_STATE_PRESSED);
1536         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1537                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1538                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1539         PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1540                 StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1541                         | StateSet.VIEW_STATE_PRESSED);
1542         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1543                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1544                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1545         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1546                 StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1547                         | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1548         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1549                 StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1550                         | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1551                         | StateSet.VIEW_STATE_PRESSED);
1552     }
1553 
1554     /**
1555      * Accessibility event types that are dispatched for text population.
1556      */
1557     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1558             AccessibilityEvent.TYPE_VIEW_CLICKED
1559             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1560             | AccessibilityEvent.TYPE_VIEW_SELECTED
1561             | AccessibilityEvent.TYPE_VIEW_FOCUSED
1562             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1563             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1564             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1565             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1566             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1567             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1568             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1569 
1570     /**
1571      * Temporary Rect currently for use in setBackground().  This will probably
1572      * be extended in the future to hold our own class with more than just
1573      * a Rect. :)
1574      */
1575     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1576 
1577     /**
1578      * Map used to store views' tags.
1579      */
1580     private SparseArray<Object> mKeyedTags;
1581 
1582     /**
1583      * The next available accessibility id.
1584      */
1585     private static int sNextAccessibilityViewId;
1586 
1587     /**
1588      * The animation currently associated with this view.
1589      * @hide
1590      */
1591     protected Animation mCurrentAnimation = null;
1592 
1593     /**
1594      * Width as measured during measure pass.
1595      * {@hide}
1596      */
1597     @ViewDebug.ExportedProperty(category = "measurement")
1598     int mMeasuredWidth;
1599 
1600     /**
1601      * Height as measured during measure pass.
1602      * {@hide}
1603      */
1604     @ViewDebug.ExportedProperty(category = "measurement")
1605     int mMeasuredHeight;
1606 
1607     /**
1608      * Flag to indicate that this view was marked INVALIDATED, or had its display list
1609      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1610      * its display list. This flag, used only when hw accelerated, allows us to clear the
1611      * flag while retaining this information until it's needed (at getDisplayList() time and
1612      * in drawChild(), when we decide to draw a view's children's display lists into our own).
1613      *
1614      * {@hide}
1615      */
1616     boolean mRecreateDisplayList = false;
1617 
1618     /**
1619      * The view's identifier.
1620      * {@hide}
1621      *
1622      * @see #setId(int)
1623      * @see #getId()
1624      */
1625     @IdRes
1626     @ViewDebug.ExportedProperty(resolveId = true)
1627     int mID = NO_ID;
1628 
1629     /**
1630      * The stable ID of this view for accessibility purposes.
1631      */
1632     int mAccessibilityViewId = NO_ID;
1633 
1634     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1635 
1636     SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1637 
1638     /**
1639      * The view's tag.
1640      * {@hide}
1641      *
1642      * @see #setTag(Object)
1643      * @see #getTag()
1644      */
1645     protected Object mTag = null;
1646 
1647     // for mPrivateFlags:
1648     /** {@hide} */
1649     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1650     /** {@hide} */
1651     static final int PFLAG_FOCUSED                     = 0x00000002;
1652     /** {@hide} */
1653     static final int PFLAG_SELECTED                    = 0x00000004;
1654     /** {@hide} */
1655     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1656     /** {@hide} */
1657     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1658     /** {@hide} */
1659     static final int PFLAG_DRAWN                       = 0x00000020;
1660     /**
1661      * When this flag is set, this view is running an animation on behalf of its
1662      * children and should therefore not cancel invalidate requests, even if they
1663      * lie outside of this view's bounds.
1664      *
1665      * {@hide}
1666      */
1667     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1668     /** {@hide} */
1669     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1670     /** {@hide} */
1671     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1672     /** {@hide} */
1673     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1674     /** {@hide} */
1675     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1676     /** {@hide} */
1677     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1678     /** {@hide} */
1679     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1680 
1681     private static final int PFLAG_PRESSED             = 0x00004000;
1682 
1683     /** {@hide} */
1684     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1685     /**
1686      * Flag used to indicate that this view should be drawn once more (and only once
1687      * more) after its animation has completed.
1688      * {@hide}
1689      */
1690     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1691 
1692     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1693 
1694     /**
1695      * Indicates that the View returned true when onSetAlpha() was called and that
1696      * the alpha must be restored.
1697      * {@hide}
1698      */
1699     static final int PFLAG_ALPHA_SET                   = 0x00040000;
1700 
1701     /**
1702      * Set by {@link #setScrollContainer(boolean)}.
1703      */
1704     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1705 
1706     /**
1707      * Set by {@link #setScrollContainer(boolean)}.
1708      */
1709     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1710 
1711     /**
1712      * View flag indicating whether this view was invalidated (fully or partially.)
1713      *
1714      * @hide
1715      */
1716     static final int PFLAG_DIRTY                       = 0x00200000;
1717 
1718     /**
1719      * View flag indicating whether this view was invalidated by an opaque
1720      * invalidate request.
1721      *
1722      * @hide
1723      */
1724     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1725 
1726     /**
1727      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1728      *
1729      * @hide
1730      */
1731     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1732 
1733     /**
1734      * Indicates whether the background is opaque.
1735      *
1736      * @hide
1737      */
1738     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1739 
1740     /**
1741      * Indicates whether the scrollbars are opaque.
1742      *
1743      * @hide
1744      */
1745     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1746 
1747     /**
1748      * Indicates whether the view is opaque.
1749      *
1750      * @hide
1751      */
1752     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1753 
1754     /**
1755      * Indicates a prepressed state;
1756      * the short time between ACTION_DOWN and recognizing
1757      * a 'real' press. Prepressed is used to recognize quick taps
1758      * even when they are shorter than ViewConfiguration.getTapTimeout().
1759      *
1760      * @hide
1761      */
1762     private static final int PFLAG_PREPRESSED          = 0x02000000;
1763 
1764     /**
1765      * Indicates whether the view is temporarily detached.
1766      *
1767      * @hide
1768      */
1769     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1770 
1771     /**
1772      * Indicates that we should awaken scroll bars once attached
1773      *
1774      * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1775      * during window attachment and it is no longer needed. Feel free to repurpose it.
1776      *
1777      * @hide
1778      */
1779     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1780 
1781     /**
1782      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1783      * @hide
1784      */
1785     private static final int PFLAG_HOVERED             = 0x10000000;
1786 
1787     /**
1788      * no longer needed, should be reused
1789      */
1790     private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1791 
1792     /** {@hide} */
1793     static final int PFLAG_ACTIVATED                   = 0x40000000;
1794 
1795     /**
1796      * Indicates that this view was specifically invalidated, not just dirtied because some
1797      * child view was invalidated. The flag is used to determine when we need to recreate
1798      * a view's display list (as opposed to just returning a reference to its existing
1799      * display list).
1800      *
1801      * @hide
1802      */
1803     static final int PFLAG_INVALIDATED                 = 0x80000000;
1804 
1805     /**
1806      * Masks for mPrivateFlags2, as generated by dumpFlags():
1807      *
1808      * |-------|-------|-------|-------|
1809      *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1810      *                                1  PFLAG2_DRAG_HOVERED
1811      *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1812      *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1813      *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1814      *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1815      *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1816      *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1817      *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1818      *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1819      *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1820      *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1821      *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1822      *                         111       PFLAG2_TEXT_DIRECTION_MASK
1823      *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1824      *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1825      *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1826      *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1827      *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1828      *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1829      *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1830      *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1831      *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1832      *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1833      *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1834      *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1835      *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1836      *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1837      *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1838      *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1839      *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1840      *     1                             PFLAG2_VIEW_QUICK_REJECTED
1841      *    1                              PFLAG2_PADDING_RESOLVED
1842      *   1                               PFLAG2_DRAWABLE_RESOLVED
1843      *  1                                PFLAG2_HAS_TRANSIENT_STATE
1844      * |-------|-------|-------|-------|
1845      */
1846 
1847     /**
1848      * Indicates that this view has reported that it can accept the current drag's content.
1849      * Cleared when the drag operation concludes.
1850      * @hide
1851      */
1852     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1853 
1854     /**
1855      * Indicates that this view is currently directly under the drag location in a
1856      * drag-and-drop operation involving content that it can accept.  Cleared when
1857      * the drag exits the view, or when the drag operation concludes.
1858      * @hide
1859      */
1860     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1861 
1862     /** @hide */
1863     @IntDef({
1864         LAYOUT_DIRECTION_LTR,
1865         LAYOUT_DIRECTION_RTL,
1866         LAYOUT_DIRECTION_INHERIT,
1867         LAYOUT_DIRECTION_LOCALE
1868     })
1869     @Retention(RetentionPolicy.SOURCE)
1870     // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1871     public @interface LayoutDir {}
1872 
1873     /** @hide */
1874     @IntDef({
1875         LAYOUT_DIRECTION_LTR,
1876         LAYOUT_DIRECTION_RTL
1877     })
1878     @Retention(RetentionPolicy.SOURCE)
1879     public @interface ResolvedLayoutDir {}
1880 
1881     /**
1882      * A flag to indicate that the layout direction of this view has not been defined yet.
1883      * @hide
1884      */
1885     public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1886 
1887     /**
1888      * Horizontal layout direction of this view is from Left to Right.
1889      * Use with {@link #setLayoutDirection}.
1890      */
1891     public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1892 
1893     /**
1894      * Horizontal layout direction of this view is from Right to Left.
1895      * Use with {@link #setLayoutDirection}.
1896      */
1897     public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1898 
1899     /**
1900      * Horizontal layout direction of this view is inherited from its parent.
1901      * Use with {@link #setLayoutDirection}.
1902      */
1903     public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1904 
1905     /**
1906      * Horizontal layout direction of this view is from deduced from the default language
1907      * script for the locale. Use with {@link #setLayoutDirection}.
1908      */
1909     public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1910 
1911     /**
1912      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1913      * @hide
1914      */
1915     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1916 
1917     /**
1918      * Mask for use with private flags indicating bits used for horizontal layout direction.
1919      * @hide
1920      */
1921     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1922 
1923     /**
1924      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1925      * right-to-left direction.
1926      * @hide
1927      */
1928     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1929 
1930     /**
1931      * Indicates whether the view horizontal layout direction has been resolved.
1932      * @hide
1933      */
1934     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1935 
1936     /**
1937      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1938      * @hide
1939      */
1940     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1941             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1942 
1943     /*
1944      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1945      * flag value.
1946      * @hide
1947      */
1948     private static final int[] LAYOUT_DIRECTION_FLAGS = {
1949             LAYOUT_DIRECTION_LTR,
1950             LAYOUT_DIRECTION_RTL,
1951             LAYOUT_DIRECTION_INHERIT,
1952             LAYOUT_DIRECTION_LOCALE
1953     };
1954 
1955     /**
1956      * Default horizontal layout direction.
1957      */
1958     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1959 
1960     /**
1961      * Default horizontal layout direction.
1962      * @hide
1963      */
1964     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1965 
1966     /**
1967      * Text direction is inherited through {@link ViewGroup}
1968      */
1969     public static final int TEXT_DIRECTION_INHERIT = 0;
1970 
1971     /**
1972      * Text direction is using "first strong algorithm". The first strong directional character
1973      * determines the paragraph direction. If there is no strong directional character, the
1974      * paragraph direction is the view's resolved layout direction.
1975      */
1976     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1977 
1978     /**
1979      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1980      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1981      * If there are neither, the paragraph direction is the view's resolved layout direction.
1982      */
1983     public static final int TEXT_DIRECTION_ANY_RTL = 2;
1984 
1985     /**
1986      * Text direction is forced to LTR.
1987      */
1988     public static final int TEXT_DIRECTION_LTR = 3;
1989 
1990     /**
1991      * Text direction is forced to RTL.
1992      */
1993     public static final int TEXT_DIRECTION_RTL = 4;
1994 
1995     /**
1996      * Text direction is coming from the system Locale.
1997      */
1998     public static final int TEXT_DIRECTION_LOCALE = 5;
1999 
2000     /**
2001      * Text direction is using "first strong algorithm". The first strong directional character
2002      * determines the paragraph direction. If there is no strong directional character, the
2003      * paragraph direction is LTR.
2004      */
2005     public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2006 
2007     /**
2008      * Text direction is using "first strong algorithm". The first strong directional character
2009      * determines the paragraph direction. If there is no strong directional character, the
2010      * paragraph direction is RTL.
2011      */
2012     public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2013 
2014     /**
2015      * Default text direction is inherited
2016      */
2017     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2018 
2019     /**
2020      * Default resolved text direction
2021      * @hide
2022      */
2023     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2024 
2025     /**
2026      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2027      * @hide
2028      */
2029     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2030 
2031     /**
2032      * Mask for use with private flags indicating bits used for text direction.
2033      * @hide
2034      */
2035     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2036             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2037 
2038     /**
2039      * Array of text direction flags for mapping attribute "textDirection" to correct
2040      * flag value.
2041      * @hide
2042      */
2043     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2044             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2045             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2046             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2047             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2048             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2049             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2050             TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2051             TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2052     };
2053 
2054     /**
2055      * Indicates whether the view text direction has been resolved.
2056      * @hide
2057      */
2058     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2059             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2060 
2061     /**
2062      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2063      * @hide
2064      */
2065     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2066 
2067     /**
2068      * Mask for use with private flags indicating bits used for resolved text direction.
2069      * @hide
2070      */
2071     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2072             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2073 
2074     /**
2075      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2076      * @hide
2077      */
2078     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2079             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2080 
2081     /** @hide */
2082     @IntDef({
2083         TEXT_ALIGNMENT_INHERIT,
2084         TEXT_ALIGNMENT_GRAVITY,
2085         TEXT_ALIGNMENT_CENTER,
2086         TEXT_ALIGNMENT_TEXT_START,
2087         TEXT_ALIGNMENT_TEXT_END,
2088         TEXT_ALIGNMENT_VIEW_START,
2089         TEXT_ALIGNMENT_VIEW_END
2090     })
2091     @Retention(RetentionPolicy.SOURCE)
2092     public @interface TextAlignment {}
2093 
2094     /**
2095      * Default text alignment. The text alignment of this View is inherited from its parent.
2096      * Use with {@link #setTextAlignment(int)}
2097      */
2098     public static final int TEXT_ALIGNMENT_INHERIT = 0;
2099 
2100     /**
2101      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2102      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2103      *
2104      * Use with {@link #setTextAlignment(int)}
2105      */
2106     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2107 
2108     /**
2109      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2110      *
2111      * Use with {@link #setTextAlignment(int)}
2112      */
2113     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2114 
2115     /**
2116      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2117      *
2118      * Use with {@link #setTextAlignment(int)}
2119      */
2120     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2121 
2122     /**
2123      * Center the paragraph, e.g. ALIGN_CENTER.
2124      *
2125      * Use with {@link #setTextAlignment(int)}
2126      */
2127     public static final int TEXT_ALIGNMENT_CENTER = 4;
2128 
2129     /**
2130      * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2131      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2132      *
2133      * Use with {@link #setTextAlignment(int)}
2134      */
2135     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2136 
2137     /**
2138      * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2139      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2140      *
2141      * Use with {@link #setTextAlignment(int)}
2142      */
2143     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2144 
2145     /**
2146      * Default text alignment is inherited
2147      */
2148     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2149 
2150     /**
2151      * Default resolved text alignment
2152      * @hide
2153      */
2154     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2155 
2156     /**
2157       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2158       * @hide
2159       */
2160     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2161 
2162     /**
2163       * Mask for use with private flags indicating bits used for text alignment.
2164       * @hide
2165       */
2166     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2167 
2168     /**
2169      * Array of text direction flags for mapping attribute "textAlignment" to correct
2170      * flag value.
2171      * @hide
2172      */
2173     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2174             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2175             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2176             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2177             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2178             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2179             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2180             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2181     };
2182 
2183     /**
2184      * Indicates whether the view text alignment has been resolved.
2185      * @hide
2186      */
2187     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2188 
2189     /**
2190      * Bit shift to get the resolved text alignment.
2191      * @hide
2192      */
2193     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2194 
2195     /**
2196      * Mask for use with private flags indicating bits used for text alignment.
2197      * @hide
2198      */
2199     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2200             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2201 
2202     /**
2203      * Indicates whether if the view text alignment has been resolved to gravity
2204      */
2205     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2206             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2207 
2208     // Accessiblity constants for mPrivateFlags2
2209 
2210     /**
2211      * Shift for the bits in {@link #mPrivateFlags2} related to the
2212      * "importantForAccessibility" attribute.
2213      */
2214     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2215 
2216     /**
2217      * Automatically determine whether a view is important for accessibility.
2218      */
2219     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2220 
2221     /**
2222      * The view is important for accessibility.
2223      */
2224     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2225 
2226     /**
2227      * The view is not important for accessibility.
2228      */
2229     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2230 
2231     /**
2232      * The view is not important for accessibility, nor are any of its
2233      * descendant views.
2234      */
2235     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2236 
2237     /**
2238      * The default whether the view is important for accessibility.
2239      */
2240     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2241 
2242     /**
2243      * Mask for obtainig the bits which specify how to determine
2244      * whether a view is important for accessibility.
2245      */
2246     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2247         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2248         | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2249         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2250 
2251     /**
2252      * Shift for the bits in {@link #mPrivateFlags2} related to the
2253      * "accessibilityLiveRegion" attribute.
2254      */
2255     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2256 
2257     /**
2258      * Live region mode specifying that accessibility services should not
2259      * automatically announce changes to this view. This is the default live
2260      * region mode for most views.
2261      * <p>
2262      * Use with {@link #setAccessibilityLiveRegion(int)}.
2263      */
2264     public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2265 
2266     /**
2267      * Live region mode specifying that accessibility services should announce
2268      * changes to this view.
2269      * <p>
2270      * Use with {@link #setAccessibilityLiveRegion(int)}.
2271      */
2272     public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2273 
2274     /**
2275      * Live region mode specifying that accessibility services should interrupt
2276      * ongoing speech to immediately announce changes to this view.
2277      * <p>
2278      * Use with {@link #setAccessibilityLiveRegion(int)}.
2279      */
2280     public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2281 
2282     /**
2283      * The default whether the view is important for accessibility.
2284      */
2285     static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2286 
2287     /**
2288      * Mask for obtaining the bits which specify a view's accessibility live
2289      * region mode.
2290      */
2291     static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2292             | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2293             << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2294 
2295     /**
2296      * Flag indicating whether a view has accessibility focus.
2297      */
2298     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2299 
2300     /**
2301      * Flag whether the accessibility state of the subtree rooted at this view changed.
2302      */
2303     static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2304 
2305     /**
2306      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2307      * is used to check whether later changes to the view's transform should invalidate the
2308      * view to force the quickReject test to run again.
2309      */
2310     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2311 
2312     /**
2313      * Flag indicating that start/end padding has been resolved into left/right padding
2314      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2315      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2316      * during measurement. In some special cases this is required such as when an adapter-based
2317      * view measures prospective children without attaching them to a window.
2318      */
2319     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2320 
2321     /**
2322      * Flag indicating that the start/end drawables has been resolved into left/right ones.
2323      */
2324     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2325 
2326     /**
2327      * Indicates that the view is tracking some sort of transient state
2328      * that the app should not need to be aware of, but that the framework
2329      * should take special care to preserve.
2330      */
2331     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2332 
2333     /**
2334      * Group of bits indicating that RTL properties resolution is done.
2335      */
2336     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2337             PFLAG2_TEXT_DIRECTION_RESOLVED |
2338             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2339             PFLAG2_PADDING_RESOLVED |
2340             PFLAG2_DRAWABLE_RESOLVED;
2341 
2342     // There are a couple of flags left in mPrivateFlags2
2343 
2344     /* End of masks for mPrivateFlags2 */
2345 
2346     /**
2347      * Masks for mPrivateFlags3, as generated by dumpFlags():
2348      *
2349      * |-------|-------|-------|-------|
2350      *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2351      *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2352      *                               1   PFLAG3_IS_LAID_OUT
2353      *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2354      *                             1     PFLAG3_CALLED_SUPER
2355      *                            1      PFLAG3_APPLYING_INSETS
2356      *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2357      *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2358      *                         1         PFLAG3_ASSIST_BLOCKED
2359      * |-------|-------|-------|-------|
2360      */
2361 
2362     /**
2363      * Flag indicating that view has a transform animation set on it. This is used to track whether
2364      * an animation is cleared between successive frames, in order to tell the associated
2365      * DisplayList to clear its animation matrix.
2366      */
2367     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2368 
2369     /**
2370      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2371      * animation is cleared between successive frames, in order to tell the associated
2372      * DisplayList to restore its alpha value.
2373      */
2374     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2375 
2376     /**
2377      * Flag indicating that the view has been through at least one layout since it
2378      * was last attached to a window.
2379      */
2380     static final int PFLAG3_IS_LAID_OUT = 0x4;
2381 
2382     /**
2383      * Flag indicating that a call to measure() was skipped and should be done
2384      * instead when layout() is invoked.
2385      */
2386     static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2387 
2388     /**
2389      * Flag indicating that an overridden method correctly called down to
2390      * the superclass implementation as required by the API spec.
2391      */
2392     static final int PFLAG3_CALLED_SUPER = 0x10;
2393 
2394     /**
2395      * Flag indicating that we're in the process of applying window insets.
2396      */
2397     static final int PFLAG3_APPLYING_INSETS = 0x20;
2398 
2399     /**
2400      * Flag indicating that we're in the process of fitting system windows using the old method.
2401      */
2402     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2403 
2404     /**
2405      * Flag indicating that nested scrolling is enabled for this view.
2406      * The view will optionally cooperate with views up its parent chain to allow for
2407      * integrated nested scrolling along the same axis.
2408      */
2409     static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2410 
2411     /**
2412      * Flag indicating that the bottom scroll indicator should be displayed
2413      * when this view can scroll up.
2414      */
2415     static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2416 
2417     /**
2418      * Flag indicating that the bottom scroll indicator should be displayed
2419      * when this view can scroll down.
2420      */
2421     static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2422 
2423     /**
2424      * Flag indicating that the left scroll indicator should be displayed
2425      * when this view can scroll left.
2426      */
2427     static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2428 
2429     /**
2430      * Flag indicating that the right scroll indicator should be displayed
2431      * when this view can scroll right.
2432      */
2433     static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2434 
2435     /**
2436      * Flag indicating that the start scroll indicator should be displayed
2437      * when this view can scroll in the start direction.
2438      */
2439     static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2440 
2441     /**
2442      * Flag indicating that the end scroll indicator should be displayed
2443      * when this view can scroll in the end direction.
2444      */
2445     static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2446 
2447     /* End of masks for mPrivateFlags3 */
2448 
2449     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2450 
2451     static final int SCROLL_INDICATORS_NONE = 0x0000;
2452 
2453     /**
2454      * Mask for use with setFlags indicating bits used for indicating which
2455      * scroll indicators are enabled.
2456      */
2457     static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2458             | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2459             | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2460             | PFLAG3_SCROLL_INDICATOR_END;
2461 
2462     /**
2463      * Left-shift required to translate between public scroll indicator flags
2464      * and internal PFLAGS3 flags. When used as a right-shift, translates
2465      * PFLAGS3 flags to public flags.
2466      */
2467     static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2468 
2469     /** @hide */
2470     @Retention(RetentionPolicy.SOURCE)
2471     @IntDef(flag = true,
2472             value = {
2473                     SCROLL_INDICATOR_TOP,
2474                     SCROLL_INDICATOR_BOTTOM,
2475                     SCROLL_INDICATOR_LEFT,
2476                     SCROLL_INDICATOR_RIGHT,
2477                     SCROLL_INDICATOR_START,
2478                     SCROLL_INDICATOR_END,
2479             })
2480     public @interface ScrollIndicators {}
2481 
2482     /**
2483      * Scroll indicator direction for the top edge of the view.
2484      *
2485      * @see #setScrollIndicators(int)
2486      * @see #setScrollIndicators(int, int)
2487      * @see #getScrollIndicators()
2488      */
2489     public static final int SCROLL_INDICATOR_TOP =
2490             PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2491 
2492     /**
2493      * Scroll indicator direction for the bottom edge of the view.
2494      *
2495      * @see #setScrollIndicators(int)
2496      * @see #setScrollIndicators(int, int)
2497      * @see #getScrollIndicators()
2498      */
2499     public static final int SCROLL_INDICATOR_BOTTOM =
2500             PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2501 
2502     /**
2503      * Scroll indicator direction for the left edge of the view.
2504      *
2505      * @see #setScrollIndicators(int)
2506      * @see #setScrollIndicators(int, int)
2507      * @see #getScrollIndicators()
2508      */
2509     public static final int SCROLL_INDICATOR_LEFT =
2510             PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2511 
2512     /**
2513      * Scroll indicator direction for the right edge of the view.
2514      *
2515      * @see #setScrollIndicators(int)
2516      * @see #setScrollIndicators(int, int)
2517      * @see #getScrollIndicators()
2518      */
2519     public static final int SCROLL_INDICATOR_RIGHT =
2520             PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2521 
2522     /**
2523      * Scroll indicator direction for the starting edge of the view.
2524      * <p>
2525      * Resolved according to the view's layout direction, see
2526      * {@link #getLayoutDirection()} for more information.
2527      *
2528      * @see #setScrollIndicators(int)
2529      * @see #setScrollIndicators(int, int)
2530      * @see #getScrollIndicators()
2531      */
2532     public static final int SCROLL_INDICATOR_START =
2533             PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2534 
2535     /**
2536      * Scroll indicator direction for the ending edge of the view.
2537      * <p>
2538      * Resolved according to the view's layout direction, see
2539      * {@link #getLayoutDirection()} for more information.
2540      *
2541      * @see #setScrollIndicators(int)
2542      * @see #setScrollIndicators(int, int)
2543      * @see #getScrollIndicators()
2544      */
2545     public static final int SCROLL_INDICATOR_END =
2546             PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2547 
2548     /**
2549      * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2550      * into this view.<p>
2551      */
2552     static final int PFLAG3_ASSIST_BLOCKED = 0x100;
2553 
2554     /**
2555      * Always allow a user to over-scroll this view, provided it is a
2556      * view that can scroll.
2557      *
2558      * @see #getOverScrollMode()
2559      * @see #setOverScrollMode(int)
2560      */
2561     public static final int OVER_SCROLL_ALWAYS = 0;
2562 
2563     /**
2564      * Allow a user to over-scroll this view only if the content is large
2565      * enough to meaningfully scroll, provided it is a view that can scroll.
2566      *
2567      * @see #getOverScrollMode()
2568      * @see #setOverScrollMode(int)
2569      */
2570     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2571 
2572     /**
2573      * Never allow a user to over-scroll this view.
2574      *
2575      * @see #getOverScrollMode()
2576      * @see #setOverScrollMode(int)
2577      */
2578     public static final int OVER_SCROLL_NEVER = 2;
2579 
2580     /**
2581      * Special constant for {@link #setSystemUiVisibility(int)}: View has
2582      * requested the system UI (status bar) to be visible (the default).
2583      *
2584      * @see #setSystemUiVisibility(int)
2585      */
2586     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2587 
2588     /**
2589      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2590      * system UI to enter an unobtrusive "low profile" mode.
2591      *
2592      * <p>This is for use in games, book readers, video players, or any other
2593      * "immersive" application where the usual system chrome is deemed too distracting.
2594      *
2595      * <p>In low profile mode, the status bar and/or navigation icons may dim.
2596      *
2597      * @see #setSystemUiVisibility(int)
2598      */
2599     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2600 
2601     /**
2602      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2603      * system navigation be temporarily hidden.
2604      *
2605      * <p>This is an even less obtrusive state than that called for by
2606      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2607      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2608      * those to disappear. This is useful (in conjunction with the
2609      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2610      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2611      * window flags) for displaying content using every last pixel on the display.
2612      *
2613      * <p>There is a limitation: because navigation controls are so important, the least user
2614      * interaction will cause them to reappear immediately.  When this happens, both
2615      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2616      * so that both elements reappear at the same time.
2617      *
2618      * @see #setSystemUiVisibility(int)
2619      */
2620     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2621 
2622     /**
2623      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2624      * into the normal fullscreen mode so that its content can take over the screen
2625      * while still allowing the user to interact with the application.
2626      *
2627      * <p>This has the same visual effect as
2628      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2629      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2630      * meaning that non-critical screen decorations (such as the status bar) will be
2631      * hidden while the user is in the View's window, focusing the experience on
2632      * that content.  Unlike the window flag, if you are using ActionBar in
2633      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2634      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2635      * hide the action bar.
2636      *
2637      * <p>This approach to going fullscreen is best used over the window flag when
2638      * it is a transient state -- that is, the application does this at certain
2639      * points in its user interaction where it wants to allow the user to focus
2640      * on content, but not as a continuous state.  For situations where the application
2641      * would like to simply stay full screen the entire time (such as a game that
2642      * wants to take over the screen), the
2643      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2644      * is usually a better approach.  The state set here will be removed by the system
2645      * in various situations (such as the user moving to another application) like
2646      * the other system UI states.
2647      *
2648      * <p>When using this flag, the application should provide some easy facility
2649      * for the user to go out of it.  A common example would be in an e-book
2650      * reader, where tapping on the screen brings back whatever screen and UI
2651      * decorations that had been hidden while the user was immersed in reading
2652      * the book.
2653      *
2654      * @see #setSystemUiVisibility(int)
2655      */
2656     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2657 
2658     /**
2659      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2660      * flags, we would like a stable view of the content insets given to
2661      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2662      * will always represent the worst case that the application can expect
2663      * as a continuous state.  In the stock Android UI this is the space for
2664      * the system bar, nav bar, and status bar, but not more transient elements
2665      * such as an input method.
2666      *
2667      * The stable layout your UI sees is based on the system UI modes you can
2668      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2669      * then you will get a stable layout for changes of the
2670      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2671      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2672      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2673      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2674      * with a stable layout.  (Note that you should avoid using
2675      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2676      *
2677      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2678      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2679      * then a hidden status bar will be considered a "stable" state for purposes
2680      * here.  This allows your UI to continually hide the status bar, while still
2681      * using the system UI flags to hide the action bar while still retaining
2682      * a stable layout.  Note that changing the window fullscreen flag will never
2683      * provide a stable layout for a clean transition.
2684      *
2685      * <p>If you are using ActionBar in
2686      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2687      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2688      * insets it adds to those given to the application.
2689      */
2690     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2691 
2692     /**
2693      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2694      * to be laid out as if it has requested
2695      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2696      * allows it to avoid artifacts when switching in and out of that mode, at
2697      * the expense that some of its user interface may be covered by screen
2698      * decorations when they are shown.  You can perform layout of your inner
2699      * UI elements to account for the navigation system UI through the
2700      * {@link #fitSystemWindows(Rect)} method.
2701      */
2702     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2703 
2704     /**
2705      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2706      * to be laid out as if it has requested
2707      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2708      * allows it to avoid artifacts when switching in and out of that mode, at
2709      * the expense that some of its user interface may be covered by screen
2710      * decorations when they are shown.  You can perform layout of your inner
2711      * UI elements to account for non-fullscreen system UI through the
2712      * {@link #fitSystemWindows(Rect)} method.
2713      */
2714     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2715 
2716     /**
2717      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2718      * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2719      * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2720      * user interaction.
2721      * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2722      * has an effect when used in combination with that flag.</p>
2723      */
2724     public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2725 
2726     /**
2727      * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2728      * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2729      * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2730      * experience while also hiding the system bars.  If this flag is not set,
2731      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2732      * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2733      * if the user swipes from the top of the screen.
2734      * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2735      * system gestures, such as swiping from the top of the screen.  These transient system bars
2736      * will overlay app’s content, may have some degree of transparency, and will automatically
2737      * hide after a short timeout.
2738      * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2739      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2740      * with one or both of those flags.</p>
2741      */
2742     public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2743 
2744     /**
2745      * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2746      * is compatible with light status bar backgrounds.
2747      *
2748      * <p>For this to take effect, the window must request
2749      * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2750      *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2751      * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2752      *         FLAG_TRANSLUCENT_STATUS}.
2753      *
2754      * @see android.R.attr#windowLightStatusBar
2755      */
2756     public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2757 
2758     /**
2759      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2760      */
2761     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2762 
2763     /**
2764      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2765      */
2766     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2767 
2768     /**
2769      * @hide
2770      *
2771      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2772      * out of the public fields to keep the undefined bits out of the developer's way.
2773      *
2774      * Flag to make the status bar not expandable.  Unless you also
2775      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2776      */
2777     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2778 
2779     /**
2780      * @hide
2781      *
2782      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2783      * out of the public fields to keep the undefined bits out of the developer's way.
2784      *
2785      * Flag to hide notification icons and scrolling ticker text.
2786      */
2787     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2788 
2789     /**
2790      * @hide
2791      *
2792      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2793      * out of the public fields to keep the undefined bits out of the developer's way.
2794      *
2795      * Flag to disable incoming notification alerts.  This will not block
2796      * icons, but it will block sound, vibrating and other visual or aural notifications.
2797      */
2798     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2799 
2800     /**
2801      * @hide
2802      *
2803      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2804      * out of the public fields to keep the undefined bits out of the developer's way.
2805      *
2806      * Flag to hide only the scrolling ticker.  Note that
2807      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2808      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2809      */
2810     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2811 
2812     /**
2813      * @hide
2814      *
2815      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2816      * out of the public fields to keep the undefined bits out of the developer's way.
2817      *
2818      * Flag to hide the center system info area.
2819      */
2820     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2821 
2822     /**
2823      * @hide
2824      *
2825      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2826      * out of the public fields to keep the undefined bits out of the developer's way.
2827      *
2828      * Flag to hide only the home button.  Don't use this
2829      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2830      */
2831     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2832 
2833     /**
2834      * @hide
2835      *
2836      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2837      * out of the public fields to keep the undefined bits out of the developer's way.
2838      *
2839      * Flag to hide only the back button. Don't use this
2840      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2841      */
2842     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2843 
2844     /**
2845      * @hide
2846      *
2847      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2848      * out of the public fields to keep the undefined bits out of the developer's way.
2849      *
2850      * Flag to hide only the clock.  You might use this if your activity has
2851      * its own clock making the status bar's clock redundant.
2852      */
2853     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2854 
2855     /**
2856      * @hide
2857      *
2858      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2859      * out of the public fields to keep the undefined bits out of the developer's way.
2860      *
2861      * Flag to hide only the recent apps button. Don't use this
2862      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2863      */
2864     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2865 
2866     /**
2867      * @hide
2868      *
2869      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2870      * out of the public fields to keep the undefined bits out of the developer's way.
2871      *
2872      * Flag to disable the global search gesture. Don't use this
2873      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2874      */
2875     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2876 
2877     /**
2878      * @hide
2879      *
2880      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2881      * out of the public fields to keep the undefined bits out of the developer's way.
2882      *
2883      * Flag to specify that the status bar is displayed in transient mode.
2884      */
2885     public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2886 
2887     /**
2888      * @hide
2889      *
2890      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2891      * out of the public fields to keep the undefined bits out of the developer's way.
2892      *
2893      * Flag to specify that the navigation bar is displayed in transient mode.
2894      */
2895     public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2896 
2897     /**
2898      * @hide
2899      *
2900      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2901      * out of the public fields to keep the undefined bits out of the developer's way.
2902      *
2903      * Flag to specify that the hidden status bar would like to be shown.
2904      */
2905     public static final int STATUS_BAR_UNHIDE = 0x10000000;
2906 
2907     /**
2908      * @hide
2909      *
2910      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2911      * out of the public fields to keep the undefined bits out of the developer's way.
2912      *
2913      * Flag to specify that the hidden navigation bar would like to be shown.
2914      */
2915     public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2916 
2917     /**
2918      * @hide
2919      *
2920      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2921      * out of the public fields to keep the undefined bits out of the developer's way.
2922      *
2923      * Flag to specify that the status bar is displayed in translucent mode.
2924      */
2925     public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2926 
2927     /**
2928      * @hide
2929      *
2930      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2931      * out of the public fields to keep the undefined bits out of the developer's way.
2932      *
2933      * Flag to specify that the navigation bar is displayed in translucent mode.
2934      */
2935     public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2936 
2937     /**
2938      * @hide
2939      *
2940      * Whether Recents is visible or not.
2941      */
2942     public static final int RECENT_APPS_VISIBLE = 0x00004000;
2943 
2944     /**
2945      * @hide
2946      *
2947      * Makes system ui transparent.
2948      */
2949     public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2950 
2951     /**
2952      * @hide
2953      */
2954     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2955 
2956     /**
2957      * These are the system UI flags that can be cleared by events outside
2958      * of an application.  Currently this is just the ability to tap on the
2959      * screen while hiding the navigation bar to have it return.
2960      * @hide
2961      */
2962     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2963             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2964             | SYSTEM_UI_FLAG_FULLSCREEN;
2965 
2966     /**
2967      * Flags that can impact the layout in relation to system UI.
2968      */
2969     public static final int SYSTEM_UI_LAYOUT_FLAGS =
2970             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2971             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2972 
2973     /** @hide */
2974     @IntDef(flag = true,
2975             value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2976     @Retention(RetentionPolicy.SOURCE)
2977     public @interface FindViewFlags {}
2978 
2979     /**
2980      * Find views that render the specified text.
2981      *
2982      * @see #findViewsWithText(ArrayList, CharSequence, int)
2983      */
2984     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2985 
2986     /**
2987      * Find find views that contain the specified content description.
2988      *
2989      * @see #findViewsWithText(ArrayList, CharSequence, int)
2990      */
2991     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2992 
2993     /**
2994      * Find views that contain {@link AccessibilityNodeProvider}. Such
2995      * a View is a root of virtual view hierarchy and may contain the searched
2996      * text. If this flag is set Views with providers are automatically
2997      * added and it is a responsibility of the client to call the APIs of
2998      * the provider to determine whether the virtual tree rooted at this View
2999      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3000      * representing the virtual views with this text.
3001      *
3002      * @see #findViewsWithText(ArrayList, CharSequence, int)
3003      *
3004      * @hide
3005      */
3006     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3007 
3008     /**
3009      * The undefined cursor position.
3010      *
3011      * @hide
3012      */
3013     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3014 
3015     /**
3016      * Indicates that the screen has changed state and is now off.
3017      *
3018      * @see #onScreenStateChanged(int)
3019      */
3020     public static final int SCREEN_STATE_OFF = 0x0;
3021 
3022     /**
3023      * Indicates that the screen has changed state and is now on.
3024      *
3025      * @see #onScreenStateChanged(int)
3026      */
3027     public static final int SCREEN_STATE_ON = 0x1;
3028 
3029     /**
3030      * Indicates no axis of view scrolling.
3031      */
3032     public static final int SCROLL_AXIS_NONE = 0;
3033 
3034     /**
3035      * Indicates scrolling along the horizontal axis.
3036      */
3037     public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3038 
3039     /**
3040      * Indicates scrolling along the vertical axis.
3041      */
3042     public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3043 
3044     /**
3045      * Controls the over-scroll mode for this view.
3046      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3047      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3048      * and {@link #OVER_SCROLL_NEVER}.
3049      */
3050     private int mOverScrollMode;
3051 
3052     /**
3053      * The parent this view is attached to.
3054      * {@hide}
3055      *
3056      * @see #getParent()
3057      */
3058     protected ViewParent mParent;
3059 
3060     /**
3061      * {@hide}
3062      */
3063     AttachInfo mAttachInfo;
3064 
3065     /**
3066      * {@hide}
3067      */
3068     @ViewDebug.ExportedProperty(flagMapping = {
3069         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3070                 name = "FORCE_LAYOUT"),
3071         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3072                 name = "LAYOUT_REQUIRED"),
3073         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3074             name = "DRAWING_CACHE_INVALID", outputIf = false),
3075         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3076         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3077         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3078         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3079     }, formatToHexString = true)
3080     int mPrivateFlags;
3081     int mPrivateFlags2;
3082     int mPrivateFlags3;
3083 
3084     /**
3085      * This view's request for the visibility of the status bar.
3086      * @hide
3087      */
3088     @ViewDebug.ExportedProperty(flagMapping = {
3089         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3090                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3091                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3092         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3093                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3094                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3095         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3096                                 equals = SYSTEM_UI_FLAG_VISIBLE,
3097                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3098     }, formatToHexString = true)
3099     int mSystemUiVisibility;
3100 
3101     /**
3102      * Reference count for transient state.
3103      * @see #setHasTransientState(boolean)
3104      */
3105     int mTransientStateCount = 0;
3106 
3107     /**
3108      * Count of how many windows this view has been attached to.
3109      */
3110     int mWindowAttachCount;
3111 
3112     /**
3113      * The layout parameters associated with this view and used by the parent
3114      * {@link android.view.ViewGroup} to determine how this view should be
3115      * laid out.
3116      * {@hide}
3117      */
3118     protected ViewGroup.LayoutParams mLayoutParams;
3119 
3120     /**
3121      * The view flags hold various views states.
3122      * {@hide}
3123      */
3124     @ViewDebug.ExportedProperty(formatToHexString = true)
3125     int mViewFlags;
3126 
3127     static class TransformationInfo {
3128         /**
3129          * The transform matrix for the View. This transform is calculated internally
3130          * based on the translation, rotation, and scale properties.
3131          *
3132          * Do *not* use this variable directly; instead call getMatrix(), which will
3133          * load the value from the View's RenderNode.
3134          */
3135         private final Matrix mMatrix = new Matrix();
3136 
3137         /**
3138          * The inverse transform matrix for the View. This transform is calculated
3139          * internally based on the translation, rotation, and scale properties.
3140          *
3141          * Do *not* use this variable directly; instead call getInverseMatrix(),
3142          * which will load the value from the View's RenderNode.
3143          */
3144         private Matrix mInverseMatrix;
3145 
3146         /**
3147          * The opacity of the View. This is a value from 0 to 1, where 0 means
3148          * completely transparent and 1 means completely opaque.
3149          */
3150         @ViewDebug.ExportedProperty
3151         float mAlpha = 1f;
3152 
3153         /**
3154          * The opacity of the view as manipulated by the Fade transition. This is a hidden
3155          * property only used by transitions, which is composited with the other alpha
3156          * values to calculate the final visual alpha value.
3157          */
3158         float mTransitionAlpha = 1f;
3159     }
3160 
3161     TransformationInfo mTransformationInfo;
3162 
3163     /**
3164      * Current clip bounds. to which all drawing of this view are constrained.
3165      */
3166     Rect mClipBounds = null;
3167 
3168     private boolean mLastIsOpaque;
3169 
3170     /**
3171      * The distance in pixels from the left edge of this view's parent
3172      * to the left edge of this view.
3173      * {@hide}
3174      */
3175     @ViewDebug.ExportedProperty(category = "layout")
3176     protected int mLeft;
3177     /**
3178      * The distance in pixels from the left edge of this view's parent
3179      * to the right edge of this view.
3180      * {@hide}
3181      */
3182     @ViewDebug.ExportedProperty(category = "layout")
3183     protected int mRight;
3184     /**
3185      * The distance in pixels from the top edge of this view's parent
3186      * to the top edge of this view.
3187      * {@hide}
3188      */
3189     @ViewDebug.ExportedProperty(category = "layout")
3190     protected int mTop;
3191     /**
3192      * The distance in pixels from the top edge of this view's parent
3193      * to the bottom edge of this view.
3194      * {@hide}
3195      */
3196     @ViewDebug.ExportedProperty(category = "layout")
3197     protected int mBottom;
3198 
3199     /**
3200      * The offset, in pixels, by which the content of this view is scrolled
3201      * horizontally.
3202      * {@hide}
3203      */
3204     @ViewDebug.ExportedProperty(category = "scrolling")
3205     protected int mScrollX;
3206     /**
3207      * The offset, in pixels, by which the content of this view is scrolled
3208      * vertically.
3209      * {@hide}
3210      */
3211     @ViewDebug.ExportedProperty(category = "scrolling")
3212     protected int mScrollY;
3213 
3214     /**
3215      * The left padding in pixels, that is the distance in pixels between the
3216      * left edge of this view and the left edge of its content.
3217      * {@hide}
3218      */
3219     @ViewDebug.ExportedProperty(category = "padding")
3220     protected int mPaddingLeft = 0;
3221     /**
3222      * The right padding in pixels, that is the distance in pixels between the
3223      * right edge of this view and the right edge of its content.
3224      * {@hide}
3225      */
3226     @ViewDebug.ExportedProperty(category = "padding")
3227     protected int mPaddingRight = 0;
3228     /**
3229      * The top padding in pixels, that is the distance in pixels between the
3230      * top edge of this view and the top edge of its content.
3231      * {@hide}
3232      */
3233     @ViewDebug.ExportedProperty(category = "padding")
3234     protected int mPaddingTop;
3235     /**
3236      * The bottom padding in pixels, that is the distance in pixels between the
3237      * bottom edge of this view and the bottom edge of its content.
3238      * {@hide}
3239      */
3240     @ViewDebug.ExportedProperty(category = "padding")
3241     protected int mPaddingBottom;
3242 
3243     /**
3244      * The layout insets in pixels, that is the distance in pixels between the
3245      * visible edges of this view its bounds.
3246      */
3247     private Insets mLayoutInsets;
3248 
3249     /**
3250      * Briefly describes the view and is primarily used for accessibility support.
3251      */
3252     private CharSequence mContentDescription;
3253 
3254     /**
3255      * Specifies the id of a view for which this view serves as a label for
3256      * accessibility purposes.
3257      */
3258     private int mLabelForId = View.NO_ID;
3259 
3260     /**
3261      * Predicate for matching labeled view id with its label for
3262      * accessibility purposes.
3263      */
3264     private MatchLabelForPredicate mMatchLabelForPredicate;
3265 
3266     /**
3267      * Specifies a view before which this one is visited in accessibility traversal.
3268      */
3269     private int mAccessibilityTraversalBeforeId = NO_ID;
3270 
3271     /**
3272      * Specifies a view after which this one is visited in accessibility traversal.
3273      */
3274     private int mAccessibilityTraversalAfterId = NO_ID;
3275 
3276     /**
3277      * Predicate for matching a view by its id.
3278      */
3279     private MatchIdPredicate mMatchIdPredicate;
3280 
3281     /**
3282      * Cache the paddingRight set by the user to append to the scrollbar's size.
3283      *
3284      * @hide
3285      */
3286     @ViewDebug.ExportedProperty(category = "padding")
3287     protected int mUserPaddingRight;
3288 
3289     /**
3290      * Cache the paddingBottom set by the user to append to the scrollbar's size.
3291      *
3292      * @hide
3293      */
3294     @ViewDebug.ExportedProperty(category = "padding")
3295     protected int mUserPaddingBottom;
3296 
3297     /**
3298      * Cache the paddingLeft set by the user to append to the scrollbar's size.
3299      *
3300      * @hide
3301      */
3302     @ViewDebug.ExportedProperty(category = "padding")
3303     protected int mUserPaddingLeft;
3304 
3305     /**
3306      * Cache the paddingStart set by the user to append to the scrollbar's size.
3307      *
3308      */
3309     @ViewDebug.ExportedProperty(category = "padding")
3310     int mUserPaddingStart;
3311 
3312     /**
3313      * Cache the paddingEnd set by the user to append to the scrollbar's size.
3314      *
3315      */
3316     @ViewDebug.ExportedProperty(category = "padding")
3317     int mUserPaddingEnd;
3318 
3319     /**
3320      * Cache initial left padding.
3321      *
3322      * @hide
3323      */
3324     int mUserPaddingLeftInitial;
3325 
3326     /**
3327      * Cache initial right padding.
3328      *
3329      * @hide
3330      */
3331     int mUserPaddingRightInitial;
3332 
3333     /**
3334      * Default undefined padding
3335      */
3336     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3337 
3338     /**
3339      * Cache if a left padding has been defined
3340      */
3341     private boolean mLeftPaddingDefined = false;
3342 
3343     /**
3344      * Cache if a right padding has been defined
3345      */
3346     private boolean mRightPaddingDefined = false;
3347 
3348     /**
3349      * @hide
3350      */
3351     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3352     /**
3353      * @hide
3354      */
3355     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3356 
3357     private LongSparseLongArray mMeasureCache;
3358 
3359     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3360     private Drawable mBackground;
3361     private TintInfo mBackgroundTint;
3362 
3363     @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3364     private ForegroundInfo mForegroundInfo;
3365 
3366     private Drawable mScrollIndicatorDrawable;
3367 
3368     /**
3369      * RenderNode used for backgrounds.
3370      * <p>
3371      * When non-null and valid, this is expected to contain an up-to-date copy
3372      * of the background drawable. It is cleared on temporary detach, and reset
3373      * on cleanup.
3374      */
3375     private RenderNode mBackgroundRenderNode;
3376 
3377     private int mBackgroundResource;
3378     private boolean mBackgroundSizeChanged;
3379 
3380     private String mTransitionName;
3381 
3382     static class TintInfo {
3383         ColorStateList mTintList;
3384         PorterDuff.Mode mTintMode;
3385         boolean mHasTintMode;
3386         boolean mHasTintList;
3387     }
3388 
3389     private static class ForegroundInfo {
3390         private Drawable mDrawable;
3391         private TintInfo mTintInfo;
3392         private int mGravity = Gravity.FILL;
3393         private boolean mInsidePadding = true;
3394         private boolean mBoundsChanged = true;
3395         private final Rect mSelfBounds = new Rect();
3396         private final Rect mOverlayBounds = new Rect();
3397     }
3398 
3399     static class ListenerInfo {
3400         /**
3401          * Listener used to dispatch focus change events.
3402          * This field should be made private, so it is hidden from the SDK.
3403          * {@hide}
3404          */
3405         protected OnFocusChangeListener mOnFocusChangeListener;
3406 
3407         /**
3408          * Listeners for layout change events.
3409          */
3410         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3411 
3412         protected OnScrollChangeListener mOnScrollChangeListener;
3413 
3414         /**
3415          * Listeners for attach events.
3416          */
3417         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3418 
3419         /**
3420          * Listener used to dispatch click events.
3421          * This field should be made private, so it is hidden from the SDK.
3422          * {@hide}
3423          */
3424         public OnClickListener mOnClickListener;
3425 
3426         /**
3427          * Listener used to dispatch long click events.
3428          * This field should be made private, so it is hidden from the SDK.
3429          * {@hide}
3430          */
3431         protected OnLongClickListener mOnLongClickListener;
3432 
3433         /**
3434          * Listener used to dispatch context click events. This field should be made private, so it
3435          * is hidden from the SDK.
3436          * {@hide}
3437          */
3438         protected OnContextClickListener mOnContextClickListener;
3439 
3440         /**
3441          * Listener used to build the context menu.
3442          * This field should be made private, so it is hidden from the SDK.
3443          * {@hide}
3444          */
3445         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3446 
3447         private OnKeyListener mOnKeyListener;
3448 
3449         private OnTouchListener mOnTouchListener;
3450 
3451         private OnHoverListener mOnHoverListener;
3452 
3453         private OnGenericMotionListener mOnGenericMotionListener;
3454 
3455         private OnDragListener mOnDragListener;
3456 
3457         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3458 
3459         OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3460     }
3461 
3462     ListenerInfo mListenerInfo;
3463 
3464     /**
3465      * The application environment this view lives in.
3466      * This field should be made private, so it is hidden from the SDK.
3467      * {@hide}
3468      */
3469     @ViewDebug.ExportedProperty(deepExport = true)
3470     protected Context mContext;
3471 
3472     private final Resources mResources;
3473 
3474     private ScrollabilityCache mScrollCache;
3475 
3476     private int[] mDrawableState = null;
3477 
3478     ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3479 
3480     /**
3481      * Animator that automatically runs based on state changes.
3482      */
3483     private StateListAnimator mStateListAnimator;
3484 
3485     /**
3486      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3487      * the user may specify which view to go to next.
3488      */
3489     private int mNextFocusLeftId = View.NO_ID;
3490 
3491     /**
3492      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3493      * the user may specify which view to go to next.
3494      */
3495     private int mNextFocusRightId = View.NO_ID;
3496 
3497     /**
3498      * When this view has focus and the next focus is {@link #FOCUS_UP},
3499      * the user may specify which view to go to next.
3500      */
3501     private int mNextFocusUpId = View.NO_ID;
3502 
3503     /**
3504      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3505      * the user may specify which view to go to next.
3506      */
3507     private int mNextFocusDownId = View.NO_ID;
3508 
3509     /**
3510      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3511      * the user may specify which view to go to next.
3512      */
3513     int mNextFocusForwardId = View.NO_ID;
3514 
3515     private CheckForLongPress mPendingCheckForLongPress;
3516     private CheckForTap mPendingCheckForTap = null;
3517     private PerformClick mPerformClick;
3518     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3519 
3520     private UnsetPressedState mUnsetPressedState;
3521 
3522     /**
3523      * Whether the long press's action has been invoked.  The tap's action is invoked on the
3524      * up event while a long press is invoked as soon as the long press duration is reached, so
3525      * a long press could be performed before the tap is checked, in which case the tap's action
3526      * should not be invoked.
3527      */
3528     private boolean mHasPerformedLongPress;
3529 
3530     /**
3531      * Whether a context click button is currently pressed down. This is true when the stylus is
3532      * touching the screen and the primary button has been pressed, or if a mouse's right button is
3533      * pressed. This is false once the button is released or if the stylus has been lifted.
3534      */
3535     private boolean mInContextButtonPress;
3536 
3537     /**
3538      * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3539      * true after a stylus button press has occured, when the next up event should not be recognized
3540      * as a tap.
3541      */
3542     private boolean mIgnoreNextUpEvent;
3543 
3544     /**
3545      * The minimum height of the view. We'll try our best to have the height
3546      * of this view to at least this amount.
3547      */
3548     @ViewDebug.ExportedProperty(category = "measurement")
3549     private int mMinHeight;
3550 
3551     /**
3552      * The minimum width of the view. We'll try our best to have the width
3553      * of this view to at least this amount.
3554      */
3555     @ViewDebug.ExportedProperty(category = "measurement")
3556     private int mMinWidth;
3557 
3558     /**
3559      * The delegate to handle touch events that are physically in this view
3560      * but should be handled by another view.
3561      */
3562     private TouchDelegate mTouchDelegate = null;
3563 
3564     /**
3565      * Solid color to use as a background when creating the drawing cache. Enables
3566      * the cache to use 16 bit bitmaps instead of 32 bit.
3567      */
3568     private int mDrawingCacheBackgroundColor = 0;
3569 
3570     /**
3571      * Special tree observer used when mAttachInfo is null.
3572      */
3573     private ViewTreeObserver mFloatingTreeObserver;
3574 
3575     /**
3576      * Cache the touch slop from the context that created the view.
3577      */
3578     private int mTouchSlop;
3579 
3580     /**
3581      * Object that handles automatic animation of view properties.
3582      */
3583     private ViewPropertyAnimator mAnimator = null;
3584 
3585     /**
3586      * Flag indicating that a drag can cross window boundaries.  When
3587      * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3588      * with this flag set, all visible applications will be able to participate
3589      * in the drag operation and receive the dragged content.
3590      *
3591      * @hide
3592      */
3593     public static final int DRAG_FLAG_GLOBAL = 1;
3594 
3595     /**
3596      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3597      */
3598     private float mVerticalScrollFactor;
3599 
3600     /**
3601      * Position of the vertical scroll bar.
3602      */
3603     private int mVerticalScrollbarPosition;
3604 
3605     /**
3606      * Position the scroll bar at the default position as determined by the system.
3607      */
3608     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3609 
3610     /**
3611      * Position the scroll bar along the left edge.
3612      */
3613     public static final int SCROLLBAR_POSITION_LEFT = 1;
3614 
3615     /**
3616      * Position the scroll bar along the right edge.
3617      */
3618     public static final int SCROLLBAR_POSITION_RIGHT = 2;
3619 
3620     /**
3621      * Indicates that the view does not have a layer.
3622      *
3623      * @see #getLayerType()
3624      * @see #setLayerType(int, android.graphics.Paint)
3625      * @see #LAYER_TYPE_SOFTWARE
3626      * @see #LAYER_TYPE_HARDWARE
3627      */
3628     public static final int LAYER_TYPE_NONE = 0;
3629 
3630     /**
3631      * <p>Indicates that the view has a software layer. A software layer is backed
3632      * by a bitmap and causes the view to be rendered using Android's software
3633      * rendering pipeline, even if hardware acceleration is enabled.</p>
3634      *
3635      * <p>Software layers have various usages:</p>
3636      * <p>When the application is not using hardware acceleration, a software layer
3637      * is useful to apply a specific color filter and/or blending mode and/or
3638      * translucency to a view and all its children.</p>
3639      * <p>When the application is using hardware acceleration, a software layer
3640      * is useful to render drawing primitives not supported by the hardware
3641      * accelerated pipeline. It can also be used to cache a complex view tree
3642      * into a texture and reduce the complexity of drawing operations. For instance,
3643      * when animating a complex view tree with a translation, a software layer can
3644      * be used to render the view tree only once.</p>
3645      * <p>Software layers should be avoided when the affected view tree updates
3646      * often. Every update will require to re-render the software layer, which can
3647      * potentially be slow (particularly when hardware acceleration is turned on
3648      * since the layer will have to be uploaded into a hardware texture after every
3649      * update.)</p>
3650      *
3651      * @see #getLayerType()
3652      * @see #setLayerType(int, android.graphics.Paint)
3653      * @see #LAYER_TYPE_NONE
3654      * @see #LAYER_TYPE_HARDWARE
3655      */
3656     public static final int LAYER_TYPE_SOFTWARE = 1;
3657 
3658     /**
3659      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3660      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3661      * OpenGL hardware) and causes the view to be rendered using Android's hardware
3662      * rendering pipeline, but only if hardware acceleration is turned on for the
3663      * view hierarchy. When hardware acceleration is turned off, hardware layers
3664      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3665      *
3666      * <p>A hardware layer is useful to apply a specific color filter and/or
3667      * blending mode and/or translucency to a view and all its children.</p>
3668      * <p>A hardware layer can be used to cache a complex view tree into a
3669      * texture and reduce the complexity of drawing operations. For instance,
3670      * when animating a complex view tree with a translation, a hardware layer can
3671      * be used to render the view tree only once.</p>
3672      * <p>A hardware layer can also be used to increase the rendering quality when
3673      * rotation transformations are applied on a view. It can also be used to
3674      * prevent potential clipping issues when applying 3D transforms on a view.</p>
3675      *
3676      * @see #getLayerType()
3677      * @see #setLayerType(int, android.graphics.Paint)
3678      * @see #LAYER_TYPE_NONE
3679      * @see #LAYER_TYPE_SOFTWARE
3680      */
3681     public static final int LAYER_TYPE_HARDWARE = 2;
3682 
3683     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3684             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3685             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3686             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3687     })
3688     int mLayerType = LAYER_TYPE_NONE;
3689     Paint mLayerPaint;
3690 
3691     /**
3692      * Set to true when drawing cache is enabled and cannot be created.
3693      *
3694      * @hide
3695      */
3696     public boolean mCachingFailed;
3697     private Bitmap mDrawingCache;
3698     private Bitmap mUnscaledDrawingCache;
3699 
3700     /**
3701      * RenderNode holding View properties, potentially holding a DisplayList of View content.
3702      * <p>
3703      * When non-null and valid, this is expected to contain an up-to-date copy
3704      * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3705      * cleanup.
3706      */
3707     final RenderNode mRenderNode;
3708 
3709     /**
3710      * Set to true when the view is sending hover accessibility events because it
3711      * is the innermost hovered view.
3712      */
3713     private boolean mSendingHoverAccessibilityEvents;
3714 
3715     /**
3716      * Delegate for injecting accessibility functionality.
3717      */
3718     AccessibilityDelegate mAccessibilityDelegate;
3719 
3720     /**
3721      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3722      * and add/remove objects to/from the overlay directly through the Overlay methods.
3723      */
3724     ViewOverlay mOverlay;
3725 
3726     /**
3727      * The currently active parent view for receiving delegated nested scrolling events.
3728      * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3729      * by {@link #stopNestedScroll()} at the same point where we clear
3730      * requestDisallowInterceptTouchEvent.
3731      */
3732     private ViewParent mNestedScrollingParent;
3733 
3734     /**
3735      * Consistency verifier for debugging purposes.
3736      * @hide
3737      */
3738     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3739             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3740                     new InputEventConsistencyVerifier(this, 0) : null;
3741 
3742     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3743 
3744     private int[] mTempNestedScrollConsumed;
3745 
3746     /**
3747      * An overlay is going to draw this View instead of being drawn as part of this
3748      * View's parent. mGhostView is the View in the Overlay that must be invalidated
3749      * when this view is invalidated.
3750      */
3751     GhostView mGhostView;
3752 
3753     /**
3754      * Holds pairs of adjacent attribute data: attribute name followed by its value.
3755      * @hide
3756      */
3757     @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3758     public String[] mAttributes;
3759 
3760     /**
3761      * Maps a Resource id to its name.
3762      */
3763     private static SparseArray<String> mAttributeMap;
3764 
3765     /**
3766      * @hide
3767      */
3768     String mStartActivityRequestWho;
3769 
3770     /**
3771      * Simple constructor to use when creating a view from code.
3772      *
3773      * @param context The Context the view is running in, through which it can
3774      *        access the current theme, resources, etc.
3775      */
View(Context context)3776     public View(Context context) {
3777         mContext = context;
3778         mResources = context != null ? context.getResources() : null;
3779         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3780         // Set some flags defaults
3781         mPrivateFlags2 =
3782                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3783                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3784                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3785                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3786                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3787                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3788         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3789         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3790         mUserPaddingStart = UNDEFINED_PADDING;
3791         mUserPaddingEnd = UNDEFINED_PADDING;
3792         mRenderNode = RenderNode.create(getClass().getName(), this);
3793 
3794         if (!sCompatibilityDone && context != null) {
3795             final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3796 
3797             // Older apps may need this compatibility hack for measurement.
3798             sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3799 
3800             // Older apps expect onMeasure() to always be called on a layout pass, regardless
3801             // of whether a layout was requested on that View.
3802             sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3803 
3804             Canvas.sCompatibilityRestore = targetSdkVersion < M;
3805 
3806             // In M and newer, our widgets can pass a "hint" value in the size
3807             // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
3808             // know what the expected parent size is going to be, so e.g. list items can size
3809             // themselves at 1/3 the size of their container. It breaks older apps though,
3810             // specifically apps that use some popular open source libraries.
3811             sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
3812 
3813             sCompatibilityDone = true;
3814         }
3815     }
3816 
3817     /**
3818      * Constructor that is called when inflating a view from XML. This is called
3819      * when a view is being constructed from an XML file, supplying attributes
3820      * that were specified in the XML file. This version uses a default style of
3821      * 0, so the only attribute values applied are those in the Context's Theme
3822      * and the given AttributeSet.
3823      *
3824      * <p>
3825      * The method onFinishInflate() will be called after all children have been
3826      * added.
3827      *
3828      * @param context The Context the view is running in, through which it can
3829      *        access the current theme, resources, etc.
3830      * @param attrs The attributes of the XML tag that is inflating the view.
3831      * @see #View(Context, AttributeSet, int)
3832      */
3833     public View(Context context, @Nullable AttributeSet attrs) {
3834         this(context, attrs, 0);
3835     }
3836 
3837     /**
3838      * Perform inflation from XML and apply a class-specific base style from a
3839      * theme attribute. This constructor of View allows subclasses to use their
3840      * own base style when they are inflating. For example, a Button class's
3841      * constructor would call this version of the super class constructor and
3842      * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3843      * allows the theme's button style to modify all of the base view attributes
3844      * (in particular its background) as well as the Button class's attributes.
3845      *
3846      * @param context The Context the view is running in, through which it can
3847      *        access the current theme, resources, etc.
3848      * @param attrs The attributes of the XML tag that is inflating the view.
3849      * @param defStyleAttr An attribute in the current theme that contains a
3850      *        reference to a style resource that supplies default values for
3851      *        the view. Can be 0 to not look for defaults.
3852      * @see #View(Context, AttributeSet)
3853      */
3854     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3855         this(context, attrs, defStyleAttr, 0);
3856     }
3857 
3858     /**
3859      * Perform inflation from XML and apply a class-specific base style from a
3860      * theme attribute or style resource. This constructor of View allows
3861      * subclasses to use their own base style when they are inflating.
3862      * <p>
3863      * When determining the final value of a particular attribute, there are
3864      * four inputs that come into play:
3865      * <ol>
3866      * <li>Any attribute values in the given AttributeSet.
3867      * <li>The style resource specified in the AttributeSet (named "style").
3868      * <li>The default style specified by <var>defStyleAttr</var>.
3869      * <li>The default style specified by <var>defStyleRes</var>.
3870      * <li>The base values in this theme.
3871      * </ol>
3872      * <p>
3873      * Each of these inputs is considered in-order, with the first listed taking
3874      * precedence over the following ones. In other words, if in the
3875      * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3876      * , then the button's text will <em>always</em> be black, regardless of
3877      * what is specified in any of the styles.
3878      *
3879      * @param context The Context the view is running in, through which it can
3880      *        access the current theme, resources, etc.
3881      * @param attrs The attributes of the XML tag that is inflating the view.
3882      * @param defStyleAttr An attribute in the current theme that contains a
3883      *        reference to a style resource that supplies default values for
3884      *        the view. Can be 0 to not look for defaults.
3885      * @param defStyleRes A resource identifier of a style resource that
3886      *        supplies default values for the view, used only if
3887      *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3888      *        to not look for defaults.
3889      * @see #View(Context, AttributeSet, int)
3890      */
3891     public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3892         this(context);
3893 
3894         final TypedArray a = context.obtainStyledAttributes(
3895                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3896 
3897         if (mDebugViewAttributes) {
3898             saveAttributeData(attrs, a);
3899         }
3900 
3901         Drawable background = null;
3902 
3903         int leftPadding = -1;
3904         int topPadding = -1;
3905         int rightPadding = -1;
3906         int bottomPadding = -1;
3907         int startPadding = UNDEFINED_PADDING;
3908         int endPadding = UNDEFINED_PADDING;
3909 
3910         int padding = -1;
3911 
3912         int viewFlagValues = 0;
3913         int viewFlagMasks = 0;
3914 
3915         boolean setScrollContainer = false;
3916 
3917         int x = 0;
3918         int y = 0;
3919 
3920         float tx = 0;
3921         float ty = 0;
3922         float tz = 0;
3923         float elevation = 0;
3924         float rotation = 0;
3925         float rotationX = 0;
3926         float rotationY = 0;
3927         float sx = 1f;
3928         float sy = 1f;
3929         boolean transformSet = false;
3930 
3931         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3932         int overScrollMode = mOverScrollMode;
3933         boolean initializeScrollbars = false;
3934         boolean initializeScrollIndicators = false;
3935 
3936         boolean startPaddingDefined = false;
3937         boolean endPaddingDefined = false;
3938         boolean leftPaddingDefined = false;
3939         boolean rightPaddingDefined = false;
3940 
3941         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3942 
3943         final int N = a.getIndexCount();
3944         for (int i = 0; i < N; i++) {
3945             int attr = a.getIndex(i);
3946             switch (attr) {
3947                 case com.android.internal.R.styleable.View_background:
3948                     background = a.getDrawable(attr);
3949                     break;
3950                 case com.android.internal.R.styleable.View_padding:
3951                     padding = a.getDimensionPixelSize(attr, -1);
3952                     mUserPaddingLeftInitial = padding;
3953                     mUserPaddingRightInitial = padding;
3954                     leftPaddingDefined = true;
3955                     rightPaddingDefined = true;
3956                     break;
3957                  case com.android.internal.R.styleable.View_paddingLeft:
3958                     leftPadding = a.getDimensionPixelSize(attr, -1);
3959                     mUserPaddingLeftInitial = leftPadding;
3960                     leftPaddingDefined = true;
3961                     break;
3962                 case com.android.internal.R.styleable.View_paddingTop:
3963                     topPadding = a.getDimensionPixelSize(attr, -1);
3964                     break;
3965                 case com.android.internal.R.styleable.View_paddingRight:
3966                     rightPadding = a.getDimensionPixelSize(attr, -1);
3967                     mUserPaddingRightInitial = rightPadding;
3968                     rightPaddingDefined = true;
3969                     break;
3970                 case com.android.internal.R.styleable.View_paddingBottom:
3971                     bottomPadding = a.getDimensionPixelSize(attr, -1);
3972                     break;
3973                 case com.android.internal.R.styleable.View_paddingStart:
3974                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3975                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3976                     break;
3977                 case com.android.internal.R.styleable.View_paddingEnd:
3978                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3979                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3980                     break;
3981                 case com.android.internal.R.styleable.View_scrollX:
3982                     x = a.getDimensionPixelOffset(attr, 0);
3983                     break;
3984                 case com.android.internal.R.styleable.View_scrollY:
3985                     y = a.getDimensionPixelOffset(attr, 0);
3986                     break;
3987                 case com.android.internal.R.styleable.View_alpha:
3988                     setAlpha(a.getFloat(attr, 1f));
3989                     break;
3990                 case com.android.internal.R.styleable.View_transformPivotX:
3991                     setPivotX(a.getDimensionPixelOffset(attr, 0));
3992                     break;
3993                 case com.android.internal.R.styleable.View_transformPivotY:
3994                     setPivotY(a.getDimensionPixelOffset(attr, 0));
3995                     break;
3996                 case com.android.internal.R.styleable.View_translationX:
3997                     tx = a.getDimensionPixelOffset(attr, 0);
3998                     transformSet = true;
3999                     break;
4000                 case com.android.internal.R.styleable.View_translationY:
4001                     ty = a.getDimensionPixelOffset(attr, 0);
4002                     transformSet = true;
4003                     break;
4004                 case com.android.internal.R.styleable.View_translationZ:
4005                     tz = a.getDimensionPixelOffset(attr, 0);
4006                     transformSet = true;
4007                     break;
4008                 case com.android.internal.R.styleable.View_elevation:
4009                     elevation = a.getDimensionPixelOffset(attr, 0);
4010                     transformSet = true;
4011                     break;
4012                 case com.android.internal.R.styleable.View_rotation:
4013                     rotation = a.getFloat(attr, 0);
4014                     transformSet = true;
4015                     break;
4016                 case com.android.internal.R.styleable.View_rotationX:
4017                     rotationX = a.getFloat(attr, 0);
4018                     transformSet = true;
4019                     break;
4020                 case com.android.internal.R.styleable.View_rotationY:
4021                     rotationY = a.getFloat(attr, 0);
4022                     transformSet = true;
4023                     break;
4024                 case com.android.internal.R.styleable.View_scaleX:
4025                     sx = a.getFloat(attr, 1f);
4026                     transformSet = true;
4027                     break;
4028                 case com.android.internal.R.styleable.View_scaleY:
4029                     sy = a.getFloat(attr, 1f);
4030                     transformSet = true;
4031                     break;
4032                 case com.android.internal.R.styleable.View_id:
4033                     mID = a.getResourceId(attr, NO_ID);
4034                     break;
4035                 case com.android.internal.R.styleable.View_tag:
4036                     mTag = a.getText(attr);
4037                     break;
4038                 case com.android.internal.R.styleable.View_fitsSystemWindows:
4039                     if (a.getBoolean(attr, false)) {
4040                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
4041                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4042                     }
4043                     break;
4044                 case com.android.internal.R.styleable.View_focusable:
4045                     if (a.getBoolean(attr, false)) {
4046                         viewFlagValues |= FOCUSABLE;
4047                         viewFlagMasks |= FOCUSABLE_MASK;
4048                     }
4049                     break;
4050                 case com.android.internal.R.styleable.View_focusableInTouchMode:
4051                     if (a.getBoolean(attr, false)) {
4052                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4053                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4054                     }
4055                     break;
4056                 case com.android.internal.R.styleable.View_clickable:
4057                     if (a.getBoolean(attr, false)) {
4058                         viewFlagValues |= CLICKABLE;
4059                         viewFlagMasks |= CLICKABLE;
4060                     }
4061                     break;
4062                 case com.android.internal.R.styleable.View_longClickable:
4063                     if (a.getBoolean(attr, false)) {
4064                         viewFlagValues |= LONG_CLICKABLE;
4065                         viewFlagMasks |= LONG_CLICKABLE;
4066                     }
4067                     break;
4068                 case com.android.internal.R.styleable.View_contextClickable:
4069                     if (a.getBoolean(attr, false)) {
4070                         viewFlagValues |= CONTEXT_CLICKABLE;
4071                         viewFlagMasks |= CONTEXT_CLICKABLE;
4072                     }
4073                     break;
4074                 case com.android.internal.R.styleable.View_saveEnabled:
4075                     if (!a.getBoolean(attr, true)) {
4076                         viewFlagValues |= SAVE_DISABLED;
4077                         viewFlagMasks |= SAVE_DISABLED_MASK;
4078                     }
4079                     break;
4080                 case com.android.internal.R.styleable.View_duplicateParentState:
4081                     if (a.getBoolean(attr, false)) {
4082                         viewFlagValues |= DUPLICATE_PARENT_STATE;
4083                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
4084                     }
4085                     break;
4086                 case com.android.internal.R.styleable.View_visibility:
4087                     final int visibility = a.getInt(attr, 0);
4088                     if (visibility != 0) {
4089                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
4090                         viewFlagMasks |= VISIBILITY_MASK;
4091                     }
4092                     break;
4093                 case com.android.internal.R.styleable.View_layoutDirection:
4094                     // Clear any layout direction flags (included resolved bits) already set
4095                     mPrivateFlags2 &=
4096                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4097                     // Set the layout direction flags depending on the value of the attribute
4098                     final int layoutDirection = a.getInt(attr, -1);
4099                     final int value = (layoutDirection != -1) ?
4100                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4101                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4102                     break;
4103                 case com.android.internal.R.styleable.View_drawingCacheQuality:
4104                     final int cacheQuality = a.getInt(attr, 0);
4105                     if (cacheQuality != 0) {
4106                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4107                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4108                     }
4109                     break;
4110                 case com.android.internal.R.styleable.View_contentDescription:
4111                     setContentDescription(a.getString(attr));
4112                     break;
4113                 case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4114                     setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4115                     break;
4116                 case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4117                     setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4118                     break;
4119                 case com.android.internal.R.styleable.View_labelFor:
4120                     setLabelFor(a.getResourceId(attr, NO_ID));
4121                     break;
4122                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
4123                     if (!a.getBoolean(attr, true)) {
4124                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4125                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4126                     }
4127                     break;
4128                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4129                     if (!a.getBoolean(attr, true)) {
4130                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4131                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4132                     }
4133                     break;
4134                 case R.styleable.View_scrollbars:
4135                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4136                     if (scrollbars != SCROLLBARS_NONE) {
4137                         viewFlagValues |= scrollbars;
4138                         viewFlagMasks |= SCROLLBARS_MASK;
4139                         initializeScrollbars = true;
4140                     }
4141                     break;
4142                 //noinspection deprecation
4143                 case R.styleable.View_fadingEdge:
4144                     if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4145                         // Ignore the attribute starting with ICS
4146                         break;
4147                     }
4148                     // With builds < ICS, fall through and apply fading edges
4149                 case R.styleable.View_requiresFadingEdge:
4150                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4151                     if (fadingEdge != FADING_EDGE_NONE) {
4152                         viewFlagValues |= fadingEdge;
4153                         viewFlagMasks |= FADING_EDGE_MASK;
4154                         initializeFadingEdgeInternal(a);
4155                     }
4156                     break;
4157                 case R.styleable.View_scrollbarStyle:
4158                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4159                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4160                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4161                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4162                     }
4163                     break;
4164                 case R.styleable.View_isScrollContainer:
4165                     setScrollContainer = true;
4166                     if (a.getBoolean(attr, false)) {
4167                         setScrollContainer(true);
4168                     }
4169                     break;
4170                 case com.android.internal.R.styleable.View_keepScreenOn:
4171                     if (a.getBoolean(attr, false)) {
4172                         viewFlagValues |= KEEP_SCREEN_ON;
4173                         viewFlagMasks |= KEEP_SCREEN_ON;
4174                     }
4175                     break;
4176                 case R.styleable.View_filterTouchesWhenObscured:
4177                     if (a.getBoolean(attr, false)) {
4178                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4179                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4180                     }
4181                     break;
4182                 case R.styleable.View_nextFocusLeft:
4183                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4184                     break;
4185                 case R.styleable.View_nextFocusRight:
4186                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4187                     break;
4188                 case R.styleable.View_nextFocusUp:
4189                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4190                     break;
4191                 case R.styleable.View_nextFocusDown:
4192                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4193                     break;
4194                 case R.styleable.View_nextFocusForward:
4195                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4196                     break;
4197                 case R.styleable.View_minWidth:
4198                     mMinWidth = a.getDimensionPixelSize(attr, 0);
4199                     break;
4200                 case R.styleable.View_minHeight:
4201                     mMinHeight = a.getDimensionPixelSize(attr, 0);
4202                     break;
4203                 case R.styleable.View_onClick:
4204                     if (context.isRestricted()) {
4205                         throw new IllegalStateException("The android:onClick attribute cannot "
4206                                 + "be used within a restricted context");
4207                     }
4208 
4209                     final String handlerName = a.getString(attr);
4210                     if (handlerName != null) {
4211                         setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4212                     }
4213                     break;
4214                 case R.styleable.View_overScrollMode:
4215                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4216                     break;
4217                 case R.styleable.View_verticalScrollbarPosition:
4218                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4219                     break;
4220                 case R.styleable.View_layerType:
4221                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4222                     break;
4223                 case R.styleable.View_textDirection:
4224                     // Clear any text direction flag already set
4225                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4226                     // Set the text direction flags depending on the value of the attribute
4227                     final int textDirection = a.getInt(attr, -1);
4228                     if (textDirection != -1) {
4229                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4230                     }
4231                     break;
4232                 case R.styleable.View_textAlignment:
4233                     // Clear any text alignment flag already set
4234                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4235                     // Set the text alignment flag depending on the value of the attribute
4236                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4237                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4238                     break;
4239                 case R.styleable.View_importantForAccessibility:
4240                     setImportantForAccessibility(a.getInt(attr,
4241                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4242                     break;
4243                 case R.styleable.View_accessibilityLiveRegion:
4244                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4245                     break;
4246                 case R.styleable.View_transitionName:
4247                     setTransitionName(a.getString(attr));
4248                     break;
4249                 case R.styleable.View_nestedScrollingEnabled:
4250                     setNestedScrollingEnabled(a.getBoolean(attr, false));
4251                     break;
4252                 case R.styleable.View_stateListAnimator:
4253                     setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4254                             a.getResourceId(attr, 0)));
4255                     break;
4256                 case R.styleable.View_backgroundTint:
4257                     // This will get applied later during setBackground().
4258                     if (mBackgroundTint == null) {
4259                         mBackgroundTint = new TintInfo();
4260                     }
4261                     mBackgroundTint.mTintList = a.getColorStateList(
4262                             R.styleable.View_backgroundTint);
4263                     mBackgroundTint.mHasTintList = true;
4264                     break;
4265                 case R.styleable.View_backgroundTintMode:
4266                     // This will get applied later during setBackground().
4267                     if (mBackgroundTint == null) {
4268                         mBackgroundTint = new TintInfo();
4269                     }
4270                     mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4271                             R.styleable.View_backgroundTintMode, -1), null);
4272                     mBackgroundTint.mHasTintMode = true;
4273                     break;
4274                 case R.styleable.View_outlineProvider:
4275                     setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4276                             PROVIDER_BACKGROUND));
4277                     break;
4278                 case R.styleable.View_foreground:
4279                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4280                         setForeground(a.getDrawable(attr));
4281                     }
4282                     break;
4283                 case R.styleable.View_foregroundGravity:
4284                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4285                         setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4286                     }
4287                     break;
4288                 case R.styleable.View_foregroundTintMode:
4289                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4290                         setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4291                     }
4292                     break;
4293                 case R.styleable.View_foregroundTint:
4294                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4295                         setForegroundTintList(a.getColorStateList(attr));
4296                     }
4297                     break;
4298                 case R.styleable.View_foregroundInsidePadding:
4299                     if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4300                         if (mForegroundInfo == null) {
4301                             mForegroundInfo = new ForegroundInfo();
4302                         }
4303                         mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4304                                 mForegroundInfo.mInsidePadding);
4305                     }
4306                     break;
4307                 case R.styleable.View_scrollIndicators:
4308                     final int scrollIndicators =
4309                             (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4310                                     & SCROLL_INDICATORS_PFLAG3_MASK;
4311                     if (scrollIndicators != 0) {
4312                         mPrivateFlags3 |= scrollIndicators;
4313                         initializeScrollIndicators = true;
4314                     }
4315                     break;
4316             }
4317         }
4318 
setOverScrollMode(overScrollMode)4319         setOverScrollMode(overScrollMode);
4320 
4321         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4322         // the resolved layout direction). Those cached values will be used later during padding
4323         // resolution.
4324         mUserPaddingStart = startPadding;
4325         mUserPaddingEnd = endPadding;
4326 
4327         if (background != null) {
4328             setBackground(background);
4329         }
4330 
4331         // setBackground above will record that padding is currently provided by the background.
4332         // If we have padding specified via xml, record that here instead and use it.
4333         mLeftPaddingDefined = leftPaddingDefined;
4334         mRightPaddingDefined = rightPaddingDefined;
4335 
4336         if (padding >= 0) {
4337             leftPadding = padding;
4338             topPadding = padding;
4339             rightPadding = padding;
4340             bottomPadding = padding;
4341             mUserPaddingLeftInitial = padding;
4342             mUserPaddingRightInitial = padding;
4343         }
4344 
4345         if (isRtlCompatibilityMode()) {
4346             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4347             // left / right padding are used if defined (meaning here nothing to do). If they are not
4348             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4349             // start / end and resolve them as left / right (layout direction is not taken into account).
4350             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4351             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4352             // defined.
4353             if (!mLeftPaddingDefined && startPaddingDefined) {
4354                 leftPadding = startPadding;
4355             }
4356             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4357             if (!mRightPaddingDefined && endPaddingDefined) {
4358                 rightPadding = endPadding;
4359             }
4360             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4361         } else {
4362             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4363             // values defined. Otherwise, left /right values are used.
4364             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4365             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4366             // defined.
4367             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4368 
4369             if (mLeftPaddingDefined && !hasRelativePadding) {
4370                 mUserPaddingLeftInitial = leftPadding;
4371             }
4372             if (mRightPaddingDefined && !hasRelativePadding) {
4373                 mUserPaddingRightInitial = rightPadding;
4374             }
4375         }
4376 
internalSetPadding( mUserPaddingLeftInitial, topPadding >= 0 ? topPadding : mPaddingTop, mUserPaddingRightInitial, bottomPadding >= 0 ? bottomPadding : mPaddingBottom)4377         internalSetPadding(
4378                 mUserPaddingLeftInitial,
4379                 topPadding >= 0 ? topPadding : mPaddingTop,
4380                 mUserPaddingRightInitial,
4381                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4382 
4383         if (viewFlagMasks != 0) {
setFlags(viewFlagValues, viewFlagMasks)4384             setFlags(viewFlagValues, viewFlagMasks);
4385         }
4386 
4387         if (initializeScrollbars) {
4388             initializeScrollbarsInternal(a);
4389         }
4390 
4391         if (initializeScrollIndicators) {
initializeScrollIndicatorsInternal()4392             initializeScrollIndicatorsInternal();
4393         }
4394 
a.recycle()4395         a.recycle();
4396 
4397         // Needs to be called after mViewFlags is set
4398         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
recomputePadding()4399             recomputePadding();
4400         }
4401 
4402         if (x != 0 || y != 0) {
scrollTo(x, y)4403             scrollTo(x, y);
4404         }
4405 
4406         if (transformSet) {
4407             setTranslationX(tx);
4408             setTranslationY(ty);
4409             setTranslationZ(tz);
4410             setElevation(elevation);
4411             setRotation(rotation);
4412             setRotationX(rotationX);
4413             setRotationY(rotationY);
4414             setScaleX(sx);
4415             setScaleY(sy);
4416         }
4417 
4418         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4419             setScrollContainer(true);
4420         }
4421 
computeOpaqueFlags()4422         computeOpaqueFlags();
4423     }
4424 
4425     /**
4426      * An implementation of OnClickListener that attempts to lazily load a
4427      * named click handling method from a parent or ancestor context.
4428      */
4429     private static class DeclaredOnClickListener implements OnClickListener {
4430         private final View mHostView;
4431         private final String mMethodName;
4432 
4433         private Method mMethod;
4434 
DeclaredOnClickListener(@onNull View hostView, @NonNull String methodName)4435         public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4436             mHostView = hostView;
4437             mMethodName = methodName;
4438         }
4439 
4440         @Override
onClick(@onNull View v)4441         public void onClick(@NonNull View v) {
4442             if (mMethod == null) {
4443                 mMethod = resolveMethod(mHostView.getContext(), mMethodName);
4444             }
4445 
4446             try {
4447                 mMethod.invoke(mHostView.getContext(), v);
4448             } catch (IllegalAccessException e) {
4449                 throw new IllegalStateException(
4450                         "Could not execute non-public method for android:onClick", e);
4451             } catch (InvocationTargetException e) {
4452                 throw new IllegalStateException(
4453                         "Could not execute method for android:onClick", e);
4454             }
4455         }
4456 
4457         @NonNull
resolveMethod(@ullable Context context, @NonNull String name)4458         private Method resolveMethod(@Nullable Context context, @NonNull String name) {
4459             while (context != null) {
4460                 try {
4461                     if (!context.isRestricted()) {
4462                         return context.getClass().getMethod(mMethodName, View.class);
4463                     }
4464                 } catch (NoSuchMethodException e) {
4465                     // Failed to find method, keep searching up the hierarchy.
4466                 }
4467 
4468                 if (context instanceof ContextWrapper) {
4469                     context = ((ContextWrapper) context).getBaseContext();
4470                 } else {
4471                     // Can't search up the hierarchy, null out and fail.
4472                     context = null;
4473                 }
4474             }
4475 
4476             final int id = mHostView.getId();
4477             final String idText = id == NO_ID ? "" : " with id '"
4478                     + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4479             throw new IllegalStateException("Could not find method " + mMethodName
4480                     + "(View) in a parent or ancestor Context for android:onClick "
4481                     + "attribute defined on view " + mHostView.getClass() + idText);
4482         }
4483     }
4484 
4485     /**
4486      * Non-public constructor for use in testing
4487      */
View()4488     View() {
4489         mResources = null;
4490         mRenderNode = RenderNode.create(getClass().getName(), this);
4491     }
4492 
getAttributeMap()4493     private static SparseArray<String> getAttributeMap() {
4494         if (mAttributeMap == null) {
4495             mAttributeMap = new SparseArray<>();
4496         }
4497         return mAttributeMap;
4498     }
4499 
saveAttributeData(@ullable AttributeSet attrs, @NonNull TypedArray t)4500     private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4501         final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4502         final int indexCount = t.getIndexCount();
4503         final String[] attributes = new String[(attrsCount + indexCount) * 2];
4504 
4505         int i = 0;
4506 
4507         // Store raw XML attributes.
4508         for (int j = 0; j < attrsCount; ++j) {
4509             attributes[i] = attrs.getAttributeName(j);
4510             attributes[i + 1] = attrs.getAttributeValue(j);
4511             i += 2;
4512         }
4513 
4514         // Store resolved styleable attributes.
4515         final Resources res = t.getResources();
4516         final SparseArray<String> attributeMap = getAttributeMap();
4517         for (int j = 0; j < indexCount; ++j) {
4518             final int index = t.getIndex(j);
4519             if (!t.hasValueOrEmpty(index)) {
4520                 // Value is undefined. Skip it.
4521                 continue;
4522             }
4523 
4524             final int resourceId = t.getResourceId(index, 0);
4525             if (resourceId == 0) {
4526                 // Value is not a reference. Skip it.
4527                 continue;
4528             }
4529 
4530             String resourceName = attributeMap.get(resourceId);
4531             if (resourceName == null) {
4532                 try {
4533                     resourceName = res.getResourceName(resourceId);
4534                 } catch (Resources.NotFoundException e) {
4535                     resourceName = "0x" + Integer.toHexString(resourceId);
4536                 }
4537                 attributeMap.put(resourceId, resourceName);
4538             }
4539 
4540             attributes[i] = resourceName;
4541             attributes[i + 1] = t.getString(index);
4542             i += 2;
4543         }
4544 
4545         // Trim to fit contents.
4546         final String[] trimmed = new String[i];
4547         System.arraycopy(attributes, 0, trimmed, 0, i);
4548         mAttributes = trimmed;
4549     }
4550 
toString()4551     public String toString() {
4552         StringBuilder out = new StringBuilder(128);
4553         out.append(getClass().getName());
4554         out.append('{');
4555         out.append(Integer.toHexString(System.identityHashCode(this)));
4556         out.append(' ');
4557         switch (mViewFlags&VISIBILITY_MASK) {
4558             case VISIBLE: out.append('V'); break;
4559             case INVISIBLE: out.append('I'); break;
4560             case GONE: out.append('G'); break;
4561             default: out.append('.'); break;
4562         }
4563         out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4564         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4565         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4566         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4567         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4568         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4569         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4570         out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4571         out.append(' ');
4572         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4573         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4574         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4575         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4576             out.append('p');
4577         } else {
4578             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4579         }
4580         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4581         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4582         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4583         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4584         out.append(' ');
4585         out.append(mLeft);
4586         out.append(',');
4587         out.append(mTop);
4588         out.append('-');
4589         out.append(mRight);
4590         out.append(',');
4591         out.append(mBottom);
4592         final int id = getId();
4593         if (id != NO_ID) {
4594             out.append(" #");
4595             out.append(Integer.toHexString(id));
4596             final Resources r = mResources;
4597             if (Resources.resourceHasPackage(id) && r != null) {
4598                 try {
4599                     String pkgname;
4600                     switch (id&0xff000000) {
4601                         case 0x7f000000:
4602                             pkgname="app";
4603                             break;
4604                         case 0x01000000:
4605                             pkgname="android";
4606                             break;
4607                         default:
4608                             pkgname = r.getResourcePackageName(id);
4609                             break;
4610                     }
4611                     String typename = r.getResourceTypeName(id);
4612                     String entryname = r.getResourceEntryName(id);
4613                     out.append(" ");
4614                     out.append(pkgname);
4615                     out.append(":");
4616                     out.append(typename);
4617                     out.append("/");
4618                     out.append(entryname);
4619                 } catch (Resources.NotFoundException e) {
4620                 }
4621             }
4622         }
4623         out.append("}");
4624         return out.toString();
4625     }
4626 
4627     /**
4628      * <p>
4629      * Initializes the fading edges from a given set of styled attributes. This
4630      * method should be called by subclasses that need fading edges and when an
4631      * instance of these subclasses is created programmatically rather than
4632      * being inflated from XML. This method is automatically called when the XML
4633      * is inflated.
4634      * </p>
4635      *
4636      * @param a the styled attributes set to initialize the fading edges from
4637      *
4638      * @removed
4639      */
initializeFadingEdge(TypedArray a)4640     protected void initializeFadingEdge(TypedArray a) {
4641         // This method probably shouldn't have been included in the SDK to begin with.
4642         // It relies on 'a' having been initialized using an attribute filter array that is
4643         // not publicly available to the SDK. The old method has been renamed
4644         // to initializeFadingEdgeInternal and hidden for framework use only;
4645         // this one initializes using defaults to make it safe to call for apps.
4646 
4647         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4648 
4649         initializeFadingEdgeInternal(arr);
4650 
4651         arr.recycle();
4652     }
4653 
4654     /**
4655      * <p>
4656      * Initializes the fading edges from a given set of styled attributes. This
4657      * method should be called by subclasses that need fading edges and when an
4658      * instance of these subclasses is created programmatically rather than
4659      * being inflated from XML. This method is automatically called when the XML
4660      * is inflated.
4661      * </p>
4662      *
4663      * @param a the styled attributes set to initialize the fading edges from
4664      * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4665      */
initializeFadingEdgeInternal(TypedArray a)4666     protected void initializeFadingEdgeInternal(TypedArray a) {
4667         initScrollCache();
4668 
4669         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4670                 R.styleable.View_fadingEdgeLength,
4671                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4672     }
4673 
4674     /**
4675      * Returns the size of the vertical faded edges used to indicate that more
4676      * content in this view is visible.
4677      *
4678      * @return The size in pixels of the vertical faded edge or 0 if vertical
4679      *         faded edges are not enabled for this view.
4680      * @attr ref android.R.styleable#View_fadingEdgeLength
4681      */
getVerticalFadingEdgeLength()4682     public int getVerticalFadingEdgeLength() {
4683         if (isVerticalFadingEdgeEnabled()) {
4684             ScrollabilityCache cache = mScrollCache;
4685             if (cache != null) {
4686                 return cache.fadingEdgeLength;
4687             }
4688         }
4689         return 0;
4690     }
4691 
4692     /**
4693      * Set the size of the faded edge used to indicate that more content in this
4694      * view is available.  Will not change whether the fading edge is enabled; use
4695      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4696      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4697      * for the vertical or horizontal fading edges.
4698      *
4699      * @param length The size in pixels of the faded edge used to indicate that more
4700      *        content in this view is visible.
4701      */
setFadingEdgeLength(int length)4702     public void setFadingEdgeLength(int length) {
4703         initScrollCache();
4704         mScrollCache.fadingEdgeLength = length;
4705     }
4706 
4707     /**
4708      * Returns the size of the horizontal faded edges used to indicate that more
4709      * content in this view is visible.
4710      *
4711      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4712      *         faded edges are not enabled for this view.
4713      * @attr ref android.R.styleable#View_fadingEdgeLength
4714      */
getHorizontalFadingEdgeLength()4715     public int getHorizontalFadingEdgeLength() {
4716         if (isHorizontalFadingEdgeEnabled()) {
4717             ScrollabilityCache cache = mScrollCache;
4718             if (cache != null) {
4719                 return cache.fadingEdgeLength;
4720             }
4721         }
4722         return 0;
4723     }
4724 
4725     /**
4726      * Returns the width of the vertical scrollbar.
4727      *
4728      * @return The width in pixels of the vertical scrollbar or 0 if there
4729      *         is no vertical scrollbar.
4730      */
getVerticalScrollbarWidth()4731     public int getVerticalScrollbarWidth() {
4732         ScrollabilityCache cache = mScrollCache;
4733         if (cache != null) {
4734             ScrollBarDrawable scrollBar = cache.scrollBar;
4735             if (scrollBar != null) {
4736                 int size = scrollBar.getSize(true);
4737                 if (size <= 0) {
4738                     size = cache.scrollBarSize;
4739                 }
4740                 return size;
4741             }
4742             return 0;
4743         }
4744         return 0;
4745     }
4746 
4747     /**
4748      * Returns the height of the horizontal scrollbar.
4749      *
4750      * @return The height in pixels of the horizontal scrollbar or 0 if
4751      *         there is no horizontal scrollbar.
4752      */
getHorizontalScrollbarHeight()4753     protected int getHorizontalScrollbarHeight() {
4754         ScrollabilityCache cache = mScrollCache;
4755         if (cache != null) {
4756             ScrollBarDrawable scrollBar = cache.scrollBar;
4757             if (scrollBar != null) {
4758                 int size = scrollBar.getSize(false);
4759                 if (size <= 0) {
4760                     size = cache.scrollBarSize;
4761                 }
4762                 return size;
4763             }
4764             return 0;
4765         }
4766         return 0;
4767     }
4768 
4769     /**
4770      * <p>
4771      * Initializes the scrollbars from a given set of styled attributes. This
4772      * method should be called by subclasses that need scrollbars and when an
4773      * instance of these subclasses is created programmatically rather than
4774      * being inflated from XML. This method is automatically called when the XML
4775      * is inflated.
4776      * </p>
4777      *
4778      * @param a the styled attributes set to initialize the scrollbars from
4779      *
4780      * @removed
4781      */
initializeScrollbars(TypedArray a)4782     protected void initializeScrollbars(TypedArray a) {
4783         // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4784         // using the View filter array which is not available to the SDK. As such, internal
4785         // framework usage now uses initializeScrollbarsInternal and we grab a default
4786         // TypedArray with the right filter instead here.
4787         TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4788 
4789         initializeScrollbarsInternal(arr);
4790 
4791         // We ignored the method parameter. Recycle the one we actually did use.
4792         arr.recycle();
4793     }
4794 
4795     /**
4796      * <p>
4797      * Initializes the scrollbars from a given set of styled attributes. This
4798      * method should be called by subclasses that need scrollbars and when an
4799      * instance of these subclasses is created programmatically rather than
4800      * being inflated from XML. This method is automatically called when the XML
4801      * is inflated.
4802      * </p>
4803      *
4804      * @param a the styled attributes set to initialize the scrollbars from
4805      * @hide
4806      */
initializeScrollbarsInternal(TypedArray a)4807     protected void initializeScrollbarsInternal(TypedArray a) {
4808         initScrollCache();
4809 
4810         final ScrollabilityCache scrollabilityCache = mScrollCache;
4811 
4812         if (scrollabilityCache.scrollBar == null) {
4813             scrollabilityCache.scrollBar = new ScrollBarDrawable();
4814             scrollabilityCache.scrollBar.setCallback(this);
4815             scrollabilityCache.scrollBar.setState(getDrawableState());
4816         }
4817 
4818         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4819 
4820         if (!fadeScrollbars) {
4821             scrollabilityCache.state = ScrollabilityCache.ON;
4822         }
4823         scrollabilityCache.fadeScrollBars = fadeScrollbars;
4824 
4825 
4826         scrollabilityCache.scrollBarFadeDuration = a.getInt(
4827                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4828                         .getScrollBarFadeDuration());
4829         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4830                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
4831                 ViewConfiguration.getScrollDefaultDelay());
4832 
4833 
4834         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4835                 com.android.internal.R.styleable.View_scrollbarSize,
4836                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
4837 
4838         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4839         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4840 
4841         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4842         if (thumb != null) {
4843             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4844         }
4845 
4846         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4847                 false);
4848         if (alwaysDraw) {
4849             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4850         }
4851 
4852         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4853         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4854 
4855         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4856         if (thumb != null) {
4857             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4858         }
4859 
4860         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4861                 false);
4862         if (alwaysDraw) {
4863             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4864         }
4865 
4866         // Apply layout direction to the new Drawables if needed
4867         final int layoutDirection = getLayoutDirection();
4868         if (track != null) {
4869             track.setLayoutDirection(layoutDirection);
4870         }
4871         if (thumb != null) {
4872             thumb.setLayoutDirection(layoutDirection);
4873         }
4874 
4875         // Re-apply user/background padding so that scrollbar(s) get added
4876         resolvePadding();
4877     }
4878 
initializeScrollIndicatorsInternal()4879     private void initializeScrollIndicatorsInternal() {
4880         // Some day maybe we'll break this into top/left/start/etc. and let the
4881         // client control it. Until then, you can have any scroll indicator you
4882         // want as long as it's a 1dp foreground-colored rectangle.
4883         if (mScrollIndicatorDrawable == null) {
4884             mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
4885         }
4886     }
4887 
4888     /**
4889      * <p>
4890      * Initalizes the scrollability cache if necessary.
4891      * </p>
4892      */
initScrollCache()4893     private void initScrollCache() {
4894         if (mScrollCache == null) {
4895             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4896         }
4897     }
4898 
getScrollCache()4899     private ScrollabilityCache getScrollCache() {
4900         initScrollCache();
4901         return mScrollCache;
4902     }
4903 
4904     /**
4905      * Set the position of the vertical scroll bar. Should be one of
4906      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4907      * {@link #SCROLLBAR_POSITION_RIGHT}.
4908      *
4909      * @param position Where the vertical scroll bar should be positioned.
4910      */
setVerticalScrollbarPosition(int position)4911     public void setVerticalScrollbarPosition(int position) {
4912         if (mVerticalScrollbarPosition != position) {
4913             mVerticalScrollbarPosition = position;
4914             computeOpaqueFlags();
4915             resolvePadding();
4916         }
4917     }
4918 
4919     /**
4920      * @return The position where the vertical scroll bar will show, if applicable.
4921      * @see #setVerticalScrollbarPosition(int)
4922      */
getVerticalScrollbarPosition()4923     public int getVerticalScrollbarPosition() {
4924         return mVerticalScrollbarPosition;
4925     }
4926 
4927     /**
4928      * Sets the state of all scroll indicators.
4929      * <p>
4930      * See {@link #setScrollIndicators(int, int)} for usage information.
4931      *
4932      * @param indicators a bitmask of indicators that should be enabled, or
4933      *                   {@code 0} to disable all indicators
4934      * @see #setScrollIndicators(int, int)
4935      * @see #getScrollIndicators()
4936      * @attr ref android.R.styleable#View_scrollIndicators
4937      */
setScrollIndicators(@crollIndicators int indicators)4938     public void setScrollIndicators(@ScrollIndicators int indicators) {
4939         setScrollIndicators(indicators,
4940                 SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
4941     }
4942 
4943     /**
4944      * Sets the state of the scroll indicators specified by the mask. To change
4945      * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
4946      * <p>
4947      * When a scroll indicator is enabled, it will be displayed if the view
4948      * can scroll in the direction of the indicator.
4949      * <p>
4950      * Multiple indicator types may be enabled or disabled by passing the
4951      * logical OR of the desired types. If multiple types are specified, they
4952      * will all be set to the same enabled state.
4953      * <p>
4954      * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
4955      *
4956      * @param indicators the indicator direction, or the logical OR of multiple
4957      *             indicator directions. One or more of:
4958      *             <ul>
4959      *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
4960      *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
4961      *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
4962      *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
4963      *               <li>{@link #SCROLL_INDICATOR_START}</li>
4964      *               <li>{@link #SCROLL_INDICATOR_END}</li>
4965      *             </ul>
4966      * @see #setScrollIndicators(int)
4967      * @see #getScrollIndicators()
4968      * @attr ref android.R.styleable#View_scrollIndicators
4969      */
setScrollIndicators(@crollIndicators int indicators, @ScrollIndicators int mask)4970     public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
4971         // Shift and sanitize mask.
4972         mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
4973         mask &= SCROLL_INDICATORS_PFLAG3_MASK;
4974 
4975         // Shift and mask indicators.
4976         indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
4977         indicators &= mask;
4978 
4979         // Merge with non-masked flags.
4980         final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
4981 
4982         if (mPrivateFlags3 != updatedFlags) {
4983             mPrivateFlags3 = updatedFlags;
4984 
4985             if (indicators != 0) {
4986                 initializeScrollIndicatorsInternal();
4987             }
4988             invalidate();
4989         }
4990     }
4991 
4992     /**
4993      * Returns a bitmask representing the enabled scroll indicators.
4994      * <p>
4995      * For example, if the top and left scroll indicators are enabled and all
4996      * other indicators are disabled, the return value will be
4997      * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
4998      * <p>
4999      * To check whether the bottom scroll indicator is enabled, use the value
5000      * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5001      *
5002      * @return a bitmask representing the enabled scroll indicators
5003      */
5004     @ScrollIndicators
getScrollIndicators()5005     public int getScrollIndicators() {
5006         return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5007                 >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5008     }
5009 
getListenerInfo()5010     ListenerInfo getListenerInfo() {
5011         if (mListenerInfo != null) {
5012             return mListenerInfo;
5013         }
5014         mListenerInfo = new ListenerInfo();
5015         return mListenerInfo;
5016     }
5017 
5018     /**
5019      * Register a callback to be invoked when the scroll X or Y positions of
5020      * this view change.
5021      * <p>
5022      * <b>Note:</b> Some views handle scrolling independently from View and may
5023      * have their own separate listeners for scroll-type events. For example,
5024      * {@link android.widget.ListView ListView} allows clients to register an
5025      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5026      * to listen for changes in list scroll position.
5027      *
5028      * @param l The listener to notify when the scroll X or Y position changes.
5029      * @see android.view.View#getScrollX()
5030      * @see android.view.View#getScrollY()
5031      */
setOnScrollChangeListener(OnScrollChangeListener l)5032     public void setOnScrollChangeListener(OnScrollChangeListener l) {
5033         getListenerInfo().mOnScrollChangeListener = l;
5034     }
5035 
5036     /**
5037      * Register a callback to be invoked when focus of this view changed.
5038      *
5039      * @param l The callback that will run.
5040      */
setOnFocusChangeListener(OnFocusChangeListener l)5041     public void setOnFocusChangeListener(OnFocusChangeListener l) {
5042         getListenerInfo().mOnFocusChangeListener = l;
5043     }
5044 
5045     /**
5046      * Add a listener that will be called when the bounds of the view change due to
5047      * layout processing.
5048      *
5049      * @param listener The listener that will be called when layout bounds change.
5050      */
addOnLayoutChangeListener(OnLayoutChangeListener listener)5051     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5052         ListenerInfo li = getListenerInfo();
5053         if (li.mOnLayoutChangeListeners == null) {
5054             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5055         }
5056         if (!li.mOnLayoutChangeListeners.contains(listener)) {
5057             li.mOnLayoutChangeListeners.add(listener);
5058         }
5059     }
5060 
5061     /**
5062      * Remove a listener for layout changes.
5063      *
5064      * @param listener The listener for layout bounds change.
5065      */
removeOnLayoutChangeListener(OnLayoutChangeListener listener)5066     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5067         ListenerInfo li = mListenerInfo;
5068         if (li == null || li.mOnLayoutChangeListeners == null) {
5069             return;
5070         }
5071         li.mOnLayoutChangeListeners.remove(listener);
5072     }
5073 
5074     /**
5075      * Add a listener for attach state changes.
5076      *
5077      * This listener will be called whenever this view is attached or detached
5078      * from a window. Remove the listener using
5079      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5080      *
5081      * @param listener Listener to attach
5082      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5083      */
addOnAttachStateChangeListener(OnAttachStateChangeListener listener)5084     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5085         ListenerInfo li = getListenerInfo();
5086         if (li.mOnAttachStateChangeListeners == null) {
5087             li.mOnAttachStateChangeListeners
5088                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5089         }
5090         li.mOnAttachStateChangeListeners.add(listener);
5091     }
5092 
5093     /**
5094      * Remove a listener for attach state changes. The listener will receive no further
5095      * notification of window attach/detach events.
5096      *
5097      * @param listener Listener to remove
5098      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5099      */
removeOnAttachStateChangeListener(OnAttachStateChangeListener listener)5100     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5101         ListenerInfo li = mListenerInfo;
5102         if (li == null || li.mOnAttachStateChangeListeners == null) {
5103             return;
5104         }
5105         li.mOnAttachStateChangeListeners.remove(listener);
5106     }
5107 
5108     /**
5109      * Returns the focus-change callback registered for this view.
5110      *
5111      * @return The callback, or null if one is not registered.
5112      */
getOnFocusChangeListener()5113     public OnFocusChangeListener getOnFocusChangeListener() {
5114         ListenerInfo li = mListenerInfo;
5115         return li != null ? li.mOnFocusChangeListener : null;
5116     }
5117 
5118     /**
5119      * Register a callback to be invoked when this view is clicked. If this view is not
5120      * clickable, it becomes clickable.
5121      *
5122      * @param l The callback that will run
5123      *
5124      * @see #setClickable(boolean)
5125      */
setOnClickListener(@ullable OnClickListener l)5126     public void setOnClickListener(@Nullable OnClickListener l) {
5127         if (!isClickable()) {
5128             setClickable(true);
5129         }
5130         getListenerInfo().mOnClickListener = l;
5131     }
5132 
5133     /**
5134      * Return whether this view has an attached OnClickListener.  Returns
5135      * true if there is a listener, false if there is none.
5136      */
hasOnClickListeners()5137     public boolean hasOnClickListeners() {
5138         ListenerInfo li = mListenerInfo;
5139         return (li != null && li.mOnClickListener != null);
5140     }
5141 
5142     /**
5143      * Register a callback to be invoked when this view is clicked and held. If this view is not
5144      * long clickable, it becomes long clickable.
5145      *
5146      * @param l The callback that will run
5147      *
5148      * @see #setLongClickable(boolean)
5149      */
setOnLongClickListener(@ullable OnLongClickListener l)5150     public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5151         if (!isLongClickable()) {
5152             setLongClickable(true);
5153         }
5154         getListenerInfo().mOnLongClickListener = l;
5155     }
5156 
5157     /**
5158      * Register a callback to be invoked when this view is context clicked. If the view is not
5159      * context clickable, it becomes context clickable.
5160      *
5161      * @param l The callback that will run
5162      * @see #setContextClickable(boolean)
5163      */
setOnContextClickListener(@ullable OnContextClickListener l)5164     public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5165         if (!isContextClickable()) {
5166             setContextClickable(true);
5167         }
5168         getListenerInfo().mOnContextClickListener = l;
5169     }
5170 
5171     /**
5172      * Register a callback to be invoked when the context menu for this view is
5173      * being built. If this view is not long clickable, it becomes long clickable.
5174      *
5175      * @param l The callback that will run
5176      *
5177      */
setOnCreateContextMenuListener(OnCreateContextMenuListener l)5178     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5179         if (!isLongClickable()) {
5180             setLongClickable(true);
5181         }
5182         getListenerInfo().mOnCreateContextMenuListener = l;
5183     }
5184 
5185     /**
5186      * Call this view's OnClickListener, if it is defined.  Performs all normal
5187      * actions associated with clicking: reporting accessibility event, playing
5188      * a sound, etc.
5189      *
5190      * @return True there was an assigned OnClickListener that was called, false
5191      *         otherwise is returned.
5192      */
performClick()5193     public boolean performClick() {
5194         final boolean result;
5195         final ListenerInfo li = mListenerInfo;
5196         if (li != null && li.mOnClickListener != null) {
5197             playSoundEffect(SoundEffectConstants.CLICK);
5198             li.mOnClickListener.onClick(this);
5199             result = true;
5200         } else {
5201             result = false;
5202         }
5203 
5204         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5205         return result;
5206     }
5207 
5208     /**
5209      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5210      * this only calls the listener, and does not do any associated clicking
5211      * actions like reporting an accessibility event.
5212      *
5213      * @return True there was an assigned OnClickListener that was called, false
5214      *         otherwise is returned.
5215      */
callOnClick()5216     public boolean callOnClick() {
5217         ListenerInfo li = mListenerInfo;
5218         if (li != null && li.mOnClickListener != null) {
5219             li.mOnClickListener.onClick(this);
5220             return true;
5221         }
5222         return false;
5223     }
5224 
5225     /**
5226      * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
5227      * OnLongClickListener did not consume the event.
5228      *
5229      * @return True if one of the above receivers consumed the event, false otherwise.
5230      */
performLongClick()5231     public boolean performLongClick() {
5232         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5233 
5234         boolean handled = false;
5235         ListenerInfo li = mListenerInfo;
5236         if (li != null && li.mOnLongClickListener != null) {
5237             handled = li.mOnLongClickListener.onLongClick(View.this);
5238         }
5239         if (!handled) {
5240             handled = showContextMenu();
5241         }
5242         if (handled) {
5243             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5244         }
5245         return handled;
5246     }
5247 
5248     /**
5249      * Call this view's OnContextClickListener, if it is defined.
5250      *
5251      * @return True if there was an assigned OnContextClickListener that consumed the event, false
5252      *         otherwise.
5253      */
performContextClick()5254     public boolean performContextClick() {
5255         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5256 
5257         boolean handled = false;
5258         ListenerInfo li = mListenerInfo;
5259         if (li != null && li.mOnContextClickListener != null) {
5260             handled = li.mOnContextClickListener.onContextClick(View.this);
5261         }
5262         if (handled) {
5263             performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5264         }
5265         return handled;
5266     }
5267 
5268     /**
5269      * Performs button-related actions during a touch down event.
5270      *
5271      * @param event The event.
5272      * @return True if the down was consumed.
5273      *
5274      * @hide
5275      */
performButtonActionOnTouchDown(MotionEvent event)5276     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5277         if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
5278             (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5279             showContextMenu(event.getX(), event.getY(), event.getMetaState());
5280             mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5281             return true;
5282         }
5283         return false;
5284     }
5285 
5286     /**
5287      * Bring up the context menu for this view.
5288      *
5289      * @return Whether a context menu was displayed.
5290      */
showContextMenu()5291     public boolean showContextMenu() {
5292         return getParent().showContextMenuForChild(this);
5293     }
5294 
5295     /**
5296      * Bring up the context menu for this view, referring to the item under the specified point.
5297      *
5298      * @param x The referenced x coordinate.
5299      * @param y The referenced y coordinate.
5300      * @param metaState The keyboard modifiers that were pressed.
5301      * @return Whether a context menu was displayed.
5302      *
5303      * @hide
5304      */
showContextMenu(float x, float y, int metaState)5305     public boolean showContextMenu(float x, float y, int metaState) {
5306         return showContextMenu();
5307     }
5308 
5309     /**
5310      * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5311      *
5312      * @param callback Callback that will control the lifecycle of the action mode
5313      * @return The new action mode if it is started, null otherwise
5314      *
5315      * @see ActionMode
5316      * @see #startActionMode(android.view.ActionMode.Callback, int)
5317      */
startActionMode(ActionMode.Callback callback)5318     public ActionMode startActionMode(ActionMode.Callback callback) {
5319         return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5320     }
5321 
5322     /**
5323      * Start an action mode with the given type.
5324      *
5325      * @param callback Callback that will control the lifecycle of the action mode
5326      * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5327      * @return The new action mode if it is started, null otherwise
5328      *
5329      * @see ActionMode
5330      */
startActionMode(ActionMode.Callback callback, int type)5331     public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5332         ViewParent parent = getParent();
5333         if (parent == null) return null;
5334         try {
5335             return parent.startActionModeForChild(this, callback, type);
5336         } catch (AbstractMethodError ame) {
5337             // Older implementations of custom views might not implement this.
5338             return parent.startActionModeForChild(this, callback);
5339         }
5340     }
5341 
5342     /**
5343      * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5344      * Context, creating a unique View identifier to retrieve the result.
5345      *
5346      * @param intent The Intent to be started.
5347      * @param requestCode The request code to use.
5348      * @hide
5349      */
startActivityForResult(Intent intent, int requestCode)5350     public void startActivityForResult(Intent intent, int requestCode) {
5351         mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5352         getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5353     }
5354 
5355     /**
5356      * If this View corresponds to the calling who, dispatches the activity result.
5357      * @param who The identifier for the targeted View to receive the result.
5358      * @param requestCode The integer request code originally supplied to
5359      *                    startActivityForResult(), allowing you to identify who this
5360      *                    result came from.
5361      * @param resultCode The integer result code returned by the child activity
5362      *                   through its setResult().
5363      * @param data An Intent, which can return result data to the caller
5364      *               (various data can be attached to Intent "extras").
5365      * @return {@code true} if the activity result was dispatched.
5366      * @hide
5367      */
dispatchActivityResult( String who, int requestCode, int resultCode, Intent data)5368     public boolean dispatchActivityResult(
5369             String who, int requestCode, int resultCode, Intent data) {
5370         if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5371             onActivityResult(requestCode, resultCode, data);
5372             mStartActivityRequestWho = null;
5373             return true;
5374         }
5375         return false;
5376     }
5377 
5378     /**
5379      * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5380      *
5381      * @param requestCode The integer request code originally supplied to
5382      *                    startActivityForResult(), allowing you to identify who this
5383      *                    result came from.
5384      * @param resultCode The integer result code returned by the child activity
5385      *                   through its setResult().
5386      * @param data An Intent, which can return result data to the caller
5387      *               (various data can be attached to Intent "extras").
5388      * @hide
5389      */
onActivityResult(int requestCode, int resultCode, Intent data)5390     public void onActivityResult(int requestCode, int resultCode, Intent data) {
5391         // Do nothing.
5392     }
5393 
5394     /**
5395      * Register a callback to be invoked when a hardware key is pressed in this view.
5396      * Key presses in software input methods will generally not trigger the methods of
5397      * this listener.
5398      * @param l the key listener to attach to this view
5399      */
setOnKeyListener(OnKeyListener l)5400     public void setOnKeyListener(OnKeyListener l) {
5401         getListenerInfo().mOnKeyListener = l;
5402     }
5403 
5404     /**
5405      * Register a callback to be invoked when a touch event is sent to this view.
5406      * @param l the touch listener to attach to this view
5407      */
setOnTouchListener(OnTouchListener l)5408     public void setOnTouchListener(OnTouchListener l) {
5409         getListenerInfo().mOnTouchListener = l;
5410     }
5411 
5412     /**
5413      * Register a callback to be invoked when a generic motion event is sent to this view.
5414      * @param l the generic motion listener to attach to this view
5415      */
setOnGenericMotionListener(OnGenericMotionListener l)5416     public void setOnGenericMotionListener(OnGenericMotionListener l) {
5417         getListenerInfo().mOnGenericMotionListener = l;
5418     }
5419 
5420     /**
5421      * Register a callback to be invoked when a hover event is sent to this view.
5422      * @param l the hover listener to attach to this view
5423      */
setOnHoverListener(OnHoverListener l)5424     public void setOnHoverListener(OnHoverListener l) {
5425         getListenerInfo().mOnHoverListener = l;
5426     }
5427 
5428     /**
5429      * Register a drag event listener callback object for this View. The parameter is
5430      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5431      * View, the system calls the
5432      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5433      * @param l An implementation of {@link android.view.View.OnDragListener}.
5434      */
setOnDragListener(OnDragListener l)5435     public void setOnDragListener(OnDragListener l) {
5436         getListenerInfo().mOnDragListener = l;
5437     }
5438 
5439     /**
5440      * Give this view focus. This will cause
5441      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5442      *
5443      * Note: this does not check whether this {@link View} should get focus, it just
5444      * gives it focus no matter what.  It should only be called internally by framework
5445      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5446      *
5447      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5448      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5449      *        focus moved when requestFocus() is called. It may not always
5450      *        apply, in which case use the default View.FOCUS_DOWN.
5451      * @param previouslyFocusedRect The rectangle of the view that had focus
5452      *        prior in this View's coordinate system.
5453      */
handleFocusGainInternal(@ocusRealDirection int direction, Rect previouslyFocusedRect)5454     void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5455         if (DBG) {
5456             System.out.println(this + " requestFocus()");
5457         }
5458 
5459         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5460             mPrivateFlags |= PFLAG_FOCUSED;
5461 
5462             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5463 
5464             if (mParent != null) {
5465                 mParent.requestChildFocus(this, this);
5466             }
5467 
5468             if (mAttachInfo != null) {
5469                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5470             }
5471 
5472             onFocusChanged(true, direction, previouslyFocusedRect);
5473             refreshDrawableState();
5474         }
5475     }
5476 
5477     /**
5478      * Populates <code>outRect</code> with the hotspot bounds. By default,
5479      * the hotspot bounds are identical to the screen bounds.
5480      *
5481      * @param outRect rect to populate with hotspot bounds
5482      * @hide Only for internal use by views and widgets.
5483      */
getHotspotBounds(Rect outRect)5484     public void getHotspotBounds(Rect outRect) {
5485         final Drawable background = getBackground();
5486         if (background != null) {
5487             background.getHotspotBounds(outRect);
5488         } else {
5489             getBoundsOnScreen(outRect);
5490         }
5491     }
5492 
5493     /**
5494      * Request that a rectangle of this view be visible on the screen,
5495      * scrolling if necessary just enough.
5496      *
5497      * <p>A View should call this if it maintains some notion of which part
5498      * of its content is interesting.  For example, a text editing view
5499      * should call this when its cursor moves.
5500      *
5501      * @param rectangle The rectangle.
5502      * @return Whether any parent scrolled.
5503      */
requestRectangleOnScreen(Rect rectangle)5504     public boolean requestRectangleOnScreen(Rect rectangle) {
5505         return requestRectangleOnScreen(rectangle, false);
5506     }
5507 
5508     /**
5509      * Request that a rectangle of this view be visible on the screen,
5510      * scrolling if necessary just enough.
5511      *
5512      * <p>A View should call this if it maintains some notion of which part
5513      * of its content is interesting.  For example, a text editing view
5514      * should call this when its cursor moves.
5515      *
5516      * <p>When <code>immediate</code> is set to true, scrolling will not be
5517      * animated.
5518      *
5519      * @param rectangle The rectangle.
5520      * @param immediate True to forbid animated scrolling, false otherwise
5521      * @return Whether any parent scrolled.
5522      */
requestRectangleOnScreen(Rect rectangle, boolean immediate)5523     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5524         if (mParent == null) {
5525             return false;
5526         }
5527 
5528         View child = this;
5529 
5530         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5531         position.set(rectangle);
5532 
5533         ViewParent parent = mParent;
5534         boolean scrolled = false;
5535         while (parent != null) {
5536             rectangle.set((int) position.left, (int) position.top,
5537                     (int) position.right, (int) position.bottom);
5538 
5539             scrolled |= parent.requestChildRectangleOnScreen(child,
5540                     rectangle, immediate);
5541 
5542             if (!child.hasIdentityMatrix()) {
5543                 child.getMatrix().mapRect(position);
5544             }
5545 
5546             position.offset(child.mLeft, child.mTop);
5547 
5548             if (!(parent instanceof View)) {
5549                 break;
5550             }
5551 
5552             View parentView = (View) parent;
5553 
5554             position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5555 
5556             child = parentView;
5557             parent = child.getParent();
5558         }
5559 
5560         return scrolled;
5561     }
5562 
5563     /**
5564      * Called when this view wants to give up focus. If focus is cleared
5565      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5566      * <p>
5567      * <strong>Note:</strong> When a View clears focus the framework is trying
5568      * to give focus to the first focusable View from the top. Hence, if this
5569      * View is the first from the top that can take focus, then all callbacks
5570      * related to clearing focus will be invoked after which the framework will
5571      * give focus to this view.
5572      * </p>
5573      */
clearFocus()5574     public void clearFocus() {
5575         if (DBG) {
5576             System.out.println(this + " clearFocus()");
5577         }
5578 
5579         clearFocusInternal(null, true, true);
5580     }
5581 
5582     /**
5583      * Clears focus from the view, optionally propagating the change up through
5584      * the parent hierarchy and requesting that the root view place new focus.
5585      *
5586      * @param propagate whether to propagate the change up through the parent
5587      *            hierarchy
5588      * @param refocus when propagate is true, specifies whether to request the
5589      *            root view place new focus
5590      */
clearFocusInternal(View focused, boolean propagate, boolean refocus)5591     void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5592         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5593             mPrivateFlags &= ~PFLAG_FOCUSED;
5594 
5595             if (propagate && mParent != null) {
5596                 mParent.clearChildFocus(this);
5597             }
5598 
5599             onFocusChanged(false, 0, null);
5600             refreshDrawableState();
5601 
5602             if (propagate && (!refocus || !rootViewRequestFocus())) {
5603                 notifyGlobalFocusCleared(this);
5604             }
5605         }
5606     }
5607 
notifyGlobalFocusCleared(View oldFocus)5608     void notifyGlobalFocusCleared(View oldFocus) {
5609         if (oldFocus != null && mAttachInfo != null) {
5610             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5611         }
5612     }
5613 
rootViewRequestFocus()5614     boolean rootViewRequestFocus() {
5615         final View root = getRootView();
5616         return root != null && root.requestFocus();
5617     }
5618 
5619     /**
5620      * Called internally by the view system when a new view is getting focus.
5621      * This is what clears the old focus.
5622      * <p>
5623      * <b>NOTE:</b> The parent view's focused child must be updated manually
5624      * after calling this method. Otherwise, the view hierarchy may be left in
5625      * an inconstent state.
5626      */
unFocus(View focused)5627     void unFocus(View focused) {
5628         if (DBG) {
5629             System.out.println(this + " unFocus()");
5630         }
5631 
5632         clearFocusInternal(focused, false, false);
5633     }
5634 
5635     /**
5636      * Returns true if this view has focus itself, or is the ancestor of the
5637      * view that has focus.
5638      *
5639      * @return True if this view has or contains focus, false otherwise.
5640      */
5641     @ViewDebug.ExportedProperty(category = "focus")
hasFocus()5642     public boolean hasFocus() {
5643         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5644     }
5645 
5646     /**
5647      * Returns true if this view is focusable or if it contains a reachable View
5648      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5649      * is a View whose parents do not block descendants focus.
5650      *
5651      * Only {@link #VISIBLE} views are considered focusable.
5652      *
5653      * @return True if the view is focusable or if the view contains a focusable
5654      *         View, false otherwise.
5655      *
5656      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5657      * @see ViewGroup#getTouchscreenBlocksFocus()
5658      */
hasFocusable()5659     public boolean hasFocusable() {
5660         if (!isFocusableInTouchMode()) {
5661             for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5662                 final ViewGroup g = (ViewGroup) p;
5663                 if (g.shouldBlockFocusForTouchscreen()) {
5664                     return false;
5665                 }
5666             }
5667         }
5668         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5669     }
5670 
5671     /**
5672      * Called by the view system when the focus state of this view changes.
5673      * When the focus change event is caused by directional navigation, direction
5674      * and previouslyFocusedRect provide insight into where the focus is coming from.
5675      * When overriding, be sure to call up through to the super class so that
5676      * the standard focus handling will occur.
5677      *
5678      * @param gainFocus True if the View has focus; false otherwise.
5679      * @param direction The direction focus has moved when requestFocus()
5680      *                  is called to give this view focus. Values are
5681      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5682      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5683      *                  It may not always apply, in which case use the default.
5684      * @param previouslyFocusedRect The rectangle, in this view's coordinate
5685      *        system, of the previously focused view.  If applicable, this will be
5686      *        passed in as finer grained information about where the focus is coming
5687      *        from (in addition to direction).  Will be <code>null</code> otherwise.
5688      */
5689     @CallSuper
onFocusChanged(boolean gainFocus, @FocusDirection int direction, @Nullable Rect previouslyFocusedRect)5690     protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5691             @Nullable Rect previouslyFocusedRect) {
5692         if (gainFocus) {
5693             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5694         } else {
5695             notifyViewAccessibilityStateChangedIfNeeded(
5696                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5697         }
5698 
5699         InputMethodManager imm = InputMethodManager.peekInstance();
5700         if (!gainFocus) {
5701             if (isPressed()) {
5702                 setPressed(false);
5703             }
5704             if (imm != null && mAttachInfo != null
5705                     && mAttachInfo.mHasWindowFocus) {
5706                 imm.focusOut(this);
5707             }
5708             onFocusLost();
5709         } else if (imm != null && mAttachInfo != null
5710                 && mAttachInfo.mHasWindowFocus) {
5711             imm.focusIn(this);
5712         }
5713 
5714         invalidate(true);
5715         ListenerInfo li = mListenerInfo;
5716         if (li != null && li.mOnFocusChangeListener != null) {
5717             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5718         }
5719 
5720         if (mAttachInfo != null) {
5721             mAttachInfo.mKeyDispatchState.reset(this);
5722         }
5723     }
5724 
5725     /**
5726      * Sends an accessibility event of the given type. If accessibility is
5727      * not enabled this method has no effect. The default implementation calls
5728      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5729      * to populate information about the event source (this View), then calls
5730      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5731      * populate the text content of the event source including its descendants,
5732      * and last calls
5733      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5734      * on its parent to request sending of the event to interested parties.
5735      * <p>
5736      * If an {@link AccessibilityDelegate} has been specified via calling
5737      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5738      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5739      * responsible for handling this call.
5740      * </p>
5741      *
5742      * @param eventType The type of the event to send, as defined by several types from
5743      * {@link android.view.accessibility.AccessibilityEvent}, such as
5744      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5745      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5746      *
5747      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5748      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5749      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5750      * @see AccessibilityDelegate
5751      */
sendAccessibilityEvent(int eventType)5752     public void sendAccessibilityEvent(int eventType) {
5753         if (mAccessibilityDelegate != null) {
5754             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5755         } else {
5756             sendAccessibilityEventInternal(eventType);
5757         }
5758     }
5759 
5760     /**
5761      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5762      * {@link AccessibilityEvent} to make an announcement which is related to some
5763      * sort of a context change for which none of the events representing UI transitions
5764      * is a good fit. For example, announcing a new page in a book. If accessibility
5765      * is not enabled this method does nothing.
5766      *
5767      * @param text The announcement text.
5768      */
announceForAccessibility(CharSequence text)5769     public void announceForAccessibility(CharSequence text) {
5770         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5771             AccessibilityEvent event = AccessibilityEvent.obtain(
5772                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
5773             onInitializeAccessibilityEvent(event);
5774             event.getText().add(text);
5775             event.setContentDescription(null);
5776             mParent.requestSendAccessibilityEvent(this, event);
5777         }
5778     }
5779 
5780     /**
5781      * @see #sendAccessibilityEvent(int)
5782      *
5783      * Note: Called from the default {@link AccessibilityDelegate}.
5784      *
5785      * @hide
5786      */
sendAccessibilityEventInternal(int eventType)5787     public void sendAccessibilityEventInternal(int eventType) {
5788         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5789             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5790         }
5791     }
5792 
5793     /**
5794      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5795      * takes as an argument an empty {@link AccessibilityEvent} and does not
5796      * perform a check whether accessibility is enabled.
5797      * <p>
5798      * If an {@link AccessibilityDelegate} has been specified via calling
5799      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5800      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5801      * is responsible for handling this call.
5802      * </p>
5803      *
5804      * @param event The event to send.
5805      *
5806      * @see #sendAccessibilityEvent(int)
5807      */
sendAccessibilityEventUnchecked(AccessibilityEvent event)5808     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5809         if (mAccessibilityDelegate != null) {
5810             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5811         } else {
5812             sendAccessibilityEventUncheckedInternal(event);
5813         }
5814     }
5815 
5816     /**
5817      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5818      *
5819      * Note: Called from the default {@link AccessibilityDelegate}.
5820      *
5821      * @hide
5822      */
sendAccessibilityEventUncheckedInternal(AccessibilityEvent event)5823     public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5824         if (!isShown()) {
5825             return;
5826         }
5827         onInitializeAccessibilityEvent(event);
5828         // Only a subset of accessibility events populates text content.
5829         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5830             dispatchPopulateAccessibilityEvent(event);
5831         }
5832         // In the beginning we called #isShown(), so we know that getParent() is not null.
5833         getParent().requestSendAccessibilityEvent(this, event);
5834     }
5835 
5836     /**
5837      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5838      * to its children for adding their text content to the event. Note that the
5839      * event text is populated in a separate dispatch path since we add to the
5840      * event not only the text of the source but also the text of all its descendants.
5841      * A typical implementation will call
5842      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5843      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5844      * on each child. Override this method if custom population of the event text
5845      * content is required.
5846      * <p>
5847      * If an {@link AccessibilityDelegate} has been specified via calling
5848      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5849      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5850      * is responsible for handling this call.
5851      * </p>
5852      * <p>
5853      * <em>Note:</em> Accessibility events of certain types are not dispatched for
5854      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5855      * </p>
5856      *
5857      * @param event The event.
5858      *
5859      * @return True if the event population was completed.
5860      */
dispatchPopulateAccessibilityEvent(AccessibilityEvent event)5861     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5862         if (mAccessibilityDelegate != null) {
5863             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5864         } else {
5865             return dispatchPopulateAccessibilityEventInternal(event);
5866         }
5867     }
5868 
5869     /**
5870      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5871      *
5872      * Note: Called from the default {@link AccessibilityDelegate}.
5873      *
5874      * @hide
5875      */
dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event)5876     public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5877         onPopulateAccessibilityEvent(event);
5878         return false;
5879     }
5880 
5881     /**
5882      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5883      * giving a chance to this View to populate the accessibility event with its
5884      * text content. While this method is free to modify event
5885      * attributes other than text content, doing so should normally be performed in
5886      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5887      * <p>
5888      * Example: Adding formatted date string to an accessibility event in addition
5889      *          to the text added by the super implementation:
5890      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5891      *     super.onPopulateAccessibilityEvent(event);
5892      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5893      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5894      *         mCurrentDate.getTimeInMillis(), flags);
5895      *     event.getText().add(selectedDateUtterance);
5896      * }</pre>
5897      * <p>
5898      * If an {@link AccessibilityDelegate} has been specified via calling
5899      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5900      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5901      * is responsible for handling this call.
5902      * </p>
5903      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5904      * information to the event, in case the default implementation has basic information to add.
5905      * </p>
5906      *
5907      * @param event The accessibility event which to populate.
5908      *
5909      * @see #sendAccessibilityEvent(int)
5910      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5911      */
5912     @CallSuper
onPopulateAccessibilityEvent(AccessibilityEvent event)5913     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5914         if (mAccessibilityDelegate != null) {
5915             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5916         } else {
5917             onPopulateAccessibilityEventInternal(event);
5918         }
5919     }
5920 
5921     /**
5922      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5923      *
5924      * Note: Called from the default {@link AccessibilityDelegate}.
5925      *
5926      * @hide
5927      */
onPopulateAccessibilityEventInternal(AccessibilityEvent event)5928     public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5929     }
5930 
5931     /**
5932      * Initializes an {@link AccessibilityEvent} with information about
5933      * this View which is the event source. In other words, the source of
5934      * an accessibility event is the view whose state change triggered firing
5935      * the event.
5936      * <p>
5937      * Example: Setting the password property of an event in addition
5938      *          to properties set by the super implementation:
5939      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5940      *     super.onInitializeAccessibilityEvent(event);
5941      *     event.setPassword(true);
5942      * }</pre>
5943      * <p>
5944      * If an {@link AccessibilityDelegate} has been specified via calling
5945      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5946      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5947      * is responsible for handling this call.
5948      * </p>
5949      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5950      * information to the event, in case the default implementation has basic information to add.
5951      * </p>
5952      * @param event The event to initialize.
5953      *
5954      * @see #sendAccessibilityEvent(int)
5955      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5956      */
5957     @CallSuper
onInitializeAccessibilityEvent(AccessibilityEvent event)5958     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5959         if (mAccessibilityDelegate != null) {
5960             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5961         } else {
5962             onInitializeAccessibilityEventInternal(event);
5963         }
5964     }
5965 
5966     /**
5967      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5968      *
5969      * Note: Called from the default {@link AccessibilityDelegate}.
5970      *
5971      * @hide
5972      */
onInitializeAccessibilityEventInternal(AccessibilityEvent event)5973     public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5974         event.setSource(this);
5975         event.setClassName(getAccessibilityClassName());
5976         event.setPackageName(getContext().getPackageName());
5977         event.setEnabled(isEnabled());
5978         event.setContentDescription(mContentDescription);
5979 
5980         switch (event.getEventType()) {
5981             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5982                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
5983                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5984                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5985                 event.setItemCount(focusablesTempList.size());
5986                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5987                 if (mAttachInfo != null) {
5988                     focusablesTempList.clear();
5989                 }
5990             } break;
5991             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5992                 CharSequence text = getIterableTextForAccessibility();
5993                 if (text != null && text.length() > 0) {
5994                     event.setFromIndex(getAccessibilitySelectionStart());
5995                     event.setToIndex(getAccessibilitySelectionEnd());
5996                     event.setItemCount(text.length());
5997                 }
5998             } break;
5999         }
6000     }
6001 
6002     /**
6003      * Returns an {@link AccessibilityNodeInfo} representing this view from the
6004      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6005      * This method is responsible for obtaining an accessibility node info from a
6006      * pool of reusable instances and calling
6007      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6008      * initialize the former.
6009      * <p>
6010      * Note: The client is responsible for recycling the obtained instance by calling
6011      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6012      * </p>
6013      *
6014      * @return A populated {@link AccessibilityNodeInfo}.
6015      *
6016      * @see AccessibilityNodeInfo
6017      */
createAccessibilityNodeInfo()6018     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6019         if (mAccessibilityDelegate != null) {
6020             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6021         } else {
6022             return createAccessibilityNodeInfoInternal();
6023         }
6024     }
6025 
6026     /**
6027      * @see #createAccessibilityNodeInfo()
6028      *
6029      * @hide
6030      */
createAccessibilityNodeInfoInternal()6031     public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6032         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6033         if (provider != null) {
6034             return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6035         } else {
6036             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6037             onInitializeAccessibilityNodeInfo(info);
6038             return info;
6039         }
6040     }
6041 
6042     /**
6043      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6044      * The base implementation sets:
6045      * <ul>
6046      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6047      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6048      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6049      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6050      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6051      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6052      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6053      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6054      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6055      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6056      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6057      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6058      *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6059      * </ul>
6060      * <p>
6061      * Subclasses should override this method, call the super implementation,
6062      * and set additional attributes.
6063      * </p>
6064      * <p>
6065      * If an {@link AccessibilityDelegate} has been specified via calling
6066      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6067      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6068      * is responsible for handling this call.
6069      * </p>
6070      *
6071      * @param info The instance to initialize.
6072      */
6073     @CallSuper
onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)6074     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6075         if (mAccessibilityDelegate != null) {
6076             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6077         } else {
6078             onInitializeAccessibilityNodeInfoInternal(info);
6079         }
6080     }
6081 
6082     /**
6083      * Gets the location of this view in screen coordinates.
6084      *
6085      * @param outRect The output location
6086      * @hide
6087      */
getBoundsOnScreen(Rect outRect)6088     public void getBoundsOnScreen(Rect outRect) {
6089         getBoundsOnScreen(outRect, false);
6090     }
6091 
6092     /**
6093      * Gets the location of this view in screen coordinates.
6094      *
6095      * @param outRect The output location
6096      * @param clipToParent Whether to clip child bounds to the parent ones.
6097      * @hide
6098      */
getBoundsOnScreen(Rect outRect, boolean clipToParent)6099     public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6100         if (mAttachInfo == null) {
6101             return;
6102         }
6103 
6104         RectF position = mAttachInfo.mTmpTransformRect;
6105         position.set(0, 0, mRight - mLeft, mBottom - mTop);
6106 
6107         if (!hasIdentityMatrix()) {
6108             getMatrix().mapRect(position);
6109         }
6110 
6111         position.offset(mLeft, mTop);
6112 
6113         ViewParent parent = mParent;
6114         while (parent instanceof View) {
6115             View parentView = (View) parent;
6116 
6117             position.offset(-parentView.mScrollX, -parentView.mScrollY);
6118 
6119             if (clipToParent) {
6120                 position.left = Math.max(position.left, 0);
6121                 position.top = Math.max(position.top, 0);
6122                 position.right = Math.min(position.right, parentView.getWidth());
6123                 position.bottom = Math.min(position.bottom, parentView.getHeight());
6124             }
6125 
6126             if (!parentView.hasIdentityMatrix()) {
6127                 parentView.getMatrix().mapRect(position);
6128             }
6129 
6130             position.offset(parentView.mLeft, parentView.mTop);
6131 
6132             parent = parentView.mParent;
6133         }
6134 
6135         if (parent instanceof ViewRootImpl) {
6136             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6137             position.offset(0, -viewRootImpl.mCurScrollY);
6138         }
6139 
6140         position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6141 
6142         outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
6143                 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
6144     }
6145 
6146     /**
6147      * Return the class name of this object to be used for accessibility purposes.
6148      * Subclasses should only override this if they are implementing something that
6149      * should be seen as a completely new class of view when used by accessibility,
6150      * unrelated to the class it is deriving from.  This is used to fill in
6151      * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6152      */
getAccessibilityClassName()6153     public CharSequence getAccessibilityClassName() {
6154         return View.class.getName();
6155     }
6156 
6157     /**
6158      * Called when assist structure is being retrieved from a view as part of
6159      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6160      * @param structure Fill in with structured view data.  The default implementation
6161      * fills in all data that can be inferred from the view itself.
6162      */
onProvideStructure(ViewStructure structure)6163     public void onProvideStructure(ViewStructure structure) {
6164         final int id = mID;
6165         if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6166                 && (id&0x0000ffff) != 0) {
6167             String pkg, type, entry;
6168             try {
6169                 final Resources res = getResources();
6170                 entry = res.getResourceEntryName(id);
6171                 type = res.getResourceTypeName(id);
6172                 pkg = res.getResourcePackageName(id);
6173             } catch (Resources.NotFoundException e) {
6174                 entry = type = pkg = null;
6175             }
6176             structure.setId(id, pkg, type, entry);
6177         } else {
6178             structure.setId(id, null, null, null);
6179         }
6180         structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6181         if (!hasIdentityMatrix()) {
6182             structure.setTransformation(getMatrix());
6183         }
6184         structure.setElevation(getZ());
6185         structure.setVisibility(getVisibility());
6186         structure.setEnabled(isEnabled());
6187         if (isClickable()) {
6188             structure.setClickable(true);
6189         }
6190         if (isFocusable()) {
6191             structure.setFocusable(true);
6192         }
6193         if (isFocused()) {
6194             structure.setFocused(true);
6195         }
6196         if (isAccessibilityFocused()) {
6197             structure.setAccessibilityFocused(true);
6198         }
6199         if (isSelected()) {
6200             structure.setSelected(true);
6201         }
6202         if (isActivated()) {
6203             structure.setActivated(true);
6204         }
6205         if (isLongClickable()) {
6206             structure.setLongClickable(true);
6207         }
6208         if (this instanceof Checkable) {
6209             structure.setCheckable(true);
6210             if (((Checkable)this).isChecked()) {
6211                 structure.setChecked(true);
6212             }
6213         }
6214         if (isContextClickable()) {
6215             structure.setContextClickable(true);
6216         }
6217         structure.setClassName(getAccessibilityClassName().toString());
6218         structure.setContentDescription(getContentDescription());
6219     }
6220 
6221     /**
6222      * Called when assist structure is being retrieved from a view as part of
6223      * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6224      * generate additional virtual structure under this view.  The defaullt implementation
6225      * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6226      * view's virtual accessibility nodes, if any.  You can override this for a more
6227      * optimal implementation providing this data.
6228      */
onProvideVirtualStructure(ViewStructure structure)6229     public void onProvideVirtualStructure(ViewStructure structure) {
6230         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6231         if (provider != null) {
6232             AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6233             structure.setChildCount(1);
6234             ViewStructure root = structure.newChild(0);
6235             populateVirtualStructure(root, provider, info);
6236             info.recycle();
6237         }
6238     }
6239 
populateVirtualStructure(ViewStructure structure, AccessibilityNodeProvider provider, AccessibilityNodeInfo info)6240     private void populateVirtualStructure(ViewStructure structure,
6241             AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6242         structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6243                 null, null, null);
6244         Rect rect = structure.getTempRect();
6245         info.getBoundsInParent(rect);
6246         structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6247         structure.setVisibility(VISIBLE);
6248         structure.setEnabled(info.isEnabled());
6249         if (info.isClickable()) {
6250             structure.setClickable(true);
6251         }
6252         if (info.isFocusable()) {
6253             structure.setFocusable(true);
6254         }
6255         if (info.isFocused()) {
6256             structure.setFocused(true);
6257         }
6258         if (info.isAccessibilityFocused()) {
6259             structure.setAccessibilityFocused(true);
6260         }
6261         if (info.isSelected()) {
6262             structure.setSelected(true);
6263         }
6264         if (info.isLongClickable()) {
6265             structure.setLongClickable(true);
6266         }
6267         if (info.isCheckable()) {
6268             structure.setCheckable(true);
6269             if (info.isChecked()) {
6270                 structure.setChecked(true);
6271             }
6272         }
6273         if (info.isContextClickable()) {
6274             structure.setContextClickable(true);
6275         }
6276         CharSequence cname = info.getClassName();
6277         structure.setClassName(cname != null ? cname.toString() : null);
6278         structure.setContentDescription(info.getContentDescription());
6279         if (info.getText() != null || info.getError() != null) {
6280             structure.setText(info.getText(), info.getTextSelectionStart(),
6281                     info.getTextSelectionEnd());
6282         }
6283         final int NCHILDREN = info.getChildCount();
6284         if (NCHILDREN > 0) {
6285             structure.setChildCount(NCHILDREN);
6286             for (int i=0; i<NCHILDREN; i++) {
6287                 AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6288                         AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6289                 ViewStructure child = structure.newChild(i);
6290                 populateVirtualStructure(child, provider, cinfo);
6291                 cinfo.recycle();
6292             }
6293         }
6294     }
6295 
6296     /**
6297      * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6298      * implementation calls {@link #onProvideStructure} and
6299      * {@link #onProvideVirtualStructure}.
6300      */
dispatchProvideStructure(ViewStructure structure)6301     public void dispatchProvideStructure(ViewStructure structure) {
6302         if (!isAssistBlocked()) {
6303             onProvideStructure(structure);
6304             onProvideVirtualStructure(structure);
6305         } else {
6306             structure.setClassName(getAccessibilityClassName().toString());
6307             structure.setAssistBlocked(true);
6308         }
6309     }
6310 
6311     /**
6312      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6313      *
6314      * Note: Called from the default {@link AccessibilityDelegate}.
6315      *
6316      * @hide
6317      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)6318     public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6319         if (mAttachInfo == null) {
6320             return;
6321         }
6322 
6323         Rect bounds = mAttachInfo.mTmpInvalRect;
6324 
6325         getDrawingRect(bounds);
6326         info.setBoundsInParent(bounds);
6327 
6328         getBoundsOnScreen(bounds, true);
6329         info.setBoundsInScreen(bounds);
6330 
6331         ViewParent parent = getParentForAccessibility();
6332         if (parent instanceof View) {
6333             info.setParent((View) parent);
6334         }
6335 
6336         if (mID != View.NO_ID) {
6337             View rootView = getRootView();
6338             if (rootView == null) {
6339                 rootView = this;
6340             }
6341 
6342             View label = rootView.findLabelForView(this, mID);
6343             if (label != null) {
6344                 info.setLabeledBy(label);
6345             }
6346 
6347             if ((mAttachInfo.mAccessibilityFetchFlags
6348                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6349                     && Resources.resourceHasPackage(mID)) {
6350                 try {
6351                     String viewId = getResources().getResourceName(mID);
6352                     info.setViewIdResourceName(viewId);
6353                 } catch (Resources.NotFoundException nfe) {
6354                     /* ignore */
6355                 }
6356             }
6357         }
6358 
6359         if (mLabelForId != View.NO_ID) {
6360             View rootView = getRootView();
6361             if (rootView == null) {
6362                 rootView = this;
6363             }
6364             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6365             if (labeled != null) {
6366                 info.setLabelFor(labeled);
6367             }
6368         }
6369 
6370         if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6371             View rootView = getRootView();
6372             if (rootView == null) {
6373                 rootView = this;
6374             }
6375             View next = rootView.findViewInsideOutShouldExist(this,
6376                     mAccessibilityTraversalBeforeId);
6377             if (next != null && next.includeForAccessibility()) {
6378                 info.setTraversalBefore(next);
6379             }
6380         }
6381 
6382         if (mAccessibilityTraversalAfterId != View.NO_ID) {
6383             View rootView = getRootView();
6384             if (rootView == null) {
6385                 rootView = this;
6386             }
6387             View next = rootView.findViewInsideOutShouldExist(this,
6388                     mAccessibilityTraversalAfterId);
6389             if (next != null && next.includeForAccessibility()) {
6390                 info.setTraversalAfter(next);
6391             }
6392         }
6393 
6394         info.setVisibleToUser(isVisibleToUser());
6395 
6396         info.setPackageName(mContext.getPackageName());
6397         info.setClassName(getAccessibilityClassName());
6398         info.setContentDescription(getContentDescription());
6399 
6400         info.setEnabled(isEnabled());
6401         info.setClickable(isClickable());
6402         info.setFocusable(isFocusable());
6403         info.setFocused(isFocused());
6404         info.setAccessibilityFocused(isAccessibilityFocused());
6405         info.setSelected(isSelected());
6406         info.setLongClickable(isLongClickable());
6407         info.setContextClickable(isContextClickable());
6408         info.setLiveRegion(getAccessibilityLiveRegion());
6409 
6410         // TODO: These make sense only if we are in an AdapterView but all
6411         // views can be selected. Maybe from accessibility perspective
6412         // we should report as selectable view in an AdapterView.
6413         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6414         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6415 
6416         if (isFocusable()) {
6417             if (isFocused()) {
6418                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6419             } else {
6420                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6421             }
6422         }
6423 
6424         if (!isAccessibilityFocused()) {
6425             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6426         } else {
6427             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6428         }
6429 
6430         if (isClickable() && isEnabled()) {
6431             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6432         }
6433 
6434         if (isLongClickable() && isEnabled()) {
6435             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6436         }
6437 
6438         if (isContextClickable() && isEnabled()) {
6439             info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6440         }
6441 
6442         CharSequence text = getIterableTextForAccessibility();
6443         if (text != null && text.length() > 0) {
6444             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6445 
6446             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6447             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6448             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6449             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6450                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6451                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6452         }
6453 
6454         info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6455     }
6456 
findLabelForView(View view, int labeledId)6457     private View findLabelForView(View view, int labeledId) {
6458         if (mMatchLabelForPredicate == null) {
6459             mMatchLabelForPredicate = new MatchLabelForPredicate();
6460         }
6461         mMatchLabelForPredicate.mLabeledId = labeledId;
6462         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6463     }
6464 
6465     /**
6466      * Computes whether this view is visible to the user. Such a view is
6467      * attached, visible, all its predecessors are visible, it is not clipped
6468      * entirely by its predecessors, and has an alpha greater than zero.
6469      *
6470      * @return Whether the view is visible on the screen.
6471      *
6472      * @hide
6473      */
isVisibleToUser()6474     protected boolean isVisibleToUser() {
6475         return isVisibleToUser(null);
6476     }
6477 
6478     /**
6479      * Computes whether the given portion of this view is visible to the user.
6480      * Such a view is attached, visible, all its predecessors are visible,
6481      * has an alpha greater than zero, and the specified portion is not
6482      * clipped entirely by its predecessors.
6483      *
6484      * @param boundInView the portion of the view to test; coordinates should be relative; may be
6485      *                    <code>null</code>, and the entire view will be tested in this case.
6486      *                    When <code>true</code> is returned by the function, the actual visible
6487      *                    region will be stored in this parameter; that is, if boundInView is fully
6488      *                    contained within the view, no modification will be made, otherwise regions
6489      *                    outside of the visible area of the view will be clipped.
6490      *
6491      * @return Whether the specified portion of the view is visible on the screen.
6492      *
6493      * @hide
6494      */
isVisibleToUser(Rect boundInView)6495     protected boolean isVisibleToUser(Rect boundInView) {
6496         if (mAttachInfo != null) {
6497             // Attached to invisible window means this view is not visible.
6498             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6499                 return false;
6500             }
6501             // An invisible predecessor or one with alpha zero means
6502             // that this view is not visible to the user.
6503             Object current = this;
6504             while (current instanceof View) {
6505                 View view = (View) current;
6506                 // We have attach info so this view is attached and there is no
6507                 // need to check whether we reach to ViewRootImpl on the way up.
6508                 if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6509                         view.getVisibility() != VISIBLE) {
6510                     return false;
6511                 }
6512                 current = view.mParent;
6513             }
6514             // Check if the view is entirely covered by its predecessors.
6515             Rect visibleRect = mAttachInfo.mTmpInvalRect;
6516             Point offset = mAttachInfo.mPoint;
6517             if (!getGlobalVisibleRect(visibleRect, offset)) {
6518                 return false;
6519             }
6520             // Check if the visible portion intersects the rectangle of interest.
6521             if (boundInView != null) {
6522                 visibleRect.offset(-offset.x, -offset.y);
6523                 return boundInView.intersect(visibleRect);
6524             }
6525             return true;
6526         }
6527         return false;
6528     }
6529 
6530     /**
6531      * Returns the delegate for implementing accessibility support via
6532      * composition. For more details see {@link AccessibilityDelegate}.
6533      *
6534      * @return The delegate, or null if none set.
6535      *
6536      * @hide
6537      */
getAccessibilityDelegate()6538     public AccessibilityDelegate getAccessibilityDelegate() {
6539         return mAccessibilityDelegate;
6540     }
6541 
6542     /**
6543      * Sets a delegate for implementing accessibility support via composition as
6544      * opposed to inheritance. The delegate's primary use is for implementing
6545      * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
6546      *
6547      * @param delegate The delegate instance.
6548      *
6549      * @see AccessibilityDelegate
6550      */
setAccessibilityDelegate(@ullable AccessibilityDelegate delegate)6551     public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6552         mAccessibilityDelegate = delegate;
6553     }
6554 
6555     /**
6556      * Gets the provider for managing a virtual view hierarchy rooted at this View
6557      * and reported to {@link android.accessibilityservice.AccessibilityService}s
6558      * that explore the window content.
6559      * <p>
6560      * If this method returns an instance, this instance is responsible for managing
6561      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6562      * View including the one representing the View itself. Similarly the returned
6563      * instance is responsible for performing accessibility actions on any virtual
6564      * view or the root view itself.
6565      * </p>
6566      * <p>
6567      * If an {@link AccessibilityDelegate} has been specified via calling
6568      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6569      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6570      * is responsible for handling this call.
6571      * </p>
6572      *
6573      * @return The provider.
6574      *
6575      * @see AccessibilityNodeProvider
6576      */
getAccessibilityNodeProvider()6577     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6578         if (mAccessibilityDelegate != null) {
6579             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6580         } else {
6581             return null;
6582         }
6583     }
6584 
6585     /**
6586      * Gets the unique identifier of this view on the screen for accessibility purposes.
6587      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6588      *
6589      * @return The view accessibility id.
6590      *
6591      * @hide
6592      */
getAccessibilityViewId()6593     public int getAccessibilityViewId() {
6594         if (mAccessibilityViewId == NO_ID) {
6595             mAccessibilityViewId = sNextAccessibilityViewId++;
6596         }
6597         return mAccessibilityViewId;
6598     }
6599 
6600     /**
6601      * Gets the unique identifier of the window in which this View reseides.
6602      *
6603      * @return The window accessibility id.
6604      *
6605      * @hide
6606      */
getAccessibilityWindowId()6607     public int getAccessibilityWindowId() {
6608         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6609                 : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6610     }
6611 
6612     /**
6613      * Gets the {@link View} description. It briefly describes the view and is
6614      * primarily used for accessibility support. Set this property to enable
6615      * better accessibility support for your application. This is especially
6616      * true for views that do not have textual representation (For example,
6617      * ImageButton).
6618      *
6619      * @return The content description.
6620      *
6621      * @attr ref android.R.styleable#View_contentDescription
6622      */
6623     @ViewDebug.ExportedProperty(category = "accessibility")
getContentDescription()6624     public CharSequence getContentDescription() {
6625         return mContentDescription;
6626     }
6627 
6628     /**
6629      * Sets the {@link View} description. It briefly describes the view and is
6630      * primarily used for accessibility support. Set this property to enable
6631      * better accessibility support for your application. This is especially
6632      * true for views that do not have textual representation (For example,
6633      * ImageButton).
6634      *
6635      * @param contentDescription The content description.
6636      *
6637      * @attr ref android.R.styleable#View_contentDescription
6638      */
6639     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)6640     public void setContentDescription(CharSequence contentDescription) {
6641         if (mContentDescription == null) {
6642             if (contentDescription == null) {
6643                 return;
6644             }
6645         } else if (mContentDescription.equals(contentDescription)) {
6646             return;
6647         }
6648         mContentDescription = contentDescription;
6649         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6650         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6651             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6652             notifySubtreeAccessibilityStateChangedIfNeeded();
6653         } else {
6654             notifyViewAccessibilityStateChangedIfNeeded(
6655                     AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6656         }
6657     }
6658 
6659     /**
6660      * Sets the id of a view before which this one is visited in accessibility traversal.
6661      * A screen-reader must visit the content of this view before the content of the one
6662      * it precedes. For example, if view B is set to be before view A, then a screen-reader
6663      * will traverse the entire content of B before traversing the entire content of A,
6664      * regardles of what traversal strategy it is using.
6665      * <p>
6666      * Views that do not have specified before/after relationships are traversed in order
6667      * determined by the screen-reader.
6668      * </p>
6669      * <p>
6670      * Setting that this view is before a view that is not important for accessibility
6671      * or if this view is not important for accessibility will have no effect as the
6672      * screen-reader is not aware of unimportant views.
6673      * </p>
6674      *
6675      * @param beforeId The id of a view this one precedes in accessibility traversal.
6676      *
6677      * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6678      *
6679      * @see #setImportantForAccessibility(int)
6680      */
6681     @RemotableViewMethod
setAccessibilityTraversalBefore(int beforeId)6682     public void setAccessibilityTraversalBefore(int beforeId) {
6683         if (mAccessibilityTraversalBeforeId == beforeId) {
6684             return;
6685         }
6686         mAccessibilityTraversalBeforeId = beforeId;
6687         notifyViewAccessibilityStateChangedIfNeeded(
6688                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6689     }
6690 
6691     /**
6692      * Gets the id of a view before which this one is visited in accessibility traversal.
6693      *
6694      * @return The id of a view this one precedes in accessibility traversal if
6695      *         specified, otherwise {@link #NO_ID}.
6696      *
6697      * @see #setAccessibilityTraversalBefore(int)
6698      */
getAccessibilityTraversalBefore()6699     public int getAccessibilityTraversalBefore() {
6700         return mAccessibilityTraversalBeforeId;
6701     }
6702 
6703     /**
6704      * Sets the id of a view after which this one is visited in accessibility traversal.
6705      * A screen-reader must visit the content of the other view before the content of this
6706      * one. For example, if view B is set to be after view A, then a screen-reader
6707      * will traverse the entire content of A before traversing the entire content of B,
6708      * regardles of what traversal strategy it is using.
6709      * <p>
6710      * Views that do not have specified before/after relationships are traversed in order
6711      * determined by the screen-reader.
6712      * </p>
6713      * <p>
6714      * Setting that this view is after a view that is not important for accessibility
6715      * or if this view is not important for accessibility will have no effect as the
6716      * screen-reader is not aware of unimportant views.
6717      * </p>
6718      *
6719      * @param afterId The id of a view this one succedees in accessibility traversal.
6720      *
6721      * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6722      *
6723      * @see #setImportantForAccessibility(int)
6724      */
6725     @RemotableViewMethod
setAccessibilityTraversalAfter(int afterId)6726     public void setAccessibilityTraversalAfter(int afterId) {
6727         if (mAccessibilityTraversalAfterId == afterId) {
6728             return;
6729         }
6730         mAccessibilityTraversalAfterId = afterId;
6731         notifyViewAccessibilityStateChangedIfNeeded(
6732                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6733     }
6734 
6735     /**
6736      * Gets the id of a view after which this one is visited in accessibility traversal.
6737      *
6738      * @return The id of a view this one succeedes in accessibility traversal if
6739      *         specified, otherwise {@link #NO_ID}.
6740      *
6741      * @see #setAccessibilityTraversalAfter(int)
6742      */
getAccessibilityTraversalAfter()6743     public int getAccessibilityTraversalAfter() {
6744         return mAccessibilityTraversalAfterId;
6745     }
6746 
6747     /**
6748      * Gets the id of a view for which this view serves as a label for
6749      * accessibility purposes.
6750      *
6751      * @return The labeled view id.
6752      */
6753     @ViewDebug.ExportedProperty(category = "accessibility")
getLabelFor()6754     public int getLabelFor() {
6755         return mLabelForId;
6756     }
6757 
6758     /**
6759      * Sets the id of a view for which this view serves as a label for
6760      * accessibility purposes.
6761      *
6762      * @param id The labeled view id.
6763      */
6764     @RemotableViewMethod
setLabelFor(@dRes int id)6765     public void setLabelFor(@IdRes int id) {
6766         if (mLabelForId == id) {
6767             return;
6768         }
6769         mLabelForId = id;
6770         if (mLabelForId != View.NO_ID
6771                 && mID == View.NO_ID) {
6772             mID = generateViewId();
6773         }
6774         notifyViewAccessibilityStateChangedIfNeeded(
6775                 AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6776     }
6777 
6778     /**
6779      * Invoked whenever this view loses focus, either by losing window focus or by losing
6780      * focus within its window. This method can be used to clear any state tied to the
6781      * focus. For instance, if a button is held pressed with the trackball and the window
6782      * loses focus, this method can be used to cancel the press.
6783      *
6784      * Subclasses of View overriding this method should always call super.onFocusLost().
6785      *
6786      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6787      * @see #onWindowFocusChanged(boolean)
6788      *
6789      * @hide pending API council approval
6790      */
6791     @CallSuper
onFocusLost()6792     protected void onFocusLost() {
6793         resetPressedState();
6794     }
6795 
resetPressedState()6796     private void resetPressedState() {
6797         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6798             return;
6799         }
6800 
6801         if (isPressed()) {
6802             setPressed(false);
6803 
6804             if (!mHasPerformedLongPress) {
6805                 removeLongPressCallback();
6806             }
6807         }
6808     }
6809 
6810     /**
6811      * Returns true if this view has focus
6812      *
6813      * @return True if this view has focus, false otherwise.
6814      */
6815     @ViewDebug.ExportedProperty(category = "focus")
isFocused()6816     public boolean isFocused() {
6817         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6818     }
6819 
6820     /**
6821      * Find the view in the hierarchy rooted at this view that currently has
6822      * focus.
6823      *
6824      * @return The view that currently has focus, or null if no focused view can
6825      *         be found.
6826      */
findFocus()6827     public View findFocus() {
6828         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6829     }
6830 
6831     /**
6832      * Indicates whether this view is one of the set of scrollable containers in
6833      * its window.
6834      *
6835      * @return whether this view is one of the set of scrollable containers in
6836      * its window
6837      *
6838      * @attr ref android.R.styleable#View_isScrollContainer
6839      */
isScrollContainer()6840     public boolean isScrollContainer() {
6841         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6842     }
6843 
6844     /**
6845      * Change whether this view is one of the set of scrollable containers in
6846      * its window.  This will be used to determine whether the window can
6847      * resize or must pan when a soft input area is open -- scrollable
6848      * containers allow the window to use resize mode since the container
6849      * will appropriately shrink.
6850      *
6851      * @attr ref android.R.styleable#View_isScrollContainer
6852      */
setScrollContainer(boolean isScrollContainer)6853     public void setScrollContainer(boolean isScrollContainer) {
6854         if (isScrollContainer) {
6855             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6856                 mAttachInfo.mScrollContainers.add(this);
6857                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6858             }
6859             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6860         } else {
6861             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6862                 mAttachInfo.mScrollContainers.remove(this);
6863             }
6864             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6865         }
6866     }
6867 
6868     /**
6869      * Returns the quality of the drawing cache.
6870      *
6871      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6872      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6873      *
6874      * @see #setDrawingCacheQuality(int)
6875      * @see #setDrawingCacheEnabled(boolean)
6876      * @see #isDrawingCacheEnabled()
6877      *
6878      * @attr ref android.R.styleable#View_drawingCacheQuality
6879      */
6880     @DrawingCacheQuality
getDrawingCacheQuality()6881     public int getDrawingCacheQuality() {
6882         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6883     }
6884 
6885     /**
6886      * Set the drawing cache quality of this view. This value is used only when the
6887      * drawing cache is enabled
6888      *
6889      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6890      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6891      *
6892      * @see #getDrawingCacheQuality()
6893      * @see #setDrawingCacheEnabled(boolean)
6894      * @see #isDrawingCacheEnabled()
6895      *
6896      * @attr ref android.R.styleable#View_drawingCacheQuality
6897      */
setDrawingCacheQuality(@rawingCacheQuality int quality)6898     public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6899         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6900     }
6901 
6902     /**
6903      * Returns whether the screen should remain on, corresponding to the current
6904      * value of {@link #KEEP_SCREEN_ON}.
6905      *
6906      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6907      *
6908      * @see #setKeepScreenOn(boolean)
6909      *
6910      * @attr ref android.R.styleable#View_keepScreenOn
6911      */
getKeepScreenOn()6912     public boolean getKeepScreenOn() {
6913         return (mViewFlags & KEEP_SCREEN_ON) != 0;
6914     }
6915 
6916     /**
6917      * Controls whether the screen should remain on, modifying the
6918      * value of {@link #KEEP_SCREEN_ON}.
6919      *
6920      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6921      *
6922      * @see #getKeepScreenOn()
6923      *
6924      * @attr ref android.R.styleable#View_keepScreenOn
6925      */
setKeepScreenOn(boolean keepScreenOn)6926     public void setKeepScreenOn(boolean keepScreenOn) {
6927         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6928     }
6929 
6930     /**
6931      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6932      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6933      *
6934      * @attr ref android.R.styleable#View_nextFocusLeft
6935      */
getNextFocusLeftId()6936     public int getNextFocusLeftId() {
6937         return mNextFocusLeftId;
6938     }
6939 
6940     /**
6941      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6942      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6943      * decide automatically.
6944      *
6945      * @attr ref android.R.styleable#View_nextFocusLeft
6946      */
setNextFocusLeftId(int nextFocusLeftId)6947     public void setNextFocusLeftId(int nextFocusLeftId) {
6948         mNextFocusLeftId = nextFocusLeftId;
6949     }
6950 
6951     /**
6952      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6953      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6954      *
6955      * @attr ref android.R.styleable#View_nextFocusRight
6956      */
getNextFocusRightId()6957     public int getNextFocusRightId() {
6958         return mNextFocusRightId;
6959     }
6960 
6961     /**
6962      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6963      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6964      * decide automatically.
6965      *
6966      * @attr ref android.R.styleable#View_nextFocusRight
6967      */
setNextFocusRightId(int nextFocusRightId)6968     public void setNextFocusRightId(int nextFocusRightId) {
6969         mNextFocusRightId = nextFocusRightId;
6970     }
6971 
6972     /**
6973      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6974      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6975      *
6976      * @attr ref android.R.styleable#View_nextFocusUp
6977      */
getNextFocusUpId()6978     public int getNextFocusUpId() {
6979         return mNextFocusUpId;
6980     }
6981 
6982     /**
6983      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6984      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6985      * decide automatically.
6986      *
6987      * @attr ref android.R.styleable#View_nextFocusUp
6988      */
setNextFocusUpId(int nextFocusUpId)6989     public void setNextFocusUpId(int nextFocusUpId) {
6990         mNextFocusUpId = nextFocusUpId;
6991     }
6992 
6993     /**
6994      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6995      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6996      *
6997      * @attr ref android.R.styleable#View_nextFocusDown
6998      */
getNextFocusDownId()6999     public int getNextFocusDownId() {
7000         return mNextFocusDownId;
7001     }
7002 
7003     /**
7004      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7005      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7006      * decide automatically.
7007      *
7008      * @attr ref android.R.styleable#View_nextFocusDown
7009      */
setNextFocusDownId(int nextFocusDownId)7010     public void setNextFocusDownId(int nextFocusDownId) {
7011         mNextFocusDownId = nextFocusDownId;
7012     }
7013 
7014     /**
7015      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7016      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7017      *
7018      * @attr ref android.R.styleable#View_nextFocusForward
7019      */
getNextFocusForwardId()7020     public int getNextFocusForwardId() {
7021         return mNextFocusForwardId;
7022     }
7023 
7024     /**
7025      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7026      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7027      * decide automatically.
7028      *
7029      * @attr ref android.R.styleable#View_nextFocusForward
7030      */
setNextFocusForwardId(int nextFocusForwardId)7031     public void setNextFocusForwardId(int nextFocusForwardId) {
7032         mNextFocusForwardId = nextFocusForwardId;
7033     }
7034 
7035     /**
7036      * Returns the visibility of this view and all of its ancestors
7037      *
7038      * @return True if this view and all of its ancestors are {@link #VISIBLE}
7039      */
isShown()7040     public boolean isShown() {
7041         View current = this;
7042         //noinspection ConstantConditions
7043         do {
7044             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7045                 return false;
7046             }
7047             ViewParent parent = current.mParent;
7048             if (parent == null) {
7049                 return false; // We are not attached to the view root
7050             }
7051             if (!(parent instanceof View)) {
7052                 return true;
7053             }
7054             current = (View) parent;
7055         } while (current != null);
7056 
7057         return false;
7058     }
7059 
7060     /**
7061      * Called by the view hierarchy when the content insets for a window have
7062      * changed, to allow it to adjust its content to fit within those windows.
7063      * The content insets tell you the space that the status bar, input method,
7064      * and other system windows infringe on the application's window.
7065      *
7066      * <p>You do not normally need to deal with this function, since the default
7067      * window decoration given to applications takes care of applying it to the
7068      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7069      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7070      * and your content can be placed under those system elements.  You can then
7071      * use this method within your view hierarchy if you have parts of your UI
7072      * which you would like to ensure are not being covered.
7073      *
7074      * <p>The default implementation of this method simply applies the content
7075      * insets to the view's padding, consuming that content (modifying the
7076      * insets to be 0), and returning true.  This behavior is off by default, but can
7077      * be enabled through {@link #setFitsSystemWindows(boolean)}.
7078      *
7079      * <p>This function's traversal down the hierarchy is depth-first.  The same content
7080      * insets object is propagated down the hierarchy, so any changes made to it will
7081      * be seen by all following views (including potentially ones above in
7082      * the hierarchy since this is a depth-first traversal).  The first view
7083      * that returns true will abort the entire traversal.
7084      *
7085      * <p>The default implementation works well for a situation where it is
7086      * used with a container that covers the entire window, allowing it to
7087      * apply the appropriate insets to its content on all edges.  If you need
7088      * a more complicated layout (such as two different views fitting system
7089      * windows, one on the top of the window, and one on the bottom),
7090      * you can override the method and handle the insets however you would like.
7091      * Note that the insets provided by the framework are always relative to the
7092      * far edges of the window, not accounting for the location of the called view
7093      * within that window.  (In fact when this method is called you do not yet know
7094      * where the layout will place the view, as it is done before layout happens.)
7095      *
7096      * <p>Note: unlike many View methods, there is no dispatch phase to this
7097      * call.  If you are overriding it in a ViewGroup and want to allow the
7098      * call to continue to your children, you must be sure to call the super
7099      * implementation.
7100      *
7101      * <p>Here is a sample layout that makes use of fitting system windows
7102      * to have controls for a video view placed inside of the window decorations
7103      * that it hides and shows.  This can be used with code like the second
7104      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7105      *
7106      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7107      *
7108      * @param insets Current content insets of the window.  Prior to
7109      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7110      * the insets or else you and Android will be unhappy.
7111      *
7112      * @return {@code true} if this view applied the insets and it should not
7113      * continue propagating further down the hierarchy, {@code false} otherwise.
7114      * @see #getFitsSystemWindows()
7115      * @see #setFitsSystemWindows(boolean)
7116      * @see #setSystemUiVisibility(int)
7117      *
7118      * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7119      * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7120      * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7121      * to implement handling their own insets.
7122      */
fitSystemWindows(Rect insets)7123     protected boolean fitSystemWindows(Rect insets) {
7124         if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7125             if (insets == null) {
7126                 // Null insets by definition have already been consumed.
7127                 // This call cannot apply insets since there are none to apply,
7128                 // so return false.
7129                 return false;
7130             }
7131             // If we're not in the process of dispatching the newer apply insets call,
7132             // that means we're not in the compatibility path. Dispatch into the newer
7133             // apply insets path and take things from there.
7134             try {
7135                 mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7136                 return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7137             } finally {
7138                 mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7139             }
7140         } else {
7141             // We're being called from the newer apply insets path.
7142             // Perform the standard fallback behavior.
7143             return fitSystemWindowsInt(insets);
7144         }
7145     }
7146 
fitSystemWindowsInt(Rect insets)7147     private boolean fitSystemWindowsInt(Rect insets) {
7148         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7149             mUserPaddingStart = UNDEFINED_PADDING;
7150             mUserPaddingEnd = UNDEFINED_PADDING;
7151             Rect localInsets = sThreadLocal.get();
7152             if (localInsets == null) {
7153                 localInsets = new Rect();
7154                 sThreadLocal.set(localInsets);
7155             }
7156             boolean res = computeFitSystemWindows(insets, localInsets);
7157             mUserPaddingLeftInitial = localInsets.left;
7158             mUserPaddingRightInitial = localInsets.right;
7159             internalSetPadding(localInsets.left, localInsets.top,
7160                     localInsets.right, localInsets.bottom);
7161             return res;
7162         }
7163         return false;
7164     }
7165 
7166     /**
7167      * Called when the view should apply {@link WindowInsets} according to its internal policy.
7168      *
7169      * <p>This method should be overridden by views that wish to apply a policy different from or
7170      * in addition to the default behavior. Clients that wish to force a view subtree
7171      * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7172      *
7173      * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7174      * it will be called during dispatch instead of this method. The listener may optionally
7175      * call this method from its own implementation if it wishes to apply the view's default
7176      * insets policy in addition to its own.</p>
7177      *
7178      * <p>Implementations of this method should either return the insets parameter unchanged
7179      * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7180      * that this view applied itself. This allows new inset types added in future platform
7181      * versions to pass through existing implementations unchanged without being erroneously
7182      * consumed.</p>
7183      *
7184      * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7185      * property is set then the view will consume the system window insets and apply them
7186      * as padding for the view.</p>
7187      *
7188      * @param insets Insets to apply
7189      * @return The supplied insets with any applied insets consumed
7190      */
onApplyWindowInsets(WindowInsets insets)7191     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7192         if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7193             // We weren't called from within a direct call to fitSystemWindows,
7194             // call into it as a fallback in case we're in a class that overrides it
7195             // and has logic to perform.
7196             if (fitSystemWindows(insets.getSystemWindowInsets())) {
7197                 return insets.consumeSystemWindowInsets();
7198             }
7199         } else {
7200             // We were called from within a direct call to fitSystemWindows.
7201             if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7202                 return insets.consumeSystemWindowInsets();
7203             }
7204         }
7205         return insets;
7206     }
7207 
7208     /**
7209      * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7210      * window insets to this view. The listener's
7211      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7212      * method will be called instead of the view's
7213      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7214      *
7215      * @param listener Listener to set
7216      *
7217      * @see #onApplyWindowInsets(WindowInsets)
7218      */
setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener)7219     public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7220         getListenerInfo().mOnApplyWindowInsetsListener = listener;
7221     }
7222 
7223     /**
7224      * Request to apply the given window insets to this view or another view in its subtree.
7225      *
7226      * <p>This method should be called by clients wishing to apply insets corresponding to areas
7227      * obscured by window decorations or overlays. This can include the status and navigation bars,
7228      * action bars, input methods and more. New inset categories may be added in the future.
7229      * The method returns the insets provided minus any that were applied by this view or its
7230      * children.</p>
7231      *
7232      * <p>Clients wishing to provide custom behavior should override the
7233      * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7234      * {@link OnApplyWindowInsetsListener} via the
7235      * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7236      * method.</p>
7237      *
7238      * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7239      * </p>
7240      *
7241      * @param insets Insets to apply
7242      * @return The provided insets minus the insets that were consumed
7243      */
dispatchApplyWindowInsets(WindowInsets insets)7244     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7245         try {
7246             mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7247             if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7248                 return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7249             } else {
7250                 return onApplyWindowInsets(insets);
7251             }
7252         } finally {
7253             mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7254         }
7255     }
7256 
7257     /**
7258      * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7259      * only available if the view is attached.
7260      *
7261      * @return WindowInsets from the top of the view hierarchy or null if View is detached
7262      */
getRootWindowInsets()7263     public WindowInsets getRootWindowInsets() {
7264         if (mAttachInfo != null) {
7265             return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7266         }
7267         return null;
7268     }
7269 
7270     /**
7271      * @hide Compute the insets that should be consumed by this view and the ones
7272      * that should propagate to those under it.
7273      */
computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)7274     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7275         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7276                 || mAttachInfo == null
7277                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7278                         && !mAttachInfo.mOverscanRequested)) {
7279             outLocalInsets.set(inoutInsets);
7280             inoutInsets.set(0, 0, 0, 0);
7281             return true;
7282         } else {
7283             // The application wants to take care of fitting system window for
7284             // the content...  however we still need to take care of any overscan here.
7285             final Rect overscan = mAttachInfo.mOverscanInsets;
7286             outLocalInsets.set(overscan);
7287             inoutInsets.left -= overscan.left;
7288             inoutInsets.top -= overscan.top;
7289             inoutInsets.right -= overscan.right;
7290             inoutInsets.bottom -= overscan.bottom;
7291             return false;
7292         }
7293     }
7294 
7295     /**
7296      * Compute insets that should be consumed by this view and the ones that should propagate
7297      * to those under it.
7298      *
7299      * @param in Insets currently being processed by this View, likely received as a parameter
7300      *           to {@link #onApplyWindowInsets(WindowInsets)}.
7301      * @param outLocalInsets A Rect that will receive the insets that should be consumed
7302      *                       by this view
7303      * @return Insets that should be passed along to views under this one
7304      */
computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets)7305     public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7306         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7307                 || mAttachInfo == null
7308                 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7309             outLocalInsets.set(in.getSystemWindowInsets());
7310             return in.consumeSystemWindowInsets();
7311         } else {
7312             outLocalInsets.set(0, 0, 0, 0);
7313             return in;
7314         }
7315     }
7316 
7317     /**
7318      * Sets whether or not this view should account for system screen decorations
7319      * such as the status bar and inset its content; that is, controlling whether
7320      * the default implementation of {@link #fitSystemWindows(Rect)} will be
7321      * executed.  See that method for more details.
7322      *
7323      * <p>Note that if you are providing your own implementation of
7324      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7325      * flag to true -- your implementation will be overriding the default
7326      * implementation that checks this flag.
7327      *
7328      * @param fitSystemWindows If true, then the default implementation of
7329      * {@link #fitSystemWindows(Rect)} will be executed.
7330      *
7331      * @attr ref android.R.styleable#View_fitsSystemWindows
7332      * @see #getFitsSystemWindows()
7333      * @see #fitSystemWindows(Rect)
7334      * @see #setSystemUiVisibility(int)
7335      */
setFitsSystemWindows(boolean fitSystemWindows)7336     public void setFitsSystemWindows(boolean fitSystemWindows) {
7337         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7338     }
7339 
7340     /**
7341      * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7342      * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7343      * will be executed.
7344      *
7345      * @return {@code true} if the default implementation of
7346      * {@link #fitSystemWindows(Rect)} will be executed.
7347      *
7348      * @attr ref android.R.styleable#View_fitsSystemWindows
7349      * @see #setFitsSystemWindows(boolean)
7350      * @see #fitSystemWindows(Rect)
7351      * @see #setSystemUiVisibility(int)
7352      */
7353     @ViewDebug.ExportedProperty
getFitsSystemWindows()7354     public boolean getFitsSystemWindows() {
7355         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7356     }
7357 
7358     /** @hide */
fitsSystemWindows()7359     public boolean fitsSystemWindows() {
7360         return getFitsSystemWindows();
7361     }
7362 
7363     /**
7364      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7365      * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7366      */
requestFitSystemWindows()7367     public void requestFitSystemWindows() {
7368         if (mParent != null) {
7369             mParent.requestFitSystemWindows();
7370         }
7371     }
7372 
7373     /**
7374      * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7375      */
requestApplyInsets()7376     public void requestApplyInsets() {
7377         requestFitSystemWindows();
7378     }
7379 
7380     /**
7381      * For use by PhoneWindow to make its own system window fitting optional.
7382      * @hide
7383      */
makeOptionalFitsSystemWindows()7384     public void makeOptionalFitsSystemWindows() {
7385         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7386     }
7387 
7388     /**
7389      * Returns the outsets, which areas of the device that aren't a surface, but we would like to
7390      * treat them as such.
7391      * @hide
7392      */
getOutsets(Rect outOutsetRect)7393     public void getOutsets(Rect outOutsetRect) {
7394         if (mAttachInfo != null) {
7395             outOutsetRect.set(mAttachInfo.mOutsets);
7396         } else {
7397             outOutsetRect.setEmpty();
7398         }
7399     }
7400 
7401     /**
7402      * Returns the visibility status for this view.
7403      *
7404      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7405      * @attr ref android.R.styleable#View_visibility
7406      */
7407     @ViewDebug.ExportedProperty(mapping = {
7408         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
7409         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7410         @ViewDebug.IntToString(from = GONE,      to = "GONE")
7411     })
7412     @Visibility
getVisibility()7413     public int getVisibility() {
7414         return mViewFlags & VISIBILITY_MASK;
7415     }
7416 
7417     /**
7418      * Set the enabled state of this view.
7419      *
7420      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7421      * @attr ref android.R.styleable#View_visibility
7422      */
7423     @RemotableViewMethod
setVisibility(@isibility int visibility)7424     public void setVisibility(@Visibility int visibility) {
7425         setFlags(visibility, VISIBILITY_MASK);
7426     }
7427 
7428     /**
7429      * Returns the enabled status for this view. The interpretation of the
7430      * enabled state varies by subclass.
7431      *
7432      * @return True if this view is enabled, false otherwise.
7433      */
7434     @ViewDebug.ExportedProperty
isEnabled()7435     public boolean isEnabled() {
7436         return (mViewFlags & ENABLED_MASK) == ENABLED;
7437     }
7438 
7439     /**
7440      * Set the enabled state of this view. The interpretation of the enabled
7441      * state varies by subclass.
7442      *
7443      * @param enabled True if this view is enabled, false otherwise.
7444      */
7445     @RemotableViewMethod
setEnabled(boolean enabled)7446     public void setEnabled(boolean enabled) {
7447         if (enabled == isEnabled()) return;
7448 
7449         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7450 
7451         /*
7452          * The View most likely has to change its appearance, so refresh
7453          * the drawable state.
7454          */
7455         refreshDrawableState();
7456 
7457         // Invalidate too, since the default behavior for views is to be
7458         // be drawn at 50% alpha rather than to change the drawable.
7459         invalidate(true);
7460 
7461         if (!enabled) {
7462             cancelPendingInputEvents();
7463         }
7464     }
7465 
7466     /**
7467      * Set whether this view can receive the focus.
7468      *
7469      * Setting this to false will also ensure that this view is not focusable
7470      * in touch mode.
7471      *
7472      * @param focusable If true, this view can receive the focus.
7473      *
7474      * @see #setFocusableInTouchMode(boolean)
7475      * @attr ref android.R.styleable#View_focusable
7476      */
setFocusable(boolean focusable)7477     public void setFocusable(boolean focusable) {
7478         if (!focusable) {
7479             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7480         }
7481         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7482     }
7483 
7484     /**
7485      * Set whether this view can receive focus while in touch mode.
7486      *
7487      * Setting this to true will also ensure that this view is focusable.
7488      *
7489      * @param focusableInTouchMode If true, this view can receive the focus while
7490      *   in touch mode.
7491      *
7492      * @see #setFocusable(boolean)
7493      * @attr ref android.R.styleable#View_focusableInTouchMode
7494      */
setFocusableInTouchMode(boolean focusableInTouchMode)7495     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7496         // Focusable in touch mode should always be set before the focusable flag
7497         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7498         // which, in touch mode, will not successfully request focus on this view
7499         // because the focusable in touch mode flag is not set
7500         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7501         if (focusableInTouchMode) {
7502             setFlags(FOCUSABLE, FOCUSABLE_MASK);
7503         }
7504     }
7505 
7506     /**
7507      * Set whether this view should have sound effects enabled for events such as
7508      * clicking and touching.
7509      *
7510      * <p>You may wish to disable sound effects for a view if you already play sounds,
7511      * for instance, a dial key that plays dtmf tones.
7512      *
7513      * @param soundEffectsEnabled whether sound effects are enabled for this view.
7514      * @see #isSoundEffectsEnabled()
7515      * @see #playSoundEffect(int)
7516      * @attr ref android.R.styleable#View_soundEffectsEnabled
7517      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)7518     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7519         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7520     }
7521 
7522     /**
7523      * @return whether this view should have sound effects enabled for events such as
7524      *     clicking and touching.
7525      *
7526      * @see #setSoundEffectsEnabled(boolean)
7527      * @see #playSoundEffect(int)
7528      * @attr ref android.R.styleable#View_soundEffectsEnabled
7529      */
7530     @ViewDebug.ExportedProperty
isSoundEffectsEnabled()7531     public boolean isSoundEffectsEnabled() {
7532         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7533     }
7534 
7535     /**
7536      * Set whether this view should have haptic feedback for events such as
7537      * long presses.
7538      *
7539      * <p>You may wish to disable haptic feedback if your view already controls
7540      * its own haptic feedback.
7541      *
7542      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7543      * @see #isHapticFeedbackEnabled()
7544      * @see #performHapticFeedback(int)
7545      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7546      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)7547     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7548         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7549     }
7550 
7551     /**
7552      * @return whether this view should have haptic feedback enabled for events
7553      * long presses.
7554      *
7555      * @see #setHapticFeedbackEnabled(boolean)
7556      * @see #performHapticFeedback(int)
7557      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7558      */
7559     @ViewDebug.ExportedProperty
isHapticFeedbackEnabled()7560     public boolean isHapticFeedbackEnabled() {
7561         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7562     }
7563 
7564     /**
7565      * Returns the layout direction for this view.
7566      *
7567      * @return One of {@link #LAYOUT_DIRECTION_LTR},
7568      *   {@link #LAYOUT_DIRECTION_RTL},
7569      *   {@link #LAYOUT_DIRECTION_INHERIT} or
7570      *   {@link #LAYOUT_DIRECTION_LOCALE}.
7571      *
7572      * @attr ref android.R.styleable#View_layoutDirection
7573      *
7574      * @hide
7575      */
7576     @ViewDebug.ExportedProperty(category = "layout", mapping = {
7577         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7578         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7579         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7580         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7581     })
7582     @LayoutDir
getRawLayoutDirection()7583     public int getRawLayoutDirection() {
7584         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7585     }
7586 
7587     /**
7588      * Set the layout direction for this view. This will propagate a reset of layout direction
7589      * resolution to the view's children and resolve layout direction for this view.
7590      *
7591      * @param layoutDirection the layout direction to set. Should be one of:
7592      *
7593      * {@link #LAYOUT_DIRECTION_LTR},
7594      * {@link #LAYOUT_DIRECTION_RTL},
7595      * {@link #LAYOUT_DIRECTION_INHERIT},
7596      * {@link #LAYOUT_DIRECTION_LOCALE}.
7597      *
7598      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7599      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7600      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7601      *
7602      * @attr ref android.R.styleable#View_layoutDirection
7603      */
7604     @RemotableViewMethod
setLayoutDirection(@ayoutDir int layoutDirection)7605     public void setLayoutDirection(@LayoutDir int layoutDirection) {
7606         if (getRawLayoutDirection() != layoutDirection) {
7607             // Reset the current layout direction and the resolved one
7608             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7609             resetRtlProperties();
7610             // Set the new layout direction (filtered)
7611             mPrivateFlags2 |=
7612                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7613             // We need to resolve all RTL properties as they all depend on layout direction
7614             resolveRtlPropertiesIfNeeded();
7615             requestLayout();
7616             invalidate(true);
7617         }
7618     }
7619 
7620     /**
7621      * Returns the resolved layout direction for this view.
7622      *
7623      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7624      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7625      *
7626      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7627      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7628      *
7629      * @attr ref android.R.styleable#View_layoutDirection
7630      */
7631     @ViewDebug.ExportedProperty(category = "layout", mapping = {
7632         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7633         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7634     })
7635     @ResolvedLayoutDir
getLayoutDirection()7636     public int getLayoutDirection() {
7637         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7638         if (targetSdkVersion < JELLY_BEAN_MR1) {
7639             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7640             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7641         }
7642         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7643                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7644     }
7645 
7646     /**
7647      * Indicates whether or not this view's layout is right-to-left. This is resolved from
7648      * layout attribute and/or the inherited value from the parent
7649      *
7650      * @return true if the layout is right-to-left.
7651      *
7652      * @hide
7653      */
7654     @ViewDebug.ExportedProperty(category = "layout")
isLayoutRtl()7655     public boolean isLayoutRtl() {
7656         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7657     }
7658 
7659     /**
7660      * Indicates whether the view is currently tracking transient state that the
7661      * app should not need to concern itself with saving and restoring, but that
7662      * the framework should take special note to preserve when possible.
7663      *
7664      * <p>A view with transient state cannot be trivially rebound from an external
7665      * data source, such as an adapter binding item views in a list. This may be
7666      * because the view is performing an animation, tracking user selection
7667      * of content, or similar.</p>
7668      *
7669      * @return true if the view has transient state
7670      */
7671     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()7672     public boolean hasTransientState() {
7673         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7674     }
7675 
7676     /**
7677      * Set whether this view is currently tracking transient state that the
7678      * framework should attempt to preserve when possible. This flag is reference counted,
7679      * so every call to setHasTransientState(true) should be paired with a later call
7680      * to setHasTransientState(false).
7681      *
7682      * <p>A view with transient state cannot be trivially rebound from an external
7683      * data source, such as an adapter binding item views in a list. This may be
7684      * because the view is performing an animation, tracking user selection
7685      * of content, or similar.</p>
7686      *
7687      * @param hasTransientState true if this view has transient state
7688      */
setHasTransientState(boolean hasTransientState)7689     public void setHasTransientState(boolean hasTransientState) {
7690         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7691                 mTransientStateCount - 1;
7692         if (mTransientStateCount < 0) {
7693             mTransientStateCount = 0;
7694             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7695                     "unmatched pair of setHasTransientState calls");
7696         } else if ((hasTransientState && mTransientStateCount == 1) ||
7697                 (!hasTransientState && mTransientStateCount == 0)) {
7698             // update flag if we've just incremented up from 0 or decremented down to 0
7699             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7700                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7701             if (mParent != null) {
7702                 try {
7703                     mParent.childHasTransientStateChanged(this, hasTransientState);
7704                 } catch (AbstractMethodError e) {
7705                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7706                             " does not fully implement ViewParent", e);
7707                 }
7708             }
7709         }
7710     }
7711 
7712     /**
7713      * Returns true if this view is currently attached to a window.
7714      */
isAttachedToWindow()7715     public boolean isAttachedToWindow() {
7716         return mAttachInfo != null;
7717     }
7718 
7719     /**
7720      * Returns true if this view has been through at least one layout since it
7721      * was last attached to or detached from a window.
7722      */
isLaidOut()7723     public boolean isLaidOut() {
7724         return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7725     }
7726 
7727     /**
7728      * If this view doesn't do any drawing on its own, set this flag to
7729      * allow further optimizations. By default, this flag is not set on
7730      * View, but could be set on some View subclasses such as ViewGroup.
7731      *
7732      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7733      * you should clear this flag.
7734      *
7735      * @param willNotDraw whether or not this View draw on its own
7736      */
setWillNotDraw(boolean willNotDraw)7737     public void setWillNotDraw(boolean willNotDraw) {
7738         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7739     }
7740 
7741     /**
7742      * Returns whether or not this View draws on its own.
7743      *
7744      * @return true if this view has nothing to draw, false otherwise
7745      */
7746     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()7747     public boolean willNotDraw() {
7748         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7749     }
7750 
7751     /**
7752      * When a View's drawing cache is enabled, drawing is redirected to an
7753      * offscreen bitmap. Some views, like an ImageView, must be able to
7754      * bypass this mechanism if they already draw a single bitmap, to avoid
7755      * unnecessary usage of the memory.
7756      *
7757      * @param willNotCacheDrawing true if this view does not cache its
7758      *        drawing, false otherwise
7759      */
setWillNotCacheDrawing(boolean willNotCacheDrawing)7760     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7761         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7762     }
7763 
7764     /**
7765      * Returns whether or not this View can cache its drawing or not.
7766      *
7767      * @return true if this view does not cache its drawing, false otherwise
7768      */
7769     @ViewDebug.ExportedProperty(category = "drawing")
willNotCacheDrawing()7770     public boolean willNotCacheDrawing() {
7771         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7772     }
7773 
7774     /**
7775      * Indicates whether this view reacts to click events or not.
7776      *
7777      * @return true if the view is clickable, false otherwise
7778      *
7779      * @see #setClickable(boolean)
7780      * @attr ref android.R.styleable#View_clickable
7781      */
7782     @ViewDebug.ExportedProperty
isClickable()7783     public boolean isClickable() {
7784         return (mViewFlags & CLICKABLE) == CLICKABLE;
7785     }
7786 
7787     /**
7788      * Enables or disables click events for this view. When a view
7789      * is clickable it will change its state to "pressed" on every click.
7790      * Subclasses should set the view clickable to visually react to
7791      * user's clicks.
7792      *
7793      * @param clickable true to make the view clickable, false otherwise
7794      *
7795      * @see #isClickable()
7796      * @attr ref android.R.styleable#View_clickable
7797      */
setClickable(boolean clickable)7798     public void setClickable(boolean clickable) {
7799         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7800     }
7801 
7802     /**
7803      * Indicates whether this view reacts to long click events or not.
7804      *
7805      * @return true if the view is long clickable, false otherwise
7806      *
7807      * @see #setLongClickable(boolean)
7808      * @attr ref android.R.styleable#View_longClickable
7809      */
isLongClickable()7810     public boolean isLongClickable() {
7811         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7812     }
7813 
7814     /**
7815      * Enables or disables long click events for this view. When a view is long
7816      * clickable it reacts to the user holding down the button for a longer
7817      * duration than a tap. This event can either launch the listener or a
7818      * context menu.
7819      *
7820      * @param longClickable true to make the view long clickable, false otherwise
7821      * @see #isLongClickable()
7822      * @attr ref android.R.styleable#View_longClickable
7823      */
setLongClickable(boolean longClickable)7824     public void setLongClickable(boolean longClickable) {
7825         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7826     }
7827 
7828     /**
7829      * Indicates whether this view reacts to context clicks or not.
7830      *
7831      * @return true if the view is context clickable, false otherwise
7832      * @see #setContextClickable(boolean)
7833      * @attr ref android.R.styleable#View_contextClickable
7834      */
isContextClickable()7835     public boolean isContextClickable() {
7836         return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
7837     }
7838 
7839     /**
7840      * Enables or disables context clicking for this view. This event can launch the listener.
7841      *
7842      * @param contextClickable true to make the view react to a context click, false otherwise
7843      * @see #isContextClickable()
7844      * @attr ref android.R.styleable#View_contextClickable
7845      */
setContextClickable(boolean contextClickable)7846     public void setContextClickable(boolean contextClickable) {
7847         setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
7848     }
7849 
7850     /**
7851      * Sets the pressed state for this view and provides a touch coordinate for
7852      * animation hinting.
7853      *
7854      * @param pressed Pass true to set the View's internal state to "pressed",
7855      *            or false to reverts the View's internal state from a
7856      *            previously set "pressed" state.
7857      * @param x The x coordinate of the touch that caused the press
7858      * @param y The y coordinate of the touch that caused the press
7859      */
setPressed(boolean pressed, float x, float y)7860     private void setPressed(boolean pressed, float x, float y) {
7861         if (pressed) {
7862             drawableHotspotChanged(x, y);
7863         }
7864 
7865         setPressed(pressed);
7866     }
7867 
7868     /**
7869      * Sets the pressed state for this view.
7870      *
7871      * @see #isClickable()
7872      * @see #setClickable(boolean)
7873      *
7874      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7875      *        the View's internal state from a previously set "pressed" state.
7876      */
setPressed(boolean pressed)7877     public void setPressed(boolean pressed) {
7878         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7879 
7880         if (pressed) {
7881             mPrivateFlags |= PFLAG_PRESSED;
7882         } else {
7883             mPrivateFlags &= ~PFLAG_PRESSED;
7884         }
7885 
7886         if (needsRefresh) {
7887             refreshDrawableState();
7888         }
7889         dispatchSetPressed(pressed);
7890     }
7891 
7892     /**
7893      * Dispatch setPressed to all of this View's children.
7894      *
7895      * @see #setPressed(boolean)
7896      *
7897      * @param pressed The new pressed state
7898      */
dispatchSetPressed(boolean pressed)7899     protected void dispatchSetPressed(boolean pressed) {
7900     }
7901 
7902     /**
7903      * Indicates whether the view is currently in pressed state. Unless
7904      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7905      * the pressed state.
7906      *
7907      * @see #setPressed(boolean)
7908      * @see #isClickable()
7909      * @see #setClickable(boolean)
7910      *
7911      * @return true if the view is currently pressed, false otherwise
7912      */
7913     @ViewDebug.ExportedProperty
isPressed()7914     public boolean isPressed() {
7915         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7916     }
7917 
7918     /**
7919      * @hide
7920      * Indicates whether this view will participate in data collection through
7921      * {@link ViewStructure}.  If true, it will not provide any data
7922      * for itself or its children.  If false, the normal data collection will be allowed.
7923      *
7924      * @return Returns false if assist data collection is not blocked, else true.
7925      *
7926      * @see #setAssistBlocked(boolean)
7927      * @attr ref android.R.styleable#View_assistBlocked
7928      */
isAssistBlocked()7929     public boolean isAssistBlocked() {
7930         return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
7931     }
7932 
7933     /**
7934      * @hide
7935      * Controls whether assist data collection from this view and its children is enabled
7936      * (that is, whether {@link #onProvideStructure} and
7937      * {@link #onProvideVirtualStructure} will be called).  The default value is false,
7938      * allowing normal assist collection.  Setting this to false will disable assist collection.
7939      *
7940      * @param enabled Set to true to <em>disable</em> assist data collection, or false
7941      * (the default) to allow it.
7942      *
7943      * @see #isAssistBlocked()
7944      * @see #onProvideStructure
7945      * @see #onProvideVirtualStructure
7946      * @attr ref android.R.styleable#View_assistBlocked
7947      */
setAssistBlocked(boolean enabled)7948     public void setAssistBlocked(boolean enabled) {
7949         if (enabled) {
7950             mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
7951         } else {
7952             mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
7953         }
7954     }
7955 
7956     /**
7957      * Indicates whether this view will save its state (that is,
7958      * whether its {@link #onSaveInstanceState} method will be called).
7959      *
7960      * @return Returns true if the view state saving is enabled, else false.
7961      *
7962      * @see #setSaveEnabled(boolean)
7963      * @attr ref android.R.styleable#View_saveEnabled
7964      */
isSaveEnabled()7965     public boolean isSaveEnabled() {
7966         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7967     }
7968 
7969     /**
7970      * Controls whether the saving of this view's state is
7971      * enabled (that is, whether its {@link #onSaveInstanceState} method
7972      * will be called).  Note that even if freezing is enabled, the
7973      * view still must have an id assigned to it (via {@link #setId(int)})
7974      * for its state to be saved.  This flag can only disable the
7975      * saving of this view; any child views may still have their state saved.
7976      *
7977      * @param enabled Set to false to <em>disable</em> state saving, or true
7978      * (the default) to allow it.
7979      *
7980      * @see #isSaveEnabled()
7981      * @see #setId(int)
7982      * @see #onSaveInstanceState()
7983      * @attr ref android.R.styleable#View_saveEnabled
7984      */
setSaveEnabled(boolean enabled)7985     public void setSaveEnabled(boolean enabled) {
7986         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
7987     }
7988 
7989     /**
7990      * Gets whether the framework should discard touches when the view's
7991      * window is obscured by another visible window.
7992      * Refer to the {@link View} security documentation for more details.
7993      *
7994      * @return True if touch filtering is enabled.
7995      *
7996      * @see #setFilterTouchesWhenObscured(boolean)
7997      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7998      */
7999     @ViewDebug.ExportedProperty
getFilterTouchesWhenObscured()8000     public boolean getFilterTouchesWhenObscured() {
8001         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8002     }
8003 
8004     /**
8005      * Sets whether the framework should discard touches when the view's
8006      * window is obscured by another visible window.
8007      * Refer to the {@link View} security documentation for more details.
8008      *
8009      * @param enabled True if touch filtering should be enabled.
8010      *
8011      * @see #getFilterTouchesWhenObscured
8012      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8013      */
setFilterTouchesWhenObscured(boolean enabled)8014     public void setFilterTouchesWhenObscured(boolean enabled) {
8015         setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8016                 FILTER_TOUCHES_WHEN_OBSCURED);
8017     }
8018 
8019     /**
8020      * Indicates whether the entire hierarchy under this view will save its
8021      * state when a state saving traversal occurs from its parent.  The default
8022      * is true; if false, these views will not be saved unless
8023      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8024      *
8025      * @return Returns true if the view state saving from parent is enabled, else false.
8026      *
8027      * @see #setSaveFromParentEnabled(boolean)
8028      */
isSaveFromParentEnabled()8029     public boolean isSaveFromParentEnabled() {
8030         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8031     }
8032 
8033     /**
8034      * Controls whether the entire hierarchy under this view will save its
8035      * state when a state saving traversal occurs from its parent.  The default
8036      * is true; if false, these views will not be saved unless
8037      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8038      *
8039      * @param enabled Set to false to <em>disable</em> state saving, or true
8040      * (the default) to allow it.
8041      *
8042      * @see #isSaveFromParentEnabled()
8043      * @see #setId(int)
8044      * @see #onSaveInstanceState()
8045      */
setSaveFromParentEnabled(boolean enabled)8046     public void setSaveFromParentEnabled(boolean enabled) {
8047         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8048     }
8049 
8050 
8051     /**
8052      * Returns whether this View is able to take focus.
8053      *
8054      * @return True if this view can take focus, or false otherwise.
8055      * @attr ref android.R.styleable#View_focusable
8056      */
8057     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()8058     public final boolean isFocusable() {
8059         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8060     }
8061 
8062     /**
8063      * When a view is focusable, it may not want to take focus when in touch mode.
8064      * For example, a button would like focus when the user is navigating via a D-pad
8065      * so that the user can click on it, but once the user starts touching the screen,
8066      * the button shouldn't take focus
8067      * @return Whether the view is focusable in touch mode.
8068      * @attr ref android.R.styleable#View_focusableInTouchMode
8069      */
8070     @ViewDebug.ExportedProperty
isFocusableInTouchMode()8071     public final boolean isFocusableInTouchMode() {
8072         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8073     }
8074 
8075     /**
8076      * Find the nearest view in the specified direction that can take focus.
8077      * This does not actually give focus to that view.
8078      *
8079      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8080      *
8081      * @return The nearest focusable in the specified direction, or null if none
8082      *         can be found.
8083      */
focusSearch(@ocusRealDirection int direction)8084     public View focusSearch(@FocusRealDirection int direction) {
8085         if (mParent != null) {
8086             return mParent.focusSearch(this, direction);
8087         } else {
8088             return null;
8089         }
8090     }
8091 
8092     /**
8093      * This method is the last chance for the focused view and its ancestors to
8094      * respond to an arrow key. This is called when the focused view did not
8095      * consume the key internally, nor could the view system find a new view in
8096      * the requested direction to give focus to.
8097      *
8098      * @param focused The currently focused view.
8099      * @param direction The direction focus wants to move. One of FOCUS_UP,
8100      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8101      * @return True if the this view consumed this unhandled move.
8102      */
dispatchUnhandledMove(View focused, @FocusRealDirection int direction)8103     public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8104         return false;
8105     }
8106 
8107     /**
8108      * If a user manually specified the next view id for a particular direction,
8109      * use the root to look up the view.
8110      * @param root The root view of the hierarchy containing this view.
8111      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8112      * or FOCUS_BACKWARD.
8113      * @return The user specified next view, or null if there is none.
8114      */
findUserSetNextFocus(View root, @FocusDirection int direction)8115     View findUserSetNextFocus(View root, @FocusDirection int direction) {
8116         switch (direction) {
8117             case FOCUS_LEFT:
8118                 if (mNextFocusLeftId == View.NO_ID) return null;
8119                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8120             case FOCUS_RIGHT:
8121                 if (mNextFocusRightId == View.NO_ID) return null;
8122                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
8123             case FOCUS_UP:
8124                 if (mNextFocusUpId == View.NO_ID) return null;
8125                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
8126             case FOCUS_DOWN:
8127                 if (mNextFocusDownId == View.NO_ID) return null;
8128                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
8129             case FOCUS_FORWARD:
8130                 if (mNextFocusForwardId == View.NO_ID) return null;
8131                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8132             case FOCUS_BACKWARD: {
8133                 if (mID == View.NO_ID) return null;
8134                 final int id = mID;
8135                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8136                     @Override
8137                     public boolean apply(View t) {
8138                         return t.mNextFocusForwardId == id;
8139                     }
8140                 });
8141             }
8142         }
8143         return null;
8144     }
8145 
8146     private View findViewInsideOutShouldExist(View root, int id) {
8147         if (mMatchIdPredicate == null) {
8148             mMatchIdPredicate = new MatchIdPredicate();
8149         }
8150         mMatchIdPredicate.mId = id;
8151         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8152         if (result == null) {
8153             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8154         }
8155         return result;
8156     }
8157 
8158     /**
8159      * Find and return all focusable views that are descendants of this view,
8160      * possibly including this view if it is focusable itself.
8161      *
8162      * @param direction The direction of the focus
8163      * @return A list of focusable views
8164      */
8165     public ArrayList<View> getFocusables(@FocusDirection int direction) {
8166         ArrayList<View> result = new ArrayList<View>(24);
8167         addFocusables(result, direction);
8168         return result;
8169     }
8170 
8171     /**
8172      * Add any focusable views that are descendants of this view (possibly
8173      * including this view if it is focusable itself) to views.  If we are in touch mode,
8174      * only add views that are also focusable in touch mode.
8175      *
8176      * @param views Focusable views found so far
8177      * @param direction The direction of the focus
8178      */
8179     public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8180         addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
8181     }
8182 
8183     /**
8184      * Adds any focusable views that are descendants of this view (possibly
8185      * including this view if it is focusable itself) to views. This method
8186      * adds all focusable views regardless if we are in touch mode or
8187      * only views focusable in touch mode if we are in touch mode or
8188      * only views that can take accessibility focus if accessibility is enabled
8189      * depending on the focusable mode parameter.
8190      *
8191      * @param views Focusable views found so far or null if all we are interested is
8192      *        the number of focusables.
8193      * @param direction The direction of the focus.
8194      * @param focusableMode The type of focusables to be added.
8195      *
8196      * @see #FOCUSABLES_ALL
8197      * @see #FOCUSABLES_TOUCH_MODE
8198      */
8199     public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8200             @FocusableMode int focusableMode) {
8201         if (views == null) {
8202             return;
8203         }
8204         if (!isFocusable()) {
8205             return;
8206         }
8207         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8208                 && isInTouchMode() && !isFocusableInTouchMode()) {
8209             return;
8210         }
8211         views.add(this);
8212     }
8213 
8214     /**
8215      * Finds the Views that contain given text. The containment is case insensitive.
8216      * The search is performed by either the text that the View renders or the content
8217      * description that describes the view for accessibility purposes and the view does
8218      * not render or both. Clients can specify how the search is to be performed via
8219      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8220      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8221      *
8222      * @param outViews The output list of matching Views.
8223      * @param searched The text to match against.
8224      *
8225      * @see #FIND_VIEWS_WITH_TEXT
8226      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8227      * @see #setContentDescription(CharSequence)
8228      */
8229     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8230             @FindViewFlags int flags) {
8231         if (getAccessibilityNodeProvider() != null) {
8232             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8233                 outViews.add(this);
8234             }
8235         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8236                 && (searched != null && searched.length() > 0)
8237                 && (mContentDescription != null && mContentDescription.length() > 0)) {
8238             String searchedLowerCase = searched.toString().toLowerCase();
8239             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8240             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8241                 outViews.add(this);
8242             }
8243         }
8244     }
8245 
8246     /**
8247      * Find and return all touchable views that are descendants of this view,
8248      * possibly including this view if it is touchable itself.
8249      *
8250      * @return A list of touchable views
8251      */
8252     public ArrayList<View> getTouchables() {
8253         ArrayList<View> result = new ArrayList<View>();
8254         addTouchables(result);
8255         return result;
8256     }
8257 
8258     /**
8259      * Add any touchable views that are descendants of this view (possibly
8260      * including this view if it is touchable itself) to views.
8261      *
8262      * @param views Touchable views found so far
8263      */
8264     public void addTouchables(ArrayList<View> views) {
8265         final int viewFlags = mViewFlags;
8266 
8267         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8268                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8269                 && (viewFlags & ENABLED_MASK) == ENABLED) {
8270             views.add(this);
8271         }
8272     }
8273 
8274     /**
8275      * Returns whether this View is accessibility focused.
8276      *
8277      * @return True if this View is accessibility focused.
8278      */
8279     public boolean isAccessibilityFocused() {
8280         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8281     }
8282 
8283     /**
8284      * Call this to try to give accessibility focus to this view.
8285      *
8286      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8287      * returns false or the view is no visible or the view already has accessibility
8288      * focus.
8289      *
8290      * See also {@link #focusSearch(int)}, which is what you call to say that you
8291      * have focus, and you want your parent to look for the next one.
8292      *
8293      * @return Whether this view actually took accessibility focus.
8294      *
8295      * @hide
8296      */
8297     public boolean requestAccessibilityFocus() {
8298         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8299         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8300             return false;
8301         }
8302         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8303             return false;
8304         }
8305         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8306             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8307             ViewRootImpl viewRootImpl = getViewRootImpl();
8308             if (viewRootImpl != null) {
8309                 viewRootImpl.setAccessibilityFocus(this, null);
8310             }
8311             invalidate();
8312             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8313             return true;
8314         }
8315         return false;
8316     }
8317 
8318     /**
8319      * Call this to try to clear accessibility focus of this view.
8320      *
8321      * See also {@link #focusSearch(int)}, which is what you call to say that you
8322      * have focus, and you want your parent to look for the next one.
8323      *
8324      * @hide
8325      */
8326     public void clearAccessibilityFocus() {
8327         clearAccessibilityFocusNoCallbacks();
8328         // Clear the global reference of accessibility focus if this
8329         // view or any of its descendants had accessibility focus.
8330         ViewRootImpl viewRootImpl = getViewRootImpl();
8331         if (viewRootImpl != null) {
8332             View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8333             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8334                 viewRootImpl.setAccessibilityFocus(null, null);
8335             }
8336         }
8337     }
8338 
8339     private void sendAccessibilityHoverEvent(int eventType) {
8340         // Since we are not delivering to a client accessibility events from not
8341         // important views (unless the clinet request that) we need to fire the
8342         // event from the deepest view exposed to the client. As a consequence if
8343         // the user crosses a not exposed view the client will see enter and exit
8344         // of the exposed predecessor followed by and enter and exit of that same
8345         // predecessor when entering and exiting the not exposed descendant. This
8346         // is fine since the client has a clear idea which view is hovered at the
8347         // price of a couple more events being sent. This is a simple and
8348         // working solution.
8349         View source = this;
8350         while (true) {
8351             if (source.includeForAccessibility()) {
8352                 source.sendAccessibilityEvent(eventType);
8353                 return;
8354             }
8355             ViewParent parent = source.getParent();
8356             if (parent instanceof View) {
8357                 source = (View) parent;
8358             } else {
8359                 return;
8360             }
8361         }
8362     }
8363 
8364     /**
8365      * Clears accessibility focus without calling any callback methods
8366      * normally invoked in {@link #clearAccessibilityFocus()}. This method
8367      * is used for clearing accessibility focus when giving this focus to
8368      * another view.
8369      */
8370     void clearAccessibilityFocusNoCallbacks() {
8371         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
8372             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
8373             invalidate();
8374             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
8375         }
8376     }
8377 
8378     /**
8379      * Call this to try to give focus to a specific view or to one of its
8380      * descendants.
8381      *
8382      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8383      * false), or if it is focusable and it is not focusable in touch mode
8384      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8385      *
8386      * See also {@link #focusSearch(int)}, which is what you call to say that you
8387      * have focus, and you want your parent to look for the next one.
8388      *
8389      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
8390      * {@link #FOCUS_DOWN} and <code>null</code>.
8391      *
8392      * @return Whether this view or one of its descendants actually took focus.
8393      */
8394     public final boolean requestFocus() {
8395         return requestFocus(View.FOCUS_DOWN);
8396     }
8397 
8398     /**
8399      * Call this to try to give focus to a specific view or to one of its
8400      * descendants and give it a hint about what direction focus is heading.
8401      *
8402      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8403      * false), or if it is focusable and it is not focusable in touch mode
8404      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8405      *
8406      * See also {@link #focusSearch(int)}, which is what you call to say that you
8407      * have focus, and you want your parent to look for the next one.
8408      *
8409      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
8410      * <code>null</code> set for the previously focused rectangle.
8411      *
8412      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8413      * @return Whether this view or one of its descendants actually took focus.
8414      */
8415     public final boolean requestFocus(int direction) {
8416         return requestFocus(direction, null);
8417     }
8418 
8419     /**
8420      * Call this to try to give focus to a specific view or to one of its descendants
8421      * and give it hints about the direction and a specific rectangle that the focus
8422      * is coming from.  The rectangle can help give larger views a finer grained hint
8423      * about where focus is coming from, and therefore, where to show selection, or
8424      * forward focus change internally.
8425      *
8426      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8427      * false), or if it is focusable and it is not focusable in touch mode
8428      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8429      *
8430      * A View will not take focus if it is not visible.
8431      *
8432      * A View will not take focus if one of its parents has
8433      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
8434      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
8435      *
8436      * See also {@link #focusSearch(int)}, which is what you call to say that you
8437      * have focus, and you want your parent to look for the next one.
8438      *
8439      * You may wish to override this method if your custom {@link View} has an internal
8440      * {@link View} that it wishes to forward the request to.
8441      *
8442      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8443      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8444      *        to give a finer grained hint about where focus is coming from.  May be null
8445      *        if there is no hint.
8446      * @return Whether this view or one of its descendants actually took focus.
8447      */
8448     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8449         return requestFocusNoSearch(direction, previouslyFocusedRect);
8450     }
8451 
8452     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8453         // need to be focusable
8454         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8455                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8456             return false;
8457         }
8458 
8459         // need to be focusable in touch mode if in touch mode
8460         if (isInTouchMode() &&
8461             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8462                return false;
8463         }
8464 
8465         // need to not have any parents blocking us
8466         if (hasAncestorThatBlocksDescendantFocus()) {
8467             return false;
8468         }
8469 
8470         handleFocusGainInternal(direction, previouslyFocusedRect);
8471         return true;
8472     }
8473 
8474     /**
8475      * Call this to try to give focus to a specific view or to one of its descendants. This is a
8476      * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8477      * touch mode to request focus when they are touched.
8478      *
8479      * @return Whether this view or one of its descendants actually took focus.
8480      *
8481      * @see #isInTouchMode()
8482      *
8483      */
8484     public final boolean requestFocusFromTouch() {
8485         // Leave touch mode if we need to
8486         if (isInTouchMode()) {
8487             ViewRootImpl viewRoot = getViewRootImpl();
8488             if (viewRoot != null) {
8489                 viewRoot.ensureTouchMode(false);
8490             }
8491         }
8492         return requestFocus(View.FOCUS_DOWN);
8493     }
8494 
8495     /**
8496      * @return Whether any ancestor of this view blocks descendant focus.
8497      */
8498     private boolean hasAncestorThatBlocksDescendantFocus() {
8499         final boolean focusableInTouchMode = isFocusableInTouchMode();
8500         ViewParent ancestor = mParent;
8501         while (ancestor instanceof ViewGroup) {
8502             final ViewGroup vgAncestor = (ViewGroup) ancestor;
8503             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8504                     || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8505                 return true;
8506             } else {
8507                 ancestor = vgAncestor.getParent();
8508             }
8509         }
8510         return false;
8511     }
8512 
8513     /**
8514      * Gets the mode for determining whether this View is important for accessibility
8515      * which is if it fires accessibility events and if it is reported to
8516      * accessibility services that query the screen.
8517      *
8518      * @return The mode for determining whether a View is important for accessibility.
8519      *
8520      * @attr ref android.R.styleable#View_importantForAccessibility
8521      *
8522      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8523      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8524      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8525      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8526      */
8527     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8528             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8529             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8530             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8531             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8532                     to = "noHideDescendants")
8533         })
8534     public int getImportantForAccessibility() {
8535         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8536                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8537     }
8538 
8539     /**
8540      * Sets the live region mode for this view. This indicates to accessibility
8541      * services whether they should automatically notify the user about changes
8542      * to the view's content description or text, or to the content descriptions
8543      * or text of the view's children (where applicable).
8544      * <p>
8545      * For example, in a login screen with a TextView that displays an "incorrect
8546      * password" notification, that view should be marked as a live region with
8547      * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8548      * <p>
8549      * To disable change notifications for this view, use
8550      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8551      * mode for most views.
8552      * <p>
8553      * To indicate that the user should be notified of changes, use
8554      * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8555      * <p>
8556      * If the view's changes should interrupt ongoing speech and notify the user
8557      * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8558      *
8559      * @param mode The live region mode for this view, one of:
8560      *        <ul>
8561      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8562      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8563      *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8564      *        </ul>
8565      * @attr ref android.R.styleable#View_accessibilityLiveRegion
8566      */
8567     public void setAccessibilityLiveRegion(int mode) {
8568         if (mode != getAccessibilityLiveRegion()) {
8569             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8570             mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8571                     & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8572             notifyViewAccessibilityStateChangedIfNeeded(
8573                     AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8574         }
8575     }
8576 
8577     /**
8578      * Gets the live region mode for this View.
8579      *
8580      * @return The live region mode for the view.
8581      *
8582      * @attr ref android.R.styleable#View_accessibilityLiveRegion
8583      *
8584      * @see #setAccessibilityLiveRegion(int)
8585      */
8586     public int getAccessibilityLiveRegion() {
8587         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8588                 >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8589     }
8590 
8591     /**
8592      * Sets how to determine whether this view is important for accessibility
8593      * which is if it fires accessibility events and if it is reported to
8594      * accessibility services that query the screen.
8595      *
8596      * @param mode How to determine whether this view is important for accessibility.
8597      *
8598      * @attr ref android.R.styleable#View_importantForAccessibility
8599      *
8600      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8601      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8602      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8603      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8604      */
8605     public void setImportantForAccessibility(int mode) {
8606         final int oldMode = getImportantForAccessibility();
8607         if (mode != oldMode) {
8608             // If we're moving between AUTO and another state, we might not need
8609             // to send a subtree changed notification. We'll store the computed
8610             // importance, since we'll need to check it later to make sure.
8611             final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8612                     || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8613             final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8614             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8615             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8616                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8617             if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8618                 notifySubtreeAccessibilityStateChangedIfNeeded();
8619             } else {
8620                 notifyViewAccessibilityStateChangedIfNeeded(
8621                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8622             }
8623         }
8624     }
8625 
8626     /**
8627      * Computes whether this view should be exposed for accessibility. In
8628      * general, views that are interactive or provide information are exposed
8629      * while views that serve only as containers are hidden.
8630      * <p>
8631      * If an ancestor of this view has importance
8632      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8633      * returns <code>false</code>.
8634      * <p>
8635      * Otherwise, the value is computed according to the view's
8636      * {@link #getImportantForAccessibility()} value:
8637      * <ol>
8638      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8639      * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8640      * </code>
8641      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8642      * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8643      * view satisfies any of the following:
8644      * <ul>
8645      * <li>Is actionable, e.g. {@link #isClickable()},
8646      * {@link #isLongClickable()}, or {@link #isFocusable()}
8647      * <li>Has an {@link AccessibilityDelegate}
8648      * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8649      * {@link OnKeyListener}, etc.
8650      * <li>Is an accessibility live region, e.g.
8651      * {@link #getAccessibilityLiveRegion()} is not
8652      * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8653      * </ul>
8654      * </ol>
8655      *
8656      * @return Whether the view is exposed for accessibility.
8657      * @see #setImportantForAccessibility(int)
8658      * @see #getImportantForAccessibility()
8659      */
8660     public boolean isImportantForAccessibility() {
8661         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8662                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8663         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8664                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8665             return false;
8666         }
8667 
8668         // Check parent mode to ensure we're not hidden.
8669         ViewParent parent = mParent;
8670         while (parent instanceof View) {
8671             if (((View) parent).getImportantForAccessibility()
8672                     == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8673                 return false;
8674             }
8675             parent = parent.getParent();
8676         }
8677 
8678         return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8679                 || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8680                 || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8681     }
8682 
8683     /**
8684      * Gets the parent for accessibility purposes. Note that the parent for
8685      * accessibility is not necessary the immediate parent. It is the first
8686      * predecessor that is important for accessibility.
8687      *
8688      * @return The parent for accessibility purposes.
8689      */
8690     public ViewParent getParentForAccessibility() {
8691         if (mParent instanceof View) {
8692             View parentView = (View) mParent;
8693             if (parentView.includeForAccessibility()) {
8694                 return mParent;
8695             } else {
8696                 return mParent.getParentForAccessibility();
8697             }
8698         }
8699         return null;
8700     }
8701 
8702     /**
8703      * Adds the children of this View relevant for accessibility to the given list
8704      * as output. Since some Views are not important for accessibility the added
8705      * child views are not necessarily direct children of this view, rather they are
8706      * the first level of descendants important for accessibility.
8707      *
8708      * @param outChildren The output list that will receive children for accessibility.
8709      */
8710     public void addChildrenForAccessibility(ArrayList<View> outChildren) {
8711 
8712     }
8713 
8714     /**
8715      * Whether to regard this view for accessibility. A view is regarded for
8716      * accessibility if it is important for accessibility or the querying
8717      * accessibility service has explicitly requested that view not
8718      * important for accessibility are regarded.
8719      *
8720      * @return Whether to regard the view for accessibility.
8721      *
8722      * @hide
8723      */
8724     public boolean includeForAccessibility() {
8725         if (mAttachInfo != null) {
8726             return (mAttachInfo.mAccessibilityFetchFlags
8727                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8728                     || isImportantForAccessibility();
8729         }
8730         return false;
8731     }
8732 
8733     /**
8734      * Returns whether the View is considered actionable from
8735      * accessibility perspective. Such view are important for
8736      * accessibility.
8737      *
8738      * @return True if the view is actionable for accessibility.
8739      *
8740      * @hide
8741      */
8742     public boolean isActionableForAccessibility() {
8743         return (isClickable() || isLongClickable() || isFocusable());
8744     }
8745 
8746     /**
8747      * Returns whether the View has registered callbacks which makes it
8748      * important for accessibility.
8749      *
8750      * @return True if the view is actionable for accessibility.
8751      */
8752     private boolean hasListenersForAccessibility() {
8753         ListenerInfo info = getListenerInfo();
8754         return mTouchDelegate != null || info.mOnKeyListener != null
8755                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
8756                 || info.mOnHoverListener != null || info.mOnDragListener != null;
8757     }
8758 
8759     /**
8760      * Notifies that the accessibility state of this view changed. The change
8761      * is local to this view and does not represent structural changes such
8762      * as children and parent. For example, the view became focusable. The
8763      * notification is at at most once every
8764      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8765      * to avoid unnecessary load to the system. Also once a view has a pending
8766      * notification this method is a NOP until the notification has been sent.
8767      *
8768      * @hide
8769      */
8770     public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
8771         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8772             return;
8773         }
8774         if (mSendViewStateChangedAccessibilityEvent == null) {
8775             mSendViewStateChangedAccessibilityEvent =
8776                     new SendViewStateChangedAccessibilityEvent();
8777         }
8778         mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
8779     }
8780 
8781     /**
8782      * Notifies that the accessibility state of this view changed. The change
8783      * is *not* local to this view and does represent structural changes such
8784      * as children and parent. For example, the view size changed. The
8785      * notification is at at most once every
8786      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8787      * to avoid unnecessary load to the system. Also once a view has a pending
8788      * notification this method is a NOP until the notification has been sent.
8789      *
8790      * @hide
8791      */
8792     public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8793         if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8794             return;
8795         }
8796         if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8797             mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8798             if (mParent != null) {
8799                 try {
8800                     mParent.notifySubtreeAccessibilityStateChanged(
8801                             this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8802                 } catch (AbstractMethodError e) {
8803                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8804                             " does not fully implement ViewParent", e);
8805                 }
8806             }
8807         }
8808     }
8809 
8810     /**
8811      * Change the visibility of the View without triggering any other changes. This is
8812      * important for transitions, where visibility changes should not adjust focus or
8813      * trigger a new layout. This is only used when the visibility has already been changed
8814      * and we need a transient value during an animation. When the animation completes,
8815      * the original visibility value is always restored.
8816      *
8817      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8818      * @hide
8819      */
8820     public void setTransitionVisibility(@Visibility int visibility) {
8821         mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
8822     }
8823 
8824     /**
8825      * Reset the flag indicating the accessibility state of the subtree rooted
8826      * at this view changed.
8827      */
8828     void resetSubtreeAccessibilityStateChanged() {
8829         mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8830     }
8831 
8832     /**
8833      * Report an accessibility action to this view's parents for delegated processing.
8834      *
8835      * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8836      * call this method to delegate an accessibility action to a supporting parent. If the parent
8837      * returns true from its
8838      * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8839      * method this method will return true to signify that the action was consumed.</p>
8840      *
8841      * <p>This method is useful for implementing nested scrolling child views. If
8842      * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8843      * a custom view implementation may invoke this method to allow a parent to consume the
8844      * scroll first. If this method returns true the custom view should skip its own scrolling
8845      * behavior.</p>
8846      *
8847      * @param action Accessibility action to delegate
8848      * @param arguments Optional action arguments
8849      * @return true if the action was consumed by a parent
8850      */
8851     public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8852         for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8853             if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8854                 return true;
8855             }
8856         }
8857         return false;
8858     }
8859 
8860     /**
8861      * Performs the specified accessibility action on the view. For
8862      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8863      * <p>
8864      * If an {@link AccessibilityDelegate} has been specified via calling
8865      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8866      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8867      * is responsible for handling this call.
8868      * </p>
8869      *
8870      * <p>The default implementation will delegate
8871      * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8872      * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8873      * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8874      *
8875      * @param action The action to perform.
8876      * @param arguments Optional action arguments.
8877      * @return Whether the action was performed.
8878      */
8879     public boolean performAccessibilityAction(int action, Bundle arguments) {
8880       if (mAccessibilityDelegate != null) {
8881           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8882       } else {
8883           return performAccessibilityActionInternal(action, arguments);
8884       }
8885     }
8886 
8887    /**
8888     * @see #performAccessibilityAction(int, Bundle)
8889     *
8890     * Note: Called from the default {@link AccessibilityDelegate}.
8891     *
8892     * @hide
8893     */
8894     public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8895         if (isNestedScrollingEnabled()
8896                 && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
8897                 || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
8898                 || action == R.id.accessibilityActionScrollUp
8899                 || action == R.id.accessibilityActionScrollLeft
8900                 || action == R.id.accessibilityActionScrollDown
8901                 || action == R.id.accessibilityActionScrollRight)) {
8902             if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
8903                 return true;
8904             }
8905         }
8906 
8907         switch (action) {
8908             case AccessibilityNodeInfo.ACTION_CLICK: {
8909                 if (isClickable()) {
8910                     performClick();
8911                     return true;
8912                 }
8913             } break;
8914             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8915                 if (isLongClickable()) {
8916                     performLongClick();
8917                     return true;
8918                 }
8919             } break;
8920             case AccessibilityNodeInfo.ACTION_FOCUS: {
8921                 if (!hasFocus()) {
8922                     // Get out of touch mode since accessibility
8923                     // wants to move focus around.
8924                     getViewRootImpl().ensureTouchMode(false);
8925                     return requestFocus();
8926                 }
8927             } break;
8928             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8929                 if (hasFocus()) {
8930                     clearFocus();
8931                     return !isFocused();
8932                 }
8933             } break;
8934             case AccessibilityNodeInfo.ACTION_SELECT: {
8935                 if (!isSelected()) {
8936                     setSelected(true);
8937                     return isSelected();
8938                 }
8939             } break;
8940             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8941                 if (isSelected()) {
8942                     setSelected(false);
8943                     return !isSelected();
8944                 }
8945             } break;
8946             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8947                 if (!isAccessibilityFocused()) {
8948                     return requestAccessibilityFocus();
8949                 }
8950             } break;
8951             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8952                 if (isAccessibilityFocused()) {
8953                     clearAccessibilityFocus();
8954                     return true;
8955                 }
8956             } break;
8957             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8958                 if (arguments != null) {
8959                     final int granularity = arguments.getInt(
8960                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8961                     final boolean extendSelection = arguments.getBoolean(
8962                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8963                     return traverseAtGranularity(granularity, true, extendSelection);
8964                 }
8965             } break;
8966             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8967                 if (arguments != null) {
8968                     final int granularity = arguments.getInt(
8969                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8970                     final boolean extendSelection = arguments.getBoolean(
8971                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8972                     return traverseAtGranularity(granularity, false, extendSelection);
8973                 }
8974             } break;
8975             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8976                 CharSequence text = getIterableTextForAccessibility();
8977                 if (text == null) {
8978                     return false;
8979                 }
8980                 final int start = (arguments != null) ? arguments.getInt(
8981                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8982                 final int end = (arguments != null) ? arguments.getInt(
8983                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8984                 // Only cursor position can be specified (selection length == 0)
8985                 if ((getAccessibilitySelectionStart() != start
8986                         || getAccessibilitySelectionEnd() != end)
8987                         && (start == end)) {
8988                     setAccessibilitySelection(start, end);
8989                     notifyViewAccessibilityStateChangedIfNeeded(
8990                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8991                     return true;
8992                 }
8993             } break;
8994             case R.id.accessibilityActionShowOnScreen: {
8995                 if (mAttachInfo != null) {
8996                     final Rect r = mAttachInfo.mTmpInvalRect;
8997                     getDrawingRect(r);
8998                     return requestRectangleOnScreen(r, true);
8999                 }
9000             } break;
9001             case R.id.accessibilityActionContextClick: {
9002                 if (isContextClickable()) {
9003                     performContextClick();
9004                     return true;
9005                 }
9006             } break;
9007         }
9008         return false;
9009     }
9010 
9011     private boolean traverseAtGranularity(int granularity, boolean forward,
9012             boolean extendSelection) {
9013         CharSequence text = getIterableTextForAccessibility();
9014         if (text == null || text.length() == 0) {
9015             return false;
9016         }
9017         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9018         if (iterator == null) {
9019             return false;
9020         }
9021         int current = getAccessibilitySelectionEnd();
9022         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9023             current = forward ? 0 : text.length();
9024         }
9025         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9026         if (range == null) {
9027             return false;
9028         }
9029         final int segmentStart = range[0];
9030         final int segmentEnd = range[1];
9031         int selectionStart;
9032         int selectionEnd;
9033         if (extendSelection && isAccessibilitySelectionExtendable()) {
9034             selectionStart = getAccessibilitySelectionStart();
9035             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9036                 selectionStart = forward ? segmentStart : segmentEnd;
9037             }
9038             selectionEnd = forward ? segmentEnd : segmentStart;
9039         } else {
9040             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9041         }
9042         setAccessibilitySelection(selectionStart, selectionEnd);
9043         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9044                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9045         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9046         return true;
9047     }
9048 
9049     /**
9050      * Gets the text reported for accessibility purposes.
9051      *
9052      * @return The accessibility text.
9053      *
9054      * @hide
9055      */
9056     public CharSequence getIterableTextForAccessibility() {
9057         return getContentDescription();
9058     }
9059 
9060     /**
9061      * Gets whether accessibility selection can be extended.
9062      *
9063      * @return If selection is extensible.
9064      *
9065      * @hide
9066      */
9067     public boolean isAccessibilitySelectionExtendable() {
9068         return false;
9069     }
9070 
9071     /**
9072      * @hide
9073      */
9074     public int getAccessibilitySelectionStart() {
9075         return mAccessibilityCursorPosition;
9076     }
9077 
9078     /**
9079      * @hide
9080      */
9081     public int getAccessibilitySelectionEnd() {
9082         return getAccessibilitySelectionStart();
9083     }
9084 
9085     /**
9086      * @hide
9087      */
9088     public void setAccessibilitySelection(int start, int end) {
9089         if (start ==  end && end == mAccessibilityCursorPosition) {
9090             return;
9091         }
9092         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9093             mAccessibilityCursorPosition = start;
9094         } else {
9095             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9096         }
9097         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9098     }
9099 
9100     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9101             int fromIndex, int toIndex) {
9102         if (mParent == null) {
9103             return;
9104         }
9105         AccessibilityEvent event = AccessibilityEvent.obtain(
9106                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9107         onInitializeAccessibilityEvent(event);
9108         onPopulateAccessibilityEvent(event);
9109         event.setFromIndex(fromIndex);
9110         event.setToIndex(toIndex);
9111         event.setAction(action);
9112         event.setMovementGranularity(granularity);
9113         mParent.requestSendAccessibilityEvent(this, event);
9114     }
9115 
9116     /**
9117      * @hide
9118      */
9119     public TextSegmentIterator getIteratorForGranularity(int granularity) {
9120         switch (granularity) {
9121             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9122                 CharSequence text = getIterableTextForAccessibility();
9123                 if (text != null && text.length() > 0) {
9124                     CharacterTextSegmentIterator iterator =
9125                         CharacterTextSegmentIterator.getInstance(
9126                                 mContext.getResources().getConfiguration().locale);
9127                     iterator.initialize(text.toString());
9128                     return iterator;
9129                 }
9130             } break;
9131             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9132                 CharSequence text = getIterableTextForAccessibility();
9133                 if (text != null && text.length() > 0) {
9134                     WordTextSegmentIterator iterator =
9135                         WordTextSegmentIterator.getInstance(
9136                                 mContext.getResources().getConfiguration().locale);
9137                     iterator.initialize(text.toString());
9138                     return iterator;
9139                 }
9140             } break;
9141             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9142                 CharSequence text = getIterableTextForAccessibility();
9143                 if (text != null && text.length() > 0) {
9144                     ParagraphTextSegmentIterator iterator =
9145                         ParagraphTextSegmentIterator.getInstance();
9146                     iterator.initialize(text.toString());
9147                     return iterator;
9148                 }
9149             } break;
9150         }
9151         return null;
9152     }
9153 
9154     /**
9155      * @hide
9156      */
9157     public void dispatchStartTemporaryDetach() {
9158         onStartTemporaryDetach();
9159     }
9160 
9161     /**
9162      * This is called when a container is going to temporarily detach a child, with
9163      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9164      * It will either be followed by {@link #onFinishTemporaryDetach()} or
9165      * {@link #onDetachedFromWindow()} when the container is done.
9166      */
9167     public void onStartTemporaryDetach() {
9168         removeUnsetPressCallback();
9169         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9170     }
9171 
9172     /**
9173      * @hide
9174      */
9175     public void dispatchFinishTemporaryDetach() {
9176         onFinishTemporaryDetach();
9177     }
9178 
9179     /**
9180      * Called after {@link #onStartTemporaryDetach} when the container is done
9181      * changing the view.
9182      */
9183     public void onFinishTemporaryDetach() {
9184     }
9185 
9186     /**
9187      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9188      * for this view's window.  Returns null if the view is not currently attached
9189      * to the window.  Normally you will not need to use this directly, but
9190      * just use the standard high-level event callbacks like
9191      * {@link #onKeyDown(int, KeyEvent)}.
9192      */
9193     public KeyEvent.DispatcherState getKeyDispatcherState() {
9194         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9195     }
9196 
9197     /**
9198      * Dispatch a key event before it is processed by any input method
9199      * associated with the view hierarchy.  This can be used to intercept
9200      * key events in special situations before the IME consumes them; a
9201      * typical example would be handling the BACK key to update the application's
9202      * UI instead of allowing the IME to see it and close itself.
9203      *
9204      * @param event The key event to be dispatched.
9205      * @return True if the event was handled, false otherwise.
9206      */
9207     public boolean dispatchKeyEventPreIme(KeyEvent event) {
9208         return onKeyPreIme(event.getKeyCode(), event);
9209     }
9210 
9211     /**
9212      * Dispatch a key event to the next view on the focus path. This path runs
9213      * from the top of the view tree down to the currently focused view. If this
9214      * view has focus, it will dispatch to itself. Otherwise it will dispatch
9215      * the next node down the focus path. This method also fires any key
9216      * listeners.
9217      *
9218      * @param event The key event to be dispatched.
9219      * @return True if the event was handled, false otherwise.
9220      */
9221     public boolean dispatchKeyEvent(KeyEvent event) {
9222         if (mInputEventConsistencyVerifier != null) {
9223             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9224         }
9225 
9226         // Give any attached key listener a first crack at the event.
9227         //noinspection SimplifiableIfStatement
9228         ListenerInfo li = mListenerInfo;
9229         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9230                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9231             return true;
9232         }
9233 
9234         if (event.dispatch(this, mAttachInfo != null
9235                 ? mAttachInfo.mKeyDispatchState : null, this)) {
9236             return true;
9237         }
9238 
9239         if (mInputEventConsistencyVerifier != null) {
9240             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9241         }
9242         return false;
9243     }
9244 
9245     /**
9246      * Dispatches a key shortcut event.
9247      *
9248      * @param event The key event to be dispatched.
9249      * @return True if the event was handled by the view, false otherwise.
9250      */
9251     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9252         return onKeyShortcut(event.getKeyCode(), event);
9253     }
9254 
9255     /**
9256      * Pass the touch screen motion event down to the target view, or this
9257      * view if it is the target.
9258      *
9259      * @param event The motion event to be dispatched.
9260      * @return True if the event was handled by the view, false otherwise.
9261      */
9262     public boolean dispatchTouchEvent(MotionEvent event) {
9263         // If the event should be handled by accessibility focus first.
9264         if (event.isTargetAccessibilityFocus()) {
9265             // We don't have focus or no virtual descendant has it, do not handle the event.
9266             if (!isAccessibilityFocusedViewOrHost()) {
9267                 return false;
9268             }
9269             // We have focus and got the event, then use normal event dispatch.
9270             event.setTargetAccessibilityFocus(false);
9271         }
9272 
9273         boolean result = false;
9274 
9275         if (mInputEventConsistencyVerifier != null) {
9276             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9277         }
9278 
9279         final int actionMasked = event.getActionMasked();
9280         if (actionMasked == MotionEvent.ACTION_DOWN) {
9281             // Defensive cleanup for new gesture
9282             stopNestedScroll();
9283         }
9284 
9285         if (onFilterTouchEventForSecurity(event)) {
9286             //noinspection SimplifiableIfStatement
9287             ListenerInfo li = mListenerInfo;
9288             if (li != null && li.mOnTouchListener != null
9289                     && (mViewFlags & ENABLED_MASK) == ENABLED
9290                     && li.mOnTouchListener.onTouch(this, event)) {
9291                 result = true;
9292             }
9293 
9294             if (!result && onTouchEvent(event)) {
9295                 result = true;
9296             }
9297         }
9298 
9299         if (!result && mInputEventConsistencyVerifier != null) {
9300             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9301         }
9302 
9303         // Clean up after nested scrolls if this is the end of a gesture;
9304         // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
9305         // of the gesture.
9306         if (actionMasked == MotionEvent.ACTION_UP ||
9307                 actionMasked == MotionEvent.ACTION_CANCEL ||
9308                 (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
9309             stopNestedScroll();
9310         }
9311 
9312         return result;
9313     }
9314 
9315     boolean isAccessibilityFocusedViewOrHost() {
9316         return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
9317                 .getAccessibilityFocusedHost() == this);
9318     }
9319 
9320     /**
9321      * Filter the touch event to apply security policies.
9322      *
9323      * @param event The motion event to be filtered.
9324      * @return True if the event should be dispatched, false if the event should be dropped.
9325      *
9326      * @see #getFilterTouchesWhenObscured
9327      */
9328     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
9329         //noinspection RedundantIfStatement
9330         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
9331                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
9332             // Window is obscured, drop this touch.
9333             return false;
9334         }
9335         return true;
9336     }
9337 
9338     /**
9339      * Pass a trackball motion event down to the focused view.
9340      *
9341      * @param event The motion event to be dispatched.
9342      * @return True if the event was handled by the view, false otherwise.
9343      */
9344     public boolean dispatchTrackballEvent(MotionEvent event) {
9345         if (mInputEventConsistencyVerifier != null) {
9346             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
9347         }
9348 
9349         return onTrackballEvent(event);
9350     }
9351 
9352     /**
9353      * Dispatch a generic motion event.
9354      * <p>
9355      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9356      * are delivered to the view under the pointer.  All other generic motion events are
9357      * delivered to the focused view.  Hover events are handled specially and are delivered
9358      * to {@link #onHoverEvent(MotionEvent)}.
9359      * </p>
9360      *
9361      * @param event The motion event to be dispatched.
9362      * @return True if the event was handled by the view, false otherwise.
9363      */
9364     public boolean dispatchGenericMotionEvent(MotionEvent event) {
9365         if (mInputEventConsistencyVerifier != null) {
9366             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
9367         }
9368 
9369         final int source = event.getSource();
9370         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
9371             final int action = event.getAction();
9372             if (action == MotionEvent.ACTION_HOVER_ENTER
9373                     || action == MotionEvent.ACTION_HOVER_MOVE
9374                     || action == MotionEvent.ACTION_HOVER_EXIT) {
9375                 if (dispatchHoverEvent(event)) {
9376                     return true;
9377                 }
9378             } else if (dispatchGenericPointerEvent(event)) {
9379                 return true;
9380             }
9381         } else if (dispatchGenericFocusedEvent(event)) {
9382             return true;
9383         }
9384 
9385         if (dispatchGenericMotionEventInternal(event)) {
9386             return true;
9387         }
9388 
9389         if (mInputEventConsistencyVerifier != null) {
9390             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9391         }
9392         return false;
9393     }
9394 
9395     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
9396         //noinspection SimplifiableIfStatement
9397         ListenerInfo li = mListenerInfo;
9398         if (li != null && li.mOnGenericMotionListener != null
9399                 && (mViewFlags & ENABLED_MASK) == ENABLED
9400                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
9401             return true;
9402         }
9403 
9404         if (onGenericMotionEvent(event)) {
9405             return true;
9406         }
9407 
9408         final int actionButton = event.getActionButton();
9409         switch (event.getActionMasked()) {
9410             case MotionEvent.ACTION_BUTTON_PRESS:
9411                 if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
9412                         && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9413                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9414                     if (performContextClick()) {
9415                         mInContextButtonPress = true;
9416                         setPressed(true, event.getX(), event.getY());
9417                         removeTapCallback();
9418                         removeLongPressCallback();
9419                         return true;
9420                     }
9421                 }
9422                 break;
9423 
9424             case MotionEvent.ACTION_BUTTON_RELEASE:
9425                 if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9426                         || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9427                     mInContextButtonPress = false;
9428                     mIgnoreNextUpEvent = true;
9429                 }
9430                 break;
9431         }
9432 
9433         if (mInputEventConsistencyVerifier != null) {
9434             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9435         }
9436         return false;
9437     }
9438 
9439     /**
9440      * Dispatch a hover event.
9441      * <p>
9442      * Do not call this method directly.
9443      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9444      * </p>
9445      *
9446      * @param event The motion event to be dispatched.
9447      * @return True if the event was handled by the view, false otherwise.
9448      */
9449     protected boolean dispatchHoverEvent(MotionEvent event) {
9450         ListenerInfo li = mListenerInfo;
9451         //noinspection SimplifiableIfStatement
9452         if (li != null && li.mOnHoverListener != null
9453                 && (mViewFlags & ENABLED_MASK) == ENABLED
9454                 && li.mOnHoverListener.onHover(this, event)) {
9455             return true;
9456         }
9457 
9458         return onHoverEvent(event);
9459     }
9460 
9461     /**
9462      * Returns true if the view has a child to which it has recently sent
9463      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
9464      * it does not have a hovered child, then it must be the innermost hovered view.
9465      * @hide
9466      */
9467     protected boolean hasHoveredChild() {
9468         return false;
9469     }
9470 
9471     /**
9472      * Dispatch a generic motion event to the view under the first pointer.
9473      * <p>
9474      * Do not call this method directly.
9475      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9476      * </p>
9477      *
9478      * @param event The motion event to be dispatched.
9479      * @return True if the event was handled by the view, false otherwise.
9480      */
9481     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
9482         return false;
9483     }
9484 
9485     /**
9486      * Dispatch a generic motion event to the currently focused view.
9487      * <p>
9488      * Do not call this method directly.
9489      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9490      * </p>
9491      *
9492      * @param event The motion event to be dispatched.
9493      * @return True if the event was handled by the view, false otherwise.
9494      */
9495     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9496         return false;
9497     }
9498 
9499     /**
9500      * Dispatch a pointer event.
9501      * <p>
9502      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9503      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
9504      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9505      * and should not be expected to handle other pointing device features.
9506      * </p>
9507      *
9508      * @param event The motion event to be dispatched.
9509      * @return True if the event was handled by the view, false otherwise.
9510      * @hide
9511      */
9512     public final boolean dispatchPointerEvent(MotionEvent event) {
9513         if (event.isTouchEvent()) {
9514             return dispatchTouchEvent(event);
9515         } else {
9516             return dispatchGenericMotionEvent(event);
9517         }
9518     }
9519 
9520     /**
9521      * Called when the window containing this view gains or loses window focus.
9522      * ViewGroups should override to route to their children.
9523      *
9524      * @param hasFocus True if the window containing this view now has focus,
9525      *        false otherwise.
9526      */
9527     public void dispatchWindowFocusChanged(boolean hasFocus) {
9528         onWindowFocusChanged(hasFocus);
9529     }
9530 
9531     /**
9532      * Called when the window containing this view gains or loses focus.  Note
9533      * that this is separate from view focus: to receive key events, both
9534      * your view and its window must have focus.  If a window is displayed
9535      * on top of yours that takes input focus, then your own window will lose
9536      * focus but the view focus will remain unchanged.
9537      *
9538      * @param hasWindowFocus True if the window containing this view now has
9539      *        focus, false otherwise.
9540      */
9541     public void onWindowFocusChanged(boolean hasWindowFocus) {
9542         InputMethodManager imm = InputMethodManager.peekInstance();
9543         if (!hasWindowFocus) {
9544             if (isPressed()) {
9545                 setPressed(false);
9546             }
9547             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9548                 imm.focusOut(this);
9549             }
9550             removeLongPressCallback();
9551             removeTapCallback();
9552             onFocusLost();
9553         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9554             imm.focusIn(this);
9555         }
9556         refreshDrawableState();
9557     }
9558 
9559     /**
9560      * Returns true if this view is in a window that currently has window focus.
9561      * Note that this is not the same as the view itself having focus.
9562      *
9563      * @return True if this view is in a window that currently has window focus.
9564      */
9565     public boolean hasWindowFocus() {
9566         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9567     }
9568 
9569     /**
9570      * Dispatch a view visibility change down the view hierarchy.
9571      * ViewGroups should override to route to their children.
9572      * @param changedView The view whose visibility changed. Could be 'this' or
9573      * an ancestor view.
9574      * @param visibility The new visibility of changedView: {@link #VISIBLE},
9575      * {@link #INVISIBLE} or {@link #GONE}.
9576      */
9577     protected void dispatchVisibilityChanged(@NonNull View changedView,
9578             @Visibility int visibility) {
9579         onVisibilityChanged(changedView, visibility);
9580     }
9581 
9582     /**
9583      * Called when the visibility of the view or an ancestor of the view has
9584      * changed.
9585      *
9586      * @param changedView The view whose visibility changed. May be
9587      *                    {@code this} or an ancestor view.
9588      * @param visibility The new visibility, one of {@link #VISIBLE},
9589      *                   {@link #INVISIBLE} or {@link #GONE}.
9590      */
9591     protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9592         final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9593         if (visible && mAttachInfo != null) {
9594             initialAwakenScrollBars();
9595         }
9596 
9597         final Drawable dr = mBackground;
9598         if (dr != null && visible != dr.isVisible()) {
9599             dr.setVisible(visible, false);
9600         }
9601         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9602         if (fg != null && visible != fg.isVisible()) {
9603             fg.setVisible(visible, false);
9604         }
9605     }
9606 
9607     /**
9608      * Dispatch a hint about whether this view is displayed. For instance, when
9609      * a View moves out of the screen, it might receives a display hint indicating
9610      * the view is not displayed. Applications should not <em>rely</em> on this hint
9611      * as there is no guarantee that they will receive one.
9612      *
9613      * @param hint A hint about whether or not this view is displayed:
9614      * {@link #VISIBLE} or {@link #INVISIBLE}.
9615      */
9616     public void dispatchDisplayHint(@Visibility int hint) {
9617         onDisplayHint(hint);
9618     }
9619 
9620     /**
9621      * Gives this view a hint about whether is displayed or not. For instance, when
9622      * a View moves out of the screen, it might receives a display hint indicating
9623      * the view is not displayed. Applications should not <em>rely</em> on this hint
9624      * as there is no guarantee that they will receive one.
9625      *
9626      * @param hint A hint about whether or not this view is displayed:
9627      * {@link #VISIBLE} or {@link #INVISIBLE}.
9628      */
9629     protected void onDisplayHint(@Visibility int hint) {
9630     }
9631 
9632     /**
9633      * Dispatch a window visibility change down the view hierarchy.
9634      * ViewGroups should override to route to their children.
9635      *
9636      * @param visibility The new visibility of the window.
9637      *
9638      * @see #onWindowVisibilityChanged(int)
9639      */
9640     public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9641         onWindowVisibilityChanged(visibility);
9642     }
9643 
9644     /**
9645      * Called when the window containing has change its visibility
9646      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9647      * that this tells you whether or not your window is being made visible
9648      * to the window manager; this does <em>not</em> tell you whether or not
9649      * your window is obscured by other windows on the screen, even if it
9650      * is itself visible.
9651      *
9652      * @param visibility The new visibility of the window.
9653      */
9654     protected void onWindowVisibilityChanged(@Visibility int visibility) {
9655         if (visibility == VISIBLE) {
9656             initialAwakenScrollBars();
9657         }
9658     }
9659 
9660     /**
9661      * Returns the current visibility of the window this view is attached to
9662      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9663      *
9664      * @return Returns the current visibility of the view's window.
9665      */
9666     @Visibility
9667     public int getWindowVisibility() {
9668         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9669     }
9670 
9671     /**
9672      * Retrieve the overall visible display size in which the window this view is
9673      * attached to has been positioned in.  This takes into account screen
9674      * decorations above the window, for both cases where the window itself
9675      * is being position inside of them or the window is being placed under
9676      * then and covered insets are used for the window to position its content
9677      * inside.  In effect, this tells you the available area where content can
9678      * be placed and remain visible to users.
9679      *
9680      * <p>This function requires an IPC back to the window manager to retrieve
9681      * the requested information, so should not be used in performance critical
9682      * code like drawing.
9683      *
9684      * @param outRect Filled in with the visible display frame.  If the view
9685      * is not attached to a window, this is simply the raw display size.
9686      */
9687     public void getWindowVisibleDisplayFrame(Rect outRect) {
9688         if (mAttachInfo != null) {
9689             try {
9690                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9691             } catch (RemoteException e) {
9692                 return;
9693             }
9694             // XXX This is really broken, and probably all needs to be done
9695             // in the window manager, and we need to know more about whether
9696             // we want the area behind or in front of the IME.
9697             final Rect insets = mAttachInfo.mVisibleInsets;
9698             outRect.left += insets.left;
9699             outRect.top += insets.top;
9700             outRect.right -= insets.right;
9701             outRect.bottom -= insets.bottom;
9702             return;
9703         }
9704         // The view is not attached to a display so we don't have a context.
9705         // Make a best guess about the display size.
9706         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9707         d.getRectSize(outRect);
9708     }
9709 
9710     /**
9711      * Dispatch a notification about a resource configuration change down
9712      * the view hierarchy.
9713      * ViewGroups should override to route to their children.
9714      *
9715      * @param newConfig The new resource configuration.
9716      *
9717      * @see #onConfigurationChanged(android.content.res.Configuration)
9718      */
9719     public void dispatchConfigurationChanged(Configuration newConfig) {
9720         onConfigurationChanged(newConfig);
9721     }
9722 
9723     /**
9724      * Called when the current configuration of the resources being used
9725      * by the application have changed.  You can use this to decide when
9726      * to reload resources that can changed based on orientation and other
9727      * configuration characteristics.  You only need to use this if you are
9728      * not relying on the normal {@link android.app.Activity} mechanism of
9729      * recreating the activity instance upon a configuration change.
9730      *
9731      * @param newConfig The new resource configuration.
9732      */
9733     protected void onConfigurationChanged(Configuration newConfig) {
9734     }
9735 
9736     /**
9737      * Private function to aggregate all per-view attributes in to the view
9738      * root.
9739      */
9740     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9741         performCollectViewAttributes(attachInfo, visibility);
9742     }
9743 
9744     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9745         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
9746             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
9747                 attachInfo.mKeepScreenOn = true;
9748             }
9749             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
9750             ListenerInfo li = mListenerInfo;
9751             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
9752                 attachInfo.mHasSystemUiListeners = true;
9753             }
9754         }
9755     }
9756 
9757     void needGlobalAttributesUpdate(boolean force) {
9758         final AttachInfo ai = mAttachInfo;
9759         if (ai != null && !ai.mRecomputeGlobalAttributes) {
9760             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
9761                     || ai.mHasSystemUiListeners) {
9762                 ai.mRecomputeGlobalAttributes = true;
9763             }
9764         }
9765     }
9766 
9767     /**
9768      * Returns whether the device is currently in touch mode.  Touch mode is entered
9769      * once the user begins interacting with the device by touch, and affects various
9770      * things like whether focus is always visible to the user.
9771      *
9772      * @return Whether the device is in touch mode.
9773      */
9774     @ViewDebug.ExportedProperty
9775     public boolean isInTouchMode() {
9776         if (mAttachInfo != null) {
9777             return mAttachInfo.mInTouchMode;
9778         } else {
9779             return ViewRootImpl.isInTouchMode();
9780         }
9781     }
9782 
9783     /**
9784      * Returns the context the view is running in, through which it can
9785      * access the current theme, resources, etc.
9786      *
9787      * @return The view's Context.
9788      */
9789     @ViewDebug.CapturedViewProperty
9790     public final Context getContext() {
9791         return mContext;
9792     }
9793 
9794     /**
9795      * Handle a key event before it is processed by any input method
9796      * associated with the view hierarchy.  This can be used to intercept
9797      * key events in special situations before the IME consumes them; a
9798      * typical example would be handling the BACK key to update the application's
9799      * UI instead of allowing the IME to see it and close itself.
9800      *
9801      * @param keyCode The value in event.getKeyCode().
9802      * @param event Description of the key event.
9803      * @return If you handled the event, return true. If you want to allow the
9804      *         event to be handled by the next receiver, return false.
9805      */
9806     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
9807         return false;
9808     }
9809 
9810     /**
9811      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
9812      * KeyEvent.Callback.onKeyDown()}: perform press of the view
9813      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
9814      * is released, if the view is enabled and clickable.
9815      *
9816      * <p>Key presses in software keyboards will generally NOT trigger this listener,
9817      * although some may elect to do so in some situations. Do not rely on this to
9818      * catch software key presses.
9819      *
9820      * @param keyCode A key code that represents the button pressed, from
9821      *                {@link android.view.KeyEvent}.
9822      * @param event   The KeyEvent object that defines the button action.
9823      */
9824     public boolean onKeyDown(int keyCode, KeyEvent event) {
9825         boolean result = false;
9826 
9827         if (KeyEvent.isConfirmKey(keyCode)) {
9828             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9829                 return true;
9830             }
9831             // Long clickable items don't necessarily have to be clickable
9832             if (((mViewFlags & CLICKABLE) == CLICKABLE ||
9833                     (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
9834                     (event.getRepeatCount() == 0)) {
9835                 setPressed(true);
9836                 checkForLongClick(0);
9837                 return true;
9838             }
9839         }
9840         return result;
9841     }
9842 
9843     /**
9844      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
9845      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
9846      * the event).
9847      * <p>Key presses in software keyboards will generally NOT trigger this listener,
9848      * although some may elect to do so in some situations. Do not rely on this to
9849      * catch software key presses.
9850      */
9851     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
9852         return false;
9853     }
9854 
9855     /**
9856      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9857      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9858      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9859      * {@link KeyEvent#KEYCODE_ENTER} is released.
9860      * <p>Key presses in software keyboards will generally NOT trigger this listener,
9861      * although some may elect to do so in some situations. Do not rely on this to
9862      * catch software key presses.
9863      *
9864      * @param keyCode A key code that represents the button pressed, from
9865      *                {@link android.view.KeyEvent}.
9866      * @param event   The KeyEvent object that defines the button action.
9867      */
9868     public boolean onKeyUp(int keyCode, KeyEvent event) {
9869         if (KeyEvent.isConfirmKey(keyCode)) {
9870             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9871                 return true;
9872             }
9873             if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9874                 setPressed(false);
9875 
9876                 if (!mHasPerformedLongPress) {
9877                     // This is a tap, so remove the longpress check
9878                     removeLongPressCallback();
9879                     return performClick();
9880                 }
9881             }
9882         }
9883         return false;
9884     }
9885 
9886     /**
9887      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
9888      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
9889      * the event).
9890      * <p>Key presses in software keyboards will generally NOT trigger this listener,
9891      * although some may elect to do so in some situations. Do not rely on this to
9892      * catch software key presses.
9893      *
9894      * @param keyCode     A key code that represents the button pressed, from
9895      *                    {@link android.view.KeyEvent}.
9896      * @param repeatCount The number of times the action was made.
9897      * @param event       The KeyEvent object that defines the button action.
9898      */
9899     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
9900         return false;
9901     }
9902 
9903     /**
9904      * Called on the focused view when a key shortcut event is not handled.
9905      * Override this method to implement local key shortcuts for the View.
9906      * Key shortcuts can also be implemented by setting the
9907      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
9908      *
9909      * @param keyCode The value in event.getKeyCode().
9910      * @param event Description of the key event.
9911      * @return If you handled the event, return true. If you want to allow the
9912      *         event to be handled by the next receiver, return false.
9913      */
9914     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
9915         return false;
9916     }
9917 
9918     /**
9919      * Check whether the called view is a text editor, in which case it
9920      * would make sense to automatically display a soft input window for
9921      * it.  Subclasses should override this if they implement
9922      * {@link #onCreateInputConnection(EditorInfo)} to return true if
9923      * a call on that method would return a non-null InputConnection, and
9924      * they are really a first-class editor that the user would normally
9925      * start typing on when the go into a window containing your view.
9926      *
9927      * <p>The default implementation always returns false.  This does
9928      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
9929      * will not be called or the user can not otherwise perform edits on your
9930      * view; it is just a hint to the system that this is not the primary
9931      * purpose of this view.
9932      *
9933      * @return Returns true if this view is a text editor, else false.
9934      */
9935     public boolean onCheckIsTextEditor() {
9936         return false;
9937     }
9938 
9939     /**
9940      * Create a new InputConnection for an InputMethod to interact
9941      * with the view.  The default implementation returns null, since it doesn't
9942      * support input methods.  You can override this to implement such support.
9943      * This is only needed for views that take focus and text input.
9944      *
9945      * <p>When implementing this, you probably also want to implement
9946      * {@link #onCheckIsTextEditor()} to indicate you will return a
9947      * non-null InputConnection.</p>
9948      *
9949      * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9950      * object correctly and in its entirety, so that the connected IME can rely
9951      * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9952      * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9953      * must be filled in with the correct cursor position for IMEs to work correctly
9954      * with your application.</p>
9955      *
9956      * @param outAttrs Fill in with attribute information about the connection.
9957      */
9958     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9959         return null;
9960     }
9961 
9962     /**
9963      * Called by the {@link android.view.inputmethod.InputMethodManager}
9964      * when a view who is not the current
9965      * input connection target is trying to make a call on the manager.  The
9966      * default implementation returns false; you can override this to return
9967      * true for certain views if you are performing InputConnection proxying
9968      * to them.
9969      * @param view The View that is making the InputMethodManager call.
9970      * @return Return true to allow the call, false to reject.
9971      */
9972     public boolean checkInputConnectionProxy(View view) {
9973         return false;
9974     }
9975 
9976     /**
9977      * Show the context menu for this view. It is not safe to hold on to the
9978      * menu after returning from this method.
9979      *
9980      * You should normally not overload this method. Overload
9981      * {@link #onCreateContextMenu(ContextMenu)} or define an
9982      * {@link OnCreateContextMenuListener} to add items to the context menu.
9983      *
9984      * @param menu The context menu to populate
9985      */
9986     public void createContextMenu(ContextMenu menu) {
9987         ContextMenuInfo menuInfo = getContextMenuInfo();
9988 
9989         // Sets the current menu info so all items added to menu will have
9990         // my extra info set.
9991         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
9992 
9993         onCreateContextMenu(menu);
9994         ListenerInfo li = mListenerInfo;
9995         if (li != null && li.mOnCreateContextMenuListener != null) {
9996             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
9997         }
9998 
9999         // Clear the extra information so subsequent items that aren't mine don't
10000         // have my extra info.
10001         ((MenuBuilder)menu).setCurrentMenuInfo(null);
10002 
10003         if (mParent != null) {
10004             mParent.createContextMenu(menu);
10005         }
10006     }
10007 
10008     /**
10009      * Views should implement this if they have extra information to associate
10010      * with the context menu. The return result is supplied as a parameter to
10011      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10012      * callback.
10013      *
10014      * @return Extra information about the item for which the context menu
10015      *         should be shown. This information will vary across different
10016      *         subclasses of View.
10017      */
10018     protected ContextMenuInfo getContextMenuInfo() {
10019         return null;
10020     }
10021 
10022     /**
10023      * Views should implement this if the view itself is going to add items to
10024      * the context menu.
10025      *
10026      * @param menu the context menu to populate
10027      */
10028     protected void onCreateContextMenu(ContextMenu menu) {
10029     }
10030 
10031     /**
10032      * Implement this method to handle trackball motion events.  The
10033      * <em>relative</em> movement of the trackball since the last event
10034      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10035      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10036      * that a movement of 1 corresponds to the user pressing one DPAD key (so
10037      * they will often be fractional values, representing the more fine-grained
10038      * movement information available from a trackball).
10039      *
10040      * @param event The motion event.
10041      * @return True if the event was handled, false otherwise.
10042      */
10043     public boolean onTrackballEvent(MotionEvent event) {
10044         return false;
10045     }
10046 
10047     /**
10048      * Implement this method to handle generic motion events.
10049      * <p>
10050      * Generic motion events describe joystick movements, mouse hovers, track pad
10051      * touches, scroll wheel movements and other input events.  The
10052      * {@link MotionEvent#getSource() source} of the motion event specifies
10053      * the class of input that was received.  Implementations of this method
10054      * must examine the bits in the source before processing the event.
10055      * The following code example shows how this is done.
10056      * </p><p>
10057      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10058      * are delivered to the view under the pointer.  All other generic motion events are
10059      * delivered to the focused view.
10060      * </p>
10061      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10062      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10063      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10064      *             // process the joystick movement...
10065      *             return true;
10066      *         }
10067      *     }
10068      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10069      *         switch (event.getAction()) {
10070      *             case MotionEvent.ACTION_HOVER_MOVE:
10071      *                 // process the mouse hover movement...
10072      *                 return true;
10073      *             case MotionEvent.ACTION_SCROLL:
10074      *                 // process the scroll wheel movement...
10075      *                 return true;
10076      *         }
10077      *     }
10078      *     return super.onGenericMotionEvent(event);
10079      * }</pre>
10080      *
10081      * @param event The generic motion event being processed.
10082      * @return True if the event was handled, false otherwise.
10083      */
10084     public boolean onGenericMotionEvent(MotionEvent event) {
10085         return false;
10086     }
10087 
10088     /**
10089      * Implement this method to handle hover events.
10090      * <p>
10091      * This method is called whenever a pointer is hovering into, over, or out of the
10092      * bounds of a view and the view is not currently being touched.
10093      * Hover events are represented as pointer events with action
10094      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10095      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10096      * </p>
10097      * <ul>
10098      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10099      * when the pointer enters the bounds of the view.</li>
10100      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10101      * when the pointer has already entered the bounds of the view and has moved.</li>
10102      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10103      * when the pointer has exited the bounds of the view or when the pointer is
10104      * about to go down due to a button click, tap, or similar user action that
10105      * causes the view to be touched.</li>
10106      * </ul>
10107      * <p>
10108      * The view should implement this method to return true to indicate that it is
10109      * handling the hover event, such as by changing its drawable state.
10110      * </p><p>
10111      * The default implementation calls {@link #setHovered} to update the hovered state
10112      * of the view when a hover enter or hover exit event is received, if the view
10113      * is enabled and is clickable.  The default implementation also sends hover
10114      * accessibility events.
10115      * </p>
10116      *
10117      * @param event The motion event that describes the hover.
10118      * @return True if the view handled the hover event.
10119      *
10120      * @see #isHovered
10121      * @see #setHovered
10122      * @see #onHoverChanged
10123      */
10124     public boolean onHoverEvent(MotionEvent event) {
10125         // The root view may receive hover (or touch) events that are outside the bounds of
10126         // the window.  This code ensures that we only send accessibility events for
10127         // hovers that are actually within the bounds of the root view.
10128         final int action = event.getActionMasked();
10129         if (!mSendingHoverAccessibilityEvents) {
10130             if ((action == MotionEvent.ACTION_HOVER_ENTER
10131                     || action == MotionEvent.ACTION_HOVER_MOVE)
10132                     && !hasHoveredChild()
10133                     && pointInView(event.getX(), event.getY())) {
10134                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10135                 mSendingHoverAccessibilityEvents = true;
10136             }
10137         } else {
10138             if (action == MotionEvent.ACTION_HOVER_EXIT
10139                     || (action == MotionEvent.ACTION_MOVE
10140                             && !pointInView(event.getX(), event.getY()))) {
10141                 mSendingHoverAccessibilityEvents = false;
10142                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10143             }
10144         }
10145 
10146         if (isHoverable()) {
10147             switch (action) {
10148                 case MotionEvent.ACTION_HOVER_ENTER:
10149                     setHovered(true);
10150                     break;
10151                 case MotionEvent.ACTION_HOVER_EXIT:
10152                     setHovered(false);
10153                     break;
10154             }
10155 
10156             // Dispatch the event to onGenericMotionEvent before returning true.
10157             // This is to provide compatibility with existing applications that
10158             // handled HOVER_MOVE events in onGenericMotionEvent and that would
10159             // break because of the new default handling for hoverable views
10160             // in onHoverEvent.
10161             // Note that onGenericMotionEvent will be called by default when
10162             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10163             dispatchGenericMotionEventInternal(event);
10164             // The event was already handled by calling setHovered(), so always
10165             // return true.
10166             return true;
10167         }
10168 
10169         return false;
10170     }
10171 
10172     /**
10173      * Returns true if the view should handle {@link #onHoverEvent}
10174      * by calling {@link #setHovered} to change its hovered state.
10175      *
10176      * @return True if the view is hoverable.
10177      */
10178     private boolean isHoverable() {
10179         final int viewFlags = mViewFlags;
10180         if ((viewFlags & ENABLED_MASK) == DISABLED) {
10181             return false;
10182         }
10183 
10184         return (viewFlags & CLICKABLE) == CLICKABLE
10185                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10186                 || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10187     }
10188 
10189     /**
10190      * Returns true if the view is currently hovered.
10191      *
10192      * @return True if the view is currently hovered.
10193      *
10194      * @see #setHovered
10195      * @see #onHoverChanged
10196      */
10197     @ViewDebug.ExportedProperty
10198     public boolean isHovered() {
10199         return (mPrivateFlags & PFLAG_HOVERED) != 0;
10200     }
10201 
10202     /**
10203      * Sets whether the view is currently hovered.
10204      * <p>
10205      * Calling this method also changes the drawable state of the view.  This
10206      * enables the view to react to hover by using different drawable resources
10207      * to change its appearance.
10208      * </p><p>
10209      * The {@link #onHoverChanged} method is called when the hovered state changes.
10210      * </p>
10211      *
10212      * @param hovered True if the view is hovered.
10213      *
10214      * @see #isHovered
10215      * @see #onHoverChanged
10216      */
10217     public void setHovered(boolean hovered) {
10218         if (hovered) {
10219             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10220                 mPrivateFlags |= PFLAG_HOVERED;
10221                 refreshDrawableState();
10222                 onHoverChanged(true);
10223             }
10224         } else {
10225             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10226                 mPrivateFlags &= ~PFLAG_HOVERED;
10227                 refreshDrawableState();
10228                 onHoverChanged(false);
10229             }
10230         }
10231     }
10232 
10233     /**
10234      * Implement this method to handle hover state changes.
10235      * <p>
10236      * This method is called whenever the hover state changes as a result of a
10237      * call to {@link #setHovered}.
10238      * </p>
10239      *
10240      * @param hovered The current hover state, as returned by {@link #isHovered}.
10241      *
10242      * @see #isHovered
10243      * @see #setHovered
10244      */
10245     public void onHoverChanged(boolean hovered) {
10246     }
10247 
10248     /**
10249      * Implement this method to handle touch screen motion events.
10250      * <p>
10251      * If this method is used to detect click actions, it is recommended that
10252      * the actions be performed by implementing and calling
10253      * {@link #performClick()}. This will ensure consistent system behavior,
10254      * including:
10255      * <ul>
10256      * <li>obeying click sound preferences
10257      * <li>dispatching OnClickListener calls
10258      * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
10259      * accessibility features are enabled
10260      * </ul>
10261      *
10262      * @param event The motion event.
10263      * @return True if the event was handled, false otherwise.
10264      */
10265     public boolean onTouchEvent(MotionEvent event) {
10266         final float x = event.getX();
10267         final float y = event.getY();
10268         final int viewFlags = mViewFlags;
10269         final int action = event.getAction();
10270 
10271         if ((viewFlags & ENABLED_MASK) == DISABLED) {
10272             if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
10273                 setPressed(false);
10274             }
10275             // A disabled view that is clickable still consumes the touch
10276             // events, it just doesn't respond to them.
10277             return (((viewFlags & CLICKABLE) == CLICKABLE
10278                     || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10279                     || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
10280         }
10281 
10282         if (mTouchDelegate != null) {
10283             if (mTouchDelegate.onTouchEvent(event)) {
10284                 return true;
10285             }
10286         }
10287 
10288         if (((viewFlags & CLICKABLE) == CLICKABLE ||
10289                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
10290                 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
10291             switch (action) {
10292                 case MotionEvent.ACTION_UP:
10293                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
10294                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
10295                         // take focus if we don't have it already and we should in
10296                         // touch mode.
10297                         boolean focusTaken = false;
10298                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
10299                             focusTaken = requestFocus();
10300                         }
10301 
10302                         if (prepressed) {
10303                             // The button is being released before we actually
10304                             // showed it as pressed.  Make it show the pressed
10305                             // state now (before scheduling the click) to ensure
10306                             // the user sees it.
10307                             setPressed(true, x, y);
10308                        }
10309 
10310                         if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
10311                             // This is a tap, so remove the longpress check
10312                             removeLongPressCallback();
10313 
10314                             // Only perform take click actions if we were in the pressed state
10315                             if (!focusTaken) {
10316                                 // Use a Runnable and post this rather than calling
10317                                 // performClick directly. This lets other visual state
10318                                 // of the view update before click actions start.
10319                                 if (mPerformClick == null) {
10320                                     mPerformClick = new PerformClick();
10321                                 }
10322                                 if (!post(mPerformClick)) {
10323                                     performClick();
10324                                 }
10325                             }
10326                         }
10327 
10328                         if (mUnsetPressedState == null) {
10329                             mUnsetPressedState = new UnsetPressedState();
10330                         }
10331 
10332                         if (prepressed) {
10333                             postDelayed(mUnsetPressedState,
10334                                     ViewConfiguration.getPressedStateDuration());
10335                         } else if (!post(mUnsetPressedState)) {
10336                             // If the post failed, unpress right now
10337                             mUnsetPressedState.run();
10338                         }
10339 
10340                         removeTapCallback();
10341                     }
10342                     mIgnoreNextUpEvent = false;
10343                     break;
10344 
10345                 case MotionEvent.ACTION_DOWN:
10346                     mHasPerformedLongPress = false;
10347 
10348                     if (performButtonActionOnTouchDown(event)) {
10349                         break;
10350                     }
10351 
10352                     // Walk up the hierarchy to determine if we're inside a scrolling container.
10353                     boolean isInScrollingContainer = isInScrollingContainer();
10354 
10355                     // For views inside a scrolling container, delay the pressed feedback for
10356                     // a short period in case this is a scroll.
10357                     if (isInScrollingContainer) {
10358                         mPrivateFlags |= PFLAG_PREPRESSED;
10359                         if (mPendingCheckForTap == null) {
10360                             mPendingCheckForTap = new CheckForTap();
10361                         }
10362                         mPendingCheckForTap.x = event.getX();
10363                         mPendingCheckForTap.y = event.getY();
10364                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
10365                     } else {
10366                         // Not inside a scrolling container, so show the feedback right away
10367                         setPressed(true, x, y);
10368                         checkForLongClick(0);
10369                     }
10370                     break;
10371 
10372                 case MotionEvent.ACTION_CANCEL:
10373                     setPressed(false);
10374                     removeTapCallback();
10375                     removeLongPressCallback();
10376                     mInContextButtonPress = false;
10377                     mHasPerformedLongPress = false;
10378                     mIgnoreNextUpEvent = false;
10379                     break;
10380 
10381                 case MotionEvent.ACTION_MOVE:
10382                     drawableHotspotChanged(x, y);
10383 
10384                     // Be lenient about moving outside of buttons
10385                     if (!pointInView(x, y, mTouchSlop)) {
10386                         // Outside button
10387                         removeTapCallback();
10388                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
10389                             // Remove any future long press/tap checks
10390                             removeLongPressCallback();
10391 
10392                             setPressed(false);
10393                         }
10394                     }
10395                     break;
10396             }
10397 
10398             return true;
10399         }
10400 
10401         return false;
10402     }
10403 
10404     /**
10405      * @hide
10406      */
10407     public boolean isInScrollingContainer() {
10408         ViewParent p = getParent();
10409         while (p != null && p instanceof ViewGroup) {
10410             if (((ViewGroup) p).shouldDelayChildPressedState()) {
10411                 return true;
10412             }
10413             p = p.getParent();
10414         }
10415         return false;
10416     }
10417 
10418     /**
10419      * Remove the longpress detection timer.
10420      */
10421     private void removeLongPressCallback() {
10422         if (mPendingCheckForLongPress != null) {
10423           removeCallbacks(mPendingCheckForLongPress);
10424         }
10425     }
10426 
10427     /**
10428      * Remove the pending click action
10429      */
10430     private void removePerformClickCallback() {
10431         if (mPerformClick != null) {
10432             removeCallbacks(mPerformClick);
10433         }
10434     }
10435 
10436     /**
10437      * Remove the prepress detection timer.
10438      */
10439     private void removeUnsetPressCallback() {
10440         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
10441             setPressed(false);
10442             removeCallbacks(mUnsetPressedState);
10443         }
10444     }
10445 
10446     /**
10447      * Remove the tap detection timer.
10448      */
10449     private void removeTapCallback() {
10450         if (mPendingCheckForTap != null) {
10451             mPrivateFlags &= ~PFLAG_PREPRESSED;
10452             removeCallbacks(mPendingCheckForTap);
10453         }
10454     }
10455 
10456     /**
10457      * Cancels a pending long press.  Your subclass can use this if you
10458      * want the context menu to come up if the user presses and holds
10459      * at the same place, but you don't want it to come up if they press
10460      * and then move around enough to cause scrolling.
10461      */
10462     public void cancelLongPress() {
10463         removeLongPressCallback();
10464 
10465         /*
10466          * The prepressed state handled by the tap callback is a display
10467          * construct, but the tap callback will post a long press callback
10468          * less its own timeout. Remove it here.
10469          */
10470         removeTapCallback();
10471     }
10472 
10473     /**
10474      * Remove the pending callback for sending a
10475      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
10476      */
10477     private void removeSendViewScrolledAccessibilityEventCallback() {
10478         if (mSendViewScrolledAccessibilityEvent != null) {
10479             removeCallbacks(mSendViewScrolledAccessibilityEvent);
10480             mSendViewScrolledAccessibilityEvent.mIsPending = false;
10481         }
10482     }
10483 
10484     /**
10485      * Sets the TouchDelegate for this View.
10486      */
10487     public void setTouchDelegate(TouchDelegate delegate) {
10488         mTouchDelegate = delegate;
10489     }
10490 
10491     /**
10492      * Gets the TouchDelegate for this View.
10493      */
10494     public TouchDelegate getTouchDelegate() {
10495         return mTouchDelegate;
10496     }
10497 
10498     /**
10499      * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10500      *
10501      * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10502      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10503      * available. This method should only be called for touch events.
10504      *
10505      * <p class="note">This api is not intended for most applications. Buffered dispatch
10506      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10507      * streams will not improve your input latency. Side effects include: increased latency,
10508      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10509      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10510      * you.</p>
10511      */
10512     public final void requestUnbufferedDispatch(MotionEvent event) {
10513         final int action = event.getAction();
10514         if (mAttachInfo == null
10515                 || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10516                 || !event.isTouchEvent()) {
10517             return;
10518         }
10519         mAttachInfo.mUnbufferedDispatchRequested = true;
10520     }
10521 
10522     /**
10523      * Set flags controlling behavior of this view.
10524      *
10525      * @param flags Constant indicating the value which should be set
10526      * @param mask Constant indicating the bit range that should be changed
10527      */
10528     void setFlags(int flags, int mask) {
10529         final boolean accessibilityEnabled =
10530                 AccessibilityManager.getInstance(mContext).isEnabled();
10531         final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10532 
10533         int old = mViewFlags;
10534         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10535 
10536         int changed = mViewFlags ^ old;
10537         if (changed == 0) {
10538             return;
10539         }
10540         int privateFlags = mPrivateFlags;
10541 
10542         /* Check if the FOCUSABLE bit has changed */
10543         if (((changed & FOCUSABLE_MASK) != 0) &&
10544                 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10545             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10546                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10547                 /* Give up focus if we are no longer focusable */
10548                 clearFocus();
10549             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10550                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10551                 /*
10552                  * Tell the view system that we are now available to take focus
10553                  * if no one else already has it.
10554                  */
10555                 if (mParent != null) mParent.focusableViewAvailable(this);
10556             }
10557         }
10558 
10559         final int newVisibility = flags & VISIBILITY_MASK;
10560         if (newVisibility == VISIBLE) {
10561             if ((changed & VISIBILITY_MASK) != 0) {
10562                 /*
10563                  * If this view is becoming visible, invalidate it in case it changed while
10564                  * it was not visible. Marking it drawn ensures that the invalidation will
10565                  * go through.
10566                  */
10567                 mPrivateFlags |= PFLAG_DRAWN;
10568                 invalidate(true);
10569 
10570                 needGlobalAttributesUpdate(true);
10571 
10572                 // a view becoming visible is worth notifying the parent
10573                 // about in case nothing has focus.  even if this specific view
10574                 // isn't focusable, it may contain something that is, so let
10575                 // the root view try to give this focus if nothing else does.
10576                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10577                     mParent.focusableViewAvailable(this);
10578                 }
10579             }
10580         }
10581 
10582         /* Check if the GONE bit has changed */
10583         if ((changed & GONE) != 0) {
10584             needGlobalAttributesUpdate(false);
10585             requestLayout();
10586 
10587             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10588                 if (hasFocus()) clearFocus();
10589                 clearAccessibilityFocus();
10590                 destroyDrawingCache();
10591                 if (mParent instanceof View) {
10592                     // GONE views noop invalidation, so invalidate the parent
10593                     ((View) mParent).invalidate(true);
10594                 }
10595                 // Mark the view drawn to ensure that it gets invalidated properly the next
10596                 // time it is visible and gets invalidated
10597                 mPrivateFlags |= PFLAG_DRAWN;
10598             }
10599             if (mAttachInfo != null) {
10600                 mAttachInfo.mViewVisibilityChanged = true;
10601             }
10602         }
10603 
10604         /* Check if the VISIBLE bit has changed */
10605         if ((changed & INVISIBLE) != 0) {
10606             needGlobalAttributesUpdate(false);
10607             /*
10608              * If this view is becoming invisible, set the DRAWN flag so that
10609              * the next invalidate() will not be skipped.
10610              */
10611             mPrivateFlags |= PFLAG_DRAWN;
10612 
10613             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10614                 // root view becoming invisible shouldn't clear focus and accessibility focus
10615                 if (getRootView() != this) {
10616                     if (hasFocus()) clearFocus();
10617                     clearAccessibilityFocus();
10618                 }
10619             }
10620             if (mAttachInfo != null) {
10621                 mAttachInfo.mViewVisibilityChanged = true;
10622             }
10623         }
10624 
10625         if ((changed & VISIBILITY_MASK) != 0) {
10626             // If the view is invisible, cleanup its display list to free up resources
10627             if (newVisibility != VISIBLE && mAttachInfo != null) {
10628                 cleanupDraw();
10629             }
10630 
10631             if (mParent instanceof ViewGroup) {
10632                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
10633                         (changed & VISIBILITY_MASK), newVisibility);
10634                 ((View) mParent).invalidate(true);
10635             } else if (mParent != null) {
10636                 mParent.invalidateChild(this, null);
10637             }
10638 
10639             if (mAttachInfo != null) {
10640                 dispatchVisibilityChanged(this, newVisibility);
10641                 notifySubtreeAccessibilityStateChangedIfNeeded();
10642             }
10643         }
10644 
10645         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10646             destroyDrawingCache();
10647         }
10648 
10649         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10650             destroyDrawingCache();
10651             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10652             invalidateParentCaches();
10653         }
10654 
10655         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10656             destroyDrawingCache();
10657             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10658         }
10659 
10660         if ((changed & DRAW_MASK) != 0) {
10661             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10662                 if (mBackground != null
10663                         || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
10664                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10665                 } else {
10666                     mPrivateFlags |= PFLAG_SKIP_DRAW;
10667                 }
10668             } else {
10669                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10670             }
10671             requestLayout();
10672             invalidate(true);
10673         }
10674 
10675         if ((changed & KEEP_SCREEN_ON) != 0) {
10676             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10677                 mParent.recomputeViewAttributes(this);
10678             }
10679         }
10680 
10681         if (accessibilityEnabled) {
10682             if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10683                     || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
10684                     || (changed & CONTEXT_CLICKABLE) != 0) {
10685                 if (oldIncludeForAccessibility != includeForAccessibility()) {
10686                     notifySubtreeAccessibilityStateChangedIfNeeded();
10687                 } else {
10688                     notifyViewAccessibilityStateChangedIfNeeded(
10689                             AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10690                 }
10691             } else if ((changed & ENABLED_MASK) != 0) {
10692                 notifyViewAccessibilityStateChangedIfNeeded(
10693                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10694             }
10695         }
10696     }
10697 
10698     /**
10699      * Change the view's z order in the tree, so it's on top of other sibling
10700      * views. This ordering change may affect layout, if the parent container
10701      * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10702      * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10703      * method should be followed by calls to {@link #requestLayout()} and
10704      * {@link View#invalidate()} on the view's parent to force the parent to redraw
10705      * with the new child ordering.
10706      *
10707      * @see ViewGroup#bringChildToFront(View)
10708      */
10709     public void bringToFront() {
10710         if (mParent != null) {
10711             mParent.bringChildToFront(this);
10712         }
10713     }
10714 
10715     /**
10716      * This is called in response to an internal scroll in this view (i.e., the
10717      * view scrolled its own contents). This is typically as a result of
10718      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10719      * called.
10720      *
10721      * @param l Current horizontal scroll origin.
10722      * @param t Current vertical scroll origin.
10723      * @param oldl Previous horizontal scroll origin.
10724      * @param oldt Previous vertical scroll origin.
10725      */
10726     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10727         notifySubtreeAccessibilityStateChangedIfNeeded();
10728 
10729         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10730             postSendViewScrolledAccessibilityEventCallback();
10731         }
10732 
10733         mBackgroundSizeChanged = true;
10734         if (mForegroundInfo != null) {
10735             mForegroundInfo.mBoundsChanged = true;
10736         }
10737 
10738         final AttachInfo ai = mAttachInfo;
10739         if (ai != null) {
10740             ai.mViewScrollChanged = true;
10741         }
10742 
10743         if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
10744             mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
10745         }
10746     }
10747 
10748     /**
10749      * Interface definition for a callback to be invoked when the scroll
10750      * X or Y positions of a view change.
10751      * <p>
10752      * <b>Note:</b> Some views handle scrolling independently from View and may
10753      * have their own separate listeners for scroll-type events. For example,
10754      * {@link android.widget.ListView ListView} allows clients to register an
10755      * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
10756      * to listen for changes in list scroll position.
10757      *
10758      * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
10759      */
10760     public interface OnScrollChangeListener {
10761         /**
10762          * Called when the scroll position of a view changes.
10763          *
10764          * @param v The view whose scroll position has changed.
10765          * @param scrollX Current horizontal scroll origin.
10766          * @param scrollY Current vertical scroll origin.
10767          * @param oldScrollX Previous horizontal scroll origin.
10768          * @param oldScrollY Previous vertical scroll origin.
10769          */
10770         void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
10771     }
10772 
10773     /**
10774      * Interface definition for a callback to be invoked when the layout bounds of a view
10775      * changes due to layout processing.
10776      */
10777     public interface OnLayoutChangeListener {
10778         /**
10779          * Called when the layout bounds of a view changes due to layout processing.
10780          *
10781          * @param v The view whose bounds have changed.
10782          * @param left The new value of the view's left property.
10783          * @param top The new value of the view's top property.
10784          * @param right The new value of the view's right property.
10785          * @param bottom The new value of the view's bottom property.
10786          * @param oldLeft The previous value of the view's left property.
10787          * @param oldTop The previous value of the view's top property.
10788          * @param oldRight The previous value of the view's right property.
10789          * @param oldBottom The previous value of the view's bottom property.
10790          */
10791         void onLayoutChange(View v, int left, int top, int right, int bottom,
10792             int oldLeft, int oldTop, int oldRight, int oldBottom);
10793     }
10794 
10795     /**
10796      * This is called during layout when the size of this view has changed. If
10797      * you were just added to the view hierarchy, you're called with the old
10798      * values of 0.
10799      *
10800      * @param w Current width of this view.
10801      * @param h Current height of this view.
10802      * @param oldw Old width of this view.
10803      * @param oldh Old height of this view.
10804      */
10805     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
10806     }
10807 
10808     /**
10809      * Called by draw to draw the child views. This may be overridden
10810      * by derived classes to gain control just before its children are drawn
10811      * (but after its own view has been drawn).
10812      * @param canvas the canvas on which to draw the view
10813      */
10814     protected void dispatchDraw(Canvas canvas) {
10815 
10816     }
10817 
10818     /**
10819      * Gets the parent of this view. Note that the parent is a
10820      * ViewParent and not necessarily a View.
10821      *
10822      * @return Parent of this view.
10823      */
10824     public final ViewParent getParent() {
10825         return mParent;
10826     }
10827 
10828     /**
10829      * Set the horizontal scrolled position of your view. This will cause a call to
10830      * {@link #onScrollChanged(int, int, int, int)} and the view will be
10831      * invalidated.
10832      * @param value the x position to scroll to
10833      */
10834     public void setScrollX(int value) {
10835         scrollTo(value, mScrollY);
10836     }
10837 
10838     /**
10839      * Set the vertical scrolled position of your view. This will cause a call to
10840      * {@link #onScrollChanged(int, int, int, int)} and the view will be
10841      * invalidated.
10842      * @param value the y position to scroll to
10843      */
10844     public void setScrollY(int value) {
10845         scrollTo(mScrollX, value);
10846     }
10847 
10848     /**
10849      * Return the scrolled left position of this view. This is the left edge of
10850      * the displayed part of your view. You do not need to draw any pixels
10851      * farther left, since those are outside of the frame of your view on
10852      * screen.
10853      *
10854      * @return The left edge of the displayed part of your view, in pixels.
10855      */
10856     public final int getScrollX() {
10857         return mScrollX;
10858     }
10859 
10860     /**
10861      * Return the scrolled top position of this view. This is the top edge of
10862      * the displayed part of your view. You do not need to draw any pixels above
10863      * it, since those are outside of the frame of your view on screen.
10864      *
10865      * @return The top edge of the displayed part of your view, in pixels.
10866      */
10867     public final int getScrollY() {
10868         return mScrollY;
10869     }
10870 
10871     /**
10872      * Return the width of the your view.
10873      *
10874      * @return The width of your view, in pixels.
10875      */
10876     @ViewDebug.ExportedProperty(category = "layout")
10877     public final int getWidth() {
10878         return mRight - mLeft;
10879     }
10880 
10881     /**
10882      * Return the height of your view.
10883      *
10884      * @return The height of your view, in pixels.
10885      */
10886     @ViewDebug.ExportedProperty(category = "layout")
10887     public final int getHeight() {
10888         return mBottom - mTop;
10889     }
10890 
10891     /**
10892      * Return the visible drawing bounds of your view. Fills in the output
10893      * rectangle with the values from getScrollX(), getScrollY(),
10894      * getWidth(), and getHeight(). These bounds do not account for any
10895      * transformation properties currently set on the view, such as
10896      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
10897      *
10898      * @param outRect The (scrolled) drawing bounds of the view.
10899      */
10900     public void getDrawingRect(Rect outRect) {
10901         outRect.left = mScrollX;
10902         outRect.top = mScrollY;
10903         outRect.right = mScrollX + (mRight - mLeft);
10904         outRect.bottom = mScrollY + (mBottom - mTop);
10905     }
10906 
10907     /**
10908      * Like {@link #getMeasuredWidthAndState()}, but only returns the
10909      * raw width component (that is the result is masked by
10910      * {@link #MEASURED_SIZE_MASK}).
10911      *
10912      * @return The raw measured width of this view.
10913      */
10914     public final int getMeasuredWidth() {
10915         return mMeasuredWidth & MEASURED_SIZE_MASK;
10916     }
10917 
10918     /**
10919      * Return the full width measurement information for this view as computed
10920      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10921      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10922      * This should be used during measurement and layout calculations only. Use
10923      * {@link #getWidth()} to see how wide a view is after layout.
10924      *
10925      * @return The measured width of this view as a bit mask.
10926      */
10927     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10928             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10929                     name = "MEASURED_STATE_TOO_SMALL"),
10930     })
10931     public final int getMeasuredWidthAndState() {
10932         return mMeasuredWidth;
10933     }
10934 
10935     /**
10936      * Like {@link #getMeasuredHeightAndState()}, but only returns the
10937      * raw width component (that is the result is masked by
10938      * {@link #MEASURED_SIZE_MASK}).
10939      *
10940      * @return The raw measured height of this view.
10941      */
10942     public final int getMeasuredHeight() {
10943         return mMeasuredHeight & MEASURED_SIZE_MASK;
10944     }
10945 
10946     /**
10947      * Return the full height measurement information for this view as computed
10948      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10949      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10950      * This should be used during measurement and layout calculations only. Use
10951      * {@link #getHeight()} to see how wide a view is after layout.
10952      *
10953      * @return The measured width of this view as a bit mask.
10954      */
10955     @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10956             @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10957                     name = "MEASURED_STATE_TOO_SMALL"),
10958     })
10959     public final int getMeasuredHeightAndState() {
10960         return mMeasuredHeight;
10961     }
10962 
10963     /**
10964      * Return only the state bits of {@link #getMeasuredWidthAndState()}
10965      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
10966      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
10967      * and the height component is at the shifted bits
10968      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
10969      */
10970     public final int getMeasuredState() {
10971         return (mMeasuredWidth&MEASURED_STATE_MASK)
10972                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
10973                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
10974     }
10975 
10976     /**
10977      * The transform matrix of this view, which is calculated based on the current
10978      * rotation, scale, and pivot properties.
10979      *
10980      * @see #getRotation()
10981      * @see #getScaleX()
10982      * @see #getScaleY()
10983      * @see #getPivotX()
10984      * @see #getPivotY()
10985      * @return The current transform matrix for the view
10986      */
10987     public Matrix getMatrix() {
10988         ensureTransformationInfo();
10989         final Matrix matrix = mTransformationInfo.mMatrix;
10990         mRenderNode.getMatrix(matrix);
10991         return matrix;
10992     }
10993 
10994     /**
10995      * Returns true if the transform matrix is the identity matrix.
10996      * Recomputes the matrix if necessary.
10997      *
10998      * @return True if the transform matrix is the identity matrix, false otherwise.
10999      */
11000     final boolean hasIdentityMatrix() {
11001         return mRenderNode.hasIdentityMatrix();
11002     }
11003 
11004     void ensureTransformationInfo() {
11005         if (mTransformationInfo == null) {
11006             mTransformationInfo = new TransformationInfo();
11007         }
11008     }
11009 
11010    /**
11011      * Utility method to retrieve the inverse of the current mMatrix property.
11012      * We cache the matrix to avoid recalculating it when transform properties
11013      * have not changed.
11014      *
11015      * @return The inverse of the current matrix of this view.
11016      * @hide
11017      */
11018     public final Matrix getInverseMatrix() {
11019         ensureTransformationInfo();
11020         if (mTransformationInfo.mInverseMatrix == null) {
11021             mTransformationInfo.mInverseMatrix = new Matrix();
11022         }
11023         final Matrix matrix = mTransformationInfo.mInverseMatrix;
11024         mRenderNode.getInverseMatrix(matrix);
11025         return matrix;
11026     }
11027 
11028     /**
11029      * Gets the distance along the Z axis from the camera to this view.
11030      *
11031      * @see #setCameraDistance(float)
11032      *
11033      * @return The distance along the Z axis.
11034      */
11035     public float getCameraDistance() {
11036         final float dpi = mResources.getDisplayMetrics().densityDpi;
11037         return -(mRenderNode.getCameraDistance() * dpi);
11038     }
11039 
11040     /**
11041      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11042      * views are drawn) from the camera to this view. The camera's distance
11043      * affects 3D transformations, for instance rotations around the X and Y
11044      * axis. If the rotationX or rotationY properties are changed and this view is
11045      * large (more than half the size of the screen), it is recommended to always
11046      * use a camera distance that's greater than the height (X axis rotation) or
11047      * the width (Y axis rotation) of this view.</p>
11048      *
11049      * <p>The distance of the camera from the view plane can have an affect on the
11050      * perspective distortion of the view when it is rotated around the x or y axis.
11051      * For example, a large distance will result in a large viewing angle, and there
11052      * will not be much perspective distortion of the view as it rotates. A short
11053      * distance may cause much more perspective distortion upon rotation, and can
11054      * also result in some drawing artifacts if the rotated view ends up partially
11055      * behind the camera (which is why the recommendation is to use a distance at
11056      * least as far as the size of the view, if the view is to be rotated.)</p>
11057      *
11058      * <p>The distance is expressed in "depth pixels." The default distance depends
11059      * on the screen density. For instance, on a medium density display, the
11060      * default distance is 1280. On a high density display, the default distance
11061      * is 1920.</p>
11062      *
11063      * <p>If you want to specify a distance that leads to visually consistent
11064      * results across various densities, use the following formula:</p>
11065      * <pre>
11066      * float scale = context.getResources().getDisplayMetrics().density;
11067      * view.setCameraDistance(distance * scale);
11068      * </pre>
11069      *
11070      * <p>The density scale factor of a high density display is 1.5,
11071      * and 1920 = 1280 * 1.5.</p>
11072      *
11073      * @param distance The distance in "depth pixels", if negative the opposite
11074      *        value is used
11075      *
11076      * @see #setRotationX(float)
11077      * @see #setRotationY(float)
11078      */
11079     public void setCameraDistance(float distance) {
11080         final float dpi = mResources.getDisplayMetrics().densityDpi;
11081 
11082         invalidateViewProperty(true, false);
11083         mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11084         invalidateViewProperty(false, false);
11085 
11086         invalidateParentIfNeededAndWasQuickRejected();
11087     }
11088 
11089     /**
11090      * The degrees that the view is rotated around the pivot point.
11091      *
11092      * @see #setRotation(float)
11093      * @see #getPivotX()
11094      * @see #getPivotY()
11095      *
11096      * @return The degrees of rotation.
11097      */
11098     @ViewDebug.ExportedProperty(category = "drawing")
11099     public float getRotation() {
11100         return mRenderNode.getRotation();
11101     }
11102 
11103     /**
11104      * Sets the degrees that the view is rotated around the pivot point. Increasing values
11105      * result in clockwise rotation.
11106      *
11107      * @param rotation The degrees of rotation.
11108      *
11109      * @see #getRotation()
11110      * @see #getPivotX()
11111      * @see #getPivotY()
11112      * @see #setRotationX(float)
11113      * @see #setRotationY(float)
11114      *
11115      * @attr ref android.R.styleable#View_rotation
11116      */
11117     public void setRotation(float rotation) {
11118         if (rotation != getRotation()) {
11119             // Double-invalidation is necessary to capture view's old and new areas
11120             invalidateViewProperty(true, false);
11121             mRenderNode.setRotation(rotation);
11122             invalidateViewProperty(false, true);
11123 
11124             invalidateParentIfNeededAndWasQuickRejected();
11125             notifySubtreeAccessibilityStateChangedIfNeeded();
11126         }
11127     }
11128 
11129     /**
11130      * The degrees that the view is rotated around the vertical axis through the pivot point.
11131      *
11132      * @see #getPivotX()
11133      * @see #getPivotY()
11134      * @see #setRotationY(float)
11135      *
11136      * @return The degrees of Y rotation.
11137      */
11138     @ViewDebug.ExportedProperty(category = "drawing")
11139     public float getRotationY() {
11140         return mRenderNode.getRotationY();
11141     }
11142 
11143     /**
11144      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
11145      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
11146      * down the y axis.
11147      *
11148      * When rotating large views, it is recommended to adjust the camera distance
11149      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11150      *
11151      * @param rotationY The degrees of Y rotation.
11152      *
11153      * @see #getRotationY()
11154      * @see #getPivotX()
11155      * @see #getPivotY()
11156      * @see #setRotation(float)
11157      * @see #setRotationX(float)
11158      * @see #setCameraDistance(float)
11159      *
11160      * @attr ref android.R.styleable#View_rotationY
11161      */
11162     public void setRotationY(float rotationY) {
11163         if (rotationY != getRotationY()) {
11164             invalidateViewProperty(true, false);
11165             mRenderNode.setRotationY(rotationY);
11166             invalidateViewProperty(false, true);
11167 
11168             invalidateParentIfNeededAndWasQuickRejected();
11169             notifySubtreeAccessibilityStateChangedIfNeeded();
11170         }
11171     }
11172 
11173     /**
11174      * The degrees that the view is rotated around the horizontal axis through the pivot point.
11175      *
11176      * @see #getPivotX()
11177      * @see #getPivotY()
11178      * @see #setRotationX(float)
11179      *
11180      * @return The degrees of X rotation.
11181      */
11182     @ViewDebug.ExportedProperty(category = "drawing")
11183     public float getRotationX() {
11184         return mRenderNode.getRotationX();
11185     }
11186 
11187     /**
11188      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
11189      * Increasing values result in clockwise rotation from the viewpoint of looking down the
11190      * x axis.
11191      *
11192      * When rotating large views, it is recommended to adjust the camera distance
11193      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11194      *
11195      * @param rotationX The degrees of X rotation.
11196      *
11197      * @see #getRotationX()
11198      * @see #getPivotX()
11199      * @see #getPivotY()
11200      * @see #setRotation(float)
11201      * @see #setRotationY(float)
11202      * @see #setCameraDistance(float)
11203      *
11204      * @attr ref android.R.styleable#View_rotationX
11205      */
11206     public void setRotationX(float rotationX) {
11207         if (rotationX != getRotationX()) {
11208             invalidateViewProperty(true, false);
11209             mRenderNode.setRotationX(rotationX);
11210             invalidateViewProperty(false, true);
11211 
11212             invalidateParentIfNeededAndWasQuickRejected();
11213             notifySubtreeAccessibilityStateChangedIfNeeded();
11214         }
11215     }
11216 
11217     /**
11218      * The amount that the view is scaled in x around the pivot point, as a proportion of
11219      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
11220      *
11221      * <p>By default, this is 1.0f.
11222      *
11223      * @see #getPivotX()
11224      * @see #getPivotY()
11225      * @return The scaling factor.
11226      */
11227     @ViewDebug.ExportedProperty(category = "drawing")
11228     public float getScaleX() {
11229         return mRenderNode.getScaleX();
11230     }
11231 
11232     /**
11233      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
11234      * the view's unscaled width. A value of 1 means that no scaling is applied.
11235      *
11236      * @param scaleX The scaling factor.
11237      * @see #getPivotX()
11238      * @see #getPivotY()
11239      *
11240      * @attr ref android.R.styleable#View_scaleX
11241      */
11242     public void setScaleX(float scaleX) {
11243         if (scaleX != getScaleX()) {
11244             invalidateViewProperty(true, false);
11245             mRenderNode.setScaleX(scaleX);
11246             invalidateViewProperty(false, true);
11247 
11248             invalidateParentIfNeededAndWasQuickRejected();
11249             notifySubtreeAccessibilityStateChangedIfNeeded();
11250         }
11251     }
11252 
11253     /**
11254      * The amount that the view is scaled in y around the pivot point, as a proportion of
11255      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
11256      *
11257      * <p>By default, this is 1.0f.
11258      *
11259      * @see #getPivotX()
11260      * @see #getPivotY()
11261      * @return The scaling factor.
11262      */
11263     @ViewDebug.ExportedProperty(category = "drawing")
11264     public float getScaleY() {
11265         return mRenderNode.getScaleY();
11266     }
11267 
11268     /**
11269      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
11270      * the view's unscaled width. A value of 1 means that no scaling is applied.
11271      *
11272      * @param scaleY The scaling factor.
11273      * @see #getPivotX()
11274      * @see #getPivotY()
11275      *
11276      * @attr ref android.R.styleable#View_scaleY
11277      */
11278     public void setScaleY(float scaleY) {
11279         if (scaleY != getScaleY()) {
11280             invalidateViewProperty(true, false);
11281             mRenderNode.setScaleY(scaleY);
11282             invalidateViewProperty(false, true);
11283 
11284             invalidateParentIfNeededAndWasQuickRejected();
11285             notifySubtreeAccessibilityStateChangedIfNeeded();
11286         }
11287     }
11288 
11289     /**
11290      * The x location of the point around which the view is {@link #setRotation(float) rotated}
11291      * and {@link #setScaleX(float) scaled}.
11292      *
11293      * @see #getRotation()
11294      * @see #getScaleX()
11295      * @see #getScaleY()
11296      * @see #getPivotY()
11297      * @return The x location of the pivot point.
11298      *
11299      * @attr ref android.R.styleable#View_transformPivotX
11300      */
11301     @ViewDebug.ExportedProperty(category = "drawing")
11302     public float getPivotX() {
11303         return mRenderNode.getPivotX();
11304     }
11305 
11306     /**
11307      * Sets the x location of the point around which the view is
11308      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
11309      * By default, the pivot point is centered on the object.
11310      * Setting this property disables this behavior and causes the view to use only the
11311      * explicitly set pivotX and pivotY values.
11312      *
11313      * @param pivotX The x location of the pivot point.
11314      * @see #getRotation()
11315      * @see #getScaleX()
11316      * @see #getScaleY()
11317      * @see #getPivotY()
11318      *
11319      * @attr ref android.R.styleable#View_transformPivotX
11320      */
11321     public void setPivotX(float pivotX) {
11322         if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
11323             invalidateViewProperty(true, false);
11324             mRenderNode.setPivotX(pivotX);
11325             invalidateViewProperty(false, true);
11326 
11327             invalidateParentIfNeededAndWasQuickRejected();
11328         }
11329     }
11330 
11331     /**
11332      * The y location of the point around which the view is {@link #setRotation(float) rotated}
11333      * and {@link #setScaleY(float) scaled}.
11334      *
11335      * @see #getRotation()
11336      * @see #getScaleX()
11337      * @see #getScaleY()
11338      * @see #getPivotY()
11339      * @return The y location of the pivot point.
11340      *
11341      * @attr ref android.R.styleable#View_transformPivotY
11342      */
11343     @ViewDebug.ExportedProperty(category = "drawing")
11344     public float getPivotY() {
11345         return mRenderNode.getPivotY();
11346     }
11347 
11348     /**
11349      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
11350      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
11351      * Setting this property disables this behavior and causes the view to use only the
11352      * explicitly set pivotX and pivotY values.
11353      *
11354      * @param pivotY The y location of the pivot point.
11355      * @see #getRotation()
11356      * @see #getScaleX()
11357      * @see #getScaleY()
11358      * @see #getPivotY()
11359      *
11360      * @attr ref android.R.styleable#View_transformPivotY
11361      */
11362     public void setPivotY(float pivotY) {
11363         if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
11364             invalidateViewProperty(true, false);
11365             mRenderNode.setPivotY(pivotY);
11366             invalidateViewProperty(false, true);
11367 
11368             invalidateParentIfNeededAndWasQuickRejected();
11369         }
11370     }
11371 
11372     /**
11373      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
11374      * completely transparent and 1 means the view is completely opaque.
11375      *
11376      * <p>By default this is 1.0f.
11377      * @return The opacity of the view.
11378      */
11379     @ViewDebug.ExportedProperty(category = "drawing")
11380     public float getAlpha() {
11381         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
11382     }
11383 
11384     /**
11385      * Returns whether this View has content which overlaps.
11386      *
11387      * <p>This function, intended to be overridden by specific View types, is an optimization when
11388      * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
11389      * an offscreen buffer and then composited into place, which can be expensive. If the view has
11390      * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
11391      * directly. An example of overlapping rendering is a TextView with a background image, such as
11392      * a Button. An example of non-overlapping rendering is a TextView with no background, or an
11393      * ImageView with only the foreground image. The default implementation returns true; subclasses
11394      * should override if they have cases which can be optimized.</p>
11395      *
11396      * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
11397      * necessitates that a View return true if it uses the methods internally without passing the
11398      * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
11399      *
11400      * @return true if the content in this view might overlap, false otherwise.
11401      */
11402     @ViewDebug.ExportedProperty(category = "drawing")
11403     public boolean hasOverlappingRendering() {
11404         return true;
11405     }
11406 
11407     /**
11408      * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
11409      * completely transparent and 1 means the view is completely opaque.
11410      *
11411      * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
11412      * can have significant performance implications, especially for large views. It is best to use
11413      * the alpha property sparingly and transiently, as in the case of fading animations.</p>
11414      *
11415      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
11416      * strongly recommended for performance reasons to either override
11417      * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
11418      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
11419      * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
11420      * the default path for rendering an unlayered View with alpha could add multiple milliseconds
11421      * of rendering cost, even for simple or small views. Starting with
11422      * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
11423      * applied to the view at the rendering level.</p>
11424      *
11425      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
11426      * responsible for applying the opacity itself.</p>
11427      *
11428      * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
11429      * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
11430      * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
11431      * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
11432      *
11433      * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
11434      * value will clip a View to its bounds, unless the View returns <code>false</code> from
11435      * {@link #hasOverlappingRendering}.</p>
11436      *
11437      * @param alpha The opacity of the view.
11438      *
11439      * @see #hasOverlappingRendering()
11440      * @see #setLayerType(int, android.graphics.Paint)
11441      *
11442      * @attr ref android.R.styleable#View_alpha
11443      */
11444     public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
11445         ensureTransformationInfo();
11446         if (mTransformationInfo.mAlpha != alpha) {
11447             mTransformationInfo.mAlpha = alpha;
11448             if (onSetAlpha((int) (alpha * 255))) {
11449                 mPrivateFlags |= PFLAG_ALPHA_SET;
11450                 // subclass is handling alpha - don't optimize rendering cache invalidation
11451                 invalidateParentCaches();
11452                 invalidate(true);
11453             } else {
11454                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
11455                 invalidateViewProperty(true, false);
11456                 mRenderNode.setAlpha(getFinalAlpha());
11457                 notifyViewAccessibilityStateChangedIfNeeded(
11458                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11459             }
11460         }
11461     }
11462 
11463     /**
11464      * Faster version of setAlpha() which performs the same steps except there are
11465      * no calls to invalidate(). The caller of this function should perform proper invalidation
11466      * on the parent and this object. The return value indicates whether the subclass handles
11467      * alpha (the return value for onSetAlpha()).
11468      *
11469      * @param alpha The new value for the alpha property
11470      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
11471      *         the new value for the alpha property is different from the old value
11472      */
11473     boolean setAlphaNoInvalidation(float alpha) {
11474         ensureTransformationInfo();
11475         if (mTransformationInfo.mAlpha != alpha) {
11476             mTransformationInfo.mAlpha = alpha;
11477             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
11478             if (subclassHandlesAlpha) {
11479                 mPrivateFlags |= PFLAG_ALPHA_SET;
11480                 return true;
11481             } else {
11482                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
11483                 mRenderNode.setAlpha(getFinalAlpha());
11484             }
11485         }
11486         return false;
11487     }
11488 
11489     /**
11490      * This property is hidden and intended only for use by the Fade transition, which
11491      * animates it to produce a visual translucency that does not side-effect (or get
11492      * affected by) the real alpha property. This value is composited with the other
11493      * alpha value (and the AlphaAnimation value, when that is present) to produce
11494      * a final visual translucency result, which is what is passed into the DisplayList.
11495      *
11496      * @hide
11497      */
11498     public void setTransitionAlpha(float alpha) {
11499         ensureTransformationInfo();
11500         if (mTransformationInfo.mTransitionAlpha != alpha) {
11501             mTransformationInfo.mTransitionAlpha = alpha;
11502             mPrivateFlags &= ~PFLAG_ALPHA_SET;
11503             invalidateViewProperty(true, false);
11504             mRenderNode.setAlpha(getFinalAlpha());
11505         }
11506     }
11507 
11508     /**
11509      * Calculates the visual alpha of this view, which is a combination of the actual
11510      * alpha value and the transitionAlpha value (if set).
11511      */
11512     private float getFinalAlpha() {
11513         if (mTransformationInfo != null) {
11514             return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11515         }
11516         return 1;
11517     }
11518 
11519     /**
11520      * This property is hidden and intended only for use by the Fade transition, which
11521      * animates it to produce a visual translucency that does not side-effect (or get
11522      * affected by) the real alpha property. This value is composited with the other
11523      * alpha value (and the AlphaAnimation value, when that is present) to produce
11524      * a final visual translucency result, which is what is passed into the DisplayList.
11525      *
11526      * @hide
11527      */
11528     @ViewDebug.ExportedProperty(category = "drawing")
11529     public float getTransitionAlpha() {
11530         return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11531     }
11532 
11533     /**
11534      * Top position of this view relative to its parent.
11535      *
11536      * @return The top of this view, in pixels.
11537      */
11538     @ViewDebug.CapturedViewProperty
11539     public final int getTop() {
11540         return mTop;
11541     }
11542 
11543     /**
11544      * Sets the top position of this view relative to its parent. This method is meant to be called
11545      * by the layout system and should not generally be called otherwise, because the property
11546      * may be changed at any time by the layout.
11547      *
11548      * @param top The top of this view, in pixels.
11549      */
11550     public final void setTop(int top) {
11551         if (top != mTop) {
11552             final boolean matrixIsIdentity = hasIdentityMatrix();
11553             if (matrixIsIdentity) {
11554                 if (mAttachInfo != null) {
11555                     int minTop;
11556                     int yLoc;
11557                     if (top < mTop) {
11558                         minTop = top;
11559                         yLoc = top - mTop;
11560                     } else {
11561                         minTop = mTop;
11562                         yLoc = 0;
11563                     }
11564                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11565                 }
11566             } else {
11567                 // Double-invalidation is necessary to capture view's old and new areas
11568                 invalidate(true);
11569             }
11570 
11571             int width = mRight - mLeft;
11572             int oldHeight = mBottom - mTop;
11573 
11574             mTop = top;
11575             mRenderNode.setTop(mTop);
11576 
11577             sizeChange(width, mBottom - mTop, width, oldHeight);
11578 
11579             if (!matrixIsIdentity) {
11580                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11581                 invalidate(true);
11582             }
11583             mBackgroundSizeChanged = true;
11584             if (mForegroundInfo != null) {
11585                 mForegroundInfo.mBoundsChanged = true;
11586             }
11587             invalidateParentIfNeeded();
11588             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11589                 // View was rejected last time it was drawn by its parent; this may have changed
11590                 invalidateParentIfNeeded();
11591             }
11592         }
11593     }
11594 
11595     /**
11596      * Bottom position of this view relative to its parent.
11597      *
11598      * @return The bottom of this view, in pixels.
11599      */
11600     @ViewDebug.CapturedViewProperty
11601     public final int getBottom() {
11602         return mBottom;
11603     }
11604 
11605     /**
11606      * True if this view has changed since the last time being drawn.
11607      *
11608      * @return The dirty state of this view.
11609      */
11610     public boolean isDirty() {
11611         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11612     }
11613 
11614     /**
11615      * Sets the bottom position of this view relative to its parent. This method is meant to be
11616      * called by the layout system and should not generally be called otherwise, because the
11617      * property may be changed at any time by the layout.
11618      *
11619      * @param bottom The bottom of this view, in pixels.
11620      */
11621     public final void setBottom(int bottom) {
11622         if (bottom != mBottom) {
11623             final boolean matrixIsIdentity = hasIdentityMatrix();
11624             if (matrixIsIdentity) {
11625                 if (mAttachInfo != null) {
11626                     int maxBottom;
11627                     if (bottom < mBottom) {
11628                         maxBottom = mBottom;
11629                     } else {
11630                         maxBottom = bottom;
11631                     }
11632                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11633                 }
11634             } else {
11635                 // Double-invalidation is necessary to capture view's old and new areas
11636                 invalidate(true);
11637             }
11638 
11639             int width = mRight - mLeft;
11640             int oldHeight = mBottom - mTop;
11641 
11642             mBottom = bottom;
11643             mRenderNode.setBottom(mBottom);
11644 
11645             sizeChange(width, mBottom - mTop, width, oldHeight);
11646 
11647             if (!matrixIsIdentity) {
11648                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11649                 invalidate(true);
11650             }
11651             mBackgroundSizeChanged = true;
11652             if (mForegroundInfo != null) {
11653                 mForegroundInfo.mBoundsChanged = true;
11654             }
11655             invalidateParentIfNeeded();
11656             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11657                 // View was rejected last time it was drawn by its parent; this may have changed
11658                 invalidateParentIfNeeded();
11659             }
11660         }
11661     }
11662 
11663     /**
11664      * Left position of this view relative to its parent.
11665      *
11666      * @return The left edge of this view, in pixels.
11667      */
11668     @ViewDebug.CapturedViewProperty
11669     public final int getLeft() {
11670         return mLeft;
11671     }
11672 
11673     /**
11674      * Sets the left position of this view relative to its parent. This method is meant to be called
11675      * by the layout system and should not generally be called otherwise, because the property
11676      * may be changed at any time by the layout.
11677      *
11678      * @param left The left of this view, in pixels.
11679      */
11680     public final void setLeft(int left) {
11681         if (left != mLeft) {
11682             final boolean matrixIsIdentity = hasIdentityMatrix();
11683             if (matrixIsIdentity) {
11684                 if (mAttachInfo != null) {
11685                     int minLeft;
11686                     int xLoc;
11687                     if (left < mLeft) {
11688                         minLeft = left;
11689                         xLoc = left - mLeft;
11690                     } else {
11691                         minLeft = mLeft;
11692                         xLoc = 0;
11693                     }
11694                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11695                 }
11696             } else {
11697                 // Double-invalidation is necessary to capture view's old and new areas
11698                 invalidate(true);
11699             }
11700 
11701             int oldWidth = mRight - mLeft;
11702             int height = mBottom - mTop;
11703 
11704             mLeft = left;
11705             mRenderNode.setLeft(left);
11706 
11707             sizeChange(mRight - mLeft, height, oldWidth, height);
11708 
11709             if (!matrixIsIdentity) {
11710                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11711                 invalidate(true);
11712             }
11713             mBackgroundSizeChanged = true;
11714             if (mForegroundInfo != null) {
11715                 mForegroundInfo.mBoundsChanged = true;
11716             }
11717             invalidateParentIfNeeded();
11718             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11719                 // View was rejected last time it was drawn by its parent; this may have changed
11720                 invalidateParentIfNeeded();
11721             }
11722         }
11723     }
11724 
11725     /**
11726      * Right position of this view relative to its parent.
11727      *
11728      * @return The right edge of this view, in pixels.
11729      */
11730     @ViewDebug.CapturedViewProperty
11731     public final int getRight() {
11732         return mRight;
11733     }
11734 
11735     /**
11736      * Sets the right position of this view relative to its parent. This method is meant to be called
11737      * by the layout system and should not generally be called otherwise, because the property
11738      * may be changed at any time by the layout.
11739      *
11740      * @param right The right of this view, in pixels.
11741      */
11742     public final void setRight(int right) {
11743         if (right != mRight) {
11744             final boolean matrixIsIdentity = hasIdentityMatrix();
11745             if (matrixIsIdentity) {
11746                 if (mAttachInfo != null) {
11747                     int maxRight;
11748                     if (right < mRight) {
11749                         maxRight = mRight;
11750                     } else {
11751                         maxRight = right;
11752                     }
11753                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
11754                 }
11755             } else {
11756                 // Double-invalidation is necessary to capture view's old and new areas
11757                 invalidate(true);
11758             }
11759 
11760             int oldWidth = mRight - mLeft;
11761             int height = mBottom - mTop;
11762 
11763             mRight = right;
11764             mRenderNode.setRight(mRight);
11765 
11766             sizeChange(mRight - mLeft, height, oldWidth, height);
11767 
11768             if (!matrixIsIdentity) {
11769                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11770                 invalidate(true);
11771             }
11772             mBackgroundSizeChanged = true;
11773             if (mForegroundInfo != null) {
11774                 mForegroundInfo.mBoundsChanged = true;
11775             }
11776             invalidateParentIfNeeded();
11777             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11778                 // View was rejected last time it was drawn by its parent; this may have changed
11779                 invalidateParentIfNeeded();
11780             }
11781         }
11782     }
11783 
11784     /**
11785      * The visual x position of this view, in pixels. This is equivalent to the
11786      * {@link #setTranslationX(float) translationX} property plus the current
11787      * {@link #getLeft() left} property.
11788      *
11789      * @return The visual x position of this view, in pixels.
11790      */
11791     @ViewDebug.ExportedProperty(category = "drawing")
11792     public float getX() {
11793         return mLeft + getTranslationX();
11794     }
11795 
11796     /**
11797      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
11798      * {@link #setTranslationX(float) translationX} property to be the difference between
11799      * the x value passed in and the current {@link #getLeft() left} property.
11800      *
11801      * @param x The visual x position of this view, in pixels.
11802      */
11803     public void setX(float x) {
11804         setTranslationX(x - mLeft);
11805     }
11806 
11807     /**
11808      * The visual y position of this view, in pixels. This is equivalent to the
11809      * {@link #setTranslationY(float) translationY} property plus the current
11810      * {@link #getTop() top} property.
11811      *
11812      * @return The visual y position of this view, in pixels.
11813      */
11814     @ViewDebug.ExportedProperty(category = "drawing")
11815     public float getY() {
11816         return mTop + getTranslationY();
11817     }
11818 
11819     /**
11820      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
11821      * {@link #setTranslationY(float) translationY} property to be the difference between
11822      * the y value passed in and the current {@link #getTop() top} property.
11823      *
11824      * @param y The visual y position of this view, in pixels.
11825      */
11826     public void setY(float y) {
11827         setTranslationY(y - mTop);
11828     }
11829 
11830     /**
11831      * The visual z position of this view, in pixels. This is equivalent to the
11832      * {@link #setTranslationZ(float) translationZ} property plus the current
11833      * {@link #getElevation() elevation} property.
11834      *
11835      * @return The visual z position of this view, in pixels.
11836      */
11837     @ViewDebug.ExportedProperty(category = "drawing")
11838     public float getZ() {
11839         return getElevation() + getTranslationZ();
11840     }
11841 
11842     /**
11843      * Sets the visual z position of this view, in pixels. This is equivalent to setting the
11844      * {@link #setTranslationZ(float) translationZ} property to be the difference between
11845      * the x value passed in and the current {@link #getElevation() elevation} property.
11846      *
11847      * @param z The visual z position of this view, in pixels.
11848      */
11849     public void setZ(float z) {
11850         setTranslationZ(z - getElevation());
11851     }
11852 
11853     /**
11854      * The base elevation of this view relative to its parent, in pixels.
11855      *
11856      * @return The base depth position of the view, in pixels.
11857      */
11858     @ViewDebug.ExportedProperty(category = "drawing")
11859     public float getElevation() {
11860         return mRenderNode.getElevation();
11861     }
11862 
11863     /**
11864      * Sets the base elevation of this view, in pixels.
11865      *
11866      * @attr ref android.R.styleable#View_elevation
11867      */
11868     public void setElevation(float elevation) {
11869         if (elevation != getElevation()) {
11870             invalidateViewProperty(true, false);
11871             mRenderNode.setElevation(elevation);
11872             invalidateViewProperty(false, true);
11873 
11874             invalidateParentIfNeededAndWasQuickRejected();
11875         }
11876     }
11877 
11878     /**
11879      * The horizontal location of this view relative to its {@link #getLeft() left} position.
11880      * This position is post-layout, in addition to wherever the object's
11881      * layout placed it.
11882      *
11883      * @return The horizontal position of this view relative to its left position, in pixels.
11884      */
11885     @ViewDebug.ExportedProperty(category = "drawing")
11886     public float getTranslationX() {
11887         return mRenderNode.getTranslationX();
11888     }
11889 
11890     /**
11891      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
11892      * This effectively positions the object post-layout, in addition to wherever the object's
11893      * layout placed it.
11894      *
11895      * @param translationX The horizontal position of this view relative to its left position,
11896      * in pixels.
11897      *
11898      * @attr ref android.R.styleable#View_translationX
11899      */
11900     public void setTranslationX(float translationX) {
11901         if (translationX != getTranslationX()) {
11902             invalidateViewProperty(true, false);
11903             mRenderNode.setTranslationX(translationX);
11904             invalidateViewProperty(false, true);
11905 
11906             invalidateParentIfNeededAndWasQuickRejected();
11907             notifySubtreeAccessibilityStateChangedIfNeeded();
11908         }
11909     }
11910 
11911     /**
11912      * The vertical location of this view relative to its {@link #getTop() top} position.
11913      * This position is post-layout, in addition to wherever the object's
11914      * layout placed it.
11915      *
11916      * @return The vertical position of this view relative to its top position,
11917      * in pixels.
11918      */
11919     @ViewDebug.ExportedProperty(category = "drawing")
11920     public float getTranslationY() {
11921         return mRenderNode.getTranslationY();
11922     }
11923 
11924     /**
11925      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
11926      * This effectively positions the object post-layout, in addition to wherever the object's
11927      * layout placed it.
11928      *
11929      * @param translationY The vertical position of this view relative to its top position,
11930      * in pixels.
11931      *
11932      * @attr ref android.R.styleable#View_translationY
11933      */
11934     public void setTranslationY(float translationY) {
11935         if (translationY != getTranslationY()) {
11936             invalidateViewProperty(true, false);
11937             mRenderNode.setTranslationY(translationY);
11938             invalidateViewProperty(false, true);
11939 
11940             invalidateParentIfNeededAndWasQuickRejected();
11941             notifySubtreeAccessibilityStateChangedIfNeeded();
11942         }
11943     }
11944 
11945     /**
11946      * The depth location of this view relative to its {@link #getElevation() elevation}.
11947      *
11948      * @return The depth of this view relative to its elevation.
11949      */
11950     @ViewDebug.ExportedProperty(category = "drawing")
11951     public float getTranslationZ() {
11952         return mRenderNode.getTranslationZ();
11953     }
11954 
11955     /**
11956      * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
11957      *
11958      * @attr ref android.R.styleable#View_translationZ
11959      */
11960     public void setTranslationZ(float translationZ) {
11961         if (translationZ != getTranslationZ()) {
11962             invalidateViewProperty(true, false);
11963             mRenderNode.setTranslationZ(translationZ);
11964             invalidateViewProperty(false, true);
11965 
11966             invalidateParentIfNeededAndWasQuickRejected();
11967         }
11968     }
11969 
11970     /** @hide */
11971     public void setAnimationMatrix(Matrix matrix) {
11972         invalidateViewProperty(true, false);
11973         mRenderNode.setAnimationMatrix(matrix);
11974         invalidateViewProperty(false, true);
11975 
11976         invalidateParentIfNeededAndWasQuickRejected();
11977     }
11978 
11979     /**
11980      * Returns the current StateListAnimator if exists.
11981      *
11982      * @return StateListAnimator or null if it does not exists
11983      * @see    #setStateListAnimator(android.animation.StateListAnimator)
11984      */
11985     public StateListAnimator getStateListAnimator() {
11986         return mStateListAnimator;
11987     }
11988 
11989     /**
11990      * Attaches the provided StateListAnimator to this View.
11991      * <p>
11992      * Any previously attached StateListAnimator will be detached.
11993      *
11994      * @param stateListAnimator The StateListAnimator to update the view
11995      * @see {@link android.animation.StateListAnimator}
11996      */
11997     public void setStateListAnimator(StateListAnimator stateListAnimator) {
11998         if (mStateListAnimator == stateListAnimator) {
11999             return;
12000         }
12001         if (mStateListAnimator != null) {
12002             mStateListAnimator.setTarget(null);
12003         }
12004         mStateListAnimator = stateListAnimator;
12005         if (stateListAnimator != null) {
12006             stateListAnimator.setTarget(this);
12007             if (isAttachedToWindow()) {
12008                 stateListAnimator.setState(getDrawableState());
12009             }
12010         }
12011     }
12012 
12013     /**
12014      * Returns whether the Outline should be used to clip the contents of the View.
12015      * <p>
12016      * Note that this flag will only be respected if the View's Outline returns true from
12017      * {@link Outline#canClip()}.
12018      *
12019      * @see #setOutlineProvider(ViewOutlineProvider)
12020      * @see #setClipToOutline(boolean)
12021      */
12022     public final boolean getClipToOutline() {
12023         return mRenderNode.getClipToOutline();
12024     }
12025 
12026     /**
12027      * Sets whether the View's Outline should be used to clip the contents of the View.
12028      * <p>
12029      * Only a single non-rectangular clip can be applied on a View at any time.
12030      * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12031      * circular reveal} animation take priority over Outline clipping, and
12032      * child Outline clipping takes priority over Outline clipping done by a
12033      * parent.
12034      * <p>
12035      * Note that this flag will only be respected if the View's Outline returns true from
12036      * {@link Outline#canClip()}.
12037      *
12038      * @see #setOutlineProvider(ViewOutlineProvider)
12039      * @see #getClipToOutline()
12040      */
12041     public void setClipToOutline(boolean clipToOutline) {
12042         damageInParent();
12043         if (getClipToOutline() != clipToOutline) {
12044             mRenderNode.setClipToOutline(clipToOutline);
12045         }
12046     }
12047 
12048     // correspond to the enum values of View_outlineProvider
12049     private static final int PROVIDER_BACKGROUND = 0;
12050     private static final int PROVIDER_NONE = 1;
12051     private static final int PROVIDER_BOUNDS = 2;
12052     private static final int PROVIDER_PADDED_BOUNDS = 3;
12053     private void setOutlineProviderFromAttribute(int providerInt) {
12054         switch (providerInt) {
12055             case PROVIDER_BACKGROUND:
12056                 setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12057                 break;
12058             case PROVIDER_NONE:
12059                 setOutlineProvider(null);
12060                 break;
12061             case PROVIDER_BOUNDS:
12062                 setOutlineProvider(ViewOutlineProvider.BOUNDS);
12063                 break;
12064             case PROVIDER_PADDED_BOUNDS:
12065                 setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12066                 break;
12067         }
12068     }
12069 
12070     /**
12071      * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12072      * the shape of the shadow it casts, and enables outline clipping.
12073      * <p>
12074      * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12075      * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12076      * outline provider with this method allows this behavior to be overridden.
12077      * <p>
12078      * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12079      * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12080      * <p>
12081      * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12082      *
12083      * @see #setClipToOutline(boolean)
12084      * @see #getClipToOutline()
12085      * @see #getOutlineProvider()
12086      */
12087     public void setOutlineProvider(ViewOutlineProvider provider) {
12088         mOutlineProvider = provider;
12089         invalidateOutline();
12090     }
12091 
12092     /**
12093      * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
12094      * that defines the shape of the shadow it casts, and enables outline clipping.
12095      *
12096      * @see #setOutlineProvider(ViewOutlineProvider)
12097      */
12098     public ViewOutlineProvider getOutlineProvider() {
12099         return mOutlineProvider;
12100     }
12101 
12102     /**
12103      * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
12104      *
12105      * @see #setOutlineProvider(ViewOutlineProvider)
12106      */
12107     public void invalidateOutline() {
12108         rebuildOutline();
12109 
12110         notifySubtreeAccessibilityStateChangedIfNeeded();
12111         invalidateViewProperty(false, false);
12112     }
12113 
12114     /**
12115      * Internal version of {@link #invalidateOutline()} which invalidates the
12116      * outline without invalidating the view itself. This is intended to be called from
12117      * within methods in the View class itself which are the result of the view being
12118      * invalidated already. For example, when we are drawing the background of a View,
12119      * we invalidate the outline in case it changed in the meantime, but we do not
12120      * need to invalidate the view because we're already drawing the background as part
12121      * of drawing the view in response to an earlier invalidation of the view.
12122      */
12123     private void rebuildOutline() {
12124         // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
12125         if (mAttachInfo == null) return;
12126 
12127         if (mOutlineProvider == null) {
12128             // no provider, remove outline
12129             mRenderNode.setOutline(null);
12130         } else {
12131             final Outline outline = mAttachInfo.mTmpOutline;
12132             outline.setEmpty();
12133             outline.setAlpha(1.0f);
12134 
12135             mOutlineProvider.getOutline(this, outline);
12136             mRenderNode.setOutline(outline);
12137         }
12138     }
12139 
12140     /**
12141      * HierarchyViewer only
12142      *
12143      * @hide
12144      */
12145     @ViewDebug.ExportedProperty(category = "drawing")
12146     public boolean hasShadow() {
12147         return mRenderNode.hasShadow();
12148     }
12149 
12150 
12151     /** @hide */
12152     public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
12153         mRenderNode.setRevealClip(shouldClip, x, y, radius);
12154         invalidateViewProperty(false, false);
12155     }
12156 
12157     /**
12158      * Hit rectangle in parent's coordinates
12159      *
12160      * @param outRect The hit rectangle of the view.
12161      */
12162     public void getHitRect(Rect outRect) {
12163         if (hasIdentityMatrix() || mAttachInfo == null) {
12164             outRect.set(mLeft, mTop, mRight, mBottom);
12165         } else {
12166             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
12167             tmpRect.set(0, 0, getWidth(), getHeight());
12168             getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
12169             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
12170                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
12171         }
12172     }
12173 
12174     /**
12175      * Determines whether the given point, in local coordinates is inside the view.
12176      */
12177     /*package*/ final boolean pointInView(float localX, float localY) {
12178         return localX >= 0 && localX < (mRight - mLeft)
12179                 && localY >= 0 && localY < (mBottom - mTop);
12180     }
12181 
12182     /**
12183      * Utility method to determine whether the given point, in local coordinates,
12184      * is inside the view, where the area of the view is expanded by the slop factor.
12185      * This method is called while processing touch-move events to determine if the event
12186      * is still within the view.
12187      *
12188      * @hide
12189      */
12190     public boolean pointInView(float localX, float localY, float slop) {
12191         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
12192                 localY < ((mBottom - mTop) + slop);
12193     }
12194 
12195     /**
12196      * When a view has focus and the user navigates away from it, the next view is searched for
12197      * starting from the rectangle filled in by this method.
12198      *
12199      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
12200      * of the view.  However, if your view maintains some idea of internal selection,
12201      * such as a cursor, or a selected row or column, you should override this method and
12202      * fill in a more specific rectangle.
12203      *
12204      * @param r The rectangle to fill in, in this view's coordinates.
12205      */
12206     public void getFocusedRect(Rect r) {
12207         getDrawingRect(r);
12208     }
12209 
12210     /**
12211      * If some part of this view is not clipped by any of its parents, then
12212      * return that area in r in global (root) coordinates. To convert r to local
12213      * coordinates (without taking possible View rotations into account), offset
12214      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
12215      * If the view is completely clipped or translated out, return false.
12216      *
12217      * @param r If true is returned, r holds the global coordinates of the
12218      *        visible portion of this view.
12219      * @param globalOffset If true is returned, globalOffset holds the dx,dy
12220      *        between this view and its root. globalOffet may be null.
12221      * @return true if r is non-empty (i.e. part of the view is visible at the
12222      *         root level.
12223      */
12224     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
12225         int width = mRight - mLeft;
12226         int height = mBottom - mTop;
12227         if (width > 0 && height > 0) {
12228             r.set(0, 0, width, height);
12229             if (globalOffset != null) {
12230                 globalOffset.set(-mScrollX, -mScrollY);
12231             }
12232             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
12233         }
12234         return false;
12235     }
12236 
12237     public final boolean getGlobalVisibleRect(Rect r) {
12238         return getGlobalVisibleRect(r, null);
12239     }
12240 
12241     public final boolean getLocalVisibleRect(Rect r) {
12242         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
12243         if (getGlobalVisibleRect(r, offset)) {
12244             r.offset(-offset.x, -offset.y); // make r local
12245             return true;
12246         }
12247         return false;
12248     }
12249 
12250     /**
12251      * Offset this view's vertical location by the specified number of pixels.
12252      *
12253      * @param offset the number of pixels to offset the view by
12254      */
12255     public void offsetTopAndBottom(int offset) {
12256         if (offset != 0) {
12257             final boolean matrixIsIdentity = hasIdentityMatrix();
12258             if (matrixIsIdentity) {
12259                 if (isHardwareAccelerated()) {
12260                     invalidateViewProperty(false, false);
12261                 } else {
12262                     final ViewParent p = mParent;
12263                     if (p != null && mAttachInfo != null) {
12264                         final Rect r = mAttachInfo.mTmpInvalRect;
12265                         int minTop;
12266                         int maxBottom;
12267                         int yLoc;
12268                         if (offset < 0) {
12269                             minTop = mTop + offset;
12270                             maxBottom = mBottom;
12271                             yLoc = offset;
12272                         } else {
12273                             minTop = mTop;
12274                             maxBottom = mBottom + offset;
12275                             yLoc = 0;
12276                         }
12277                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
12278                         p.invalidateChild(this, r);
12279                     }
12280                 }
12281             } else {
12282                 invalidateViewProperty(false, false);
12283             }
12284 
12285             mTop += offset;
12286             mBottom += offset;
12287             mRenderNode.offsetTopAndBottom(offset);
12288             if (isHardwareAccelerated()) {
12289                 invalidateViewProperty(false, false);
12290                 invalidateParentIfNeededAndWasQuickRejected();
12291             } else {
12292                 if (!matrixIsIdentity) {
12293                     invalidateViewProperty(false, true);
12294                 }
12295                 invalidateParentIfNeeded();
12296             }
12297             notifySubtreeAccessibilityStateChangedIfNeeded();
12298         }
12299     }
12300 
12301     /**
12302      * Offset this view's horizontal location by the specified amount of pixels.
12303      *
12304      * @param offset the number of pixels to offset the view by
12305      */
12306     public void offsetLeftAndRight(int offset) {
12307         if (offset != 0) {
12308             final boolean matrixIsIdentity = hasIdentityMatrix();
12309             if (matrixIsIdentity) {
12310                 if (isHardwareAccelerated()) {
12311                     invalidateViewProperty(false, false);
12312                 } else {
12313                     final ViewParent p = mParent;
12314                     if (p != null && mAttachInfo != null) {
12315                         final Rect r = mAttachInfo.mTmpInvalRect;
12316                         int minLeft;
12317                         int maxRight;
12318                         if (offset < 0) {
12319                             minLeft = mLeft + offset;
12320                             maxRight = mRight;
12321                         } else {
12322                             minLeft = mLeft;
12323                             maxRight = mRight + offset;
12324                         }
12325                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
12326                         p.invalidateChild(this, r);
12327                     }
12328                 }
12329             } else {
12330                 invalidateViewProperty(false, false);
12331             }
12332 
12333             mLeft += offset;
12334             mRight += offset;
12335             mRenderNode.offsetLeftAndRight(offset);
12336             if (isHardwareAccelerated()) {
12337                 invalidateViewProperty(false, false);
12338                 invalidateParentIfNeededAndWasQuickRejected();
12339             } else {
12340                 if (!matrixIsIdentity) {
12341                     invalidateViewProperty(false, true);
12342                 }
12343                 invalidateParentIfNeeded();
12344             }
12345             notifySubtreeAccessibilityStateChangedIfNeeded();
12346         }
12347     }
12348 
12349     /**
12350      * Get the LayoutParams associated with this view. All views should have
12351      * layout parameters. These supply parameters to the <i>parent</i> of this
12352      * view specifying how it should be arranged. There are many subclasses of
12353      * ViewGroup.LayoutParams, and these correspond to the different subclasses
12354      * of ViewGroup that are responsible for arranging their children.
12355      *
12356      * This method may return null if this View is not attached to a parent
12357      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
12358      * was not invoked successfully. When a View is attached to a parent
12359      * ViewGroup, this method must not return null.
12360      *
12361      * @return The LayoutParams associated with this view, or null if no
12362      *         parameters have been set yet
12363      */
12364     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
12365     public ViewGroup.LayoutParams getLayoutParams() {
12366         return mLayoutParams;
12367     }
12368 
12369     /**
12370      * Set the layout parameters associated with this view. These supply
12371      * parameters to the <i>parent</i> of this view specifying how it should be
12372      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
12373      * correspond to the different subclasses of ViewGroup that are responsible
12374      * for arranging their children.
12375      *
12376      * @param params The layout parameters for this view, cannot be null
12377      */
12378     public void setLayoutParams(ViewGroup.LayoutParams params) {
12379         if (params == null) {
12380             throw new NullPointerException("Layout parameters cannot be null");
12381         }
12382         mLayoutParams = params;
12383         resolveLayoutParams();
12384         if (mParent instanceof ViewGroup) {
12385             ((ViewGroup) mParent).onSetLayoutParams(this, params);
12386         }
12387         requestLayout();
12388     }
12389 
12390     /**
12391      * Resolve the layout parameters depending on the resolved layout direction
12392      *
12393      * @hide
12394      */
12395     public void resolveLayoutParams() {
12396         if (mLayoutParams != null) {
12397             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
12398         }
12399     }
12400 
12401     /**
12402      * Set the scrolled position of your view. This will cause a call to
12403      * {@link #onScrollChanged(int, int, int, int)} and the view will be
12404      * invalidated.
12405      * @param x the x position to scroll to
12406      * @param y the y position to scroll to
12407      */
12408     public void scrollTo(int x, int y) {
12409         if (mScrollX != x || mScrollY != y) {
12410             int oldX = mScrollX;
12411             int oldY = mScrollY;
12412             mScrollX = x;
12413             mScrollY = y;
12414             invalidateParentCaches();
12415             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
12416             if (!awakenScrollBars()) {
12417                 postInvalidateOnAnimation();
12418             }
12419         }
12420     }
12421 
12422     /**
12423      * Move the scrolled position of your view. This will cause a call to
12424      * {@link #onScrollChanged(int, int, int, int)} and the view will be
12425      * invalidated.
12426      * @param x the amount of pixels to scroll by horizontally
12427      * @param y the amount of pixels to scroll by vertically
12428      */
12429     public void scrollBy(int x, int y) {
12430         scrollTo(mScrollX + x, mScrollY + y);
12431     }
12432 
12433     /**
12434      * <p>Trigger the scrollbars to draw. When invoked this method starts an
12435      * animation to fade the scrollbars out after a default delay. If a subclass
12436      * provides animated scrolling, the start delay should equal the duration
12437      * of the scrolling animation.</p>
12438      *
12439      * <p>The animation starts only if at least one of the scrollbars is
12440      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
12441      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12442      * this method returns true, and false otherwise. If the animation is
12443      * started, this method calls {@link #invalidate()}; in that case the
12444      * caller should not call {@link #invalidate()}.</p>
12445      *
12446      * <p>This method should be invoked every time a subclass directly updates
12447      * the scroll parameters.</p>
12448      *
12449      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
12450      * and {@link #scrollTo(int, int)}.</p>
12451      *
12452      * @return true if the animation is played, false otherwise
12453      *
12454      * @see #awakenScrollBars(int)
12455      * @see #scrollBy(int, int)
12456      * @see #scrollTo(int, int)
12457      * @see #isHorizontalScrollBarEnabled()
12458      * @see #isVerticalScrollBarEnabled()
12459      * @see #setHorizontalScrollBarEnabled(boolean)
12460      * @see #setVerticalScrollBarEnabled(boolean)
12461      */
12462     protected boolean awakenScrollBars() {
12463         return mScrollCache != null &&
12464                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
12465     }
12466 
12467     /**
12468      * Trigger the scrollbars to draw.
12469      * This method differs from awakenScrollBars() only in its default duration.
12470      * initialAwakenScrollBars() will show the scroll bars for longer than
12471      * usual to give the user more of a chance to notice them.
12472      *
12473      * @return true if the animation is played, false otherwise.
12474      */
12475     private boolean initialAwakenScrollBars() {
12476         return mScrollCache != null &&
12477                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
12478     }
12479 
12480     /**
12481      * <p>
12482      * Trigger the scrollbars to draw. When invoked this method starts an
12483      * animation to fade the scrollbars out after a fixed delay. If a subclass
12484      * provides animated scrolling, the start delay should equal the duration of
12485      * the scrolling animation.
12486      * </p>
12487      *
12488      * <p>
12489      * The animation starts only if at least one of the scrollbars is enabled,
12490      * as specified by {@link #isHorizontalScrollBarEnabled()} and
12491      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12492      * this method returns true, and false otherwise. If the animation is
12493      * started, this method calls {@link #invalidate()}; in that case the caller
12494      * should not call {@link #invalidate()}.
12495      * </p>
12496      *
12497      * <p>
12498      * This method should be invoked every time a subclass directly updates the
12499      * scroll parameters.
12500      * </p>
12501      *
12502      * @param startDelay the delay, in milliseconds, after which the animation
12503      *        should start; when the delay is 0, the animation starts
12504      *        immediately
12505      * @return true if the animation is played, false otherwise
12506      *
12507      * @see #scrollBy(int, int)
12508      * @see #scrollTo(int, int)
12509      * @see #isHorizontalScrollBarEnabled()
12510      * @see #isVerticalScrollBarEnabled()
12511      * @see #setHorizontalScrollBarEnabled(boolean)
12512      * @see #setVerticalScrollBarEnabled(boolean)
12513      */
12514     protected boolean awakenScrollBars(int startDelay) {
12515         return awakenScrollBars(startDelay, true);
12516     }
12517 
12518     /**
12519      * <p>
12520      * Trigger the scrollbars to draw. When invoked this method starts an
12521      * animation to fade the scrollbars out after a fixed delay. If a subclass
12522      * provides animated scrolling, the start delay should equal the duration of
12523      * the scrolling animation.
12524      * </p>
12525      *
12526      * <p>
12527      * The animation starts only if at least one of the scrollbars is enabled,
12528      * as specified by {@link #isHorizontalScrollBarEnabled()} and
12529      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12530      * this method returns true, and false otherwise. If the animation is
12531      * started, this method calls {@link #invalidate()} if the invalidate parameter
12532      * is set to true; in that case the caller
12533      * should not call {@link #invalidate()}.
12534      * </p>
12535      *
12536      * <p>
12537      * This method should be invoked every time a subclass directly updates the
12538      * scroll parameters.
12539      * </p>
12540      *
12541      * @param startDelay the delay, in milliseconds, after which the animation
12542      *        should start; when the delay is 0, the animation starts
12543      *        immediately
12544      *
12545      * @param invalidate Whether this method should call invalidate
12546      *
12547      * @return true if the animation is played, false otherwise
12548      *
12549      * @see #scrollBy(int, int)
12550      * @see #scrollTo(int, int)
12551      * @see #isHorizontalScrollBarEnabled()
12552      * @see #isVerticalScrollBarEnabled()
12553      * @see #setHorizontalScrollBarEnabled(boolean)
12554      * @see #setVerticalScrollBarEnabled(boolean)
12555      */
12556     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12557         final ScrollabilityCache scrollCache = mScrollCache;
12558 
12559         if (scrollCache == null || !scrollCache.fadeScrollBars) {
12560             return false;
12561         }
12562 
12563         if (scrollCache.scrollBar == null) {
12564             scrollCache.scrollBar = new ScrollBarDrawable();
12565             scrollCache.scrollBar.setCallback(this);
12566             scrollCache.scrollBar.setState(getDrawableState());
12567         }
12568 
12569         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12570 
12571             if (invalidate) {
12572                 // Invalidate to show the scrollbars
12573                 postInvalidateOnAnimation();
12574             }
12575 
12576             if (scrollCache.state == ScrollabilityCache.OFF) {
12577                 // FIXME: this is copied from WindowManagerService.
12578                 // We should get this value from the system when it
12579                 // is possible to do so.
12580                 final int KEY_REPEAT_FIRST_DELAY = 750;
12581                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12582             }
12583 
12584             // Tell mScrollCache when we should start fading. This may
12585             // extend the fade start time if one was already scheduled
12586             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12587             scrollCache.fadeStartTime = fadeStartTime;
12588             scrollCache.state = ScrollabilityCache.ON;
12589 
12590             // Schedule our fader to run, unscheduling any old ones first
12591             if (mAttachInfo != null) {
12592                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
12593                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12594             }
12595 
12596             return true;
12597         }
12598 
12599         return false;
12600     }
12601 
12602     /**
12603      * Do not invalidate views which are not visible and which are not running an animation. They
12604      * will not get drawn and they should not set dirty flags as if they will be drawn
12605      */
12606     private boolean skipInvalidate() {
12607         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12608                 (!(mParent instanceof ViewGroup) ||
12609                         !((ViewGroup) mParent).isViewTransitioning(this));
12610     }
12611 
12612     /**
12613      * Mark the area defined by dirty as needing to be drawn. If the view is
12614      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12615      * point in the future.
12616      * <p>
12617      * This must be called from a UI thread. To call from a non-UI thread, call
12618      * {@link #postInvalidate()}.
12619      * <p>
12620      * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12621      * {@code dirty}.
12622      *
12623      * @param dirty the rectangle representing the bounds of the dirty region
12624      */
12625     public void invalidate(Rect dirty) {
12626         final int scrollX = mScrollX;
12627         final int scrollY = mScrollY;
12628         invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12629                 dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12630     }
12631 
12632     /**
12633      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12634      * coordinates of the dirty rect are relative to the view. If the view is
12635      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12636      * point in the future.
12637      * <p>
12638      * This must be called from a UI thread. To call from a non-UI thread, call
12639      * {@link #postInvalidate()}.
12640      *
12641      * @param l the left position of the dirty region
12642      * @param t the top position of the dirty region
12643      * @param r the right position of the dirty region
12644      * @param b the bottom position of the dirty region
12645      */
12646     public void invalidate(int l, int t, int r, int b) {
12647         final int scrollX = mScrollX;
12648         final int scrollY = mScrollY;
12649         invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12650     }
12651 
12652     /**
12653      * Invalidate the whole view. If the view is visible,
12654      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12655      * the future.
12656      * <p>
12657      * This must be called from a UI thread. To call from a non-UI thread, call
12658      * {@link #postInvalidate()}.
12659      */
12660     public void invalidate() {
12661         invalidate(true);
12662     }
12663 
12664     /**
12665      * This is where the invalidate() work actually happens. A full invalidate()
12666      * causes the drawing cache to be invalidated, but this function can be
12667      * called with invalidateCache set to false to skip that invalidation step
12668      * for cases that do not need it (for example, a component that remains at
12669      * the same dimensions with the same content).
12670      *
12671      * @param invalidateCache Whether the drawing cache for this view should be
12672      *            invalidated as well. This is usually true for a full
12673      *            invalidate, but may be set to false if the View's contents or
12674      *            dimensions have not changed.
12675      */
12676     void invalidate(boolean invalidateCache) {
12677         invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12678     }
12679 
12680     void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12681             boolean fullInvalidate) {
12682         if (mGhostView != null) {
12683             mGhostView.invalidate(true);
12684             return;
12685         }
12686 
12687         if (skipInvalidate()) {
12688             return;
12689         }
12690 
12691         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12692                 || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12693                 || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12694                 || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12695             if (fullInvalidate) {
12696                 mLastIsOpaque = isOpaque();
12697                 mPrivateFlags &= ~PFLAG_DRAWN;
12698             }
12699 
12700             mPrivateFlags |= PFLAG_DIRTY;
12701 
12702             if (invalidateCache) {
12703                 mPrivateFlags |= PFLAG_INVALIDATED;
12704                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12705             }
12706 
12707             // Propagate the damage rectangle to the parent view.
12708             final AttachInfo ai = mAttachInfo;
12709             final ViewParent p = mParent;
12710             if (p != null && ai != null && l < r && t < b) {
12711                 final Rect damage = ai.mTmpInvalRect;
12712                 damage.set(l, t, r, b);
12713                 p.invalidateChild(this, damage);
12714             }
12715 
12716             // Damage the entire projection receiver, if necessary.
12717             if (mBackground != null && mBackground.isProjected()) {
12718                 final View receiver = getProjectionReceiver();
12719                 if (receiver != null) {
12720                     receiver.damageInParent();
12721                 }
12722             }
12723 
12724             // Damage the entire IsolatedZVolume receiving this view's shadow.
12725             if (isHardwareAccelerated() && getZ() != 0) {
12726                 damageShadowReceiver();
12727             }
12728         }
12729     }
12730 
12731     /**
12732      * @return this view's projection receiver, or {@code null} if none exists
12733      */
12734     private View getProjectionReceiver() {
12735         ViewParent p = getParent();
12736         while (p != null && p instanceof View) {
12737             final View v = (View) p;
12738             if (v.isProjectionReceiver()) {
12739                 return v;
12740             }
12741             p = p.getParent();
12742         }
12743 
12744         return null;
12745     }
12746 
12747     /**
12748      * @return whether the view is a projection receiver
12749      */
12750     private boolean isProjectionReceiver() {
12751         return mBackground != null;
12752     }
12753 
12754     /**
12755      * Damage area of the screen that can be covered by this View's shadow.
12756      *
12757      * This method will guarantee that any changes to shadows cast by a View
12758      * are damaged on the screen for future redraw.
12759      */
12760     private void damageShadowReceiver() {
12761         final AttachInfo ai = mAttachInfo;
12762         if (ai != null) {
12763             ViewParent p = getParent();
12764             if (p != null && p instanceof ViewGroup) {
12765                 final ViewGroup vg = (ViewGroup) p;
12766                 vg.damageInParent();
12767             }
12768         }
12769     }
12770 
12771     /**
12772      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
12773      * set any flags or handle all of the cases handled by the default invalidation methods.
12774      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
12775      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
12776      * walk up the hierarchy, transforming the dirty rect as necessary.
12777      *
12778      * The method also handles normal invalidation logic if display list properties are not
12779      * being used in this view. The invalidateParent and forceRedraw flags are used by that
12780      * backup approach, to handle these cases used in the various property-setting methods.
12781      *
12782      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
12783      * are not being used in this view
12784      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
12785      * list properties are not being used in this view
12786      */
12787     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
12788         if (!isHardwareAccelerated()
12789                 || !mRenderNode.isValid()
12790                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
12791             if (invalidateParent) {
12792                 invalidateParentCaches();
12793             }
12794             if (forceRedraw) {
12795                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12796             }
12797             invalidate(false);
12798         } else {
12799             damageInParent();
12800         }
12801         if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
12802             damageShadowReceiver();
12803         }
12804     }
12805 
12806     /**
12807      * Tells the parent view to damage this view's bounds.
12808      *
12809      * @hide
12810      */
12811     protected void damageInParent() {
12812         final AttachInfo ai = mAttachInfo;
12813         final ViewParent p = mParent;
12814         if (p != null && ai != null) {
12815             final Rect r = ai.mTmpInvalRect;
12816             r.set(0, 0, mRight - mLeft, mBottom - mTop);
12817             if (mParent instanceof ViewGroup) {
12818                 ((ViewGroup) mParent).damageChild(this, r);
12819             } else {
12820                 mParent.invalidateChild(this, r);
12821             }
12822         }
12823     }
12824 
12825     /**
12826      * Utility method to transform a given Rect by the current matrix of this view.
12827      */
12828     void transformRect(final Rect rect) {
12829         if (!getMatrix().isIdentity()) {
12830             RectF boundingRect = mAttachInfo.mTmpTransformRect;
12831             boundingRect.set(rect);
12832             getMatrix().mapRect(boundingRect);
12833             rect.set((int) Math.floor(boundingRect.left),
12834                     (int) Math.floor(boundingRect.top),
12835                     (int) Math.ceil(boundingRect.right),
12836                     (int) Math.ceil(boundingRect.bottom));
12837         }
12838     }
12839 
12840     /**
12841      * Used to indicate that the parent of this view should clear its caches. This functionality
12842      * is used to force the parent to rebuild its display list (when hardware-accelerated),
12843      * which is necessary when various parent-managed properties of the view change, such as
12844      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
12845      * clears the parent caches and does not causes an invalidate event.
12846      *
12847      * @hide
12848      */
12849     protected void invalidateParentCaches() {
12850         if (mParent instanceof View) {
12851             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
12852         }
12853     }
12854 
12855     /**
12856      * Used to indicate that the parent of this view should be invalidated. This functionality
12857      * is used to force the parent to rebuild its display list (when hardware-accelerated),
12858      * which is necessary when various parent-managed properties of the view change, such as
12859      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
12860      * an invalidation event to the parent.
12861      *
12862      * @hide
12863      */
12864     protected void invalidateParentIfNeeded() {
12865         if (isHardwareAccelerated() && mParent instanceof View) {
12866             ((View) mParent).invalidate(true);
12867         }
12868     }
12869 
12870     /**
12871      * @hide
12872      */
12873     protected void invalidateParentIfNeededAndWasQuickRejected() {
12874         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
12875             // View was rejected last time it was drawn by its parent; this may have changed
12876             invalidateParentIfNeeded();
12877         }
12878     }
12879 
12880     /**
12881      * Indicates whether this View is opaque. An opaque View guarantees that it will
12882      * draw all the pixels overlapping its bounds using a fully opaque color.
12883      *
12884      * Subclasses of View should override this method whenever possible to indicate
12885      * whether an instance is opaque. Opaque Views are treated in a special way by
12886      * the View hierarchy, possibly allowing it to perform optimizations during
12887      * invalidate/draw passes.
12888      *
12889      * @return True if this View is guaranteed to be fully opaque, false otherwise.
12890      */
12891     @ViewDebug.ExportedProperty(category = "drawing")
12892     public boolean isOpaque() {
12893         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
12894                 getFinalAlpha() >= 1.0f;
12895     }
12896 
12897     /**
12898      * @hide
12899      */
12900     protected void computeOpaqueFlags() {
12901         // Opaque if:
12902         //   - Has a background
12903         //   - Background is opaque
12904         //   - Doesn't have scrollbars or scrollbars overlay
12905 
12906         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
12907             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
12908         } else {
12909             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
12910         }
12911 
12912         final int flags = mViewFlags;
12913         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
12914                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
12915                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
12916             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
12917         } else {
12918             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
12919         }
12920     }
12921 
12922     /**
12923      * @hide
12924      */
12925     protected boolean hasOpaqueScrollbars() {
12926         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
12927     }
12928 
12929     /**
12930      * @return A handler associated with the thread running the View. This
12931      * handler can be used to pump events in the UI events queue.
12932      */
12933     public Handler getHandler() {
12934         final AttachInfo attachInfo = mAttachInfo;
12935         if (attachInfo != null) {
12936             return attachInfo.mHandler;
12937         }
12938         return null;
12939     }
12940 
12941     /**
12942      * Gets the view root associated with the View.
12943      * @return The view root, or null if none.
12944      * @hide
12945      */
12946     public ViewRootImpl getViewRootImpl() {
12947         if (mAttachInfo != null) {
12948             return mAttachInfo.mViewRootImpl;
12949         }
12950         return null;
12951     }
12952 
12953     /**
12954      * @hide
12955      */
12956     public HardwareRenderer getHardwareRenderer() {
12957         return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
12958     }
12959 
12960     /**
12961      * <p>Causes the Runnable to be added to the message queue.
12962      * The runnable will be run on the user interface thread.</p>
12963      *
12964      * @param action The Runnable that will be executed.
12965      *
12966      * @return Returns true if the Runnable was successfully placed in to the
12967      *         message queue.  Returns false on failure, usually because the
12968      *         looper processing the message queue is exiting.
12969      *
12970      * @see #postDelayed
12971      * @see #removeCallbacks
12972      */
12973     public boolean post(Runnable action) {
12974         final AttachInfo attachInfo = mAttachInfo;
12975         if (attachInfo != null) {
12976             return attachInfo.mHandler.post(action);
12977         }
12978         // Assume that post will succeed later
12979         ViewRootImpl.getRunQueue().post(action);
12980         return true;
12981     }
12982 
12983     /**
12984      * <p>Causes the Runnable to be added to the message queue, to be run
12985      * after the specified amount of time elapses.
12986      * The runnable will be run on the user interface thread.</p>
12987      *
12988      * @param action The Runnable that will be executed.
12989      * @param delayMillis The delay (in milliseconds) until the Runnable
12990      *        will be executed.
12991      *
12992      * @return true if the Runnable was successfully placed in to the
12993      *         message queue.  Returns false on failure, usually because the
12994      *         looper processing the message queue is exiting.  Note that a
12995      *         result of true does not mean the Runnable will be processed --
12996      *         if the looper is quit before the delivery time of the message
12997      *         occurs then the message will be dropped.
12998      *
12999      * @see #post
13000      * @see #removeCallbacks
13001      */
13002     public boolean postDelayed(Runnable action, long delayMillis) {
13003         final AttachInfo attachInfo = mAttachInfo;
13004         if (attachInfo != null) {
13005             return attachInfo.mHandler.postDelayed(action, delayMillis);
13006         }
13007         // Assume that post will succeed later
13008         ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
13009         return true;
13010     }
13011 
13012     /**
13013      * <p>Causes the Runnable to execute on the next animation time step.
13014      * The runnable will be run on the user interface thread.</p>
13015      *
13016      * @param action The Runnable that will be executed.
13017      *
13018      * @see #postOnAnimationDelayed
13019      * @see #removeCallbacks
13020      */
13021     public void postOnAnimation(Runnable action) {
13022         final AttachInfo attachInfo = mAttachInfo;
13023         if (attachInfo != null) {
13024             attachInfo.mViewRootImpl.mChoreographer.postCallback(
13025                     Choreographer.CALLBACK_ANIMATION, action, null);
13026         } else {
13027             // Assume that post will succeed later
13028             ViewRootImpl.getRunQueue().post(action);
13029         }
13030     }
13031 
13032     /**
13033      * <p>Causes the Runnable to execute on the next animation time step,
13034      * after the specified amount of time elapses.
13035      * The runnable will be run on the user interface thread.</p>
13036      *
13037      * @param action The Runnable that will be executed.
13038      * @param delayMillis The delay (in milliseconds) until the Runnable
13039      *        will be executed.
13040      *
13041      * @see #postOnAnimation
13042      * @see #removeCallbacks
13043      */
13044     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13045         final AttachInfo attachInfo = mAttachInfo;
13046         if (attachInfo != null) {
13047             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13048                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13049         } else {
13050             // Assume that post will succeed later
13051             ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
13052         }
13053     }
13054 
13055     /**
13056      * <p>Removes the specified Runnable from the message queue.</p>
13057      *
13058      * @param action The Runnable to remove from the message handling queue
13059      *
13060      * @return true if this view could ask the Handler to remove the Runnable,
13061      *         false otherwise. When the returned value is true, the Runnable
13062      *         may or may not have been actually removed from the message queue
13063      *         (for instance, if the Runnable was not in the queue already.)
13064      *
13065      * @see #post
13066      * @see #postDelayed
13067      * @see #postOnAnimation
13068      * @see #postOnAnimationDelayed
13069      */
13070     public boolean removeCallbacks(Runnable action) {
13071         if (action != null) {
13072             final AttachInfo attachInfo = mAttachInfo;
13073             if (attachInfo != null) {
13074                 attachInfo.mHandler.removeCallbacks(action);
13075                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13076                         Choreographer.CALLBACK_ANIMATION, action, null);
13077             }
13078             // Assume that post will succeed later
13079             ViewRootImpl.getRunQueue().removeCallbacks(action);
13080         }
13081         return true;
13082     }
13083 
13084     /**
13085      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
13086      * Use this to invalidate the View from a non-UI thread.</p>
13087      *
13088      * <p>This method can be invoked from outside of the UI thread
13089      * only when this View is attached to a window.</p>
13090      *
13091      * @see #invalidate()
13092      * @see #postInvalidateDelayed(long)
13093      */
13094     public void postInvalidate() {
13095         postInvalidateDelayed(0);
13096     }
13097 
13098     /**
13099      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13100      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
13101      *
13102      * <p>This method can be invoked from outside of the UI thread
13103      * only when this View is attached to a window.</p>
13104      *
13105      * @param left The left coordinate of the rectangle to invalidate.
13106      * @param top The top coordinate of the rectangle to invalidate.
13107      * @param right The right coordinate of the rectangle to invalidate.
13108      * @param bottom The bottom coordinate of the rectangle to invalidate.
13109      *
13110      * @see #invalidate(int, int, int, int)
13111      * @see #invalidate(Rect)
13112      * @see #postInvalidateDelayed(long, int, int, int, int)
13113      */
13114     public void postInvalidate(int left, int top, int right, int bottom) {
13115         postInvalidateDelayed(0, left, top, right, bottom);
13116     }
13117 
13118     /**
13119      * <p>Cause an invalidate to happen on a subsequent cycle through the event
13120      * loop. Waits for the specified amount of time.</p>
13121      *
13122      * <p>This method can be invoked from outside of the UI thread
13123      * only when this View is attached to a window.</p>
13124      *
13125      * @param delayMilliseconds the duration in milliseconds to delay the
13126      *         invalidation by
13127      *
13128      * @see #invalidate()
13129      * @see #postInvalidate()
13130      */
13131     public void postInvalidateDelayed(long delayMilliseconds) {
13132         // We try only with the AttachInfo because there's no point in invalidating
13133         // if we are not attached to our window
13134         final AttachInfo attachInfo = mAttachInfo;
13135         if (attachInfo != null) {
13136             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
13137         }
13138     }
13139 
13140     /**
13141      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13142      * through the event loop. Waits for the specified amount of time.</p>
13143      *
13144      * <p>This method can be invoked from outside of the UI thread
13145      * only when this View is attached to a window.</p>
13146      *
13147      * @param delayMilliseconds the duration in milliseconds to delay the
13148      *         invalidation by
13149      * @param left The left coordinate of the rectangle to invalidate.
13150      * @param top The top coordinate of the rectangle to invalidate.
13151      * @param right The right coordinate of the rectangle to invalidate.
13152      * @param bottom The bottom coordinate of the rectangle to invalidate.
13153      *
13154      * @see #invalidate(int, int, int, int)
13155      * @see #invalidate(Rect)
13156      * @see #postInvalidate(int, int, int, int)
13157      */
13158     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
13159             int right, int bottom) {
13160 
13161         // We try only with the AttachInfo because there's no point in invalidating
13162         // if we are not attached to our window
13163         final AttachInfo attachInfo = mAttachInfo;
13164         if (attachInfo != null) {
13165             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13166             info.target = this;
13167             info.left = left;
13168             info.top = top;
13169             info.right = right;
13170             info.bottom = bottom;
13171 
13172             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
13173         }
13174     }
13175 
13176     /**
13177      * <p>Cause an invalidate to happen on the next animation time step, typically the
13178      * next display frame.</p>
13179      *
13180      * <p>This method can be invoked from outside of the UI thread
13181      * only when this View is attached to a window.</p>
13182      *
13183      * @see #invalidate()
13184      */
13185     public void postInvalidateOnAnimation() {
13186         // We try only with the AttachInfo because there's no point in invalidating
13187         // if we are not attached to our window
13188         final AttachInfo attachInfo = mAttachInfo;
13189         if (attachInfo != null) {
13190             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
13191         }
13192     }
13193 
13194     /**
13195      * <p>Cause an invalidate of the specified area to happen on the next animation
13196      * time step, typically the next display frame.</p>
13197      *
13198      * <p>This method can be invoked from outside of the UI thread
13199      * only when this View is attached to a window.</p>
13200      *
13201      * @param left The left coordinate of the rectangle to invalidate.
13202      * @param top The top coordinate of the rectangle to invalidate.
13203      * @param right The right coordinate of the rectangle to invalidate.
13204      * @param bottom The bottom coordinate of the rectangle to invalidate.
13205      *
13206      * @see #invalidate(int, int, int, int)
13207      * @see #invalidate(Rect)
13208      */
13209     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
13210         // We try only with the AttachInfo because there's no point in invalidating
13211         // if we are not attached to our window
13212         final AttachInfo attachInfo = mAttachInfo;
13213         if (attachInfo != null) {
13214             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13215             info.target = this;
13216             info.left = left;
13217             info.top = top;
13218             info.right = right;
13219             info.bottom = bottom;
13220 
13221             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
13222         }
13223     }
13224 
13225     /**
13226      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
13227      * This event is sent at most once every
13228      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
13229      */
13230     private void postSendViewScrolledAccessibilityEventCallback() {
13231         if (mSendViewScrolledAccessibilityEvent == null) {
13232             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
13233         }
13234         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
13235             mSendViewScrolledAccessibilityEvent.mIsPending = true;
13236             postDelayed(mSendViewScrolledAccessibilityEvent,
13237                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
13238         }
13239     }
13240 
13241     /**
13242      * Called by a parent to request that a child update its values for mScrollX
13243      * and mScrollY if necessary. This will typically be done if the child is
13244      * animating a scroll using a {@link android.widget.Scroller Scroller}
13245      * object.
13246      */
13247     public void computeScroll() {
13248     }
13249 
13250     /**
13251      * <p>Indicate whether the horizontal edges are faded when the view is
13252      * scrolled horizontally.</p>
13253      *
13254      * @return true if the horizontal edges should are faded on scroll, false
13255      *         otherwise
13256      *
13257      * @see #setHorizontalFadingEdgeEnabled(boolean)
13258      *
13259      * @attr ref android.R.styleable#View_requiresFadingEdge
13260      */
13261     public boolean isHorizontalFadingEdgeEnabled() {
13262         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
13263     }
13264 
13265     /**
13266      * <p>Define whether the horizontal edges should be faded when this view
13267      * is scrolled horizontally.</p>
13268      *
13269      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
13270      *                                    be faded when the view is scrolled
13271      *                                    horizontally
13272      *
13273      * @see #isHorizontalFadingEdgeEnabled()
13274      *
13275      * @attr ref android.R.styleable#View_requiresFadingEdge
13276      */
13277     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
13278         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
13279             if (horizontalFadingEdgeEnabled) {
13280                 initScrollCache();
13281             }
13282 
13283             mViewFlags ^= FADING_EDGE_HORIZONTAL;
13284         }
13285     }
13286 
13287     /**
13288      * <p>Indicate whether the vertical edges are faded when the view is
13289      * scrolled horizontally.</p>
13290      *
13291      * @return true if the vertical edges should are faded on scroll, false
13292      *         otherwise
13293      *
13294      * @see #setVerticalFadingEdgeEnabled(boolean)
13295      *
13296      * @attr ref android.R.styleable#View_requiresFadingEdge
13297      */
13298     public boolean isVerticalFadingEdgeEnabled() {
13299         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
13300     }
13301 
13302     /**
13303      * <p>Define whether the vertical edges should be faded when this view
13304      * is scrolled vertically.</p>
13305      *
13306      * @param verticalFadingEdgeEnabled true if the vertical edges should
13307      *                                  be faded when the view is scrolled
13308      *                                  vertically
13309      *
13310      * @see #isVerticalFadingEdgeEnabled()
13311      *
13312      * @attr ref android.R.styleable#View_requiresFadingEdge
13313      */
13314     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
13315         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
13316             if (verticalFadingEdgeEnabled) {
13317                 initScrollCache();
13318             }
13319 
13320             mViewFlags ^= FADING_EDGE_VERTICAL;
13321         }
13322     }
13323 
13324     /**
13325      * Returns the strength, or intensity, of the top faded edge. The strength is
13326      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13327      * returns 0.0 or 1.0 but no value in between.
13328      *
13329      * Subclasses should override this method to provide a smoother fade transition
13330      * when scrolling occurs.
13331      *
13332      * @return the intensity of the top fade as a float between 0.0f and 1.0f
13333      */
13334     protected float getTopFadingEdgeStrength() {
13335         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
13336     }
13337 
13338     /**
13339      * Returns the strength, or intensity, of the bottom faded edge. The strength is
13340      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13341      * returns 0.0 or 1.0 but no value in between.
13342      *
13343      * Subclasses should override this method to provide a smoother fade transition
13344      * when scrolling occurs.
13345      *
13346      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
13347      */
13348     protected float getBottomFadingEdgeStrength() {
13349         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
13350                 computeVerticalScrollRange() ? 1.0f : 0.0f;
13351     }
13352 
13353     /**
13354      * Returns the strength, or intensity, of the left faded edge. The strength is
13355      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13356      * returns 0.0 or 1.0 but no value in between.
13357      *
13358      * Subclasses should override this method to provide a smoother fade transition
13359      * when scrolling occurs.
13360      *
13361      * @return the intensity of the left fade as a float between 0.0f and 1.0f
13362      */
13363     protected float getLeftFadingEdgeStrength() {
13364         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
13365     }
13366 
13367     /**
13368      * Returns the strength, or intensity, of the right faded edge. The strength is
13369      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13370      * returns 0.0 or 1.0 but no value in between.
13371      *
13372      * Subclasses should override this method to provide a smoother fade transition
13373      * when scrolling occurs.
13374      *
13375      * @return the intensity of the right fade as a float between 0.0f and 1.0f
13376      */
13377     protected float getRightFadingEdgeStrength() {
13378         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
13379                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
13380     }
13381 
13382     /**
13383      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
13384      * scrollbar is not drawn by default.</p>
13385      *
13386      * @return true if the horizontal scrollbar should be painted, false
13387      *         otherwise
13388      *
13389      * @see #setHorizontalScrollBarEnabled(boolean)
13390      */
13391     public boolean isHorizontalScrollBarEnabled() {
13392         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13393     }
13394 
13395     /**
13396      * <p>Define whether the horizontal scrollbar should be drawn or not. The
13397      * scrollbar is not drawn by default.</p>
13398      *
13399      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
13400      *                                   be painted
13401      *
13402      * @see #isHorizontalScrollBarEnabled()
13403      */
13404     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
13405         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
13406             mViewFlags ^= SCROLLBARS_HORIZONTAL;
13407             computeOpaqueFlags();
13408             resolvePadding();
13409         }
13410     }
13411 
13412     /**
13413      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
13414      * scrollbar is not drawn by default.</p>
13415      *
13416      * @return true if the vertical scrollbar should be painted, false
13417      *         otherwise
13418      *
13419      * @see #setVerticalScrollBarEnabled(boolean)
13420      */
13421     public boolean isVerticalScrollBarEnabled() {
13422         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
13423     }
13424 
13425     /**
13426      * <p>Define whether the vertical scrollbar should be drawn or not. The
13427      * scrollbar is not drawn by default.</p>
13428      *
13429      * @param verticalScrollBarEnabled true if the vertical scrollbar should
13430      *                                 be painted
13431      *
13432      * @see #isVerticalScrollBarEnabled()
13433      */
13434     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
13435         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
13436             mViewFlags ^= SCROLLBARS_VERTICAL;
13437             computeOpaqueFlags();
13438             resolvePadding();
13439         }
13440     }
13441 
13442     /**
13443      * @hide
13444      */
13445     protected void recomputePadding() {
13446         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13447     }
13448 
13449     /**
13450      * Define whether scrollbars will fade when the view is not scrolling.
13451      *
13452      * @param fadeScrollbars whether to enable fading
13453      *
13454      * @attr ref android.R.styleable#View_fadeScrollbars
13455      */
13456     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
13457         initScrollCache();
13458         final ScrollabilityCache scrollabilityCache = mScrollCache;
13459         scrollabilityCache.fadeScrollBars = fadeScrollbars;
13460         if (fadeScrollbars) {
13461             scrollabilityCache.state = ScrollabilityCache.OFF;
13462         } else {
13463             scrollabilityCache.state = ScrollabilityCache.ON;
13464         }
13465     }
13466 
13467     /**
13468      *
13469      * Returns true if scrollbars will fade when this view is not scrolling
13470      *
13471      * @return true if scrollbar fading is enabled
13472      *
13473      * @attr ref android.R.styleable#View_fadeScrollbars
13474      */
13475     public boolean isScrollbarFadingEnabled() {
13476         return mScrollCache != null && mScrollCache.fadeScrollBars;
13477     }
13478 
13479     /**
13480      *
13481      * Returns the delay before scrollbars fade.
13482      *
13483      * @return the delay before scrollbars fade
13484      *
13485      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13486      */
13487     public int getScrollBarDefaultDelayBeforeFade() {
13488         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
13489                 mScrollCache.scrollBarDefaultDelayBeforeFade;
13490     }
13491 
13492     /**
13493      * Define the delay before scrollbars fade.
13494      *
13495      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
13496      *
13497      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13498      */
13499     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
13500         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
13501     }
13502 
13503     /**
13504      *
13505      * Returns the scrollbar fade duration.
13506      *
13507      * @return the scrollbar fade duration
13508      *
13509      * @attr ref android.R.styleable#View_scrollbarFadeDuration
13510      */
13511     public int getScrollBarFadeDuration() {
13512         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13513                 mScrollCache.scrollBarFadeDuration;
13514     }
13515 
13516     /**
13517      * Define the scrollbar fade duration.
13518      *
13519      * @param scrollBarFadeDuration - the scrollbar fade duration
13520      *
13521      * @attr ref android.R.styleable#View_scrollbarFadeDuration
13522      */
13523     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13524         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13525     }
13526 
13527     /**
13528      *
13529      * Returns the scrollbar size.
13530      *
13531      * @return the scrollbar size
13532      *
13533      * @attr ref android.R.styleable#View_scrollbarSize
13534      */
13535     public int getScrollBarSize() {
13536         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13537                 mScrollCache.scrollBarSize;
13538     }
13539 
13540     /**
13541      * Define the scrollbar size.
13542      *
13543      * @param scrollBarSize - the scrollbar size
13544      *
13545      * @attr ref android.R.styleable#View_scrollbarSize
13546      */
13547     public void setScrollBarSize(int scrollBarSize) {
13548         getScrollCache().scrollBarSize = scrollBarSize;
13549     }
13550 
13551     /**
13552      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13553      * inset. When inset, they add to the padding of the view. And the scrollbars
13554      * can be drawn inside the padding area or on the edge of the view. For example,
13555      * if a view has a background drawable and you want to draw the scrollbars
13556      * inside the padding specified by the drawable, you can use
13557      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13558      * appear at the edge of the view, ignoring the padding, then you can use
13559      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13560      * @param style the style of the scrollbars. Should be one of
13561      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13562      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13563      * @see #SCROLLBARS_INSIDE_OVERLAY
13564      * @see #SCROLLBARS_INSIDE_INSET
13565      * @see #SCROLLBARS_OUTSIDE_OVERLAY
13566      * @see #SCROLLBARS_OUTSIDE_INSET
13567      *
13568      * @attr ref android.R.styleable#View_scrollbarStyle
13569      */
13570     public void setScrollBarStyle(@ScrollBarStyle int style) {
13571         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13572             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13573             computeOpaqueFlags();
13574             resolvePadding();
13575         }
13576     }
13577 
13578     /**
13579      * <p>Returns the current scrollbar style.</p>
13580      * @return the current scrollbar style
13581      * @see #SCROLLBARS_INSIDE_OVERLAY
13582      * @see #SCROLLBARS_INSIDE_INSET
13583      * @see #SCROLLBARS_OUTSIDE_OVERLAY
13584      * @see #SCROLLBARS_OUTSIDE_INSET
13585      *
13586      * @attr ref android.R.styleable#View_scrollbarStyle
13587      */
13588     @ViewDebug.ExportedProperty(mapping = {
13589             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13590             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13591             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13592             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13593     })
13594     @ScrollBarStyle
13595     public int getScrollBarStyle() {
13596         return mViewFlags & SCROLLBARS_STYLE_MASK;
13597     }
13598 
13599     /**
13600      * <p>Compute the horizontal range that the horizontal scrollbar
13601      * represents.</p>
13602      *
13603      * <p>The range is expressed in arbitrary units that must be the same as the
13604      * units used by {@link #computeHorizontalScrollExtent()} and
13605      * {@link #computeHorizontalScrollOffset()}.</p>
13606      *
13607      * <p>The default range is the drawing width of this view.</p>
13608      *
13609      * @return the total horizontal range represented by the horizontal
13610      *         scrollbar
13611      *
13612      * @see #computeHorizontalScrollExtent()
13613      * @see #computeHorizontalScrollOffset()
13614      * @see android.widget.ScrollBarDrawable
13615      */
13616     protected int computeHorizontalScrollRange() {
13617         return getWidth();
13618     }
13619 
13620     /**
13621      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13622      * within the horizontal range. This value is used to compute the position
13623      * of the thumb within the scrollbar's track.</p>
13624      *
13625      * <p>The range is expressed in arbitrary units that must be the same as the
13626      * units used by {@link #computeHorizontalScrollRange()} and
13627      * {@link #computeHorizontalScrollExtent()}.</p>
13628      *
13629      * <p>The default offset is the scroll offset of this view.</p>
13630      *
13631      * @return the horizontal offset of the scrollbar's thumb
13632      *
13633      * @see #computeHorizontalScrollRange()
13634      * @see #computeHorizontalScrollExtent()
13635      * @see android.widget.ScrollBarDrawable
13636      */
13637     protected int computeHorizontalScrollOffset() {
13638         return mScrollX;
13639     }
13640 
13641     /**
13642      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13643      * within the horizontal range. This value is used to compute the length
13644      * of the thumb within the scrollbar's track.</p>
13645      *
13646      * <p>The range is expressed in arbitrary units that must be the same as the
13647      * units used by {@link #computeHorizontalScrollRange()} and
13648      * {@link #computeHorizontalScrollOffset()}.</p>
13649      *
13650      * <p>The default extent is the drawing width of this view.</p>
13651      *
13652      * @return the horizontal extent of the scrollbar's thumb
13653      *
13654      * @see #computeHorizontalScrollRange()
13655      * @see #computeHorizontalScrollOffset()
13656      * @see android.widget.ScrollBarDrawable
13657      */
13658     protected int computeHorizontalScrollExtent() {
13659         return getWidth();
13660     }
13661 
13662     /**
13663      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13664      *
13665      * <p>The range is expressed in arbitrary units that must be the same as the
13666      * units used by {@link #computeVerticalScrollExtent()} and
13667      * {@link #computeVerticalScrollOffset()}.</p>
13668      *
13669      * @return the total vertical range represented by the vertical scrollbar
13670      *
13671      * <p>The default range is the drawing height of this view.</p>
13672      *
13673      * @see #computeVerticalScrollExtent()
13674      * @see #computeVerticalScrollOffset()
13675      * @see android.widget.ScrollBarDrawable
13676      */
13677     protected int computeVerticalScrollRange() {
13678         return getHeight();
13679     }
13680 
13681     /**
13682      * <p>Compute the vertical offset of the vertical scrollbar's thumb
13683      * within the horizontal range. This value is used to compute the position
13684      * of the thumb within the scrollbar's track.</p>
13685      *
13686      * <p>The range is expressed in arbitrary units that must be the same as the
13687      * units used by {@link #computeVerticalScrollRange()} and
13688      * {@link #computeVerticalScrollExtent()}.</p>
13689      *
13690      * <p>The default offset is the scroll offset of this view.</p>
13691      *
13692      * @return the vertical offset of the scrollbar's thumb
13693      *
13694      * @see #computeVerticalScrollRange()
13695      * @see #computeVerticalScrollExtent()
13696      * @see android.widget.ScrollBarDrawable
13697      */
13698     protected int computeVerticalScrollOffset() {
13699         return mScrollY;
13700     }
13701 
13702     /**
13703      * <p>Compute the vertical extent of the vertical scrollbar's thumb
13704      * within the vertical range. This value is used to compute the length
13705      * of the thumb within the scrollbar's track.</p>
13706      *
13707      * <p>The range is expressed in arbitrary units that must be the same as the
13708      * units used by {@link #computeVerticalScrollRange()} and
13709      * {@link #computeVerticalScrollOffset()}.</p>
13710      *
13711      * <p>The default extent is the drawing height of this view.</p>
13712      *
13713      * @return the vertical extent of the scrollbar's thumb
13714      *
13715      * @see #computeVerticalScrollRange()
13716      * @see #computeVerticalScrollOffset()
13717      * @see android.widget.ScrollBarDrawable
13718      */
13719     protected int computeVerticalScrollExtent() {
13720         return getHeight();
13721     }
13722 
13723     /**
13724      * Check if this view can be scrolled horizontally in a certain direction.
13725      *
13726      * @param direction Negative to check scrolling left, positive to check scrolling right.
13727      * @return true if this view can be scrolled in the specified direction, false otherwise.
13728      */
13729     public boolean canScrollHorizontally(int direction) {
13730         final int offset = computeHorizontalScrollOffset();
13731         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
13732         if (range == 0) return false;
13733         if (direction < 0) {
13734             return offset > 0;
13735         } else {
13736             return offset < range - 1;
13737         }
13738     }
13739 
13740     /**
13741      * Check if this view can be scrolled vertically in a certain direction.
13742      *
13743      * @param direction Negative to check scrolling up, positive to check scrolling down.
13744      * @return true if this view can be scrolled in the specified direction, false otherwise.
13745      */
13746     public boolean canScrollVertically(int direction) {
13747         final int offset = computeVerticalScrollOffset();
13748         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
13749         if (range == 0) return false;
13750         if (direction < 0) {
13751             return offset > 0;
13752         } else {
13753             return offset < range - 1;
13754         }
13755     }
13756 
13757     void getScrollIndicatorBounds(@NonNull Rect out) {
13758         out.left = mScrollX;
13759         out.right = mScrollX + mRight - mLeft;
13760         out.top = mScrollY;
13761         out.bottom = mScrollY + mBottom - mTop;
13762     }
13763 
13764     private void onDrawScrollIndicators(Canvas c) {
13765         if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
13766             // No scroll indicators enabled.
13767             return;
13768         }
13769 
13770         final Drawable dr = mScrollIndicatorDrawable;
13771         if (dr == null) {
13772             // Scroll indicators aren't supported here.
13773             return;
13774         }
13775 
13776         final int h = dr.getIntrinsicHeight();
13777         final int w = dr.getIntrinsicWidth();
13778         final Rect rect = mAttachInfo.mTmpInvalRect;
13779         getScrollIndicatorBounds(rect);
13780 
13781         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
13782             final boolean canScrollUp = canScrollVertically(-1);
13783             if (canScrollUp) {
13784                 dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
13785                 dr.draw(c);
13786             }
13787         }
13788 
13789         if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
13790             final boolean canScrollDown = canScrollVertically(1);
13791             if (canScrollDown) {
13792                 dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
13793                 dr.draw(c);
13794             }
13795         }
13796 
13797         final int leftRtl;
13798         final int rightRtl;
13799         if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13800             leftRtl = PFLAG3_SCROLL_INDICATOR_END;
13801             rightRtl = PFLAG3_SCROLL_INDICATOR_START;
13802         } else {
13803             leftRtl = PFLAG3_SCROLL_INDICATOR_START;
13804             rightRtl = PFLAG3_SCROLL_INDICATOR_END;
13805         }
13806 
13807         final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
13808         if ((mPrivateFlags3 & leftMask) != 0) {
13809             final boolean canScrollLeft = canScrollHorizontally(-1);
13810             if (canScrollLeft) {
13811                 dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
13812                 dr.draw(c);
13813             }
13814         }
13815 
13816         final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
13817         if ((mPrivateFlags3 & rightMask) != 0) {
13818             final boolean canScrollRight = canScrollHorizontally(1);
13819             if (canScrollRight) {
13820                 dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
13821                 dr.draw(c);
13822             }
13823         }
13824     }
13825 
13826     /**
13827      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
13828      * scrollbars are painted only if they have been awakened first.</p>
13829      *
13830      * @param canvas the canvas on which to draw the scrollbars
13831      *
13832      * @see #awakenScrollBars(int)
13833      */
13834     protected final void onDrawScrollBars(Canvas canvas) {
13835         // scrollbars are drawn only when the animation is running
13836         final ScrollabilityCache cache = mScrollCache;
13837         if (cache != null) {
13838 
13839             int state = cache.state;
13840 
13841             if (state == ScrollabilityCache.OFF) {
13842                 return;
13843             }
13844 
13845             boolean invalidate = false;
13846 
13847             if (state == ScrollabilityCache.FADING) {
13848                 // We're fading -- get our fade interpolation
13849                 if (cache.interpolatorValues == null) {
13850                     cache.interpolatorValues = new float[1];
13851                 }
13852 
13853                 float[] values = cache.interpolatorValues;
13854 
13855                 // Stops the animation if we're done
13856                 if (cache.scrollBarInterpolator.timeToValues(values) ==
13857                         Interpolator.Result.FREEZE_END) {
13858                     cache.state = ScrollabilityCache.OFF;
13859                 } else {
13860                     cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
13861                 }
13862 
13863                 // This will make the scroll bars inval themselves after
13864                 // drawing. We only want this when we're fading so that
13865                 // we prevent excessive redraws
13866                 invalidate = true;
13867             } else {
13868                 // We're just on -- but we may have been fading before so
13869                 // reset alpha
13870                 cache.scrollBar.mutate().setAlpha(255);
13871             }
13872 
13873 
13874             final int viewFlags = mViewFlags;
13875 
13876             final boolean drawHorizontalScrollBar =
13877                 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13878             final boolean drawVerticalScrollBar =
13879                 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
13880                 && !isVerticalScrollBarHidden();
13881 
13882             if (drawVerticalScrollBar || drawHorizontalScrollBar) {
13883                 final int width = mRight - mLeft;
13884                 final int height = mBottom - mTop;
13885 
13886                 final ScrollBarDrawable scrollBar = cache.scrollBar;
13887 
13888                 final int scrollX = mScrollX;
13889                 final int scrollY = mScrollY;
13890                 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
13891 
13892                 int left;
13893                 int top;
13894                 int right;
13895                 int bottom;
13896 
13897                 if (drawHorizontalScrollBar) {
13898                     int size = scrollBar.getSize(false);
13899                     if (size <= 0) {
13900                         size = cache.scrollBarSize;
13901                     }
13902 
13903                     scrollBar.setParameters(computeHorizontalScrollRange(),
13904                                             computeHorizontalScrollOffset(),
13905                                             computeHorizontalScrollExtent(), false);
13906                     final int verticalScrollBarGap = drawVerticalScrollBar ?
13907                             getVerticalScrollbarWidth() : 0;
13908                     top = scrollY + height - size - (mUserPaddingBottom & inside);
13909                     left = scrollX + (mPaddingLeft & inside);
13910                     right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
13911                     bottom = top + size;
13912                     onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
13913                     if (invalidate) {
13914                         invalidate(left, top, right, bottom);
13915                     }
13916                 }
13917 
13918                 if (drawVerticalScrollBar) {
13919                     int size = scrollBar.getSize(true);
13920                     if (size <= 0) {
13921                         size = cache.scrollBarSize;
13922                     }
13923 
13924                     scrollBar.setParameters(computeVerticalScrollRange(),
13925                                             computeVerticalScrollOffset(),
13926                                             computeVerticalScrollExtent(), true);
13927                     int verticalScrollbarPosition = mVerticalScrollbarPosition;
13928                     if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
13929                         verticalScrollbarPosition = isLayoutRtl() ?
13930                                 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
13931                     }
13932                     switch (verticalScrollbarPosition) {
13933                         default:
13934                         case SCROLLBAR_POSITION_RIGHT:
13935                             left = scrollX + width - size - (mUserPaddingRight & inside);
13936                             break;
13937                         case SCROLLBAR_POSITION_LEFT:
13938                             left = scrollX + (mUserPaddingLeft & inside);
13939                             break;
13940                     }
13941                     top = scrollY + (mPaddingTop & inside);
13942                     right = left + size;
13943                     bottom = scrollY + height - (mUserPaddingBottom & inside);
13944                     onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
13945                     if (invalidate) {
13946                         invalidate(left, top, right, bottom);
13947                     }
13948                 }
13949             }
13950         }
13951     }
13952 
13953     /**
13954      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
13955      * FastScroller is visible.
13956      * @return whether to temporarily hide the vertical scrollbar
13957      * @hide
13958      */
13959     protected boolean isVerticalScrollBarHidden() {
13960         return false;
13961     }
13962 
13963     /**
13964      * <p>Draw the horizontal scrollbar if
13965      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
13966      *
13967      * @param canvas the canvas on which to draw the scrollbar
13968      * @param scrollBar the scrollbar's drawable
13969      *
13970      * @see #isHorizontalScrollBarEnabled()
13971      * @see #computeHorizontalScrollRange()
13972      * @see #computeHorizontalScrollExtent()
13973      * @see #computeHorizontalScrollOffset()
13974      * @see android.widget.ScrollBarDrawable
13975      * @hide
13976      */
13977     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
13978             int l, int t, int r, int b) {
13979         scrollBar.setBounds(l, t, r, b);
13980         scrollBar.draw(canvas);
13981     }
13982 
13983     /**
13984      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
13985      * returns true.</p>
13986      *
13987      * @param canvas the canvas on which to draw the scrollbar
13988      * @param scrollBar the scrollbar's drawable
13989      *
13990      * @see #isVerticalScrollBarEnabled()
13991      * @see #computeVerticalScrollRange()
13992      * @see #computeVerticalScrollExtent()
13993      * @see #computeVerticalScrollOffset()
13994      * @see android.widget.ScrollBarDrawable
13995      * @hide
13996      */
13997     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
13998             int l, int t, int r, int b) {
13999         scrollBar.setBounds(l, t, r, b);
14000         scrollBar.draw(canvas);
14001     }
14002 
14003     /**
14004      * Implement this to do your drawing.
14005      *
14006      * @param canvas the canvas on which the background will be drawn
14007      */
14008     protected void onDraw(Canvas canvas) {
14009     }
14010 
14011     /*
14012      * Caller is responsible for calling requestLayout if necessary.
14013      * (This allows addViewInLayout to not request a new layout.)
14014      */
14015     void assignParent(ViewParent parent) {
14016         if (mParent == null) {
14017             mParent = parent;
14018         } else if (parent == null) {
14019             mParent = null;
14020         } else {
14021             throw new RuntimeException("view " + this + " being added, but"
14022                     + " it already has a parent");
14023         }
14024     }
14025 
14026     /**
14027      * This is called when the view is attached to a window.  At this point it
14028      * has a Surface and will start drawing.  Note that this function is
14029      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14030      * however it may be called any time before the first onDraw -- including
14031      * before or after {@link #onMeasure(int, int)}.
14032      *
14033      * @see #onDetachedFromWindow()
14034      */
14035     @CallSuper
14036     protected void onAttachedToWindow() {
14037         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
14038             mParent.requestTransparentRegion(this);
14039         }
14040 
14041         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14042 
14043         jumpDrawablesToCurrentState();
14044 
14045         resetSubtreeAccessibilityStateChanged();
14046 
14047         // rebuild, since Outline not maintained while View is detached
14048         rebuildOutline();
14049 
14050         if (isFocused()) {
14051             InputMethodManager imm = InputMethodManager.peekInstance();
14052             if (imm != null) {
14053                 imm.focusIn(this);
14054             }
14055         }
14056     }
14057 
14058     /**
14059      * Resolve all RTL related properties.
14060      *
14061      * @return true if resolution of RTL properties has been done
14062      *
14063      * @hide
14064      */
14065     public boolean resolveRtlPropertiesIfNeeded() {
14066         if (!needRtlPropertiesResolution()) return false;
14067 
14068         // Order is important here: LayoutDirection MUST be resolved first
14069         if (!isLayoutDirectionResolved()) {
14070             resolveLayoutDirection();
14071             resolveLayoutParams();
14072         }
14073         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
14074         if (!isTextDirectionResolved()) {
14075             resolveTextDirection();
14076         }
14077         if (!isTextAlignmentResolved()) {
14078             resolveTextAlignment();
14079         }
14080         // Should resolve Drawables before Padding because we need the layout direction of the
14081         // Drawable to correctly resolve Padding.
14082         if (!areDrawablesResolved()) {
14083             resolveDrawables();
14084         }
14085         if (!isPaddingResolved()) {
14086             resolvePadding();
14087         }
14088         onRtlPropertiesChanged(getLayoutDirection());
14089         return true;
14090     }
14091 
14092     /**
14093      * Reset resolution of all RTL related properties.
14094      *
14095      * @hide
14096      */
14097     public void resetRtlProperties() {
14098         resetResolvedLayoutDirection();
14099         resetResolvedTextDirection();
14100         resetResolvedTextAlignment();
14101         resetResolvedPadding();
14102         resetResolvedDrawables();
14103     }
14104 
14105     /**
14106      * @see #onScreenStateChanged(int)
14107      */
14108     void dispatchScreenStateChanged(int screenState) {
14109         onScreenStateChanged(screenState);
14110     }
14111 
14112     /**
14113      * This method is called whenever the state of the screen this view is
14114      * attached to changes. A state change will usually occurs when the screen
14115      * turns on or off (whether it happens automatically or the user does it
14116      * manually.)
14117      *
14118      * @param screenState The new state of the screen. Can be either
14119      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
14120      */
14121     public void onScreenStateChanged(int screenState) {
14122     }
14123 
14124     /**
14125      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
14126      */
14127     private boolean hasRtlSupport() {
14128         return mContext.getApplicationInfo().hasRtlSupport();
14129     }
14130 
14131     /**
14132      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
14133      * RTL not supported)
14134      */
14135     private boolean isRtlCompatibilityMode() {
14136         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
14137         return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
14138     }
14139 
14140     /**
14141      * @return true if RTL properties need resolution.
14142      *
14143      */
14144     private boolean needRtlPropertiesResolution() {
14145         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
14146     }
14147 
14148     /**
14149      * Called when any RTL property (layout direction or text direction or text alignment) has
14150      * been changed.
14151      *
14152      * Subclasses need to override this method to take care of cached information that depends on the
14153      * resolved layout direction, or to inform child views that inherit their layout direction.
14154      *
14155      * The default implementation does nothing.
14156      *
14157      * @param layoutDirection the direction of the layout
14158      *
14159      * @see #LAYOUT_DIRECTION_LTR
14160      * @see #LAYOUT_DIRECTION_RTL
14161      */
14162     public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
14163     }
14164 
14165     /**
14166      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
14167      * that the parent directionality can and will be resolved before its children.
14168      *
14169      * @return true if resolution has been done, false otherwise.
14170      *
14171      * @hide
14172      */
14173     public boolean resolveLayoutDirection() {
14174         // Clear any previous layout direction resolution
14175         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14176 
14177         if (hasRtlSupport()) {
14178             // Set resolved depending on layout direction
14179             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
14180                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
14181                 case LAYOUT_DIRECTION_INHERIT:
14182                     // We cannot resolve yet. LTR is by default and let the resolution happen again
14183                     // later to get the correct resolved value
14184                     if (!canResolveLayoutDirection()) return false;
14185 
14186                     // Parent has not yet resolved, LTR is still the default
14187                     try {
14188                         if (!mParent.isLayoutDirectionResolved()) return false;
14189 
14190                         if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14191                             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14192                         }
14193                     } catch (AbstractMethodError e) {
14194                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14195                                 " does not fully implement ViewParent", e);
14196                     }
14197                     break;
14198                 case LAYOUT_DIRECTION_RTL:
14199                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14200                     break;
14201                 case LAYOUT_DIRECTION_LOCALE:
14202                     if((LAYOUT_DIRECTION_RTL ==
14203                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
14204                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14205                     }
14206                     break;
14207                 default:
14208                     // Nothing to do, LTR by default
14209             }
14210         }
14211 
14212         // Set to resolved
14213         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14214         return true;
14215     }
14216 
14217     /**
14218      * Check if layout direction resolution can be done.
14219      *
14220      * @return true if layout direction resolution can be done otherwise return false.
14221      */
14222     public boolean canResolveLayoutDirection() {
14223         switch (getRawLayoutDirection()) {
14224             case LAYOUT_DIRECTION_INHERIT:
14225                 if (mParent != null) {
14226                     try {
14227                         return mParent.canResolveLayoutDirection();
14228                     } catch (AbstractMethodError e) {
14229                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14230                                 " does not fully implement ViewParent", e);
14231                     }
14232                 }
14233                 return false;
14234 
14235             default:
14236                 return true;
14237         }
14238     }
14239 
14240     /**
14241      * Reset the resolved layout direction. Layout direction will be resolved during a call to
14242      * {@link #onMeasure(int, int)}.
14243      *
14244      * @hide
14245      */
14246     public void resetResolvedLayoutDirection() {
14247         // Reset the current resolved bits
14248         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14249     }
14250 
14251     /**
14252      * @return true if the layout direction is inherited.
14253      *
14254      * @hide
14255      */
14256     public boolean isLayoutDirectionInherited() {
14257         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
14258     }
14259 
14260     /**
14261      * @return true if layout direction has been resolved.
14262      */
14263     public boolean isLayoutDirectionResolved() {
14264         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14265     }
14266 
14267     /**
14268      * Return if padding has been resolved
14269      *
14270      * @hide
14271      */
14272     boolean isPaddingResolved() {
14273         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
14274     }
14275 
14276     /**
14277      * Resolves padding depending on layout direction, if applicable, and
14278      * recomputes internal padding values to adjust for scroll bars.
14279      *
14280      * @hide
14281      */
14282     public void resolvePadding() {
14283         final int resolvedLayoutDirection = getLayoutDirection();
14284 
14285         if (!isRtlCompatibilityMode()) {
14286             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
14287             // If start / end padding are defined, they will be resolved (hence overriding) to
14288             // left / right or right / left depending on the resolved layout direction.
14289             // If start / end padding are not defined, use the left / right ones.
14290             if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
14291                 Rect padding = sThreadLocal.get();
14292                 if (padding == null) {
14293                     padding = new Rect();
14294                     sThreadLocal.set(padding);
14295                 }
14296                 mBackground.getPadding(padding);
14297                 if (!mLeftPaddingDefined) {
14298                     mUserPaddingLeftInitial = padding.left;
14299                 }
14300                 if (!mRightPaddingDefined) {
14301                     mUserPaddingRightInitial = padding.right;
14302                 }
14303             }
14304             switch (resolvedLayoutDirection) {
14305                 case LAYOUT_DIRECTION_RTL:
14306                     if (mUserPaddingStart != UNDEFINED_PADDING) {
14307                         mUserPaddingRight = mUserPaddingStart;
14308                     } else {
14309                         mUserPaddingRight = mUserPaddingRightInitial;
14310                     }
14311                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
14312                         mUserPaddingLeft = mUserPaddingEnd;
14313                     } else {
14314                         mUserPaddingLeft = mUserPaddingLeftInitial;
14315                     }
14316                     break;
14317                 case LAYOUT_DIRECTION_LTR:
14318                 default:
14319                     if (mUserPaddingStart != UNDEFINED_PADDING) {
14320                         mUserPaddingLeft = mUserPaddingStart;
14321                     } else {
14322                         mUserPaddingLeft = mUserPaddingLeftInitial;
14323                     }
14324                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
14325                         mUserPaddingRight = mUserPaddingEnd;
14326                     } else {
14327                         mUserPaddingRight = mUserPaddingRightInitial;
14328                     }
14329             }
14330 
14331             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
14332         }
14333 
14334         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14335         onRtlPropertiesChanged(resolvedLayoutDirection);
14336 
14337         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
14338     }
14339 
14340     /**
14341      * Reset the resolved layout direction.
14342      *
14343      * @hide
14344      */
14345     public void resetResolvedPadding() {
14346         resetResolvedPaddingInternal();
14347     }
14348 
14349     /**
14350      * Used when we only want to reset *this* view's padding and not trigger overrides
14351      * in ViewGroup that reset children too.
14352      */
14353     void resetResolvedPaddingInternal() {
14354         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14355     }
14356 
14357     /**
14358      * This is called when the view is detached from a window.  At this point it
14359      * no longer has a surface for drawing.
14360      *
14361      * @see #onAttachedToWindow()
14362      */
14363     @CallSuper
14364     protected void onDetachedFromWindow() {
14365     }
14366 
14367     /**
14368      * This is a framework-internal mirror of onDetachedFromWindow() that's called
14369      * after onDetachedFromWindow().
14370      *
14371      * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
14372      * The super method should be called at the end of the overridden method to ensure
14373      * subclasses are destroyed first
14374      *
14375      * @hide
14376      */
14377     @CallSuper
14378     protected void onDetachedFromWindowInternal() {
14379         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
14380         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14381 
14382         removeUnsetPressCallback();
14383         removeLongPressCallback();
14384         removePerformClickCallback();
14385         removeSendViewScrolledAccessibilityEventCallback();
14386         stopNestedScroll();
14387 
14388         // Anything that started animating right before detach should already
14389         // be in its final state when re-attached.
14390         jumpDrawablesToCurrentState();
14391 
14392         destroyDrawingCache();
14393 
14394         cleanupDraw();
14395         mCurrentAnimation = null;
14396     }
14397 
14398     private void cleanupDraw() {
14399         resetDisplayList();
14400         if (mAttachInfo != null) {
14401             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
14402         }
14403     }
14404 
14405     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
14406     }
14407 
14408     /**
14409      * @return The number of times this view has been attached to a window
14410      */
14411     protected int getWindowAttachCount() {
14412         return mWindowAttachCount;
14413     }
14414 
14415     /**
14416      * Retrieve a unique token identifying the window this view is attached to.
14417      * @return Return the window's token for use in
14418      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
14419      */
14420     public IBinder getWindowToken() {
14421         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
14422     }
14423 
14424     /**
14425      * Retrieve the {@link WindowId} for the window this view is
14426      * currently attached to.
14427      */
14428     public WindowId getWindowId() {
14429         if (mAttachInfo == null) {
14430             return null;
14431         }
14432         if (mAttachInfo.mWindowId == null) {
14433             try {
14434                 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
14435                         mAttachInfo.mWindowToken);
14436                 mAttachInfo.mWindowId = new WindowId(
14437                         mAttachInfo.mIWindowId);
14438             } catch (RemoteException e) {
14439             }
14440         }
14441         return mAttachInfo.mWindowId;
14442     }
14443 
14444     /**
14445      * Retrieve a unique token identifying the top-level "real" window of
14446      * the window that this view is attached to.  That is, this is like
14447      * {@link #getWindowToken}, except if the window this view in is a panel
14448      * window (attached to another containing window), then the token of
14449      * the containing window is returned instead.
14450      *
14451      * @return Returns the associated window token, either
14452      * {@link #getWindowToken()} or the containing window's token.
14453      */
14454     public IBinder getApplicationWindowToken() {
14455         AttachInfo ai = mAttachInfo;
14456         if (ai != null) {
14457             IBinder appWindowToken = ai.mPanelParentWindowToken;
14458             if (appWindowToken == null) {
14459                 appWindowToken = ai.mWindowToken;
14460             }
14461             return appWindowToken;
14462         }
14463         return null;
14464     }
14465 
14466     /**
14467      * Gets the logical display to which the view's window has been attached.
14468      *
14469      * @return The logical display, or null if the view is not currently attached to a window.
14470      */
14471     public Display getDisplay() {
14472         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
14473     }
14474 
14475     /**
14476      * Retrieve private session object this view hierarchy is using to
14477      * communicate with the window manager.
14478      * @return the session object to communicate with the window manager
14479      */
14480     /*package*/ IWindowSession getWindowSession() {
14481         return mAttachInfo != null ? mAttachInfo.mSession : null;
14482     }
14483 
14484     /**
14485      * Return the visibility value of the least visible component passed.
14486      */
14487     int combineVisibility(int vis1, int vis2) {
14488         // This works because VISIBLE < INVISIBLE < GONE.
14489         return Math.max(vis1, vis2);
14490     }
14491 
14492     /**
14493      * @param info the {@link android.view.View.AttachInfo} to associated with
14494      *        this view
14495      */
14496     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
14497         //System.out.println("Attached! " + this);
14498         mAttachInfo = info;
14499         if (mOverlay != null) {
14500             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
14501         }
14502         mWindowAttachCount++;
14503         // We will need to evaluate the drawable state at least once.
14504         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14505         if (mFloatingTreeObserver != null) {
14506             info.mTreeObserver.merge(mFloatingTreeObserver);
14507             mFloatingTreeObserver = null;
14508         }
14509         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
14510             mAttachInfo.mScrollContainers.add(this);
14511             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
14512         }
14513         performCollectViewAttributes(mAttachInfo, visibility);
14514         onAttachedToWindow();
14515 
14516         ListenerInfo li = mListenerInfo;
14517         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14518                 li != null ? li.mOnAttachStateChangeListeners : null;
14519         if (listeners != null && listeners.size() > 0) {
14520             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14521             // perform the dispatching. The iterator is a safe guard against listeners that
14522             // could mutate the list by calling the various add/remove methods. This prevents
14523             // the array from being modified while we iterate it.
14524             for (OnAttachStateChangeListener listener : listeners) {
14525                 listener.onViewAttachedToWindow(this);
14526             }
14527         }
14528 
14529         int vis = info.mWindowVisibility;
14530         if (vis != GONE) {
14531             onWindowVisibilityChanged(vis);
14532         }
14533 
14534         // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
14535         // As all views in the subtree will already receive dispatchAttachedToWindow
14536         // traversing the subtree again here is not desired.
14537         onVisibilityChanged(this, visibility);
14538 
14539         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
14540             // If nobody has evaluated the drawable state yet, then do it now.
14541             refreshDrawableState();
14542         }
14543         needGlobalAttributesUpdate(false);
14544     }
14545 
14546     void dispatchDetachedFromWindow() {
14547         AttachInfo info = mAttachInfo;
14548         if (info != null) {
14549             int vis = info.mWindowVisibility;
14550             if (vis != GONE) {
14551                 onWindowVisibilityChanged(GONE);
14552             }
14553         }
14554 
14555         onDetachedFromWindow();
14556         onDetachedFromWindowInternal();
14557 
14558         InputMethodManager imm = InputMethodManager.peekInstance();
14559         if (imm != null) {
14560             imm.onViewDetachedFromWindow(this);
14561         }
14562 
14563         ListenerInfo li = mListenerInfo;
14564         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14565                 li != null ? li.mOnAttachStateChangeListeners : null;
14566         if (listeners != null && listeners.size() > 0) {
14567             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14568             // perform the dispatching. The iterator is a safe guard against listeners that
14569             // could mutate the list by calling the various add/remove methods. This prevents
14570             // the array from being modified while we iterate it.
14571             for (OnAttachStateChangeListener listener : listeners) {
14572                 listener.onViewDetachedFromWindow(this);
14573             }
14574         }
14575 
14576         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
14577             mAttachInfo.mScrollContainers.remove(this);
14578             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
14579         }
14580 
14581         mAttachInfo = null;
14582         if (mOverlay != null) {
14583             mOverlay.getOverlayView().dispatchDetachedFromWindow();
14584         }
14585     }
14586 
14587     /**
14588      * Cancel any deferred high-level input events that were previously posted to the event queue.
14589      *
14590      * <p>Many views post high-level events such as click handlers to the event queue
14591      * to run deferred in order to preserve a desired user experience - clearing visible
14592      * pressed states before executing, etc. This method will abort any events of this nature
14593      * that are currently in flight.</p>
14594      *
14595      * <p>Custom views that generate their own high-level deferred input events should override
14596      * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14597      *
14598      * <p>This will also cancel pending input events for any child views.</p>
14599      *
14600      * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14601      * This will not impact newer events posted after this call that may occur as a result of
14602      * lower-level input events still waiting in the queue. If you are trying to prevent
14603      * double-submitted  events for the duration of some sort of asynchronous transaction
14604      * you should also take other steps to protect against unexpected double inputs e.g. calling
14605      * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14606      * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14607      */
14608     public final void cancelPendingInputEvents() {
14609         dispatchCancelPendingInputEvents();
14610     }
14611 
14612     /**
14613      * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14614      * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14615      */
14616     void dispatchCancelPendingInputEvents() {
14617         mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14618         onCancelPendingInputEvents();
14619         if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14620             throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14621                     " did not call through to super.onCancelPendingInputEvents()");
14622         }
14623     }
14624 
14625     /**
14626      * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14627      * a parent view.
14628      *
14629      * <p>This method is responsible for removing any pending high-level input events that were
14630      * posted to the event queue to run later. Custom view classes that post their own deferred
14631      * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14632      * {@link android.os.Handler} should override this method, call
14633      * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14634      * </p>
14635      */
14636     public void onCancelPendingInputEvents() {
14637         removePerformClickCallback();
14638         cancelLongPress();
14639         mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14640     }
14641 
14642     /**
14643      * Store this view hierarchy's frozen state into the given container.
14644      *
14645      * @param container The SparseArray in which to save the view's state.
14646      *
14647      * @see #restoreHierarchyState(android.util.SparseArray)
14648      * @see #dispatchSaveInstanceState(android.util.SparseArray)
14649      * @see #onSaveInstanceState()
14650      */
14651     public void saveHierarchyState(SparseArray<Parcelable> container) {
14652         dispatchSaveInstanceState(container);
14653     }
14654 
14655     /**
14656      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
14657      * this view and its children. May be overridden to modify how freezing happens to a
14658      * view's children; for example, some views may want to not store state for their children.
14659      *
14660      * @param container The SparseArray in which to save the view's state.
14661      *
14662      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14663      * @see #saveHierarchyState(android.util.SparseArray)
14664      * @see #onSaveInstanceState()
14665      */
14666     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
14667         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
14668             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14669             Parcelable state = onSaveInstanceState();
14670             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14671                 throw new IllegalStateException(
14672                         "Derived class did not call super.onSaveInstanceState()");
14673             }
14674             if (state != null) {
14675                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
14676                 // + ": " + state);
14677                 container.put(mID, state);
14678             }
14679         }
14680     }
14681 
14682     /**
14683      * Hook allowing a view to generate a representation of its internal state
14684      * that can later be used to create a new instance with that same state.
14685      * This state should only contain information that is not persistent or can
14686      * not be reconstructed later. For example, you will never store your
14687      * current position on screen because that will be computed again when a
14688      * new instance of the view is placed in its view hierarchy.
14689      * <p>
14690      * Some examples of things you may store here: the current cursor position
14691      * in a text view (but usually not the text itself since that is stored in a
14692      * content provider or other persistent storage), the currently selected
14693      * item in a list view.
14694      *
14695      * @return Returns a Parcelable object containing the view's current dynamic
14696      *         state, or null if there is nothing interesting to save. The
14697      *         default implementation returns null.
14698      * @see #onRestoreInstanceState(android.os.Parcelable)
14699      * @see #saveHierarchyState(android.util.SparseArray)
14700      * @see #dispatchSaveInstanceState(android.util.SparseArray)
14701      * @see #setSaveEnabled(boolean)
14702      */
14703     @CallSuper
14704     protected Parcelable onSaveInstanceState() {
14705         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14706         if (mStartActivityRequestWho != null) {
14707             BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
14708             state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
14709             return state;
14710         }
14711         return BaseSavedState.EMPTY_STATE;
14712     }
14713 
14714     /**
14715      * Restore this view hierarchy's frozen state from the given container.
14716      *
14717      * @param container The SparseArray which holds previously frozen states.
14718      *
14719      * @see #saveHierarchyState(android.util.SparseArray)
14720      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14721      * @see #onRestoreInstanceState(android.os.Parcelable)
14722      */
14723     public void restoreHierarchyState(SparseArray<Parcelable> container) {
14724         dispatchRestoreInstanceState(container);
14725     }
14726 
14727     /**
14728      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
14729      * state for this view and its children. May be overridden to modify how restoring
14730      * happens to a view's children; for example, some views may want to not store state
14731      * for their children.
14732      *
14733      * @param container The SparseArray which holds previously saved state.
14734      *
14735      * @see #dispatchSaveInstanceState(android.util.SparseArray)
14736      * @see #restoreHierarchyState(android.util.SparseArray)
14737      * @see #onRestoreInstanceState(android.os.Parcelable)
14738      */
14739     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
14740         if (mID != NO_ID) {
14741             Parcelable state = container.get(mID);
14742             if (state != null) {
14743                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
14744                 // + ": " + state);
14745                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14746                 onRestoreInstanceState(state);
14747                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14748                     throw new IllegalStateException(
14749                             "Derived class did not call super.onRestoreInstanceState()");
14750                 }
14751             }
14752         }
14753     }
14754 
14755     /**
14756      * Hook allowing a view to re-apply a representation of its internal state that had previously
14757      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
14758      * null state.
14759      *
14760      * @param state The frozen state that had previously been returned by
14761      *        {@link #onSaveInstanceState}.
14762      *
14763      * @see #onSaveInstanceState()
14764      * @see #restoreHierarchyState(android.util.SparseArray)
14765      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14766      */
14767     @CallSuper
14768     protected void onRestoreInstanceState(Parcelable state) {
14769         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14770         if (state != null && !(state instanceof AbsSavedState)) {
14771             throw new IllegalArgumentException("Wrong state class, expecting View State but "
14772                     + "received " + state.getClass().toString() + " instead. This usually happens "
14773                     + "when two views of different type have the same id in the same hierarchy. "
14774                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
14775                     + "other views do not use the same id.");
14776         }
14777         if (state != null && state instanceof BaseSavedState) {
14778             mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
14779         }
14780     }
14781 
14782     /**
14783      * <p>Return the time at which the drawing of the view hierarchy started.</p>
14784      *
14785      * @return the drawing start time in milliseconds
14786      */
14787     public long getDrawingTime() {
14788         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
14789     }
14790 
14791     /**
14792      * <p>Enables or disables the duplication of the parent's state into this view. When
14793      * duplication is enabled, this view gets its drawable state from its parent rather
14794      * than from its own internal properties.</p>
14795      *
14796      * <p>Note: in the current implementation, setting this property to true after the
14797      * view was added to a ViewGroup might have no effect at all. This property should
14798      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
14799      *
14800      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
14801      * property is enabled, an exception will be thrown.</p>
14802      *
14803      * <p>Note: if the child view uses and updates additional states which are unknown to the
14804      * parent, these states should not be affected by this method.</p>
14805      *
14806      * @param enabled True to enable duplication of the parent's drawable state, false
14807      *                to disable it.
14808      *
14809      * @see #getDrawableState()
14810      * @see #isDuplicateParentStateEnabled()
14811      */
14812     public void setDuplicateParentStateEnabled(boolean enabled) {
14813         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
14814     }
14815 
14816     /**
14817      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
14818      *
14819      * @return True if this view's drawable state is duplicated from the parent,
14820      *         false otherwise
14821      *
14822      * @see #getDrawableState()
14823      * @see #setDuplicateParentStateEnabled(boolean)
14824      */
14825     public boolean isDuplicateParentStateEnabled() {
14826         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
14827     }
14828 
14829     /**
14830      * <p>Specifies the type of layer backing this view. The layer can be
14831      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14832      * {@link #LAYER_TYPE_HARDWARE}.</p>
14833      *
14834      * <p>A layer is associated with an optional {@link android.graphics.Paint}
14835      * instance that controls how the layer is composed on screen. The following
14836      * properties of the paint are taken into account when composing the layer:</p>
14837      * <ul>
14838      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14839      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14840      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14841      * </ul>
14842      *
14843      * <p>If this view has an alpha value set to < 1.0 by calling
14844      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
14845      * by this view's alpha value.</p>
14846      *
14847      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
14848      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
14849      * for more information on when and how to use layers.</p>
14850      *
14851      * @param layerType The type of layer to use with this view, must be one of
14852      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14853      *        {@link #LAYER_TYPE_HARDWARE}
14854      * @param paint The paint used to compose the layer. This argument is optional
14855      *        and can be null. It is ignored when the layer type is
14856      *        {@link #LAYER_TYPE_NONE}
14857      *
14858      * @see #getLayerType()
14859      * @see #LAYER_TYPE_NONE
14860      * @see #LAYER_TYPE_SOFTWARE
14861      * @see #LAYER_TYPE_HARDWARE
14862      * @see #setAlpha(float)
14863      *
14864      * @attr ref android.R.styleable#View_layerType
14865      */
14866     public void setLayerType(int layerType, Paint paint) {
14867         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
14868             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
14869                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
14870         }
14871 
14872         boolean typeChanged = mRenderNode.setLayerType(layerType);
14873 
14874         if (!typeChanged) {
14875             setLayerPaint(paint);
14876             return;
14877         }
14878 
14879         // Destroy any previous software drawing cache if needed
14880         if (mLayerType == LAYER_TYPE_SOFTWARE) {
14881             destroyDrawingCache();
14882         }
14883 
14884         mLayerType = layerType;
14885         final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
14886         mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
14887         mRenderNode.setLayerPaint(mLayerPaint);
14888 
14889         // draw() behaves differently if we are on a layer, so we need to
14890         // invalidate() here
14891         invalidateParentCaches();
14892         invalidate(true);
14893     }
14894 
14895     /**
14896      * Updates the {@link Paint} object used with the current layer (used only if the current
14897      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
14898      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
14899      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
14900      * ensure that the view gets redrawn immediately.
14901      *
14902      * <p>A layer is associated with an optional {@link android.graphics.Paint}
14903      * instance that controls how the layer is composed on screen. The following
14904      * properties of the paint are taken into account when composing the layer:</p>
14905      * <ul>
14906      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14907      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14908      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14909      * </ul>
14910      *
14911      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
14912      * alpha value of the layer's paint is superseded by this view's alpha value.</p>
14913      *
14914      * @param paint The paint used to compose the layer. This argument is optional
14915      *        and can be null. It is ignored when the layer type is
14916      *        {@link #LAYER_TYPE_NONE}
14917      *
14918      * @see #setLayerType(int, android.graphics.Paint)
14919      */
14920     public void setLayerPaint(Paint paint) {
14921         int layerType = getLayerType();
14922         if (layerType != LAYER_TYPE_NONE) {
14923             mLayerPaint = paint == null ? new Paint() : paint;
14924             if (layerType == LAYER_TYPE_HARDWARE) {
14925                 if (mRenderNode.setLayerPaint(mLayerPaint)) {
14926                     invalidateViewProperty(false, false);
14927                 }
14928             } else {
14929                 invalidate();
14930             }
14931         }
14932     }
14933 
14934     /**
14935      * Indicates what type of layer is currently associated with this view. By default
14936      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
14937      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
14938      * for more information on the different types of layers.
14939      *
14940      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14941      *         {@link #LAYER_TYPE_HARDWARE}
14942      *
14943      * @see #setLayerType(int, android.graphics.Paint)
14944      * @see #buildLayer()
14945      * @see #LAYER_TYPE_NONE
14946      * @see #LAYER_TYPE_SOFTWARE
14947      * @see #LAYER_TYPE_HARDWARE
14948      */
14949     public int getLayerType() {
14950         return mLayerType;
14951     }
14952 
14953     /**
14954      * Forces this view's layer to be created and this view to be rendered
14955      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
14956      * invoking this method will have no effect.
14957      *
14958      * This method can for instance be used to render a view into its layer before
14959      * starting an animation. If this view is complex, rendering into the layer
14960      * before starting the animation will avoid skipping frames.
14961      *
14962      * @throws IllegalStateException If this view is not attached to a window
14963      *
14964      * @see #setLayerType(int, android.graphics.Paint)
14965      */
14966     public void buildLayer() {
14967         if (mLayerType == LAYER_TYPE_NONE) return;
14968 
14969         final AttachInfo attachInfo = mAttachInfo;
14970         if (attachInfo == null) {
14971             throw new IllegalStateException("This view must be attached to a window first");
14972         }
14973 
14974         if (getWidth() == 0 || getHeight() == 0) {
14975             return;
14976         }
14977 
14978         switch (mLayerType) {
14979             case LAYER_TYPE_HARDWARE:
14980                 updateDisplayListIfDirty();
14981                 if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
14982                     attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
14983                 }
14984                 break;
14985             case LAYER_TYPE_SOFTWARE:
14986                 buildDrawingCache(true);
14987                 break;
14988         }
14989     }
14990 
14991     /**
14992      * If this View draws with a HardwareLayer, returns it.
14993      * Otherwise returns null
14994      *
14995      * TODO: Only TextureView uses this, can we eliminate it?
14996      */
14997     HardwareLayer getHardwareLayer() {
14998         return null;
14999     }
15000 
15001     /**
15002      * Destroys all hardware rendering resources. This method is invoked
15003      * when the system needs to reclaim resources. Upon execution of this
15004      * method, you should free any OpenGL resources created by the view.
15005      *
15006      * Note: you <strong>must</strong> call
15007      * <code>super.destroyHardwareResources()</code> when overriding
15008      * this method.
15009      *
15010      * @hide
15011      */
15012     @CallSuper
15013     protected void destroyHardwareResources() {
15014         // Although the Layer will be destroyed by RenderNode, we want to release
15015         // the staging display list, which is also a signal to RenderNode that it's
15016         // safe to free its copy of the display list as it knows that we will
15017         // push an updated DisplayList if we try to draw again
15018         resetDisplayList();
15019     }
15020 
15021     /**
15022      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
15023      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
15024      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
15025      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
15026      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
15027      * null.</p>
15028      *
15029      * <p>Enabling the drawing cache is similar to
15030      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
15031      * acceleration is turned off. When hardware acceleration is turned on, enabling the
15032      * drawing cache has no effect on rendering because the system uses a different mechanism
15033      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
15034      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
15035      * for information on how to enable software and hardware layers.</p>
15036      *
15037      * <p>This API can be used to manually generate
15038      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
15039      * {@link #getDrawingCache()}.</p>
15040      *
15041      * @param enabled true to enable the drawing cache, false otherwise
15042      *
15043      * @see #isDrawingCacheEnabled()
15044      * @see #getDrawingCache()
15045      * @see #buildDrawingCache()
15046      * @see #setLayerType(int, android.graphics.Paint)
15047      */
15048     public void setDrawingCacheEnabled(boolean enabled) {
15049         mCachingFailed = false;
15050         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
15051     }
15052 
15053     /**
15054      * <p>Indicates whether the drawing cache is enabled for this view.</p>
15055      *
15056      * @return true if the drawing cache is enabled
15057      *
15058      * @see #setDrawingCacheEnabled(boolean)
15059      * @see #getDrawingCache()
15060      */
15061     @ViewDebug.ExportedProperty(category = "drawing")
15062     public boolean isDrawingCacheEnabled() {
15063         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
15064     }
15065 
15066     /**
15067      * Debugging utility which recursively outputs the dirty state of a view and its
15068      * descendants.
15069      *
15070      * @hide
15071      */
15072     @SuppressWarnings({"UnusedDeclaration"})
15073     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
15074         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
15075                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
15076                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
15077                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
15078         if (clear) {
15079             mPrivateFlags &= clearMask;
15080         }
15081         if (this instanceof ViewGroup) {
15082             ViewGroup parent = (ViewGroup) this;
15083             final int count = parent.getChildCount();
15084             for (int i = 0; i < count; i++) {
15085                 final View child = parent.getChildAt(i);
15086                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
15087             }
15088         }
15089     }
15090 
15091     /**
15092      * This method is used by ViewGroup to cause its children to restore or recreate their
15093      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
15094      * to recreate its own display list, which would happen if it went through the normal
15095      * draw/dispatchDraw mechanisms.
15096      *
15097      * @hide
15098      */
15099     protected void dispatchGetDisplayList() {}
15100 
15101     /**
15102      * A view that is not attached or hardware accelerated cannot create a display list.
15103      * This method checks these conditions and returns the appropriate result.
15104      *
15105      * @return true if view has the ability to create a display list, false otherwise.
15106      *
15107      * @hide
15108      */
15109     public boolean canHaveDisplayList() {
15110         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
15111     }
15112 
15113     /**
15114      * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
15115      * @hide
15116      */
15117     @NonNull
15118     public RenderNode updateDisplayListIfDirty() {
15119         final RenderNode renderNode = mRenderNode;
15120         if (!canHaveDisplayList()) {
15121             // can't populate RenderNode, don't try
15122             return renderNode;
15123         }
15124 
15125         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
15126                 || !renderNode.isValid()
15127                 || (mRecreateDisplayList)) {
15128             // Don't need to recreate the display list, just need to tell our
15129             // children to restore/recreate theirs
15130             if (renderNode.isValid()
15131                     && !mRecreateDisplayList) {
15132                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15133                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15134                 dispatchGetDisplayList();
15135 
15136                 return renderNode; // no work needed
15137             }
15138 
15139             // If we got here, we're recreating it. Mark it as such to ensure that
15140             // we copy in child display lists into ours in drawChild()
15141             mRecreateDisplayList = true;
15142 
15143             int width = mRight - mLeft;
15144             int height = mBottom - mTop;
15145             int layerType = getLayerType();
15146 
15147             final DisplayListCanvas canvas = renderNode.start(width, height);
15148             canvas.setHighContrastText(mAttachInfo.mHighContrastText);
15149 
15150             try {
15151                 final HardwareLayer layer = getHardwareLayer();
15152                 if (layer != null && layer.isValid()) {
15153                     canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
15154                 } else if (layerType == LAYER_TYPE_SOFTWARE) {
15155                     buildDrawingCache(true);
15156                     Bitmap cache = getDrawingCache(true);
15157                     if (cache != null) {
15158                         canvas.drawBitmap(cache, 0, 0, mLayerPaint);
15159                     }
15160                 } else {
15161                     computeScroll();
15162 
15163                     canvas.translate(-mScrollX, -mScrollY);
15164                     mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15165                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15166 
15167                     // Fast path for layouts with no backgrounds
15168                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15169                         dispatchDraw(canvas);
15170                         if (mOverlay != null && !mOverlay.isEmpty()) {
15171                             mOverlay.getOverlayView().draw(canvas);
15172                         }
15173                     } else {
15174                         draw(canvas);
15175                     }
15176                 }
15177             } finally {
15178                 renderNode.end(canvas);
15179                 setDisplayListProperties(renderNode);
15180             }
15181         } else {
15182             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15183             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15184         }
15185         return renderNode;
15186     }
15187 
15188     private void resetDisplayList() {
15189         if (mRenderNode.isValid()) {
15190             mRenderNode.destroyDisplayListData();
15191         }
15192 
15193         if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
15194             mBackgroundRenderNode.destroyDisplayListData();
15195         }
15196     }
15197 
15198     /**
15199      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
15200      *
15201      * @return A non-scaled bitmap representing this view or null if cache is disabled.
15202      *
15203      * @see #getDrawingCache(boolean)
15204      */
15205     public Bitmap getDrawingCache() {
15206         return getDrawingCache(false);
15207     }
15208 
15209     /**
15210      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
15211      * is null when caching is disabled. If caching is enabled and the cache is not ready,
15212      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
15213      * draw from the cache when the cache is enabled. To benefit from the cache, you must
15214      * request the drawing cache by calling this method and draw it on screen if the
15215      * returned bitmap is not null.</p>
15216      *
15217      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15218      * this method will create a bitmap of the same size as this view. Because this bitmap
15219      * will be drawn scaled by the parent ViewGroup, the result on screen might show
15220      * scaling artifacts. To avoid such artifacts, you should call this method by setting
15221      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15222      * size than the view. This implies that your application must be able to handle this
15223      * size.</p>
15224      *
15225      * @param autoScale Indicates whether the generated bitmap should be scaled based on
15226      *        the current density of the screen when the application is in compatibility
15227      *        mode.
15228      *
15229      * @return A bitmap representing this view or null if cache is disabled.
15230      *
15231      * @see #setDrawingCacheEnabled(boolean)
15232      * @see #isDrawingCacheEnabled()
15233      * @see #buildDrawingCache(boolean)
15234      * @see #destroyDrawingCache()
15235      */
15236     public Bitmap getDrawingCache(boolean autoScale) {
15237         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
15238             return null;
15239         }
15240         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
15241             buildDrawingCache(autoScale);
15242         }
15243         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
15244     }
15245 
15246     /**
15247      * <p>Frees the resources used by the drawing cache. If you call
15248      * {@link #buildDrawingCache()} manually without calling
15249      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15250      * should cleanup the cache with this method afterwards.</p>
15251      *
15252      * @see #setDrawingCacheEnabled(boolean)
15253      * @see #buildDrawingCache()
15254      * @see #getDrawingCache()
15255      */
15256     public void destroyDrawingCache() {
15257         if (mDrawingCache != null) {
15258             mDrawingCache.recycle();
15259             mDrawingCache = null;
15260         }
15261         if (mUnscaledDrawingCache != null) {
15262             mUnscaledDrawingCache.recycle();
15263             mUnscaledDrawingCache = null;
15264         }
15265     }
15266 
15267     /**
15268      * Setting a solid background color for the drawing cache's bitmaps will improve
15269      * performance and memory usage. Note, though that this should only be used if this
15270      * view will always be drawn on top of a solid color.
15271      *
15272      * @param color The background color to use for the drawing cache's bitmap
15273      *
15274      * @see #setDrawingCacheEnabled(boolean)
15275      * @see #buildDrawingCache()
15276      * @see #getDrawingCache()
15277      */
15278     public void setDrawingCacheBackgroundColor(@ColorInt int color) {
15279         if (color != mDrawingCacheBackgroundColor) {
15280             mDrawingCacheBackgroundColor = color;
15281             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15282         }
15283     }
15284 
15285     /**
15286      * @see #setDrawingCacheBackgroundColor(int)
15287      *
15288      * @return The background color to used for the drawing cache's bitmap
15289      */
15290     @ColorInt
15291     public int getDrawingCacheBackgroundColor() {
15292         return mDrawingCacheBackgroundColor;
15293     }
15294 
15295     /**
15296      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
15297      *
15298      * @see #buildDrawingCache(boolean)
15299      */
15300     public void buildDrawingCache() {
15301         buildDrawingCache(false);
15302     }
15303 
15304     /**
15305      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
15306      *
15307      * <p>If you call {@link #buildDrawingCache()} manually without calling
15308      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15309      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
15310      *
15311      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15312      * this method will create a bitmap of the same size as this view. Because this bitmap
15313      * will be drawn scaled by the parent ViewGroup, the result on screen might show
15314      * scaling artifacts. To avoid such artifacts, you should call this method by setting
15315      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15316      * size than the view. This implies that your application must be able to handle this
15317      * size.</p>
15318      *
15319      * <p>You should avoid calling this method when hardware acceleration is enabled. If
15320      * you do not need the drawing cache bitmap, calling this method will increase memory
15321      * usage and cause the view to be rendered in software once, thus negatively impacting
15322      * performance.</p>
15323      *
15324      * @see #getDrawingCache()
15325      * @see #destroyDrawingCache()
15326      */
15327     public void buildDrawingCache(boolean autoScale) {
15328         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
15329                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
15330             if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
15331                 Trace.traceBegin(Trace.TRACE_TAG_VIEW,
15332                         "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
15333             }
15334             try {
15335                 buildDrawingCacheImpl(autoScale);
15336             } finally {
15337                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
15338             }
15339         }
15340     }
15341 
15342     /**
15343      * private, internal implementation of buildDrawingCache, used to enable tracing
15344      */
15345     private void buildDrawingCacheImpl(boolean autoScale) {
15346         mCachingFailed = false;
15347 
15348         int width = mRight - mLeft;
15349         int height = mBottom - mTop;
15350 
15351         final AttachInfo attachInfo = mAttachInfo;
15352         final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
15353 
15354         if (autoScale && scalingRequired) {
15355             width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
15356             height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
15357         }
15358 
15359         final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
15360         final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
15361         final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
15362 
15363         final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
15364         final long drawingCacheSize =
15365                 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
15366         if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
15367             if (width > 0 && height > 0) {
15368                 Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
15369                         + " too large to fit into a software layer (or drawing cache), needs "
15370                         + projectedBitmapSize + " bytes, only "
15371                         + drawingCacheSize + " available");
15372             }
15373             destroyDrawingCache();
15374             mCachingFailed = true;
15375             return;
15376         }
15377 
15378         boolean clear = true;
15379         Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
15380 
15381         if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
15382             Bitmap.Config quality;
15383             if (!opaque) {
15384                 // Never pick ARGB_4444 because it looks awful
15385                 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
15386                 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
15387                     case DRAWING_CACHE_QUALITY_AUTO:
15388                     case DRAWING_CACHE_QUALITY_LOW:
15389                     case DRAWING_CACHE_QUALITY_HIGH:
15390                     default:
15391                         quality = Bitmap.Config.ARGB_8888;
15392                         break;
15393                 }
15394             } else {
15395                 // Optimization for translucent windows
15396                 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
15397                 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
15398             }
15399 
15400             // Try to cleanup memory
15401             if (bitmap != null) bitmap.recycle();
15402 
15403             try {
15404                 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15405                         width, height, quality);
15406                 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
15407                 if (autoScale) {
15408                     mDrawingCache = bitmap;
15409                 } else {
15410                     mUnscaledDrawingCache = bitmap;
15411                 }
15412                 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
15413             } catch (OutOfMemoryError e) {
15414                 // If there is not enough memory to create the bitmap cache, just
15415                 // ignore the issue as bitmap caches are not required to draw the
15416                 // view hierarchy
15417                 if (autoScale) {
15418                     mDrawingCache = null;
15419                 } else {
15420                     mUnscaledDrawingCache = null;
15421                 }
15422                 mCachingFailed = true;
15423                 return;
15424             }
15425 
15426             clear = drawingCacheBackgroundColor != 0;
15427         }
15428 
15429         Canvas canvas;
15430         if (attachInfo != null) {
15431             canvas = attachInfo.mCanvas;
15432             if (canvas == null) {
15433                 canvas = new Canvas();
15434             }
15435             canvas.setBitmap(bitmap);
15436             // Temporarily clobber the cached Canvas in case one of our children
15437             // is also using a drawing cache. Without this, the children would
15438             // steal the canvas by attaching their own bitmap to it and bad, bad
15439             // thing would happen (invisible views, corrupted drawings, etc.)
15440             attachInfo.mCanvas = null;
15441         } else {
15442             // This case should hopefully never or seldom happen
15443             canvas = new Canvas(bitmap);
15444         }
15445 
15446         if (clear) {
15447             bitmap.eraseColor(drawingCacheBackgroundColor);
15448         }
15449 
15450         computeScroll();
15451         final int restoreCount = canvas.save();
15452 
15453         if (autoScale && scalingRequired) {
15454             final float scale = attachInfo.mApplicationScale;
15455             canvas.scale(scale, scale);
15456         }
15457 
15458         canvas.translate(-mScrollX, -mScrollY);
15459 
15460         mPrivateFlags |= PFLAG_DRAWN;
15461         if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
15462                 mLayerType != LAYER_TYPE_NONE) {
15463             mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
15464         }
15465 
15466         // Fast path for layouts with no backgrounds
15467         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15468             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15469             dispatchDraw(canvas);
15470             if (mOverlay != null && !mOverlay.isEmpty()) {
15471                 mOverlay.getOverlayView().draw(canvas);
15472             }
15473         } else {
15474             draw(canvas);
15475         }
15476 
15477         canvas.restoreToCount(restoreCount);
15478         canvas.setBitmap(null);
15479 
15480         if (attachInfo != null) {
15481             // Restore the cached Canvas for our siblings
15482             attachInfo.mCanvas = canvas;
15483         }
15484     }
15485 
15486     /**
15487      * Create a snapshot of the view into a bitmap.  We should probably make
15488      * some form of this public, but should think about the API.
15489      */
15490     Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
15491         int width = mRight - mLeft;
15492         int height = mBottom - mTop;
15493 
15494         final AttachInfo attachInfo = mAttachInfo;
15495         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
15496         width = (int) ((width * scale) + 0.5f);
15497         height = (int) ((height * scale) + 0.5f);
15498 
15499         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15500                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
15501         if (bitmap == null) {
15502             throw new OutOfMemoryError();
15503         }
15504 
15505         Resources resources = getResources();
15506         if (resources != null) {
15507             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
15508         }
15509 
15510         Canvas canvas;
15511         if (attachInfo != null) {
15512             canvas = attachInfo.mCanvas;
15513             if (canvas == null) {
15514                 canvas = new Canvas();
15515             }
15516             canvas.setBitmap(bitmap);
15517             // Temporarily clobber the cached Canvas in case one of our children
15518             // is also using a drawing cache. Without this, the children would
15519             // steal the canvas by attaching their own bitmap to it and bad, bad
15520             // things would happen (invisible views, corrupted drawings, etc.)
15521             attachInfo.mCanvas = null;
15522         } else {
15523             // This case should hopefully never or seldom happen
15524             canvas = new Canvas(bitmap);
15525         }
15526 
15527         if ((backgroundColor & 0xff000000) != 0) {
15528             bitmap.eraseColor(backgroundColor);
15529         }
15530 
15531         computeScroll();
15532         final int restoreCount = canvas.save();
15533         canvas.scale(scale, scale);
15534         canvas.translate(-mScrollX, -mScrollY);
15535 
15536         // Temporarily remove the dirty mask
15537         int flags = mPrivateFlags;
15538         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15539 
15540         // Fast path for layouts with no backgrounds
15541         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15542             dispatchDraw(canvas);
15543             if (mOverlay != null && !mOverlay.isEmpty()) {
15544                 mOverlay.getOverlayView().draw(canvas);
15545             }
15546         } else {
15547             draw(canvas);
15548         }
15549 
15550         mPrivateFlags = flags;
15551 
15552         canvas.restoreToCount(restoreCount);
15553         canvas.setBitmap(null);
15554 
15555         if (attachInfo != null) {
15556             // Restore the cached Canvas for our siblings
15557             attachInfo.mCanvas = canvas;
15558         }
15559 
15560         return bitmap;
15561     }
15562 
15563     /**
15564      * Indicates whether this View is currently in edit mode. A View is usually
15565      * in edit mode when displayed within a developer tool. For instance, if
15566      * this View is being drawn by a visual user interface builder, this method
15567      * should return true.
15568      *
15569      * Subclasses should check the return value of this method to provide
15570      * different behaviors if their normal behavior might interfere with the
15571      * host environment. For instance: the class spawns a thread in its
15572      * constructor, the drawing code relies on device-specific features, etc.
15573      *
15574      * This method is usually checked in the drawing code of custom widgets.
15575      *
15576      * @return True if this View is in edit mode, false otherwise.
15577      */
15578     public boolean isInEditMode() {
15579         return false;
15580     }
15581 
15582     /**
15583      * If the View draws content inside its padding and enables fading edges,
15584      * it needs to support padding offsets. Padding offsets are added to the
15585      * fading edges to extend the length of the fade so that it covers pixels
15586      * drawn inside the padding.
15587      *
15588      * Subclasses of this class should override this method if they need
15589      * to draw content inside the padding.
15590      *
15591      * @return True if padding offset must be applied, false otherwise.
15592      *
15593      * @see #getLeftPaddingOffset()
15594      * @see #getRightPaddingOffset()
15595      * @see #getTopPaddingOffset()
15596      * @see #getBottomPaddingOffset()
15597      *
15598      * @since CURRENT
15599      */
15600     protected boolean isPaddingOffsetRequired() {
15601         return false;
15602     }
15603 
15604     /**
15605      * Amount by which to extend the left fading region. Called only when
15606      * {@link #isPaddingOffsetRequired()} returns true.
15607      *
15608      * @return The left padding offset in pixels.
15609      *
15610      * @see #isPaddingOffsetRequired()
15611      *
15612      * @since CURRENT
15613      */
15614     protected int getLeftPaddingOffset() {
15615         return 0;
15616     }
15617 
15618     /**
15619      * Amount by which to extend the right fading region. Called only when
15620      * {@link #isPaddingOffsetRequired()} returns true.
15621      *
15622      * @return The right padding offset in pixels.
15623      *
15624      * @see #isPaddingOffsetRequired()
15625      *
15626      * @since CURRENT
15627      */
15628     protected int getRightPaddingOffset() {
15629         return 0;
15630     }
15631 
15632     /**
15633      * Amount by which to extend the top fading region. Called only when
15634      * {@link #isPaddingOffsetRequired()} returns true.
15635      *
15636      * @return The top padding offset in pixels.
15637      *
15638      * @see #isPaddingOffsetRequired()
15639      *
15640      * @since CURRENT
15641      */
15642     protected int getTopPaddingOffset() {
15643         return 0;
15644     }
15645 
15646     /**
15647      * Amount by which to extend the bottom fading region. Called only when
15648      * {@link #isPaddingOffsetRequired()} returns true.
15649      *
15650      * @return The bottom padding offset in pixels.
15651      *
15652      * @see #isPaddingOffsetRequired()
15653      *
15654      * @since CURRENT
15655      */
15656     protected int getBottomPaddingOffset() {
15657         return 0;
15658     }
15659 
15660     /**
15661      * @hide
15662      * @param offsetRequired
15663      */
15664     protected int getFadeTop(boolean offsetRequired) {
15665         int top = mPaddingTop;
15666         if (offsetRequired) top += getTopPaddingOffset();
15667         return top;
15668     }
15669 
15670     /**
15671      * @hide
15672      * @param offsetRequired
15673      */
15674     protected int getFadeHeight(boolean offsetRequired) {
15675         int padding = mPaddingTop;
15676         if (offsetRequired) padding += getTopPaddingOffset();
15677         return mBottom - mTop - mPaddingBottom - padding;
15678     }
15679 
15680     /**
15681      * <p>Indicates whether this view is attached to a hardware accelerated
15682      * window or not.</p>
15683      *
15684      * <p>Even if this method returns true, it does not mean that every call
15685      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
15686      * accelerated {@link android.graphics.Canvas}. For instance, if this view
15687      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
15688      * window is hardware accelerated,
15689      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
15690      * return false, and this method will return true.</p>
15691      *
15692      * @return True if the view is attached to a window and the window is
15693      *         hardware accelerated; false in any other case.
15694      */
15695     @ViewDebug.ExportedProperty(category = "drawing")
15696     public boolean isHardwareAccelerated() {
15697         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15698     }
15699 
15700     /**
15701      * Sets a rectangular area on this view to which the view will be clipped
15702      * when it is drawn. Setting the value to null will remove the clip bounds
15703      * and the view will draw normally, using its full bounds.
15704      *
15705      * @param clipBounds The rectangular area, in the local coordinates of
15706      * this view, to which future drawing operations will be clipped.
15707      */
15708     public void setClipBounds(Rect clipBounds) {
15709         if (clipBounds == mClipBounds
15710                 || (clipBounds != null && clipBounds.equals(mClipBounds))) {
15711             return;
15712         }
15713         if (clipBounds != null) {
15714             if (mClipBounds == null) {
15715                 mClipBounds = new Rect(clipBounds);
15716             } else {
15717                 mClipBounds.set(clipBounds);
15718             }
15719         } else {
15720             mClipBounds = null;
15721         }
15722         mRenderNode.setClipBounds(mClipBounds);
15723         invalidateViewProperty(false, false);
15724     }
15725 
15726     /**
15727      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
15728      *
15729      * @return A copy of the current clip bounds if clip bounds are set,
15730      * otherwise null.
15731      */
15732     public Rect getClipBounds() {
15733         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
15734     }
15735 
15736 
15737     /**
15738      * Populates an output rectangle with the clip bounds of the view,
15739      * returning {@code true} if successful or {@code false} if the view's
15740      * clip bounds are {@code null}.
15741      *
15742      * @param outRect rectangle in which to place the clip bounds of the view
15743      * @return {@code true} if successful or {@code false} if the view's
15744      *         clip bounds are {@code null}
15745      */
15746     public boolean getClipBounds(Rect outRect) {
15747         if (mClipBounds != null) {
15748             outRect.set(mClipBounds);
15749             return true;
15750         }
15751         return false;
15752     }
15753 
15754     /**
15755      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
15756      * case of an active Animation being run on the view.
15757      */
15758     private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
15759             Animation a, boolean scalingRequired) {
15760         Transformation invalidationTransform;
15761         final int flags = parent.mGroupFlags;
15762         final boolean initialized = a.isInitialized();
15763         if (!initialized) {
15764             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
15765             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
15766             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
15767             onAnimationStart();
15768         }
15769 
15770         final Transformation t = parent.getChildTransformation();
15771         boolean more = a.getTransformation(drawingTime, t, 1f);
15772         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
15773             if (parent.mInvalidationTransformation == null) {
15774                 parent.mInvalidationTransformation = new Transformation();
15775             }
15776             invalidationTransform = parent.mInvalidationTransformation;
15777             a.getTransformation(drawingTime, invalidationTransform, 1f);
15778         } else {
15779             invalidationTransform = t;
15780         }
15781 
15782         if (more) {
15783             if (!a.willChangeBounds()) {
15784                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
15785                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
15786                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
15787                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
15788                     // The child need to draw an animation, potentially offscreen, so
15789                     // make sure we do not cancel invalidate requests
15790                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15791                     parent.invalidate(mLeft, mTop, mRight, mBottom);
15792                 }
15793             } else {
15794                 if (parent.mInvalidateRegion == null) {
15795                     parent.mInvalidateRegion = new RectF();
15796                 }
15797                 final RectF region = parent.mInvalidateRegion;
15798                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
15799                         invalidationTransform);
15800 
15801                 // The child need to draw an animation, potentially offscreen, so
15802                 // make sure we do not cancel invalidate requests
15803                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15804 
15805                 final int left = mLeft + (int) region.left;
15806                 final int top = mTop + (int) region.top;
15807                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
15808                         top + (int) (region.height() + .5f));
15809             }
15810         }
15811         return more;
15812     }
15813 
15814     /**
15815      * This method is called by getDisplayList() when a display list is recorded for a View.
15816      * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
15817      */
15818     void setDisplayListProperties(RenderNode renderNode) {
15819         if (renderNode != null) {
15820             renderNode.setHasOverlappingRendering(hasOverlappingRendering());
15821             renderNode.setClipToBounds(mParent instanceof ViewGroup
15822                     && ((ViewGroup) mParent).getClipChildren());
15823 
15824             float alpha = 1;
15825             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
15826                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15827                 ViewGroup parentVG = (ViewGroup) mParent;
15828                 final Transformation t = parentVG.getChildTransformation();
15829                 if (parentVG.getChildStaticTransformation(this, t)) {
15830                     final int transformType = t.getTransformationType();
15831                     if (transformType != Transformation.TYPE_IDENTITY) {
15832                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
15833                             alpha = t.getAlpha();
15834                         }
15835                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
15836                             renderNode.setStaticMatrix(t.getMatrix());
15837                         }
15838                     }
15839                 }
15840             }
15841             if (mTransformationInfo != null) {
15842                 alpha *= getFinalAlpha();
15843                 if (alpha < 1) {
15844                     final int multipliedAlpha = (int) (255 * alpha);
15845                     if (onSetAlpha(multipliedAlpha)) {
15846                         alpha = 1;
15847                     }
15848                 }
15849                 renderNode.setAlpha(alpha);
15850             } else if (alpha < 1) {
15851                 renderNode.setAlpha(alpha);
15852             }
15853         }
15854     }
15855 
15856     /**
15857      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
15858      *
15859      * This is where the View specializes rendering behavior based on layer type,
15860      * and hardware acceleration.
15861      */
15862     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
15863         final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
15864         /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
15865          *
15866          * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
15867          * HW accelerated, it can't handle drawing RenderNodes.
15868          */
15869         boolean drawingWithRenderNode = mAttachInfo != null
15870                 && mAttachInfo.mHardwareAccelerated
15871                 && hardwareAcceleratedCanvas;
15872 
15873         boolean more = false;
15874         final boolean childHasIdentityMatrix = hasIdentityMatrix();
15875         final int parentFlags = parent.mGroupFlags;
15876 
15877         if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
15878             parent.getChildTransformation().clear();
15879             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15880         }
15881 
15882         Transformation transformToApply = null;
15883         boolean concatMatrix = false;
15884         final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
15885         final Animation a = getAnimation();
15886         if (a != null) {
15887             more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
15888             concatMatrix = a.willChangeTransformationMatrix();
15889             if (concatMatrix) {
15890                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15891             }
15892             transformToApply = parent.getChildTransformation();
15893         } else {
15894             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
15895                 // No longer animating: clear out old animation matrix
15896                 mRenderNode.setAnimationMatrix(null);
15897                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15898             }
15899             if (!drawingWithRenderNode
15900                     && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15901                 final Transformation t = parent.getChildTransformation();
15902                 final boolean hasTransform = parent.getChildStaticTransformation(this, t);
15903                 if (hasTransform) {
15904                     final int transformType = t.getTransformationType();
15905                     transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
15906                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
15907                 }
15908             }
15909         }
15910 
15911         concatMatrix |= !childHasIdentityMatrix;
15912 
15913         // Sets the flag as early as possible to allow draw() implementations
15914         // to call invalidate() successfully when doing animations
15915         mPrivateFlags |= PFLAG_DRAWN;
15916 
15917         if (!concatMatrix &&
15918                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
15919                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
15920                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
15921                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
15922             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
15923             return more;
15924         }
15925         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
15926 
15927         if (hardwareAcceleratedCanvas) {
15928             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
15929             // retain the flag's value temporarily in the mRecreateDisplayList flag
15930             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
15931             mPrivateFlags &= ~PFLAG_INVALIDATED;
15932         }
15933 
15934         RenderNode renderNode = null;
15935         Bitmap cache = null;
15936         int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
15937         if (layerType == LAYER_TYPE_SOFTWARE
15938                 || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
15939             // If not drawing with RenderNode, treat HW layers as SW
15940             layerType = LAYER_TYPE_SOFTWARE;
15941             buildDrawingCache(true);
15942             cache = getDrawingCache(true);
15943         }
15944 
15945         if (drawingWithRenderNode) {
15946             // Delay getting the display list until animation-driven alpha values are
15947             // set up and possibly passed on to the view
15948             renderNode = updateDisplayListIfDirty();
15949             if (!renderNode.isValid()) {
15950                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
15951                 // to getDisplayList(), the display list will be marked invalid and we should not
15952                 // try to use it again.
15953                 renderNode = null;
15954                 drawingWithRenderNode = false;
15955             }
15956         }
15957 
15958         int sx = 0;
15959         int sy = 0;
15960         if (!drawingWithRenderNode) {
15961             computeScroll();
15962             sx = mScrollX;
15963             sy = mScrollY;
15964         }
15965 
15966         final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
15967         final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
15968 
15969         int restoreTo = -1;
15970         if (!drawingWithRenderNode || transformToApply != null) {
15971             restoreTo = canvas.save();
15972         }
15973         if (offsetForScroll) {
15974             canvas.translate(mLeft - sx, mTop - sy);
15975         } else {
15976             if (!drawingWithRenderNode) {
15977                 canvas.translate(mLeft, mTop);
15978             }
15979             if (scalingRequired) {
15980                 if (drawingWithRenderNode) {
15981                     // TODO: Might not need this if we put everything inside the DL
15982                     restoreTo = canvas.save();
15983                 }
15984                 // mAttachInfo cannot be null, otherwise scalingRequired == false
15985                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
15986                 canvas.scale(scale, scale);
15987             }
15988         }
15989 
15990         float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
15991         if (transformToApply != null
15992                 || alpha < 1
15993                 || !hasIdentityMatrix()
15994                 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
15995             if (transformToApply != null || !childHasIdentityMatrix) {
15996                 int transX = 0;
15997                 int transY = 0;
15998 
15999                 if (offsetForScroll) {
16000                     transX = -sx;
16001                     transY = -sy;
16002                 }
16003 
16004                 if (transformToApply != null) {
16005                     if (concatMatrix) {
16006                         if (drawingWithRenderNode) {
16007                             renderNode.setAnimationMatrix(transformToApply.getMatrix());
16008                         } else {
16009                             // Undo the scroll translation, apply the transformation matrix,
16010                             // then redo the scroll translate to get the correct result.
16011                             canvas.translate(-transX, -transY);
16012                             canvas.concat(transformToApply.getMatrix());
16013                             canvas.translate(transX, transY);
16014                         }
16015                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16016                     }
16017 
16018                     float transformAlpha = transformToApply.getAlpha();
16019                     if (transformAlpha < 1) {
16020                         alpha *= transformAlpha;
16021                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16022                     }
16023                 }
16024 
16025                 if (!childHasIdentityMatrix && !drawingWithRenderNode) {
16026                     canvas.translate(-transX, -transY);
16027                     canvas.concat(getMatrix());
16028                     canvas.translate(transX, transY);
16029                 }
16030             }
16031 
16032             // Deal with alpha if it is or used to be <1
16033             if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16034                 if (alpha < 1) {
16035                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16036                 } else {
16037                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16038                 }
16039                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16040                 if (!drawingWithDrawingCache) {
16041                     final int multipliedAlpha = (int) (255 * alpha);
16042                     if (!onSetAlpha(multipliedAlpha)) {
16043                         if (drawingWithRenderNode) {
16044                             renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
16045                         } else if (layerType == LAYER_TYPE_NONE) {
16046                             canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
16047                                     multipliedAlpha);
16048                         }
16049                     } else {
16050                         // Alpha is handled by the child directly, clobber the layer's alpha
16051                         mPrivateFlags |= PFLAG_ALPHA_SET;
16052                     }
16053                 }
16054             }
16055         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16056             onSetAlpha(255);
16057             mPrivateFlags &= ~PFLAG_ALPHA_SET;
16058         }
16059 
16060         if (!drawingWithRenderNode) {
16061             // apply clips directly, since RenderNode won't do it for this draw
16062             if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
16063                 if (offsetForScroll) {
16064                     canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
16065                 } else {
16066                     if (!scalingRequired || cache == null) {
16067                         canvas.clipRect(0, 0, getWidth(), getHeight());
16068                     } else {
16069                         canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
16070                     }
16071                 }
16072             }
16073 
16074             if (mClipBounds != null) {
16075                 // clip bounds ignore scroll
16076                 canvas.clipRect(mClipBounds);
16077             }
16078         }
16079 
16080         if (!drawingWithDrawingCache) {
16081             if (drawingWithRenderNode) {
16082                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16083                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16084             } else {
16085                 // Fast path for layouts with no backgrounds
16086                 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16087                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16088                     dispatchDraw(canvas);
16089                 } else {
16090                     draw(canvas);
16091                 }
16092             }
16093         } else if (cache != null) {
16094             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16095             if (layerType == LAYER_TYPE_NONE) {
16096                 // no layer paint, use temporary paint to draw bitmap
16097                 Paint cachePaint = parent.mCachePaint;
16098                 if (cachePaint == null) {
16099                     cachePaint = new Paint();
16100                     cachePaint.setDither(false);
16101                     parent.mCachePaint = cachePaint;
16102                 }
16103                 cachePaint.setAlpha((int) (alpha * 255));
16104                 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
16105             } else {
16106                 // use layer paint to draw the bitmap, merging the two alphas, but also restore
16107                 int layerPaintAlpha = mLayerPaint.getAlpha();
16108                 mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
16109                 canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
16110                 mLayerPaint.setAlpha(layerPaintAlpha);
16111             }
16112         }
16113 
16114         if (restoreTo >= 0) {
16115             canvas.restoreToCount(restoreTo);
16116         }
16117 
16118         if (a != null && !more) {
16119             if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
16120                 onSetAlpha(255);
16121             }
16122             parent.finishAnimatingView(this, a);
16123         }
16124 
16125         if (more && hardwareAcceleratedCanvas) {
16126             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16127                 // alpha animations should cause the child to recreate its display list
16128                 invalidate(true);
16129             }
16130         }
16131 
16132         mRecreateDisplayList = false;
16133 
16134         return more;
16135     }
16136 
16137     /**
16138      * Manually render this view (and all of its children) to the given Canvas.
16139      * The view must have already done a full layout before this function is
16140      * called.  When implementing a view, implement
16141      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
16142      * If you do need to override this method, call the superclass version.
16143      *
16144      * @param canvas The Canvas to which the View is rendered.
16145      */
16146     @CallSuper
16147     public void draw(Canvas canvas) {
16148         final int privateFlags = mPrivateFlags;
16149         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
16150                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
16151         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
16152 
16153         /*
16154          * Draw traversal performs several drawing steps which must be executed
16155          * in the appropriate order:
16156          *
16157          *      1. Draw the background
16158          *      2. If necessary, save the canvas' layers to prepare for fading
16159          *      3. Draw view's content
16160          *      4. Draw children
16161          *      5. If necessary, draw the fading edges and restore layers
16162          *      6. Draw decorations (scrollbars for instance)
16163          */
16164 
16165         // Step 1, draw the background, if needed
16166         int saveCount;
16167 
16168         if (!dirtyOpaque) {
16169             drawBackground(canvas);
16170         }
16171 
16172         // skip step 2 & 5 if possible (common case)
16173         final int viewFlags = mViewFlags;
16174         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
16175         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
16176         if (!verticalEdges && !horizontalEdges) {
16177             // Step 3, draw the content
16178             if (!dirtyOpaque) onDraw(canvas);
16179 
16180             // Step 4, draw the children
16181             dispatchDraw(canvas);
16182 
16183             // Overlay is part of the content and draws beneath Foreground
16184             if (mOverlay != null && !mOverlay.isEmpty()) {
16185                 mOverlay.getOverlayView().dispatchDraw(canvas);
16186             }
16187 
16188             // Step 6, draw decorations (foreground, scrollbars)
16189             onDrawForeground(canvas);
16190 
16191             // we're done...
16192             return;
16193         }
16194 
16195         /*
16196          * Here we do the full fledged routine...
16197          * (this is an uncommon case where speed matters less,
16198          * this is why we repeat some of the tests that have been
16199          * done above)
16200          */
16201 
16202         boolean drawTop = false;
16203         boolean drawBottom = false;
16204         boolean drawLeft = false;
16205         boolean drawRight = false;
16206 
16207         float topFadeStrength = 0.0f;
16208         float bottomFadeStrength = 0.0f;
16209         float leftFadeStrength = 0.0f;
16210         float rightFadeStrength = 0.0f;
16211 
16212         // Step 2, save the canvas' layers
16213         int paddingLeft = mPaddingLeft;
16214 
16215         final boolean offsetRequired = isPaddingOffsetRequired();
16216         if (offsetRequired) {
16217             paddingLeft += getLeftPaddingOffset();
16218         }
16219 
16220         int left = mScrollX + paddingLeft;
16221         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
16222         int top = mScrollY + getFadeTop(offsetRequired);
16223         int bottom = top + getFadeHeight(offsetRequired);
16224 
16225         if (offsetRequired) {
16226             right += getRightPaddingOffset();
16227             bottom += getBottomPaddingOffset();
16228         }
16229 
16230         final ScrollabilityCache scrollabilityCache = mScrollCache;
16231         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
16232         int length = (int) fadeHeight;
16233 
16234         // clip the fade length if top and bottom fades overlap
16235         // overlapping fades produce odd-looking artifacts
16236         if (verticalEdges && (top + length > bottom - length)) {
16237             length = (bottom - top) / 2;
16238         }
16239 
16240         // also clip horizontal fades if necessary
16241         if (horizontalEdges && (left + length > right - length)) {
16242             length = (right - left) / 2;
16243         }
16244 
16245         if (verticalEdges) {
16246             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
16247             drawTop = topFadeStrength * fadeHeight > 1.0f;
16248             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
16249             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
16250         }
16251 
16252         if (horizontalEdges) {
16253             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
16254             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
16255             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
16256             drawRight = rightFadeStrength * fadeHeight > 1.0f;
16257         }
16258 
16259         saveCount = canvas.getSaveCount();
16260 
16261         int solidColor = getSolidColor();
16262         if (solidColor == 0) {
16263             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
16264 
16265             if (drawTop) {
16266                 canvas.saveLayer(left, top, right, top + length, null, flags);
16267             }
16268 
16269             if (drawBottom) {
16270                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
16271             }
16272 
16273             if (drawLeft) {
16274                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
16275             }
16276 
16277             if (drawRight) {
16278                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
16279             }
16280         } else {
16281             scrollabilityCache.setFadeColor(solidColor);
16282         }
16283 
16284         // Step 3, draw the content
16285         if (!dirtyOpaque) onDraw(canvas);
16286 
16287         // Step 4, draw the children
16288         dispatchDraw(canvas);
16289 
16290         // Step 5, draw the fade effect and restore layers
16291         final Paint p = scrollabilityCache.paint;
16292         final Matrix matrix = scrollabilityCache.matrix;
16293         final Shader fade = scrollabilityCache.shader;
16294 
16295         if (drawTop) {
16296             matrix.setScale(1, fadeHeight * topFadeStrength);
16297             matrix.postTranslate(left, top);
16298             fade.setLocalMatrix(matrix);
16299             p.setShader(fade);
16300             canvas.drawRect(left, top, right, top + length, p);
16301         }
16302 
16303         if (drawBottom) {
16304             matrix.setScale(1, fadeHeight * bottomFadeStrength);
16305             matrix.postRotate(180);
16306             matrix.postTranslate(left, bottom);
16307             fade.setLocalMatrix(matrix);
16308             p.setShader(fade);
16309             canvas.drawRect(left, bottom - length, right, bottom, p);
16310         }
16311 
16312         if (drawLeft) {
16313             matrix.setScale(1, fadeHeight * leftFadeStrength);
16314             matrix.postRotate(-90);
16315             matrix.postTranslate(left, top);
16316             fade.setLocalMatrix(matrix);
16317             p.setShader(fade);
16318             canvas.drawRect(left, top, left + length, bottom, p);
16319         }
16320 
16321         if (drawRight) {
16322             matrix.setScale(1, fadeHeight * rightFadeStrength);
16323             matrix.postRotate(90);
16324             matrix.postTranslate(right, top);
16325             fade.setLocalMatrix(matrix);
16326             p.setShader(fade);
16327             canvas.drawRect(right - length, top, right, bottom, p);
16328         }
16329 
16330         canvas.restoreToCount(saveCount);
16331 
16332         // Overlay is part of the content and draws beneath Foreground
16333         if (mOverlay != null && !mOverlay.isEmpty()) {
16334             mOverlay.getOverlayView().dispatchDraw(canvas);
16335         }
16336 
16337         // Step 6, draw decorations (foreground, scrollbars)
16338         onDrawForeground(canvas);
16339     }
16340 
16341     /**
16342      * Draws the background onto the specified canvas.
16343      *
16344      * @param canvas Canvas on which to draw the background
16345      */
16346     private void drawBackground(Canvas canvas) {
16347         final Drawable background = mBackground;
16348         if (background == null) {
16349             return;
16350         }
16351 
16352         setBackgroundBounds();
16353 
16354         // Attempt to use a display list if requested.
16355         if (canvas.isHardwareAccelerated() && mAttachInfo != null
16356                 && mAttachInfo.mHardwareRenderer != null) {
16357             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
16358 
16359             final RenderNode renderNode = mBackgroundRenderNode;
16360             if (renderNode != null && renderNode.isValid()) {
16361                 setBackgroundRenderNodeProperties(renderNode);
16362                 ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16363                 return;
16364             }
16365         }
16366 
16367         final int scrollX = mScrollX;
16368         final int scrollY = mScrollY;
16369         if ((scrollX | scrollY) == 0) {
16370             background.draw(canvas);
16371         } else {
16372             canvas.translate(scrollX, scrollY);
16373             background.draw(canvas);
16374             canvas.translate(-scrollX, -scrollY);
16375         }
16376     }
16377 
16378     /**
16379      * Sets the correct background bounds and rebuilds the outline, if needed.
16380      * <p/>
16381      * This is called by LayoutLib.
16382      */
16383     void setBackgroundBounds() {
16384         if (mBackgroundSizeChanged && mBackground != null) {
16385             mBackground.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
16386             mBackgroundSizeChanged = false;
16387             rebuildOutline();
16388         }
16389     }
16390 
16391     private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
16392         renderNode.setTranslationX(mScrollX);
16393         renderNode.setTranslationY(mScrollY);
16394     }
16395 
16396     /**
16397      * Creates a new display list or updates the existing display list for the
16398      * specified Drawable.
16399      *
16400      * @param drawable Drawable for which to create a display list
16401      * @param renderNode Existing RenderNode, or {@code null}
16402      * @return A valid display list for the specified drawable
16403      */
16404     private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
16405         if (renderNode == null) {
16406             renderNode = RenderNode.create(drawable.getClass().getName(), this);
16407         }
16408 
16409         final Rect bounds = drawable.getBounds();
16410         final int width = bounds.width();
16411         final int height = bounds.height();
16412         final DisplayListCanvas canvas = renderNode.start(width, height);
16413 
16414         // Reverse left/top translation done by drawable canvas, which will
16415         // instead be applied by rendernode's LTRB bounds below. This way, the
16416         // drawable's bounds match with its rendernode bounds and its content
16417         // will lie within those bounds in the rendernode tree.
16418         canvas.translate(-bounds.left, -bounds.top);
16419 
16420         try {
16421             drawable.draw(canvas);
16422         } finally {
16423             renderNode.end(canvas);
16424         }
16425 
16426         // Set up drawable properties that are view-independent.
16427         renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
16428         renderNode.setProjectBackwards(drawable.isProjected());
16429         renderNode.setProjectionReceiver(true);
16430         renderNode.setClipToBounds(false);
16431         return renderNode;
16432     }
16433 
16434     /**
16435      * Returns the overlay for this view, creating it if it does not yet exist.
16436      * Adding drawables to the overlay will cause them to be displayed whenever
16437      * the view itself is redrawn. Objects in the overlay should be actively
16438      * managed: remove them when they should not be displayed anymore. The
16439      * overlay will always have the same size as its host view.
16440      *
16441      * <p>Note: Overlays do not currently work correctly with {@link
16442      * SurfaceView} or {@link TextureView}; contents in overlays for these
16443      * types of views may not display correctly.</p>
16444      *
16445      * @return The ViewOverlay object for this view.
16446      * @see ViewOverlay
16447      */
16448     public ViewOverlay getOverlay() {
16449         if (mOverlay == null) {
16450             mOverlay = new ViewOverlay(mContext, this);
16451         }
16452         return mOverlay;
16453     }
16454 
16455     /**
16456      * Override this if your view is known to always be drawn on top of a solid color background,
16457      * and needs to draw fading edges. Returning a non-zero color enables the view system to
16458      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
16459      * should be set to 0xFF.
16460      *
16461      * @see #setVerticalFadingEdgeEnabled(boolean)
16462      * @see #setHorizontalFadingEdgeEnabled(boolean)
16463      *
16464      * @return The known solid color background for this view, or 0 if the color may vary
16465      */
16466     @ViewDebug.ExportedProperty(category = "drawing")
16467     @ColorInt
16468     public int getSolidColor() {
16469         return 0;
16470     }
16471 
16472     /**
16473      * Build a human readable string representation of the specified view flags.
16474      *
16475      * @param flags the view flags to convert to a string
16476      * @return a String representing the supplied flags
16477      */
16478     private static String printFlags(int flags) {
16479         String output = "";
16480         int numFlags = 0;
16481         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
16482             output += "TAKES_FOCUS";
16483             numFlags++;
16484         }
16485 
16486         switch (flags & VISIBILITY_MASK) {
16487         case INVISIBLE:
16488             if (numFlags > 0) {
16489                 output += " ";
16490             }
16491             output += "INVISIBLE";
16492             // USELESS HERE numFlags++;
16493             break;
16494         case GONE:
16495             if (numFlags > 0) {
16496                 output += " ";
16497             }
16498             output += "GONE";
16499             // USELESS HERE numFlags++;
16500             break;
16501         default:
16502             break;
16503         }
16504         return output;
16505     }
16506 
16507     /**
16508      * Build a human readable string representation of the specified private
16509      * view flags.
16510      *
16511      * @param privateFlags the private view flags to convert to a string
16512      * @return a String representing the supplied flags
16513      */
16514     private static String printPrivateFlags(int privateFlags) {
16515         String output = "";
16516         int numFlags = 0;
16517 
16518         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
16519             output += "WANTS_FOCUS";
16520             numFlags++;
16521         }
16522 
16523         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
16524             if (numFlags > 0) {
16525                 output += " ";
16526             }
16527             output += "FOCUSED";
16528             numFlags++;
16529         }
16530 
16531         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
16532             if (numFlags > 0) {
16533                 output += " ";
16534             }
16535             output += "SELECTED";
16536             numFlags++;
16537         }
16538 
16539         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
16540             if (numFlags > 0) {
16541                 output += " ";
16542             }
16543             output += "IS_ROOT_NAMESPACE";
16544             numFlags++;
16545         }
16546 
16547         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
16548             if (numFlags > 0) {
16549                 output += " ";
16550             }
16551             output += "HAS_BOUNDS";
16552             numFlags++;
16553         }
16554 
16555         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
16556             if (numFlags > 0) {
16557                 output += " ";
16558             }
16559             output += "DRAWN";
16560             // USELESS HERE numFlags++;
16561         }
16562         return output;
16563     }
16564 
16565     /**
16566      * <p>Indicates whether or not this view's layout will be requested during
16567      * the next hierarchy layout pass.</p>
16568      *
16569      * @return true if the layout will be forced during next layout pass
16570      */
16571     public boolean isLayoutRequested() {
16572         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16573     }
16574 
16575     /**
16576      * Return true if o is a ViewGroup that is laying out using optical bounds.
16577      * @hide
16578      */
16579     public static boolean isLayoutModeOptical(Object o) {
16580         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16581     }
16582 
16583     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16584         Insets parentInsets = mParent instanceof View ?
16585                 ((View) mParent).getOpticalInsets() : Insets.NONE;
16586         Insets childInsets = getOpticalInsets();
16587         return setFrame(
16588                 left   + parentInsets.left - childInsets.left,
16589                 top    + parentInsets.top  - childInsets.top,
16590                 right  + parentInsets.left + childInsets.right,
16591                 bottom + parentInsets.top  + childInsets.bottom);
16592     }
16593 
16594     /**
16595      * Assign a size and position to a view and all of its
16596      * descendants
16597      *
16598      * <p>This is the second phase of the layout mechanism.
16599      * (The first is measuring). In this phase, each parent calls
16600      * layout on all of its children to position them.
16601      * This is typically done using the child measurements
16602      * that were stored in the measure pass().</p>
16603      *
16604      * <p>Derived classes should not override this method.
16605      * Derived classes with children should override
16606      * onLayout. In that method, they should
16607      * call layout on each of their children.</p>
16608      *
16609      * @param l Left position, relative to parent
16610      * @param t Top position, relative to parent
16611      * @param r Right position, relative to parent
16612      * @param b Bottom position, relative to parent
16613      */
16614     @SuppressWarnings({"unchecked"})
16615     public void layout(int l, int t, int r, int b) {
16616         if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16617             onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16618             mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16619         }
16620 
16621         int oldL = mLeft;
16622         int oldT = mTop;
16623         int oldB = mBottom;
16624         int oldR = mRight;
16625 
16626         boolean changed = isLayoutModeOptical(mParent) ?
16627                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16628 
16629         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
16630             onLayout(changed, l, t, r, b);
16631             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
16632 
16633             ListenerInfo li = mListenerInfo;
16634             if (li != null && li.mOnLayoutChangeListeners != null) {
16635                 ArrayList<OnLayoutChangeListener> listenersCopy =
16636                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
16637                 int numListeners = listenersCopy.size();
16638                 for (int i = 0; i < numListeners; ++i) {
16639                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
16640                 }
16641             }
16642         }
16643 
16644         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
16645         mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
16646     }
16647 
16648     /**
16649      * Called from layout when this view should
16650      * assign a size and position to each of its children.
16651      *
16652      * Derived classes with children should override
16653      * this method and call layout on each of
16654      * their children.
16655      * @param changed This is a new size or position for this view
16656      * @param left Left position, relative to parent
16657      * @param top Top position, relative to parent
16658      * @param right Right position, relative to parent
16659      * @param bottom Bottom position, relative to parent
16660      */
16661     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
16662     }
16663 
16664     /**
16665      * Assign a size and position to this view.
16666      *
16667      * This is called from layout.
16668      *
16669      * @param left Left position, relative to parent
16670      * @param top Top position, relative to parent
16671      * @param right Right position, relative to parent
16672      * @param bottom Bottom position, relative to parent
16673      * @return true if the new size and position are different than the
16674      *         previous ones
16675      * {@hide}
16676      */
16677     protected boolean setFrame(int left, int top, int right, int bottom) {
16678         boolean changed = false;
16679 
16680         if (DBG) {
16681             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16682                     + right + "," + bottom + ")");
16683         }
16684 
16685         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16686             changed = true;
16687 
16688             // Remember our drawn bit
16689             int drawn = mPrivateFlags & PFLAG_DRAWN;
16690 
16691             int oldWidth = mRight - mLeft;
16692             int oldHeight = mBottom - mTop;
16693             int newWidth = right - left;
16694             int newHeight = bottom - top;
16695             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16696 
16697             // Invalidate our old position
16698             invalidate(sizeChanged);
16699 
16700             mLeft = left;
16701             mTop = top;
16702             mRight = right;
16703             mBottom = bottom;
16704             mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16705 
16706             mPrivateFlags |= PFLAG_HAS_BOUNDS;
16707 
16708 
16709             if (sizeChanged) {
16710                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16711             }
16712 
16713             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16714                 // If we are visible, force the DRAWN bit to on so that
16715                 // this invalidate will go through (at least to our parent).
16716                 // This is because someone may have invalidated this view
16717                 // before this call to setFrame came in, thereby clearing
16718                 // the DRAWN bit.
16719                 mPrivateFlags |= PFLAG_DRAWN;
16720                 invalidate(sizeChanged);
16721                 // parent display list may need to be recreated based on a change in the bounds
16722                 // of any child
16723                 invalidateParentCaches();
16724             }
16725 
16726             // Reset drawn bit to original value (invalidate turns it off)
16727             mPrivateFlags |= drawn;
16728 
16729             mBackgroundSizeChanged = true;
16730             if (mForegroundInfo != null) {
16731                 mForegroundInfo.mBoundsChanged = true;
16732             }
16733 
16734             notifySubtreeAccessibilityStateChangedIfNeeded();
16735         }
16736         return changed;
16737     }
16738 
16739     /**
16740      * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
16741      * @hide
16742      */
16743     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
16744         setFrame(left, top, right, bottom);
16745     }
16746 
16747     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
16748         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
16749         if (mOverlay != null) {
16750             mOverlay.getOverlayView().setRight(newWidth);
16751             mOverlay.getOverlayView().setBottom(newHeight);
16752         }
16753         rebuildOutline();
16754     }
16755 
16756     /**
16757      * Finalize inflating a view from XML.  This is called as the last phase
16758      * of inflation, after all child views have been added.
16759      *
16760      * <p>Even if the subclass overrides onFinishInflate, they should always be
16761      * sure to call the super method, so that we get called.
16762      */
16763     @CallSuper
16764     protected void onFinishInflate() {
16765     }
16766 
16767     /**
16768      * Returns the resources associated with this view.
16769      *
16770      * @return Resources object.
16771      */
16772     public Resources getResources() {
16773         return mResources;
16774     }
16775 
16776     /**
16777      * Invalidates the specified Drawable.
16778      *
16779      * @param drawable the drawable to invalidate
16780      */
16781     @Override
16782     public void invalidateDrawable(@NonNull Drawable drawable) {
16783         if (verifyDrawable(drawable)) {
16784             final Rect dirty = drawable.getDirtyBounds();
16785             final int scrollX = mScrollX;
16786             final int scrollY = mScrollY;
16787 
16788             invalidate(dirty.left + scrollX, dirty.top + scrollY,
16789                     dirty.right + scrollX, dirty.bottom + scrollY);
16790             rebuildOutline();
16791         }
16792     }
16793 
16794     /**
16795      * Schedules an action on a drawable to occur at a specified time.
16796      *
16797      * @param who the recipient of the action
16798      * @param what the action to run on the drawable
16799      * @param when the time at which the action must occur. Uses the
16800      *        {@link SystemClock#uptimeMillis} timebase.
16801      */
16802     @Override
16803     public void scheduleDrawable(Drawable who, Runnable what, long when) {
16804         if (verifyDrawable(who) && what != null) {
16805             final long delay = when - SystemClock.uptimeMillis();
16806             if (mAttachInfo != null) {
16807                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
16808                         Choreographer.CALLBACK_ANIMATION, what, who,
16809                         Choreographer.subtractFrameDelay(delay));
16810             } else {
16811                 ViewRootImpl.getRunQueue().postDelayed(what, delay);
16812             }
16813         }
16814     }
16815 
16816     /**
16817      * Cancels a scheduled action on a drawable.
16818      *
16819      * @param who the recipient of the action
16820      * @param what the action to cancel
16821      */
16822     @Override
16823     public void unscheduleDrawable(Drawable who, Runnable what) {
16824         if (verifyDrawable(who) && what != null) {
16825             if (mAttachInfo != null) {
16826                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16827                         Choreographer.CALLBACK_ANIMATION, what, who);
16828             }
16829             ViewRootImpl.getRunQueue().removeCallbacks(what);
16830         }
16831     }
16832 
16833     /**
16834      * Unschedule any events associated with the given Drawable.  This can be
16835      * used when selecting a new Drawable into a view, so that the previous
16836      * one is completely unscheduled.
16837      *
16838      * @param who The Drawable to unschedule.
16839      *
16840      * @see #drawableStateChanged
16841      */
16842     public void unscheduleDrawable(Drawable who) {
16843         if (mAttachInfo != null && who != null) {
16844             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16845                     Choreographer.CALLBACK_ANIMATION, null, who);
16846         }
16847     }
16848 
16849     /**
16850      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
16851      * that the View directionality can and will be resolved before its Drawables.
16852      *
16853      * Will call {@link View#onResolveDrawables} when resolution is done.
16854      *
16855      * @hide
16856      */
16857     protected void resolveDrawables() {
16858         // Drawables resolution may need to happen before resolving the layout direction (which is
16859         // done only during the measure() call).
16860         // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
16861         // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
16862         // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
16863         // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
16864         // direction to be resolved as its resolved value will be the same as its raw value.
16865         if (!isLayoutDirectionResolved() &&
16866                 getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
16867             return;
16868         }
16869 
16870         final int layoutDirection = isLayoutDirectionResolved() ?
16871                 getLayoutDirection() : getRawLayoutDirection();
16872 
16873         if (mBackground != null) {
16874             mBackground.setLayoutDirection(layoutDirection);
16875         }
16876         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16877             mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
16878         }
16879         mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
16880         onResolveDrawables(layoutDirection);
16881     }
16882 
16883     boolean areDrawablesResolved() {
16884         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
16885     }
16886 
16887     /**
16888      * Called when layout direction has been resolved.
16889      *
16890      * The default implementation does nothing.
16891      *
16892      * @param layoutDirection The resolved layout direction.
16893      *
16894      * @see #LAYOUT_DIRECTION_LTR
16895      * @see #LAYOUT_DIRECTION_RTL
16896      *
16897      * @hide
16898      */
16899     public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
16900     }
16901 
16902     /**
16903      * @hide
16904      */
16905     protected void resetResolvedDrawables() {
16906         resetResolvedDrawablesInternal();
16907     }
16908 
16909     void resetResolvedDrawablesInternal() {
16910         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
16911     }
16912 
16913     /**
16914      * If your view subclass is displaying its own Drawable objects, it should
16915      * override this function and return true for any Drawable it is
16916      * displaying.  This allows animations for those drawables to be
16917      * scheduled.
16918      *
16919      * <p>Be sure to call through to the super class when overriding this
16920      * function.
16921      *
16922      * @param who The Drawable to verify.  Return true if it is one you are
16923      *            displaying, else return the result of calling through to the
16924      *            super class.
16925      *
16926      * @return boolean If true than the Drawable is being displayed in the
16927      *         view; else false and it is not allowed to animate.
16928      *
16929      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
16930      * @see #drawableStateChanged()
16931      */
16932     @CallSuper
16933     protected boolean verifyDrawable(Drawable who) {
16934         return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
16935                 || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
16936     }
16937 
16938     /**
16939      * This function is called whenever the state of the view changes in such
16940      * a way that it impacts the state of drawables being shown.
16941      * <p>
16942      * If the View has a StateListAnimator, it will also be called to run necessary state
16943      * change animations.
16944      * <p>
16945      * Be sure to call through to the superclass when overriding this function.
16946      *
16947      * @see Drawable#setState(int[])
16948      */
16949     @CallSuper
16950     protected void drawableStateChanged() {
16951         final int[] state = getDrawableState();
16952 
16953         final Drawable bg = mBackground;
16954         if (bg != null && bg.isStateful()) {
16955             bg.setState(state);
16956         }
16957 
16958         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16959         if (fg != null && fg.isStateful()) {
16960             fg.setState(state);
16961         }
16962 
16963         if (mScrollCache != null) {
16964             final Drawable scrollBar = mScrollCache.scrollBar;
16965             if (scrollBar != null && scrollBar.isStateful()) {
16966                 scrollBar.setState(state);
16967             }
16968         }
16969 
16970         if (mStateListAnimator != null) {
16971             mStateListAnimator.setState(state);
16972         }
16973     }
16974 
16975     /**
16976      * This function is called whenever the view hotspot changes and needs to
16977      * be propagated to drawables or child views managed by the view.
16978      * <p>
16979      * Dispatching to child views is handled by
16980      * {@link #dispatchDrawableHotspotChanged(float, float)}.
16981      * <p>
16982      * Be sure to call through to the superclass when overriding this function.
16983      *
16984      * @param x hotspot x coordinate
16985      * @param y hotspot y coordinate
16986      */
16987     @CallSuper
16988     public void drawableHotspotChanged(float x, float y) {
16989         if (mBackground != null) {
16990             mBackground.setHotspot(x, y);
16991         }
16992         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16993             mForegroundInfo.mDrawable.setHotspot(x, y);
16994         }
16995 
16996         dispatchDrawableHotspotChanged(x, y);
16997     }
16998 
16999     /**
17000      * Dispatches drawableHotspotChanged to all of this View's children.
17001      *
17002      * @param x hotspot x coordinate
17003      * @param y hotspot y coordinate
17004      * @see #drawableHotspotChanged(float, float)
17005      */
17006     public void dispatchDrawableHotspotChanged(float x, float y) {
17007     }
17008 
17009     /**
17010      * Call this to force a view to update its drawable state. This will cause
17011      * drawableStateChanged to be called on this view. Views that are interested
17012      * in the new state should call getDrawableState.
17013      *
17014      * @see #drawableStateChanged
17015      * @see #getDrawableState
17016      */
17017     public void refreshDrawableState() {
17018         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17019         drawableStateChanged();
17020 
17021         ViewParent parent = mParent;
17022         if (parent != null) {
17023             parent.childDrawableStateChanged(this);
17024         }
17025     }
17026 
17027     /**
17028      * Return an array of resource IDs of the drawable states representing the
17029      * current state of the view.
17030      *
17031      * @return The current drawable state
17032      *
17033      * @see Drawable#setState(int[])
17034      * @see #drawableStateChanged()
17035      * @see #onCreateDrawableState(int)
17036      */
17037     public final int[] getDrawableState() {
17038         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
17039             return mDrawableState;
17040         } else {
17041             mDrawableState = onCreateDrawableState(0);
17042             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
17043             return mDrawableState;
17044         }
17045     }
17046 
17047     /**
17048      * Generate the new {@link android.graphics.drawable.Drawable} state for
17049      * this view. This is called by the view
17050      * system when the cached Drawable state is determined to be invalid.  To
17051      * retrieve the current state, you should use {@link #getDrawableState}.
17052      *
17053      * @param extraSpace if non-zero, this is the number of extra entries you
17054      * would like in the returned array in which you can place your own
17055      * states.
17056      *
17057      * @return Returns an array holding the current {@link Drawable} state of
17058      * the view.
17059      *
17060      * @see #mergeDrawableStates(int[], int[])
17061      */
17062     protected int[] onCreateDrawableState(int extraSpace) {
17063         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
17064                 mParent instanceof View) {
17065             return ((View) mParent).onCreateDrawableState(extraSpace);
17066         }
17067 
17068         int[] drawableState;
17069 
17070         int privateFlags = mPrivateFlags;
17071 
17072         int viewStateIndex = 0;
17073         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
17074         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
17075         if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
17076         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
17077         if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
17078         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
17079         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
17080                 HardwareRenderer.isAvailable()) {
17081             // This is set if HW acceleration is requested, even if the current
17082             // process doesn't allow it.  This is just to allow app preview
17083             // windows to better match their app.
17084             viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
17085         }
17086         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
17087 
17088         final int privateFlags2 = mPrivateFlags2;
17089         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
17090             viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
17091         }
17092         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
17093             viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
17094         }
17095 
17096         drawableState = StateSet.get(viewStateIndex);
17097 
17098         //noinspection ConstantIfStatement
17099         if (false) {
17100             Log.i("View", "drawableStateIndex=" + viewStateIndex);
17101             Log.i("View", toString()
17102                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
17103                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
17104                     + " fo=" + hasFocus()
17105                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
17106                     + " wf=" + hasWindowFocus()
17107                     + ": " + Arrays.toString(drawableState));
17108         }
17109 
17110         if (extraSpace == 0) {
17111             return drawableState;
17112         }
17113 
17114         final int[] fullState;
17115         if (drawableState != null) {
17116             fullState = new int[drawableState.length + extraSpace];
17117             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
17118         } else {
17119             fullState = new int[extraSpace];
17120         }
17121 
17122         return fullState;
17123     }
17124 
17125     /**
17126      * Merge your own state values in <var>additionalState</var> into the base
17127      * state values <var>baseState</var> that were returned by
17128      * {@link #onCreateDrawableState(int)}.
17129      *
17130      * @param baseState The base state values returned by
17131      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
17132      * own additional state values.
17133      *
17134      * @param additionalState The additional state values you would like
17135      * added to <var>baseState</var>; this array is not modified.
17136      *
17137      * @return As a convenience, the <var>baseState</var> array you originally
17138      * passed into the function is returned.
17139      *
17140      * @see #onCreateDrawableState(int)
17141      */
17142     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
17143         final int N = baseState.length;
17144         int i = N - 1;
17145         while (i >= 0 && baseState[i] == 0) {
17146             i--;
17147         }
17148         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
17149         return baseState;
17150     }
17151 
17152     /**
17153      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
17154      * on all Drawable objects associated with this view.
17155      * <p>
17156      * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
17157      * attached to this view.
17158      */
17159     @CallSuper
17160     public void jumpDrawablesToCurrentState() {
17161         if (mBackground != null) {
17162             mBackground.jumpToCurrentState();
17163         }
17164         if (mStateListAnimator != null) {
17165             mStateListAnimator.jumpToCurrentState();
17166         }
17167         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17168             mForegroundInfo.mDrawable.jumpToCurrentState();
17169         }
17170     }
17171 
17172     /**
17173      * Sets the background color for this view.
17174      * @param color the color of the background
17175      */
17176     @RemotableViewMethod
17177     public void setBackgroundColor(@ColorInt int color) {
17178         if (mBackground instanceof ColorDrawable) {
17179             ((ColorDrawable) mBackground.mutate()).setColor(color);
17180             computeOpaqueFlags();
17181             mBackgroundResource = 0;
17182         } else {
17183             setBackground(new ColorDrawable(color));
17184         }
17185     }
17186 
17187     /**
17188      * Set the background to a given resource. The resource should refer to
17189      * a Drawable object or 0 to remove the background.
17190      * @param resid The identifier of the resource.
17191      *
17192      * @attr ref android.R.styleable#View_background
17193      */
17194     @RemotableViewMethod
17195     public void setBackgroundResource(@DrawableRes int resid) {
17196         if (resid != 0 && resid == mBackgroundResource) {
17197             return;
17198         }
17199 
17200         Drawable d = null;
17201         if (resid != 0) {
17202             d = mContext.getDrawable(resid);
17203         }
17204         setBackground(d);
17205 
17206         mBackgroundResource = resid;
17207     }
17208 
17209     /**
17210      * Set the background to a given Drawable, or remove the background. If the
17211      * background has padding, this View's padding is set to the background's
17212      * padding. However, when a background is removed, this View's padding isn't
17213      * touched. If setting the padding is desired, please use
17214      * {@link #setPadding(int, int, int, int)}.
17215      *
17216      * @param background The Drawable to use as the background, or null to remove the
17217      *        background
17218      */
17219     public void setBackground(Drawable background) {
17220         //noinspection deprecation
17221         setBackgroundDrawable(background);
17222     }
17223 
17224     /**
17225      * @deprecated use {@link #setBackground(Drawable)} instead
17226      */
17227     @Deprecated
17228     public void setBackgroundDrawable(Drawable background) {
17229         computeOpaqueFlags();
17230 
17231         if (background == mBackground) {
17232             return;
17233         }
17234 
17235         boolean requestLayout = false;
17236 
17237         mBackgroundResource = 0;
17238 
17239         /*
17240          * Regardless of whether we're setting a new background or not, we want
17241          * to clear the previous drawable.
17242          */
17243         if (mBackground != null) {
17244             mBackground.setCallback(null);
17245             unscheduleDrawable(mBackground);
17246         }
17247 
17248         if (background != null) {
17249             Rect padding = sThreadLocal.get();
17250             if (padding == null) {
17251                 padding = new Rect();
17252                 sThreadLocal.set(padding);
17253             }
17254             resetResolvedDrawablesInternal();
17255             background.setLayoutDirection(getLayoutDirection());
17256             if (background.getPadding(padding)) {
17257                 resetResolvedPaddingInternal();
17258                 switch (background.getLayoutDirection()) {
17259                     case LAYOUT_DIRECTION_RTL:
17260                         mUserPaddingLeftInitial = padding.right;
17261                         mUserPaddingRightInitial = padding.left;
17262                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
17263                         break;
17264                     case LAYOUT_DIRECTION_LTR:
17265                     default:
17266                         mUserPaddingLeftInitial = padding.left;
17267                         mUserPaddingRightInitial = padding.right;
17268                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
17269                 }
17270                 mLeftPaddingDefined = false;
17271                 mRightPaddingDefined = false;
17272             }
17273 
17274             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
17275             // if it has a different minimum size, we should layout again
17276             if (mBackground == null
17277                     || mBackground.getMinimumHeight() != background.getMinimumHeight()
17278                     || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
17279                 requestLayout = true;
17280             }
17281 
17282             background.setCallback(this);
17283             if (background.isStateful()) {
17284                 background.setState(getDrawableState());
17285             }
17286             background.setVisible(getVisibility() == VISIBLE, false);
17287             mBackground = background;
17288 
17289             applyBackgroundTint();
17290 
17291             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17292                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17293                 requestLayout = true;
17294             }
17295         } else {
17296             /* Remove the background */
17297             mBackground = null;
17298             if ((mViewFlags & WILL_NOT_DRAW) != 0
17299                     && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
17300                 mPrivateFlags |= PFLAG_SKIP_DRAW;
17301             }
17302 
17303             /*
17304              * When the background is set, we try to apply its padding to this
17305              * View. When the background is removed, we don't touch this View's
17306              * padding. This is noted in the Javadocs. Hence, we don't need to
17307              * requestLayout(), the invalidate() below is sufficient.
17308              */
17309 
17310             // The old background's minimum size could have affected this
17311             // View's layout, so let's requestLayout
17312             requestLayout = true;
17313         }
17314 
17315         computeOpaqueFlags();
17316 
17317         if (requestLayout) {
17318             requestLayout();
17319         }
17320 
17321         mBackgroundSizeChanged = true;
17322         invalidate(true);
17323     }
17324 
17325     /**
17326      * Gets the background drawable
17327      *
17328      * @return The drawable used as the background for this view, if any.
17329      *
17330      * @see #setBackground(Drawable)
17331      *
17332      * @attr ref android.R.styleable#View_background
17333      */
17334     public Drawable getBackground() {
17335         return mBackground;
17336     }
17337 
17338     /**
17339      * Applies a tint to the background drawable. Does not modify the current tint
17340      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17341      * <p>
17342      * Subsequent calls to {@link #setBackground(Drawable)} will automatically
17343      * mutate the drawable and apply the specified tint and tint mode using
17344      * {@link Drawable#setTintList(ColorStateList)}.
17345      *
17346      * @param tint the tint to apply, may be {@code null} to clear tint
17347      *
17348      * @attr ref android.R.styleable#View_backgroundTint
17349      * @see #getBackgroundTintList()
17350      * @see Drawable#setTintList(ColorStateList)
17351      */
17352     public void setBackgroundTintList(@Nullable ColorStateList tint) {
17353         if (mBackgroundTint == null) {
17354             mBackgroundTint = new TintInfo();
17355         }
17356         mBackgroundTint.mTintList = tint;
17357         mBackgroundTint.mHasTintList = true;
17358 
17359         applyBackgroundTint();
17360     }
17361 
17362     /**
17363      * Return the tint applied to the background drawable, if specified.
17364      *
17365      * @return the tint applied to the background drawable
17366      * @attr ref android.R.styleable#View_backgroundTint
17367      * @see #setBackgroundTintList(ColorStateList)
17368      */
17369     @Nullable
17370     public ColorStateList getBackgroundTintList() {
17371         return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
17372     }
17373 
17374     /**
17375      * Specifies the blending mode used to apply the tint specified by
17376      * {@link #setBackgroundTintList(ColorStateList)}} to the background
17377      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17378      *
17379      * @param tintMode the blending mode used to apply the tint, may be
17380      *                 {@code null} to clear tint
17381      * @attr ref android.R.styleable#View_backgroundTintMode
17382      * @see #getBackgroundTintMode()
17383      * @see Drawable#setTintMode(PorterDuff.Mode)
17384      */
17385     public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17386         if (mBackgroundTint == null) {
17387             mBackgroundTint = new TintInfo();
17388         }
17389         mBackgroundTint.mTintMode = tintMode;
17390         mBackgroundTint.mHasTintMode = true;
17391 
17392         applyBackgroundTint();
17393     }
17394 
17395     /**
17396      * Return the blending mode used to apply the tint to the background
17397      * drawable, if specified.
17398      *
17399      * @return the blending mode used to apply the tint to the background
17400      *         drawable
17401      * @attr ref android.R.styleable#View_backgroundTintMode
17402      * @see #setBackgroundTintMode(PorterDuff.Mode)
17403      */
17404     @Nullable
17405     public PorterDuff.Mode getBackgroundTintMode() {
17406         return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
17407     }
17408 
17409     private void applyBackgroundTint() {
17410         if (mBackground != null && mBackgroundTint != null) {
17411             final TintInfo tintInfo = mBackgroundTint;
17412             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17413                 mBackground = mBackground.mutate();
17414 
17415                 if (tintInfo.mHasTintList) {
17416                     mBackground.setTintList(tintInfo.mTintList);
17417                 }
17418 
17419                 if (tintInfo.mHasTintMode) {
17420                     mBackground.setTintMode(tintInfo.mTintMode);
17421                 }
17422 
17423                 // The drawable (or one of its children) may not have been
17424                 // stateful before applying the tint, so let's try again.
17425                 if (mBackground.isStateful()) {
17426                     mBackground.setState(getDrawableState());
17427                 }
17428             }
17429         }
17430     }
17431 
17432     /**
17433      * Returns the drawable used as the foreground of this View. The
17434      * foreground drawable, if non-null, is always drawn on top of the view's content.
17435      *
17436      * @return a Drawable or null if no foreground was set
17437      *
17438      * @see #onDrawForeground(Canvas)
17439      */
17440     public Drawable getForeground() {
17441         return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17442     }
17443 
17444     /**
17445      * Supply a Drawable that is to be rendered on top of all of the content in the view.
17446      *
17447      * @param foreground the Drawable to be drawn on top of the children
17448      *
17449      * @attr ref android.R.styleable#View_foreground
17450      */
17451     public void setForeground(Drawable foreground) {
17452         if (mForegroundInfo == null) {
17453             if (foreground == null) {
17454                 // Nothing to do.
17455                 return;
17456             }
17457             mForegroundInfo = new ForegroundInfo();
17458         }
17459 
17460         if (foreground == mForegroundInfo.mDrawable) {
17461             // Nothing to do
17462             return;
17463         }
17464 
17465         if (mForegroundInfo.mDrawable != null) {
17466             mForegroundInfo.mDrawable.setCallback(null);
17467             unscheduleDrawable(mForegroundInfo.mDrawable);
17468         }
17469 
17470         mForegroundInfo.mDrawable = foreground;
17471         mForegroundInfo.mBoundsChanged = true;
17472         if (foreground != null) {
17473             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17474                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17475             }
17476             foreground.setCallback(this);
17477             foreground.setLayoutDirection(getLayoutDirection());
17478             if (foreground.isStateful()) {
17479                 foreground.setState(getDrawableState());
17480             }
17481             applyForegroundTint();
17482         } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
17483             mPrivateFlags |= PFLAG_SKIP_DRAW;
17484         }
17485         requestLayout();
17486         invalidate();
17487     }
17488 
17489     /**
17490      * Magic bit used to support features of framework-internal window decor implementation details.
17491      * This used to live exclusively in FrameLayout.
17492      *
17493      * @return true if the foreground should draw inside the padding region or false
17494      *         if it should draw inset by the view's padding
17495      * @hide internal use only; only used by FrameLayout and internal screen layouts.
17496      */
17497     public boolean isForegroundInsidePadding() {
17498         return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
17499     }
17500 
17501     /**
17502      * Describes how the foreground is positioned.
17503      *
17504      * @return foreground gravity.
17505      *
17506      * @see #setForegroundGravity(int)
17507      *
17508      * @attr ref android.R.styleable#View_foregroundGravity
17509      */
17510     public int getForegroundGravity() {
17511         return mForegroundInfo != null ? mForegroundInfo.mGravity
17512                 : Gravity.START | Gravity.TOP;
17513     }
17514 
17515     /**
17516      * Describes how the foreground is positioned. Defaults to START and TOP.
17517      *
17518      * @param gravity see {@link android.view.Gravity}
17519      *
17520      * @see #getForegroundGravity()
17521      *
17522      * @attr ref android.R.styleable#View_foregroundGravity
17523      */
17524     public void setForegroundGravity(int gravity) {
17525         if (mForegroundInfo == null) {
17526             mForegroundInfo = new ForegroundInfo();
17527         }
17528 
17529         if (mForegroundInfo.mGravity != gravity) {
17530             if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
17531                 gravity |= Gravity.START;
17532             }
17533 
17534             if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
17535                 gravity |= Gravity.TOP;
17536             }
17537 
17538             mForegroundInfo.mGravity = gravity;
17539             requestLayout();
17540         }
17541     }
17542 
17543     /**
17544      * Applies a tint to the foreground drawable. Does not modify the current tint
17545      * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17546      * <p>
17547      * Subsequent calls to {@link #setForeground(Drawable)} will automatically
17548      * mutate the drawable and apply the specified tint and tint mode using
17549      * {@link Drawable#setTintList(ColorStateList)}.
17550      *
17551      * @param tint the tint to apply, may be {@code null} to clear tint
17552      *
17553      * @attr ref android.R.styleable#View_foregroundTint
17554      * @see #getForegroundTintList()
17555      * @see Drawable#setTintList(ColorStateList)
17556      */
17557     public void setForegroundTintList(@Nullable ColorStateList tint) {
17558         if (mForegroundInfo == null) {
17559             mForegroundInfo = new ForegroundInfo();
17560         }
17561         if (mForegroundInfo.mTintInfo == null) {
17562             mForegroundInfo.mTintInfo = new TintInfo();
17563         }
17564         mForegroundInfo.mTintInfo.mTintList = tint;
17565         mForegroundInfo.mTintInfo.mHasTintList = true;
17566 
17567         applyForegroundTint();
17568     }
17569 
17570     /**
17571      * Return the tint applied to the foreground drawable, if specified.
17572      *
17573      * @return the tint applied to the foreground drawable
17574      * @attr ref android.R.styleable#View_foregroundTint
17575      * @see #setForegroundTintList(ColorStateList)
17576      */
17577     @Nullable
17578     public ColorStateList getForegroundTintList() {
17579         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17580                 ? mForegroundInfo.mTintInfo.mTintList : null;
17581     }
17582 
17583     /**
17584      * Specifies the blending mode used to apply the tint specified by
17585      * {@link #setForegroundTintList(ColorStateList)}} to the background
17586      * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17587      *
17588      * @param tintMode the blending mode used to apply the tint, may be
17589      *                 {@code null} to clear tint
17590      * @attr ref android.R.styleable#View_foregroundTintMode
17591      * @see #getForegroundTintMode()
17592      * @see Drawable#setTintMode(PorterDuff.Mode)
17593      */
17594     public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17595         if (mForegroundInfo == null) {
17596             mForegroundInfo = new ForegroundInfo();
17597         }
17598         if (mForegroundInfo.mTintInfo == null) {
17599             mForegroundInfo.mTintInfo = new TintInfo();
17600         }
17601         mForegroundInfo.mTintInfo.mTintMode = tintMode;
17602         mForegroundInfo.mTintInfo.mHasTintMode = true;
17603 
17604         applyForegroundTint();
17605     }
17606 
17607     /**
17608      * Return the blending mode used to apply the tint to the foreground
17609      * drawable, if specified.
17610      *
17611      * @return the blending mode used to apply the tint to the foreground
17612      *         drawable
17613      * @attr ref android.R.styleable#View_foregroundTintMode
17614      * @see #setForegroundTintMode(PorterDuff.Mode)
17615      */
17616     @Nullable
17617     public PorterDuff.Mode getForegroundTintMode() {
17618         return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17619                 ? mForegroundInfo.mTintInfo.mTintMode : null;
17620     }
17621 
17622     private void applyForegroundTint() {
17623         if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
17624                 && mForegroundInfo.mTintInfo != null) {
17625             final TintInfo tintInfo = mForegroundInfo.mTintInfo;
17626             if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17627                 mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
17628 
17629                 if (tintInfo.mHasTintList) {
17630                     mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
17631                 }
17632 
17633                 if (tintInfo.mHasTintMode) {
17634                     mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
17635                 }
17636 
17637                 // The drawable (or one of its children) may not have been
17638                 // stateful before applying the tint, so let's try again.
17639                 if (mForegroundInfo.mDrawable.isStateful()) {
17640                     mForegroundInfo.mDrawable.setState(getDrawableState());
17641                 }
17642             }
17643         }
17644     }
17645 
17646     /**
17647      * Draw any foreground content for this view.
17648      *
17649      * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
17650      * drawable or other view-specific decorations. The foreground is drawn on top of the
17651      * primary view content.</p>
17652      *
17653      * @param canvas canvas to draw into
17654      */
17655     public void onDrawForeground(Canvas canvas) {
17656         onDrawScrollIndicators(canvas);
17657         onDrawScrollBars(canvas);
17658 
17659         final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17660         if (foreground != null) {
17661             if (mForegroundInfo.mBoundsChanged) {
17662                 mForegroundInfo.mBoundsChanged = false;
17663                 final Rect selfBounds = mForegroundInfo.mSelfBounds;
17664                 final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17665 
17666                 if (mForegroundInfo.mInsidePadding) {
17667                     selfBounds.set(0, 0, getWidth(), getHeight());
17668                 } else {
17669                     selfBounds.set(getPaddingLeft(), getPaddingTop(),
17670                             getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17671                 }
17672 
17673                 final int ld = getLayoutDirection();
17674                 Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17675                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17676                 foreground.setBounds(overlayBounds);
17677             }
17678 
17679             foreground.draw(canvas);
17680         }
17681     }
17682 
17683     /**
17684      * Sets the padding. The view may add on the space required to display
17685      * the scrollbars, depending on the style and visibility of the scrollbars.
17686      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17687      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17688      * from the values set in this call.
17689      *
17690      * @attr ref android.R.styleable#View_padding
17691      * @attr ref android.R.styleable#View_paddingBottom
17692      * @attr ref android.R.styleable#View_paddingLeft
17693      * @attr ref android.R.styleable#View_paddingRight
17694      * @attr ref android.R.styleable#View_paddingTop
17695      * @param left the left padding in pixels
17696      * @param top the top padding in pixels
17697      * @param right the right padding in pixels
17698      * @param bottom the bottom padding in pixels
17699      */
17700     public void setPadding(int left, int top, int right, int bottom) {
17701         resetResolvedPaddingInternal();
17702 
17703         mUserPaddingStart = UNDEFINED_PADDING;
17704         mUserPaddingEnd = UNDEFINED_PADDING;
17705 
17706         mUserPaddingLeftInitial = left;
17707         mUserPaddingRightInitial = right;
17708 
17709         mLeftPaddingDefined = true;
17710         mRightPaddingDefined = true;
17711 
17712         internalSetPadding(left, top, right, bottom);
17713     }
17714 
17715     /**
17716      * @hide
17717      */
17718     protected void internalSetPadding(int left, int top, int right, int bottom) {
17719         mUserPaddingLeft = left;
17720         mUserPaddingRight = right;
17721         mUserPaddingBottom = bottom;
17722 
17723         final int viewFlags = mViewFlags;
17724         boolean changed = false;
17725 
17726         // Common case is there are no scroll bars.
17727         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
17728             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
17729                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
17730                         ? 0 : getVerticalScrollbarWidth();
17731                 switch (mVerticalScrollbarPosition) {
17732                     case SCROLLBAR_POSITION_DEFAULT:
17733                         if (isLayoutRtl()) {
17734                             left += offset;
17735                         } else {
17736                             right += offset;
17737                         }
17738                         break;
17739                     case SCROLLBAR_POSITION_RIGHT:
17740                         right += offset;
17741                         break;
17742                     case SCROLLBAR_POSITION_LEFT:
17743                         left += offset;
17744                         break;
17745                 }
17746             }
17747             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
17748                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
17749                         ? 0 : getHorizontalScrollbarHeight();
17750             }
17751         }
17752 
17753         if (mPaddingLeft != left) {
17754             changed = true;
17755             mPaddingLeft = left;
17756         }
17757         if (mPaddingTop != top) {
17758             changed = true;
17759             mPaddingTop = top;
17760         }
17761         if (mPaddingRight != right) {
17762             changed = true;
17763             mPaddingRight = right;
17764         }
17765         if (mPaddingBottom != bottom) {
17766             changed = true;
17767             mPaddingBottom = bottom;
17768         }
17769 
17770         if (changed) {
17771             requestLayout();
17772             invalidateOutline();
17773         }
17774     }
17775 
17776     /**
17777      * Sets the relative padding. The view may add on the space required to display
17778      * the scrollbars, depending on the style and visibility of the scrollbars.
17779      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
17780      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
17781      * from the values set in this call.
17782      *
17783      * @attr ref android.R.styleable#View_padding
17784      * @attr ref android.R.styleable#View_paddingBottom
17785      * @attr ref android.R.styleable#View_paddingStart
17786      * @attr ref android.R.styleable#View_paddingEnd
17787      * @attr ref android.R.styleable#View_paddingTop
17788      * @param start the start padding in pixels
17789      * @param top the top padding in pixels
17790      * @param end the end padding in pixels
17791      * @param bottom the bottom padding in pixels
17792      */
17793     public void setPaddingRelative(int start, int top, int end, int bottom) {
17794         resetResolvedPaddingInternal();
17795 
17796         mUserPaddingStart = start;
17797         mUserPaddingEnd = end;
17798         mLeftPaddingDefined = true;
17799         mRightPaddingDefined = true;
17800 
17801         switch(getLayoutDirection()) {
17802             case LAYOUT_DIRECTION_RTL:
17803                 mUserPaddingLeftInitial = end;
17804                 mUserPaddingRightInitial = start;
17805                 internalSetPadding(end, top, start, bottom);
17806                 break;
17807             case LAYOUT_DIRECTION_LTR:
17808             default:
17809                 mUserPaddingLeftInitial = start;
17810                 mUserPaddingRightInitial = end;
17811                 internalSetPadding(start, top, end, bottom);
17812         }
17813     }
17814 
17815     /**
17816      * Returns the top padding of this view.
17817      *
17818      * @return the top padding in pixels
17819      */
17820     public int getPaddingTop() {
17821         return mPaddingTop;
17822     }
17823 
17824     /**
17825      * Returns the bottom padding of this view. If there are inset and enabled
17826      * scrollbars, this value may include the space required to display the
17827      * scrollbars as well.
17828      *
17829      * @return the bottom padding in pixels
17830      */
17831     public int getPaddingBottom() {
17832         return mPaddingBottom;
17833     }
17834 
17835     /**
17836      * Returns the left padding of this view. If there are inset and enabled
17837      * scrollbars, this value may include the space required to display the
17838      * scrollbars as well.
17839      *
17840      * @return the left padding in pixels
17841      */
17842     public int getPaddingLeft() {
17843         if (!isPaddingResolved()) {
17844             resolvePadding();
17845         }
17846         return mPaddingLeft;
17847     }
17848 
17849     /**
17850      * Returns the start padding of this view depending on its resolved layout direction.
17851      * If there are inset and enabled scrollbars, this value may include the space
17852      * required to display the scrollbars as well.
17853      *
17854      * @return the start padding in pixels
17855      */
17856     public int getPaddingStart() {
17857         if (!isPaddingResolved()) {
17858             resolvePadding();
17859         }
17860         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17861                 mPaddingRight : mPaddingLeft;
17862     }
17863 
17864     /**
17865      * Returns the right padding of this view. If there are inset and enabled
17866      * scrollbars, this value may include the space required to display the
17867      * scrollbars as well.
17868      *
17869      * @return the right padding in pixels
17870      */
17871     public int getPaddingRight() {
17872         if (!isPaddingResolved()) {
17873             resolvePadding();
17874         }
17875         return mPaddingRight;
17876     }
17877 
17878     /**
17879      * Returns the end padding of this view depending on its resolved layout direction.
17880      * If there are inset and enabled scrollbars, this value may include the space
17881      * required to display the scrollbars as well.
17882      *
17883      * @return the end padding in pixels
17884      */
17885     public int getPaddingEnd() {
17886         if (!isPaddingResolved()) {
17887             resolvePadding();
17888         }
17889         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17890                 mPaddingLeft : mPaddingRight;
17891     }
17892 
17893     /**
17894      * Return if the padding has been set through relative values
17895      * {@link #setPaddingRelative(int, int, int, int)} or through
17896      * @attr ref android.R.styleable#View_paddingStart or
17897      * @attr ref android.R.styleable#View_paddingEnd
17898      *
17899      * @return true if the padding is relative or false if it is not.
17900      */
17901     public boolean isPaddingRelative() {
17902         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
17903     }
17904 
17905     Insets computeOpticalInsets() {
17906         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
17907     }
17908 
17909     /**
17910      * @hide
17911      */
17912     public void resetPaddingToInitialValues() {
17913         if (isRtlCompatibilityMode()) {
17914             mPaddingLeft = mUserPaddingLeftInitial;
17915             mPaddingRight = mUserPaddingRightInitial;
17916             return;
17917         }
17918         if (isLayoutRtl()) {
17919             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
17920             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
17921         } else {
17922             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
17923             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
17924         }
17925     }
17926 
17927     /**
17928      * @hide
17929      */
17930     public Insets getOpticalInsets() {
17931         if (mLayoutInsets == null) {
17932             mLayoutInsets = computeOpticalInsets();
17933         }
17934         return mLayoutInsets;
17935     }
17936 
17937     /**
17938      * Set this view's optical insets.
17939      *
17940      * <p>This method should be treated similarly to setMeasuredDimension and not as a general
17941      * property. Views that compute their own optical insets should call it as part of measurement.
17942      * This method does not request layout. If you are setting optical insets outside of
17943      * measure/layout itself you will want to call requestLayout() yourself.
17944      * </p>
17945      * @hide
17946      */
17947     public void setOpticalInsets(Insets insets) {
17948         mLayoutInsets = insets;
17949     }
17950 
17951     /**
17952      * Changes the selection state of this view. A view can be selected or not.
17953      * Note that selection is not the same as focus. Views are typically
17954      * selected in the context of an AdapterView like ListView or GridView;
17955      * the selected view is the view that is highlighted.
17956      *
17957      * @param selected true if the view must be selected, false otherwise
17958      */
17959     public void setSelected(boolean selected) {
17960         //noinspection DoubleNegation
17961         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
17962             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
17963             if (!selected) resetPressedState();
17964             invalidate(true);
17965             refreshDrawableState();
17966             dispatchSetSelected(selected);
17967             if (selected) {
17968                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
17969             } else {
17970                 notifyViewAccessibilityStateChangedIfNeeded(
17971                         AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17972             }
17973         }
17974     }
17975 
17976     /**
17977      * Dispatch setSelected to all of this View's children.
17978      *
17979      * @see #setSelected(boolean)
17980      *
17981      * @param selected The new selected state
17982      */
17983     protected void dispatchSetSelected(boolean selected) {
17984     }
17985 
17986     /**
17987      * Indicates the selection state of this view.
17988      *
17989      * @return true if the view is selected, false otherwise
17990      */
17991     @ViewDebug.ExportedProperty
17992     public boolean isSelected() {
17993         return (mPrivateFlags & PFLAG_SELECTED) != 0;
17994     }
17995 
17996     /**
17997      * Changes the activated state of this view. A view can be activated or not.
17998      * Note that activation is not the same as selection.  Selection is
17999      * a transient property, representing the view (hierarchy) the user is
18000      * currently interacting with.  Activation is a longer-term state that the
18001      * user can move views in and out of.  For example, in a list view with
18002      * single or multiple selection enabled, the views in the current selection
18003      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
18004      * here.)  The activated state is propagated down to children of the view it
18005      * is set on.
18006      *
18007      * @param activated true if the view must be activated, false otherwise
18008      */
18009     public void setActivated(boolean activated) {
18010         //noinspection DoubleNegation
18011         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
18012             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
18013             invalidate(true);
18014             refreshDrawableState();
18015             dispatchSetActivated(activated);
18016         }
18017     }
18018 
18019     /**
18020      * Dispatch setActivated to all of this View's children.
18021      *
18022      * @see #setActivated(boolean)
18023      *
18024      * @param activated The new activated state
18025      */
18026     protected void dispatchSetActivated(boolean activated) {
18027     }
18028 
18029     /**
18030      * Indicates the activation state of this view.
18031      *
18032      * @return true if the view is activated, false otherwise
18033      */
18034     @ViewDebug.ExportedProperty
18035     public boolean isActivated() {
18036         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
18037     }
18038 
18039     /**
18040      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
18041      * observer can be used to get notifications when global events, like
18042      * layout, happen.
18043      *
18044      * The returned ViewTreeObserver observer is not guaranteed to remain
18045      * valid for the lifetime of this View. If the caller of this method keeps
18046      * a long-lived reference to ViewTreeObserver, it should always check for
18047      * the return value of {@link ViewTreeObserver#isAlive()}.
18048      *
18049      * @return The ViewTreeObserver for this view's hierarchy.
18050      */
18051     public ViewTreeObserver getViewTreeObserver() {
18052         if (mAttachInfo != null) {
18053             return mAttachInfo.mTreeObserver;
18054         }
18055         if (mFloatingTreeObserver == null) {
18056             mFloatingTreeObserver = new ViewTreeObserver();
18057         }
18058         return mFloatingTreeObserver;
18059     }
18060 
18061     /**
18062      * <p>Finds the topmost view in the current view hierarchy.</p>
18063      *
18064      * @return the topmost view containing this view
18065      */
18066     public View getRootView() {
18067         if (mAttachInfo != null) {
18068             final View v = mAttachInfo.mRootView;
18069             if (v != null) {
18070                 return v;
18071             }
18072         }
18073 
18074         View parent = this;
18075 
18076         while (parent.mParent != null && parent.mParent instanceof View) {
18077             parent = (View) parent.mParent;
18078         }
18079 
18080         return parent;
18081     }
18082 
18083     /**
18084      * Transforms a motion event from view-local coordinates to on-screen
18085      * coordinates.
18086      *
18087      * @param ev the view-local motion event
18088      * @return false if the transformation could not be applied
18089      * @hide
18090      */
18091     public boolean toGlobalMotionEvent(MotionEvent ev) {
18092         final AttachInfo info = mAttachInfo;
18093         if (info == null) {
18094             return false;
18095         }
18096 
18097         final Matrix m = info.mTmpMatrix;
18098         m.set(Matrix.IDENTITY_MATRIX);
18099         transformMatrixToGlobal(m);
18100         ev.transform(m);
18101         return true;
18102     }
18103 
18104     /**
18105      * Transforms a motion event from on-screen coordinates to view-local
18106      * coordinates.
18107      *
18108      * @param ev the on-screen motion event
18109      * @return false if the transformation could not be applied
18110      * @hide
18111      */
18112     public boolean toLocalMotionEvent(MotionEvent ev) {
18113         final AttachInfo info = mAttachInfo;
18114         if (info == null) {
18115             return false;
18116         }
18117 
18118         final Matrix m = info.mTmpMatrix;
18119         m.set(Matrix.IDENTITY_MATRIX);
18120         transformMatrixToLocal(m);
18121         ev.transform(m);
18122         return true;
18123     }
18124 
18125     /**
18126      * Modifies the input matrix such that it maps view-local coordinates to
18127      * on-screen coordinates.
18128      *
18129      * @param m input matrix to modify
18130      * @hide
18131      */
18132     public void transformMatrixToGlobal(Matrix m) {
18133         final ViewParent parent = mParent;
18134         if (parent instanceof View) {
18135             final View vp = (View) parent;
18136             vp.transformMatrixToGlobal(m);
18137             m.preTranslate(-vp.mScrollX, -vp.mScrollY);
18138         } else if (parent instanceof ViewRootImpl) {
18139             final ViewRootImpl vr = (ViewRootImpl) parent;
18140             vr.transformMatrixToGlobal(m);
18141             m.preTranslate(0, -vr.mCurScrollY);
18142         }
18143 
18144         m.preTranslate(mLeft, mTop);
18145 
18146         if (!hasIdentityMatrix()) {
18147             m.preConcat(getMatrix());
18148         }
18149     }
18150 
18151     /**
18152      * Modifies the input matrix such that it maps on-screen coordinates to
18153      * view-local coordinates.
18154      *
18155      * @param m input matrix to modify
18156      * @hide
18157      */
18158     public void transformMatrixToLocal(Matrix m) {
18159         final ViewParent parent = mParent;
18160         if (parent instanceof View) {
18161             final View vp = (View) parent;
18162             vp.transformMatrixToLocal(m);
18163             m.postTranslate(vp.mScrollX, vp.mScrollY);
18164         } else if (parent instanceof ViewRootImpl) {
18165             final ViewRootImpl vr = (ViewRootImpl) parent;
18166             vr.transformMatrixToLocal(m);
18167             m.postTranslate(0, vr.mCurScrollY);
18168         }
18169 
18170         m.postTranslate(-mLeft, -mTop);
18171 
18172         if (!hasIdentityMatrix()) {
18173             m.postConcat(getInverseMatrix());
18174         }
18175     }
18176 
18177     /**
18178      * @hide
18179      */
18180     @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
18181             @ViewDebug.IntToString(from = 0, to = "x"),
18182             @ViewDebug.IntToString(from = 1, to = "y")
18183     })
18184     public int[] getLocationOnScreen() {
18185         int[] location = new int[2];
18186         getLocationOnScreen(location);
18187         return location;
18188     }
18189 
18190     /**
18191      * <p>Computes the coordinates of this view on the screen. The argument
18192      * must be an array of two integers. After the method returns, the array
18193      * contains the x and y location in that order.</p>
18194      *
18195      * @param location an array of two integers in which to hold the coordinates
18196      */
18197     public void getLocationOnScreen(@Size(2) int[] location) {
18198         getLocationInWindow(location);
18199 
18200         final AttachInfo info = mAttachInfo;
18201         if (info != null) {
18202             location[0] += info.mWindowLeft;
18203             location[1] += info.mWindowTop;
18204         }
18205     }
18206 
18207     /**
18208      * <p>Computes the coordinates of this view in its window. The argument
18209      * must be an array of two integers. After the method returns, the array
18210      * contains the x and y location in that order.</p>
18211      *
18212      * @param location an array of two integers in which to hold the coordinates
18213      */
18214     public void getLocationInWindow(@Size(2) int[] location) {
18215         if (location == null || location.length < 2) {
18216             throw new IllegalArgumentException("location must be an array of two integers");
18217         }
18218 
18219         if (mAttachInfo == null) {
18220             // When the view is not attached to a window, this method does not make sense
18221             location[0] = location[1] = 0;
18222             return;
18223         }
18224 
18225         float[] position = mAttachInfo.mTmpTransformLocation;
18226         position[0] = position[1] = 0.0f;
18227 
18228         if (!hasIdentityMatrix()) {
18229             getMatrix().mapPoints(position);
18230         }
18231 
18232         position[0] += mLeft;
18233         position[1] += mTop;
18234 
18235         ViewParent viewParent = mParent;
18236         while (viewParent instanceof View) {
18237             final View view = (View) viewParent;
18238 
18239             position[0] -= view.mScrollX;
18240             position[1] -= view.mScrollY;
18241 
18242             if (!view.hasIdentityMatrix()) {
18243                 view.getMatrix().mapPoints(position);
18244             }
18245 
18246             position[0] += view.mLeft;
18247             position[1] += view.mTop;
18248 
18249             viewParent = view.mParent;
18250          }
18251 
18252         if (viewParent instanceof ViewRootImpl) {
18253             // *cough*
18254             final ViewRootImpl vr = (ViewRootImpl) viewParent;
18255             position[1] -= vr.mCurScrollY;
18256         }
18257 
18258         location[0] = (int) (position[0] + 0.5f);
18259         location[1] = (int) (position[1] + 0.5f);
18260     }
18261 
18262     /**
18263      * {@hide}
18264      * @param id the id of the view to be found
18265      * @return the view of the specified id, null if cannot be found
18266      */
18267     protected View findViewTraversal(@IdRes int id) {
18268         if (id == mID) {
18269             return this;
18270         }
18271         return null;
18272     }
18273 
18274     /**
18275      * {@hide}
18276      * @param tag the tag of the view to be found
18277      * @return the view of specified tag, null if cannot be found
18278      */
18279     protected View findViewWithTagTraversal(Object tag) {
18280         if (tag != null && tag.equals(mTag)) {
18281             return this;
18282         }
18283         return null;
18284     }
18285 
18286     /**
18287      * {@hide}
18288      * @param predicate The predicate to evaluate.
18289      * @param childToSkip If not null, ignores this child during the recursive traversal.
18290      * @return The first view that matches the predicate or null.
18291      */
18292     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
18293         if (predicate.apply(this)) {
18294             return this;
18295         }
18296         return null;
18297     }
18298 
18299     /**
18300      * Look for a child view with the given id.  If this view has the given
18301      * id, return this view.
18302      *
18303      * @param id The id to search for.
18304      * @return The view that has the given id in the hierarchy or null
18305      */
18306     @Nullable
18307     public final View findViewById(@IdRes int id) {
18308         if (id < 0) {
18309             return null;
18310         }
18311         return findViewTraversal(id);
18312     }
18313 
18314     /**
18315      * Finds a view by its unuque and stable accessibility id.
18316      *
18317      * @param accessibilityId The searched accessibility id.
18318      * @return The found view.
18319      */
18320     final View findViewByAccessibilityId(int accessibilityId) {
18321         if (accessibilityId < 0) {
18322             return null;
18323         }
18324         View view = findViewByAccessibilityIdTraversal(accessibilityId);
18325         if (view != null) {
18326             return view.includeForAccessibility() ? view : null;
18327         }
18328         return null;
18329     }
18330 
18331     /**
18332      * Performs the traversal to find a view by its unuque and stable accessibility id.
18333      *
18334      * <strong>Note:</strong>This method does not stop at the root namespace
18335      * boundary since the user can touch the screen at an arbitrary location
18336      * potentially crossing the root namespace bounday which will send an
18337      * accessibility event to accessibility services and they should be able
18338      * to obtain the event source. Also accessibility ids are guaranteed to be
18339      * unique in the window.
18340      *
18341      * @param accessibilityId The accessibility id.
18342      * @return The found view.
18343      *
18344      * @hide
18345      */
18346     public View findViewByAccessibilityIdTraversal(int accessibilityId) {
18347         if (getAccessibilityViewId() == accessibilityId) {
18348             return this;
18349         }
18350         return null;
18351     }
18352 
18353     /**
18354      * Look for a child view with the given tag.  If this view has the given
18355      * tag, return this view.
18356      *
18357      * @param tag The tag to search for, using "tag.equals(getTag())".
18358      * @return The View that has the given tag in the hierarchy or null
18359      */
18360     public final View findViewWithTag(Object tag) {
18361         if (tag == null) {
18362             return null;
18363         }
18364         return findViewWithTagTraversal(tag);
18365     }
18366 
18367     /**
18368      * {@hide}
18369      * Look for a child view that matches the specified predicate.
18370      * If this view matches the predicate, return this view.
18371      *
18372      * @param predicate The predicate to evaluate.
18373      * @return The first view that matches the predicate or null.
18374      */
18375     public final View findViewByPredicate(Predicate<View> predicate) {
18376         return findViewByPredicateTraversal(predicate, null);
18377     }
18378 
18379     /**
18380      * {@hide}
18381      * Look for a child view that matches the specified predicate,
18382      * starting with the specified view and its descendents and then
18383      * recusively searching the ancestors and siblings of that view
18384      * until this view is reached.
18385      *
18386      * This method is useful in cases where the predicate does not match
18387      * a single unique view (perhaps multiple views use the same id)
18388      * and we are trying to find the view that is "closest" in scope to the
18389      * starting view.
18390      *
18391      * @param start The view to start from.
18392      * @param predicate The predicate to evaluate.
18393      * @return The first view that matches the predicate or null.
18394      */
18395     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
18396         View childToSkip = null;
18397         for (;;) {
18398             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
18399             if (view != null || start == this) {
18400                 return view;
18401             }
18402 
18403             ViewParent parent = start.getParent();
18404             if (parent == null || !(parent instanceof View)) {
18405                 return null;
18406             }
18407 
18408             childToSkip = start;
18409             start = (View) parent;
18410         }
18411     }
18412 
18413     /**
18414      * Sets the identifier for this view. The identifier does not have to be
18415      * unique in this view's hierarchy. The identifier should be a positive
18416      * number.
18417      *
18418      * @see #NO_ID
18419      * @see #getId()
18420      * @see #findViewById(int)
18421      *
18422      * @param id a number used to identify the view
18423      *
18424      * @attr ref android.R.styleable#View_id
18425      */
18426     public void setId(@IdRes int id) {
18427         mID = id;
18428         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
18429             mID = generateViewId();
18430         }
18431     }
18432 
18433     /**
18434      * {@hide}
18435      *
18436      * @param isRoot true if the view belongs to the root namespace, false
18437      *        otherwise
18438      */
18439     public void setIsRootNamespace(boolean isRoot) {
18440         if (isRoot) {
18441             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
18442         } else {
18443             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
18444         }
18445     }
18446 
18447     /**
18448      * {@hide}
18449      *
18450      * @return true if the view belongs to the root namespace, false otherwise
18451      */
18452     public boolean isRootNamespace() {
18453         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
18454     }
18455 
18456     /**
18457      * Returns this view's identifier.
18458      *
18459      * @return a positive integer used to identify the view or {@link #NO_ID}
18460      *         if the view has no ID
18461      *
18462      * @see #setId(int)
18463      * @see #findViewById(int)
18464      * @attr ref android.R.styleable#View_id
18465      */
18466     @IdRes
18467     @ViewDebug.CapturedViewProperty
18468     public int getId() {
18469         return mID;
18470     }
18471 
18472     /**
18473      * Returns this view's tag.
18474      *
18475      * @return the Object stored in this view as a tag, or {@code null} if not
18476      *         set
18477      *
18478      * @see #setTag(Object)
18479      * @see #getTag(int)
18480      */
18481     @ViewDebug.ExportedProperty
18482     public Object getTag() {
18483         return mTag;
18484     }
18485 
18486     /**
18487      * Sets the tag associated with this view. A tag can be used to mark
18488      * a view in its hierarchy and does not have to be unique within the
18489      * hierarchy. Tags can also be used to store data within a view without
18490      * resorting to another data structure.
18491      *
18492      * @param tag an Object to tag the view with
18493      *
18494      * @see #getTag()
18495      * @see #setTag(int, Object)
18496      */
18497     public void setTag(final Object tag) {
18498         mTag = tag;
18499     }
18500 
18501     /**
18502      * Returns the tag associated with this view and the specified key.
18503      *
18504      * @param key The key identifying the tag
18505      *
18506      * @return the Object stored in this view as a tag, or {@code null} if not
18507      *         set
18508      *
18509      * @see #setTag(int, Object)
18510      * @see #getTag()
18511      */
18512     public Object getTag(int key) {
18513         if (mKeyedTags != null) return mKeyedTags.get(key);
18514         return null;
18515     }
18516 
18517     /**
18518      * Sets a tag associated with this view and a key. A tag can be used
18519      * to mark a view in its hierarchy and does not have to be unique within
18520      * the hierarchy. Tags can also be used to store data within a view
18521      * without resorting to another data structure.
18522      *
18523      * The specified key should be an id declared in the resources of the
18524      * application to ensure it is unique (see the <a
18525      * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
18526      * Keys identified as belonging to
18527      * the Android framework or not associated with any package will cause
18528      * an {@link IllegalArgumentException} to be thrown.
18529      *
18530      * @param key The key identifying the tag
18531      * @param tag An Object to tag the view with
18532      *
18533      * @throws IllegalArgumentException If they specified key is not valid
18534      *
18535      * @see #setTag(Object)
18536      * @see #getTag(int)
18537      */
18538     public void setTag(int key, final Object tag) {
18539         // If the package id is 0x00 or 0x01, it's either an undefined package
18540         // or a framework id
18541         if ((key >>> 24) < 2) {
18542             throw new IllegalArgumentException("The key must be an application-specific "
18543                     + "resource id.");
18544         }
18545 
18546         setKeyedTag(key, tag);
18547     }
18548 
18549     /**
18550      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
18551      * framework id.
18552      *
18553      * @hide
18554      */
18555     public void setTagInternal(int key, Object tag) {
18556         if ((key >>> 24) != 0x1) {
18557             throw new IllegalArgumentException("The key must be a framework-specific "
18558                     + "resource id.");
18559         }
18560 
18561         setKeyedTag(key, tag);
18562     }
18563 
18564     private void setKeyedTag(int key, Object tag) {
18565         if (mKeyedTags == null) {
18566             mKeyedTags = new SparseArray<Object>(2);
18567         }
18568 
18569         mKeyedTags.put(key, tag);
18570     }
18571 
18572     /**
18573      * Prints information about this view in the log output, with the tag
18574      * {@link #VIEW_LOG_TAG}.
18575      *
18576      * @hide
18577      */
18578     public void debug() {
18579         debug(0);
18580     }
18581 
18582     /**
18583      * Prints information about this view in the log output, with the tag
18584      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18585      * indentation defined by the <code>depth</code>.
18586      *
18587      * @param depth the indentation level
18588      *
18589      * @hide
18590      */
18591     protected void debug(int depth) {
18592         String output = debugIndent(depth - 1);
18593 
18594         output += "+ " + this;
18595         int id = getId();
18596         if (id != -1) {
18597             output += " (id=" + id + ")";
18598         }
18599         Object tag = getTag();
18600         if (tag != null) {
18601             output += " (tag=" + tag + ")";
18602         }
18603         Log.d(VIEW_LOG_TAG, output);
18604 
18605         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18606             output = debugIndent(depth) + " FOCUSED";
18607             Log.d(VIEW_LOG_TAG, output);
18608         }
18609 
18610         output = debugIndent(depth);
18611         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
18612                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
18613                 + "} ";
18614         Log.d(VIEW_LOG_TAG, output);
18615 
18616         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
18617                 || mPaddingBottom != 0) {
18618             output = debugIndent(depth);
18619             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
18620                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
18621             Log.d(VIEW_LOG_TAG, output);
18622         }
18623 
18624         output = debugIndent(depth);
18625         output += "mMeasureWidth=" + mMeasuredWidth +
18626                 " mMeasureHeight=" + mMeasuredHeight;
18627         Log.d(VIEW_LOG_TAG, output);
18628 
18629         output = debugIndent(depth);
18630         if (mLayoutParams == null) {
18631             output += "BAD! no layout params";
18632         } else {
18633             output = mLayoutParams.debug(output);
18634         }
18635         Log.d(VIEW_LOG_TAG, output);
18636 
18637         output = debugIndent(depth);
18638         output += "flags={";
18639         output += View.printFlags(mViewFlags);
18640         output += "}";
18641         Log.d(VIEW_LOG_TAG, output);
18642 
18643         output = debugIndent(depth);
18644         output += "privateFlags={";
18645         output += View.printPrivateFlags(mPrivateFlags);
18646         output += "}";
18647         Log.d(VIEW_LOG_TAG, output);
18648     }
18649 
18650     /**
18651      * Creates a string of whitespaces used for indentation.
18652      *
18653      * @param depth the indentation level
18654      * @return a String containing (depth * 2 + 3) * 2 white spaces
18655      *
18656      * @hide
18657      */
18658     protected static String debugIndent(int depth) {
18659         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
18660         for (int i = 0; i < (depth * 2) + 3; i++) {
18661             spaces.append(' ').append(' ');
18662         }
18663         return spaces.toString();
18664     }
18665 
18666     /**
18667      * <p>Return the offset of the widget's text baseline from the widget's top
18668      * boundary. If this widget does not support baseline alignment, this
18669      * method returns -1. </p>
18670      *
18671      * @return the offset of the baseline within the widget's bounds or -1
18672      *         if baseline alignment is not supported
18673      */
18674     @ViewDebug.ExportedProperty(category = "layout")
18675     public int getBaseline() {
18676         return -1;
18677     }
18678 
18679     /**
18680      * Returns whether the view hierarchy is currently undergoing a layout pass. This
18681      * information is useful to avoid situations such as calling {@link #requestLayout()} during
18682      * a layout pass.
18683      *
18684      * @return whether the view hierarchy is currently undergoing a layout pass
18685      */
18686     public boolean isInLayout() {
18687         ViewRootImpl viewRoot = getViewRootImpl();
18688         return (viewRoot != null && viewRoot.isInLayout());
18689     }
18690 
18691     /**
18692      * Call this when something has changed which has invalidated the
18693      * layout of this view. This will schedule a layout pass of the view
18694      * tree. This should not be called while the view hierarchy is currently in a layout
18695      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18696      * end of the current layout pass (and then layout will run again) or after the current
18697      * frame is drawn and the next layout occurs.
18698      *
18699      * <p>Subclasses which override this method should call the superclass method to
18700      * handle possible request-during-layout errors correctly.</p>
18701      */
18702     @CallSuper
18703     public void requestLayout() {
18704         if (mMeasureCache != null) mMeasureCache.clear();
18705 
18706         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
18707             // Only trigger request-during-layout logic if this is the view requesting it,
18708             // not the views in its parent hierarchy
18709             ViewRootImpl viewRoot = getViewRootImpl();
18710             if (viewRoot != null && viewRoot.isInLayout()) {
18711                 if (!viewRoot.requestLayoutDuringLayout(this)) {
18712                     return;
18713                 }
18714             }
18715             mAttachInfo.mViewRequestingLayout = this;
18716         }
18717 
18718         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18719         mPrivateFlags |= PFLAG_INVALIDATED;
18720 
18721         if (mParent != null && !mParent.isLayoutRequested()) {
18722             mParent.requestLayout();
18723         }
18724         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
18725             mAttachInfo.mViewRequestingLayout = null;
18726         }
18727     }
18728 
18729     /**
18730      * Forces this view to be laid out during the next layout pass.
18731      * This method does not call requestLayout() or forceLayout()
18732      * on the parent.
18733      */
18734     public void forceLayout() {
18735         if (mMeasureCache != null) mMeasureCache.clear();
18736 
18737         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18738         mPrivateFlags |= PFLAG_INVALIDATED;
18739     }
18740 
18741     /**
18742      * <p>
18743      * This is called to find out how big a view should be. The parent
18744      * supplies constraint information in the width and height parameters.
18745      * </p>
18746      *
18747      * <p>
18748      * The actual measurement work of a view is performed in
18749      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
18750      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
18751      * </p>
18752      *
18753      *
18754      * @param widthMeasureSpec Horizontal space requirements as imposed by the
18755      *        parent
18756      * @param heightMeasureSpec Vertical space requirements as imposed by the
18757      *        parent
18758      *
18759      * @see #onMeasure(int, int)
18760      */
18761     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
18762         boolean optical = isLayoutModeOptical(this);
18763         if (optical != isLayoutModeOptical(mParent)) {
18764             Insets insets = getOpticalInsets();
18765             int oWidth  = insets.left + insets.right;
18766             int oHeight = insets.top  + insets.bottom;
18767             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
18768             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
18769         }
18770 
18771         // Suppress sign extension for the low bytes
18772         long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
18773         if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
18774 
18775         if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
18776                 widthMeasureSpec != mOldWidthMeasureSpec ||
18777                 heightMeasureSpec != mOldHeightMeasureSpec) {
18778 
18779             // first clears the measured dimension flag
18780             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
18781 
18782             resolveRtlPropertiesIfNeeded();
18783 
18784             int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
18785                     mMeasureCache.indexOfKey(key);
18786             if (cacheIndex < 0 || sIgnoreMeasureCache) {
18787                 // measure ourselves, this should set the measured dimension flag back
18788                 onMeasure(widthMeasureSpec, heightMeasureSpec);
18789                 mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18790             } else {
18791                 long value = mMeasureCache.valueAt(cacheIndex);
18792                 // Casting a long to int drops the high 32 bits, no mask needed
18793                 setMeasuredDimensionRaw((int) (value >> 32), (int) value);
18794                 mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18795             }
18796 
18797             // flag not set, setMeasuredDimension() was not invoked, we raise
18798             // an exception to warn the developer
18799             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
18800                 throw new IllegalStateException("View with id " + getId() + ": "
18801                         + getClass().getName() + "#onMeasure() did not set the"
18802                         + " measured dimension by calling"
18803                         + " setMeasuredDimension()");
18804             }
18805 
18806             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
18807         }
18808 
18809         mOldWidthMeasureSpec = widthMeasureSpec;
18810         mOldHeightMeasureSpec = heightMeasureSpec;
18811 
18812         mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
18813                 (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
18814     }
18815 
18816     /**
18817      * <p>
18818      * Measure the view and its content to determine the measured width and the
18819      * measured height. This method is invoked by {@link #measure(int, int)} and
18820      * should be overridden by subclasses to provide accurate and efficient
18821      * measurement of their contents.
18822      * </p>
18823      *
18824      * <p>
18825      * <strong>CONTRACT:</strong> When overriding this method, you
18826      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
18827      * measured width and height of this view. Failure to do so will trigger an
18828      * <code>IllegalStateException</code>, thrown by
18829      * {@link #measure(int, int)}. Calling the superclass'
18830      * {@link #onMeasure(int, int)} is a valid use.
18831      * </p>
18832      *
18833      * <p>
18834      * The base class implementation of measure defaults to the background size,
18835      * unless a larger size is allowed by the MeasureSpec. Subclasses should
18836      * override {@link #onMeasure(int, int)} to provide better measurements of
18837      * their content.
18838      * </p>
18839      *
18840      * <p>
18841      * If this method is overridden, it is the subclass's responsibility to make
18842      * sure the measured height and width are at least the view's minimum height
18843      * and width ({@link #getSuggestedMinimumHeight()} and
18844      * {@link #getSuggestedMinimumWidth()}).
18845      * </p>
18846      *
18847      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
18848      *                         The requirements are encoded with
18849      *                         {@link android.view.View.MeasureSpec}.
18850      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
18851      *                         The requirements are encoded with
18852      *                         {@link android.view.View.MeasureSpec}.
18853      *
18854      * @see #getMeasuredWidth()
18855      * @see #getMeasuredHeight()
18856      * @see #setMeasuredDimension(int, int)
18857      * @see #getSuggestedMinimumHeight()
18858      * @see #getSuggestedMinimumWidth()
18859      * @see android.view.View.MeasureSpec#getMode(int)
18860      * @see android.view.View.MeasureSpec#getSize(int)
18861      */
18862     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
18863         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
18864                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
18865     }
18866 
18867     /**
18868      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
18869      * measured width and measured height. Failing to do so will trigger an
18870      * exception at measurement time.</p>
18871      *
18872      * @param measuredWidth The measured width of this view.  May be a complex
18873      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18874      * {@link #MEASURED_STATE_TOO_SMALL}.
18875      * @param measuredHeight The measured height of this view.  May be a complex
18876      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18877      * {@link #MEASURED_STATE_TOO_SMALL}.
18878      */
18879     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
18880         boolean optical = isLayoutModeOptical(this);
18881         if (optical != isLayoutModeOptical(mParent)) {
18882             Insets insets = getOpticalInsets();
18883             int opticalWidth  = insets.left + insets.right;
18884             int opticalHeight = insets.top  + insets.bottom;
18885 
18886             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
18887             measuredHeight += optical ? opticalHeight : -opticalHeight;
18888         }
18889         setMeasuredDimensionRaw(measuredWidth, measuredHeight);
18890     }
18891 
18892     /**
18893      * Sets the measured dimension without extra processing for things like optical bounds.
18894      * Useful for reapplying consistent values that have already been cooked with adjustments
18895      * for optical bounds, etc. such as those from the measurement cache.
18896      *
18897      * @param measuredWidth The measured width of this view.  May be a complex
18898      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18899      * {@link #MEASURED_STATE_TOO_SMALL}.
18900      * @param measuredHeight The measured height of this view.  May be a complex
18901      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18902      * {@link #MEASURED_STATE_TOO_SMALL}.
18903      */
18904     private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
18905         mMeasuredWidth = measuredWidth;
18906         mMeasuredHeight = measuredHeight;
18907 
18908         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
18909     }
18910 
18911     /**
18912      * Merge two states as returned by {@link #getMeasuredState()}.
18913      * @param curState The current state as returned from a view or the result
18914      * of combining multiple views.
18915      * @param newState The new view state to combine.
18916      * @return Returns a new integer reflecting the combination of the two
18917      * states.
18918      */
18919     public static int combineMeasuredStates(int curState, int newState) {
18920         return curState | newState;
18921     }
18922 
18923     /**
18924      * Version of {@link #resolveSizeAndState(int, int, int)}
18925      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
18926      */
18927     public static int resolveSize(int size, int measureSpec) {
18928         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
18929     }
18930 
18931     /**
18932      * Utility to reconcile a desired size and state, with constraints imposed
18933      * by a MeasureSpec. Will take the desired size, unless a different size
18934      * is imposed by the constraints. The returned value is a compound integer,
18935      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
18936      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
18937      * resulting size is smaller than the size the view wants to be.
18938      *
18939      * @param size How big the view wants to be.
18940      * @param measureSpec Constraints imposed by the parent.
18941      * @param childMeasuredState Size information bit mask for the view's
18942      *                           children.
18943      * @return Size information bit mask as defined by
18944      *         {@link #MEASURED_SIZE_MASK} and
18945      *         {@link #MEASURED_STATE_TOO_SMALL}.
18946      */
18947     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
18948         final int specMode = MeasureSpec.getMode(measureSpec);
18949         final int specSize = MeasureSpec.getSize(measureSpec);
18950         final int result;
18951         switch (specMode) {
18952             case MeasureSpec.AT_MOST:
18953                 if (specSize < size) {
18954                     result = specSize | MEASURED_STATE_TOO_SMALL;
18955                 } else {
18956                     result = size;
18957                 }
18958                 break;
18959             case MeasureSpec.EXACTLY:
18960                 result = specSize;
18961                 break;
18962             case MeasureSpec.UNSPECIFIED:
18963             default:
18964                 result = size;
18965         }
18966         return result | (childMeasuredState & MEASURED_STATE_MASK);
18967     }
18968 
18969     /**
18970      * Utility to return a default size. Uses the supplied size if the
18971      * MeasureSpec imposed no constraints. Will get larger if allowed
18972      * by the MeasureSpec.
18973      *
18974      * @param size Default size for this view
18975      * @param measureSpec Constraints imposed by the parent
18976      * @return The size this view should be.
18977      */
18978     public static int getDefaultSize(int size, int measureSpec) {
18979         int result = size;
18980         int specMode = MeasureSpec.getMode(measureSpec);
18981         int specSize = MeasureSpec.getSize(measureSpec);
18982 
18983         switch (specMode) {
18984         case MeasureSpec.UNSPECIFIED:
18985             result = size;
18986             break;
18987         case MeasureSpec.AT_MOST:
18988         case MeasureSpec.EXACTLY:
18989             result = specSize;
18990             break;
18991         }
18992         return result;
18993     }
18994 
18995     /**
18996      * Returns the suggested minimum height that the view should use. This
18997      * returns the maximum of the view's minimum height
18998      * and the background's minimum height
18999      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
19000      * <p>
19001      * When being used in {@link #onMeasure(int, int)}, the caller should still
19002      * ensure the returned height is within the requirements of the parent.
19003      *
19004      * @return The suggested minimum height of the view.
19005      */
19006     protected int getSuggestedMinimumHeight() {
19007         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
19008 
19009     }
19010 
19011     /**
19012      * Returns the suggested minimum width that the view should use. This
19013      * returns the maximum of the view's minimum width)
19014      * and the background's minimum width
19015      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
19016      * <p>
19017      * When being used in {@link #onMeasure(int, int)}, the caller should still
19018      * ensure the returned width is within the requirements of the parent.
19019      *
19020      * @return The suggested minimum width of the view.
19021      */
19022     protected int getSuggestedMinimumWidth() {
19023         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
19024     }
19025 
19026     /**
19027      * Returns the minimum height of the view.
19028      *
19029      * @return the minimum height the view will try to be.
19030      *
19031      * @see #setMinimumHeight(int)
19032      *
19033      * @attr ref android.R.styleable#View_minHeight
19034      */
19035     public int getMinimumHeight() {
19036         return mMinHeight;
19037     }
19038 
19039     /**
19040      * Sets the minimum height of the view. It is not guaranteed the view will
19041      * be able to achieve this minimum height (for example, if its parent layout
19042      * constrains it with less available height).
19043      *
19044      * @param minHeight The minimum height the view will try to be.
19045      *
19046      * @see #getMinimumHeight()
19047      *
19048      * @attr ref android.R.styleable#View_minHeight
19049      */
19050     public void setMinimumHeight(int minHeight) {
19051         mMinHeight = minHeight;
19052         requestLayout();
19053     }
19054 
19055     /**
19056      * Returns the minimum width of the view.
19057      *
19058      * @return the minimum width the view will try to be.
19059      *
19060      * @see #setMinimumWidth(int)
19061      *
19062      * @attr ref android.R.styleable#View_minWidth
19063      */
19064     public int getMinimumWidth() {
19065         return mMinWidth;
19066     }
19067 
19068     /**
19069      * Sets the minimum width of the view. It is not guaranteed the view will
19070      * be able to achieve this minimum width (for example, if its parent layout
19071      * constrains it with less available width).
19072      *
19073      * @param minWidth The minimum width the view will try to be.
19074      *
19075      * @see #getMinimumWidth()
19076      *
19077      * @attr ref android.R.styleable#View_minWidth
19078      */
19079     public void setMinimumWidth(int minWidth) {
19080         mMinWidth = minWidth;
19081         requestLayout();
19082 
19083     }
19084 
19085     /**
19086      * Get the animation currently associated with this view.
19087      *
19088      * @return The animation that is currently playing or
19089      *         scheduled to play for this view.
19090      */
19091     public Animation getAnimation() {
19092         return mCurrentAnimation;
19093     }
19094 
19095     /**
19096      * Start the specified animation now.
19097      *
19098      * @param animation the animation to start now
19099      */
19100     public void startAnimation(Animation animation) {
19101         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
19102         setAnimation(animation);
19103         invalidateParentCaches();
19104         invalidate(true);
19105     }
19106 
19107     /**
19108      * Cancels any animations for this view.
19109      */
19110     public void clearAnimation() {
19111         if (mCurrentAnimation != null) {
19112             mCurrentAnimation.detach();
19113         }
19114         mCurrentAnimation = null;
19115         invalidateParentIfNeeded();
19116     }
19117 
19118     /**
19119      * Sets the next animation to play for this view.
19120      * If you want the animation to play immediately, use
19121      * {@link #startAnimation(android.view.animation.Animation)} instead.
19122      * This method provides allows fine-grained
19123      * control over the start time and invalidation, but you
19124      * must make sure that 1) the animation has a start time set, and
19125      * 2) the view's parent (which controls animations on its children)
19126      * will be invalidated when the animation is supposed to
19127      * start.
19128      *
19129      * @param animation The next animation, or null.
19130      */
19131     public void setAnimation(Animation animation) {
19132         mCurrentAnimation = animation;
19133 
19134         if (animation != null) {
19135             // If the screen is off assume the animation start time is now instead of
19136             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
19137             // would cause the animation to start when the screen turns back on
19138             if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
19139                     && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
19140                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
19141             }
19142             animation.reset();
19143         }
19144     }
19145 
19146     /**
19147      * Invoked by a parent ViewGroup to notify the start of the animation
19148      * currently associated with this view. If you override this method,
19149      * always call super.onAnimationStart();
19150      *
19151      * @see #setAnimation(android.view.animation.Animation)
19152      * @see #getAnimation()
19153      */
19154     @CallSuper
19155     protected void onAnimationStart() {
19156         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
19157     }
19158 
19159     /**
19160      * Invoked by a parent ViewGroup to notify the end of the animation
19161      * currently associated with this view. If you override this method,
19162      * always call super.onAnimationEnd();
19163      *
19164      * @see #setAnimation(android.view.animation.Animation)
19165      * @see #getAnimation()
19166      */
19167     @CallSuper
19168     protected void onAnimationEnd() {
19169         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
19170     }
19171 
19172     /**
19173      * Invoked if there is a Transform that involves alpha. Subclass that can
19174      * draw themselves with the specified alpha should return true, and then
19175      * respect that alpha when their onDraw() is called. If this returns false
19176      * then the view may be redirected to draw into an offscreen buffer to
19177      * fulfill the request, which will look fine, but may be slower than if the
19178      * subclass handles it internally. The default implementation returns false.
19179      *
19180      * @param alpha The alpha (0..255) to apply to the view's drawing
19181      * @return true if the view can draw with the specified alpha.
19182      */
19183     protected boolean onSetAlpha(int alpha) {
19184         return false;
19185     }
19186 
19187     /**
19188      * This is used by the RootView to perform an optimization when
19189      * the view hierarchy contains one or several SurfaceView.
19190      * SurfaceView is always considered transparent, but its children are not,
19191      * therefore all View objects remove themselves from the global transparent
19192      * region (passed as a parameter to this function).
19193      *
19194      * @param region The transparent region for this ViewAncestor (window).
19195      *
19196      * @return Returns true if the effective visibility of the view at this
19197      * point is opaque, regardless of the transparent region; returns false
19198      * if it is possible for underlying windows to be seen behind the view.
19199      *
19200      * {@hide}
19201      */
19202     public boolean gatherTransparentRegion(Region region) {
19203         final AttachInfo attachInfo = mAttachInfo;
19204         if (region != null && attachInfo != null) {
19205             final int pflags = mPrivateFlags;
19206             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
19207                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
19208                 // remove it from the transparent region.
19209                 final int[] location = attachInfo.mTransparentLocation;
19210                 getLocationInWindow(location);
19211                 region.op(location[0], location[1], location[0] + mRight - mLeft,
19212                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
19213             } else {
19214                 if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
19215                     // The SKIP_DRAW flag IS set and the background drawable exists, we remove
19216                     // the background drawable's non-transparent parts from this transparent region.
19217                     applyDrawableToTransparentRegion(mBackground, region);
19218                 }
19219                 if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19220                         && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
19221                     // Similarly, we remove the foreground drawable's non-transparent parts.
19222                     applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
19223                 }
19224             }
19225         }
19226         return true;
19227     }
19228 
19229     /**
19230      * Play a sound effect for this view.
19231      *
19232      * <p>The framework will play sound effects for some built in actions, such as
19233      * clicking, but you may wish to play these effects in your widget,
19234      * for instance, for internal navigation.
19235      *
19236      * <p>The sound effect will only be played if sound effects are enabled by the user, and
19237      * {@link #isSoundEffectsEnabled()} is true.
19238      *
19239      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
19240      */
19241     public void playSoundEffect(int soundConstant) {
19242         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
19243             return;
19244         }
19245         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
19246     }
19247 
19248     /**
19249      * BZZZTT!!1!
19250      *
19251      * <p>Provide haptic feedback to the user for this view.
19252      *
19253      * <p>The framework will provide haptic feedback for some built in actions,
19254      * such as long presses, but you may wish to provide feedback for your
19255      * own widget.
19256      *
19257      * <p>The feedback will only be performed if
19258      * {@link #isHapticFeedbackEnabled()} is true.
19259      *
19260      * @param feedbackConstant One of the constants defined in
19261      * {@link HapticFeedbackConstants}
19262      */
19263     public boolean performHapticFeedback(int feedbackConstant) {
19264         return performHapticFeedback(feedbackConstant, 0);
19265     }
19266 
19267     /**
19268      * BZZZTT!!1!
19269      *
19270      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
19271      *
19272      * @param feedbackConstant One of the constants defined in
19273      * {@link HapticFeedbackConstants}
19274      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
19275      */
19276     public boolean performHapticFeedback(int feedbackConstant, int flags) {
19277         if (mAttachInfo == null) {
19278             return false;
19279         }
19280         //noinspection SimplifiableIfStatement
19281         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
19282                 && !isHapticFeedbackEnabled()) {
19283             return false;
19284         }
19285         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
19286                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
19287     }
19288 
19289     /**
19290      * Request that the visibility of the status bar or other screen/window
19291      * decorations be changed.
19292      *
19293      * <p>This method is used to put the over device UI into temporary modes
19294      * where the user's attention is focused more on the application content,
19295      * by dimming or hiding surrounding system affordances.  This is typically
19296      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
19297      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
19298      * to be placed behind the action bar (and with these flags other system
19299      * affordances) so that smooth transitions between hiding and showing them
19300      * can be done.
19301      *
19302      * <p>Two representative examples of the use of system UI visibility is
19303      * implementing a content browsing application (like a magazine reader)
19304      * and a video playing application.
19305      *
19306      * <p>The first code shows a typical implementation of a View in a content
19307      * browsing application.  In this implementation, the application goes
19308      * into a content-oriented mode by hiding the status bar and action bar,
19309      * and putting the navigation elements into lights out mode.  The user can
19310      * then interact with content while in this mode.  Such an application should
19311      * provide an easy way for the user to toggle out of the mode (such as to
19312      * check information in the status bar or access notifications).  In the
19313      * implementation here, this is done simply by tapping on the content.
19314      *
19315      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
19316      *      content}
19317      *
19318      * <p>This second code sample shows a typical implementation of a View
19319      * in a video playing application.  In this situation, while the video is
19320      * playing the application would like to go into a complete full-screen mode,
19321      * to use as much of the display as possible for the video.  When in this state
19322      * the user can not interact with the application; the system intercepts
19323      * touching on the screen to pop the UI out of full screen mode.  See
19324      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
19325      *
19326      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
19327      *      content}
19328      *
19329      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19330      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19331      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19332      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19333      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19334      */
19335     public void setSystemUiVisibility(int visibility) {
19336         if (visibility != mSystemUiVisibility) {
19337             mSystemUiVisibility = visibility;
19338             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19339                 mParent.recomputeViewAttributes(this);
19340             }
19341         }
19342     }
19343 
19344     /**
19345      * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
19346      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19347      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19348      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19349      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19350      * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19351      */
19352     public int getSystemUiVisibility() {
19353         return mSystemUiVisibility;
19354     }
19355 
19356     /**
19357      * Returns the current system UI visibility that is currently set for
19358      * the entire window.  This is the combination of the
19359      * {@link #setSystemUiVisibility(int)} values supplied by all of the
19360      * views in the window.
19361      */
19362     public int getWindowSystemUiVisibility() {
19363         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
19364     }
19365 
19366     /**
19367      * Override to find out when the window's requested system UI visibility
19368      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
19369      * This is different from the callbacks received through
19370      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
19371      * in that this is only telling you about the local request of the window,
19372      * not the actual values applied by the system.
19373      */
19374     public void onWindowSystemUiVisibilityChanged(int visible) {
19375     }
19376 
19377     /**
19378      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
19379      * the view hierarchy.
19380      */
19381     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
19382         onWindowSystemUiVisibilityChanged(visible);
19383     }
19384 
19385     /**
19386      * Set a listener to receive callbacks when the visibility of the system bar changes.
19387      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
19388      */
19389     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
19390         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
19391         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19392             mParent.recomputeViewAttributes(this);
19393         }
19394     }
19395 
19396     /**
19397      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
19398      * the view hierarchy.
19399      */
19400     public void dispatchSystemUiVisibilityChanged(int visibility) {
19401         ListenerInfo li = mListenerInfo;
19402         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
19403             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
19404                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
19405         }
19406     }
19407 
19408     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
19409         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
19410         if (val != mSystemUiVisibility) {
19411             setSystemUiVisibility(val);
19412             return true;
19413         }
19414         return false;
19415     }
19416 
19417     /** @hide */
19418     public void setDisabledSystemUiVisibility(int flags) {
19419         if (mAttachInfo != null) {
19420             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
19421                 mAttachInfo.mDisabledSystemUiVisibility = flags;
19422                 if (mParent != null) {
19423                     mParent.recomputeViewAttributes(this);
19424                 }
19425             }
19426         }
19427     }
19428 
19429     /**
19430      * Creates an image that the system displays during the drag and drop
19431      * operation. This is called a &quot;drag shadow&quot;. The default implementation
19432      * for a DragShadowBuilder based on a View returns an image that has exactly the same
19433      * appearance as the given View. The default also positions the center of the drag shadow
19434      * directly under the touch point. If no View is provided (the constructor with no parameters
19435      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
19436      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
19437      * default is an invisible drag shadow.
19438      * <p>
19439      * You are not required to use the View you provide to the constructor as the basis of the
19440      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
19441      * anything you want as the drag shadow.
19442      * </p>
19443      * <p>
19444      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
19445      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
19446      *  size and position of the drag shadow. It uses this data to construct a
19447      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
19448      *  so that your application can draw the shadow image in the Canvas.
19449      * </p>
19450      *
19451      * <div class="special reference">
19452      * <h3>Developer Guides</h3>
19453      * <p>For a guide to implementing drag and drop features, read the
19454      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19455      * </div>
19456      */
19457     public static class DragShadowBuilder {
19458         private final WeakReference<View> mView;
19459 
19460         /**
19461          * Constructs a shadow image builder based on a View. By default, the resulting drag
19462          * shadow will have the same appearance and dimensions as the View, with the touch point
19463          * over the center of the View.
19464          * @param view A View. Any View in scope can be used.
19465          */
19466         public DragShadowBuilder(View view) {
19467             mView = new WeakReference<View>(view);
19468         }
19469 
19470         /**
19471          * Construct a shadow builder object with no associated View.  This
19472          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
19473          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
19474          * to supply the drag shadow's dimensions and appearance without
19475          * reference to any View object. If they are not overridden, then the result is an
19476          * invisible drag shadow.
19477          */
19478         public DragShadowBuilder() {
19479             mView = new WeakReference<View>(null);
19480         }
19481 
19482         /**
19483          * Returns the View object that had been passed to the
19484          * {@link #View.DragShadowBuilder(View)}
19485          * constructor.  If that View parameter was {@code null} or if the
19486          * {@link #View.DragShadowBuilder()}
19487          * constructor was used to instantiate the builder object, this method will return
19488          * null.
19489          *
19490          * @return The View object associate with this builder object.
19491          */
19492         @SuppressWarnings({"JavadocReference"})
19493         final public View getView() {
19494             return mView.get();
19495         }
19496 
19497         /**
19498          * Provides the metrics for the shadow image. These include the dimensions of
19499          * the shadow image, and the point within that shadow that should
19500          * be centered under the touch location while dragging.
19501          * <p>
19502          * The default implementation sets the dimensions of the shadow to be the
19503          * same as the dimensions of the View itself and centers the shadow under
19504          * the touch point.
19505          * </p>
19506          *
19507          * @param shadowSize A {@link android.graphics.Point} containing the width and height
19508          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
19509          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
19510          * image.
19511          *
19512          * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
19513          * shadow image that should be underneath the touch point during the drag and drop
19514          * operation. Your application must set {@link android.graphics.Point#x} to the
19515          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
19516          */
19517         public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
19518             final View view = mView.get();
19519             if (view != null) {
19520                 shadowSize.set(view.getWidth(), view.getHeight());
19521                 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
19522             } else {
19523                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
19524             }
19525         }
19526 
19527         /**
19528          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
19529          * based on the dimensions it received from the
19530          * {@link #onProvideShadowMetrics(Point, Point)} callback.
19531          *
19532          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
19533          */
19534         public void onDrawShadow(Canvas canvas) {
19535             final View view = mView.get();
19536             if (view != null) {
19537                 view.draw(canvas);
19538             } else {
19539                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
19540             }
19541         }
19542     }
19543 
19544     /**
19545      * Starts a drag and drop operation. When your application calls this method, it passes a
19546      * {@link android.view.View.DragShadowBuilder} object to the system. The
19547      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
19548      * to get metrics for the drag shadow, and then calls the object's
19549      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
19550      * <p>
19551      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
19552      *  drag events to all the View objects in your application that are currently visible. It does
19553      *  this either by calling the View object's drag listener (an implementation of
19554      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
19555      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
19556      *  Both are passed a {@link android.view.DragEvent} object that has a
19557      *  {@link android.view.DragEvent#getAction()} value of
19558      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19559      * </p>
19560      * <p>
19561      * Your application can invoke startDrag() on any attached View object. The View object does not
19562      * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
19563      * be related to the View the user selected for dragging.
19564      * </p>
19565      * @param data A {@link android.content.ClipData} object pointing to the data to be
19566      * transferred by the drag and drop operation.
19567      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19568      * drag shadow.
19569      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19570      * drop operation. This Object is put into every DragEvent object sent by the system during the
19571      * current drag.
19572      * <p>
19573      * myLocalState is a lightweight mechanism for the sending information from the dragged View
19574      * to the target Views. For example, it can contain flags that differentiate between a
19575      * a copy operation and a move operation.
19576      * </p>
19577      * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19578      * so the parameter should be set to 0.
19579      * @return {@code true} if the method completes successfully, or
19580      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19581      * do a drag, and so no drag operation is in progress.
19582      */
19583     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19584             Object myLocalState, int flags) {
19585         if (ViewDebug.DEBUG_DRAG) {
19586             Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
19587         }
19588         boolean okay = false;
19589 
19590         Point shadowSize = new Point();
19591         Point shadowTouchPoint = new Point();
19592         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
19593 
19594         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
19595                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
19596             throw new IllegalStateException("Drag shadow dimensions must not be negative");
19597         }
19598 
19599         if (ViewDebug.DEBUG_DRAG) {
19600             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
19601                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
19602         }
19603         Surface surface = new Surface();
19604         try {
19605             IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
19606                     flags, shadowSize.x, shadowSize.y, surface);
19607             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
19608                     + " surface=" + surface);
19609             if (token != null) {
19610                 Canvas canvas = surface.lockCanvas(null);
19611                 try {
19612                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
19613                     shadowBuilder.onDrawShadow(canvas);
19614                 } finally {
19615                     surface.unlockCanvasAndPost(canvas);
19616                 }
19617 
19618                 final ViewRootImpl root = getViewRootImpl();
19619 
19620                 // Cache the local state object for delivery with DragEvents
19621                 root.setLocalDragState(myLocalState);
19622 
19623                 // repurpose 'shadowSize' for the last touch point
19624                 root.getLastTouchPoint(shadowSize);
19625 
19626                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
19627                         shadowSize.x, shadowSize.y,
19628                         shadowTouchPoint.x, shadowTouchPoint.y, data);
19629                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
19630 
19631                 // Off and running!  Release our local surface instance; the drag
19632                 // shadow surface is now managed by the system process.
19633                 surface.release();
19634             }
19635         } catch (Exception e) {
19636             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
19637             surface.destroy();
19638         }
19639 
19640         return okay;
19641     }
19642 
19643     /**
19644      * Handles drag events sent by the system following a call to
19645      * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
19646      *<p>
19647      * When the system calls this method, it passes a
19648      * {@link android.view.DragEvent} object. A call to
19649      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
19650      * in DragEvent. The method uses these to determine what is happening in the drag and drop
19651      * operation.
19652      * @param event The {@link android.view.DragEvent} sent by the system.
19653      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
19654      * in DragEvent, indicating the type of drag event represented by this object.
19655      * @return {@code true} if the method was successful, otherwise {@code false}.
19656      * <p>
19657      *  The method should return {@code true} in response to an action type of
19658      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
19659      *  operation.
19660      * </p>
19661      * <p>
19662      *  The method should also return {@code true} in response to an action type of
19663      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19664      *  {@code false} if it didn't.
19665      * </p>
19666      */
19667     public boolean onDragEvent(DragEvent event) {
19668         return false;
19669     }
19670 
19671     /**
19672      * Detects if this View is enabled and has a drag event listener.
19673      * If both are true, then it calls the drag event listener with the
19674      * {@link android.view.DragEvent} it received. If the drag event listener returns
19675      * {@code true}, then dispatchDragEvent() returns {@code true}.
19676      * <p>
19677      * For all other cases, the method calls the
19678      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
19679      * method and returns its result.
19680      * </p>
19681      * <p>
19682      * This ensures that a drag event is always consumed, even if the View does not have a drag
19683      * event listener. However, if the View has a listener and the listener returns true, then
19684      * onDragEvent() is not called.
19685      * </p>
19686      */
19687     public boolean dispatchDragEvent(DragEvent event) {
19688         ListenerInfo li = mListenerInfo;
19689         //noinspection SimplifiableIfStatement
19690         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
19691                 && li.mOnDragListener.onDrag(this, event)) {
19692             return true;
19693         }
19694         return onDragEvent(event);
19695     }
19696 
19697     boolean canAcceptDrag() {
19698         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
19699     }
19700 
19701     /**
19702      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
19703      * it is ever exposed at all.
19704      * @hide
19705      */
19706     public void onCloseSystemDialogs(String reason) {
19707     }
19708 
19709     /**
19710      * Given a Drawable whose bounds have been set to draw into this view,
19711      * update a Region being computed for
19712      * {@link #gatherTransparentRegion(android.graphics.Region)} so
19713      * that any non-transparent parts of the Drawable are removed from the
19714      * given transparent region.
19715      *
19716      * @param dr The Drawable whose transparency is to be applied to the region.
19717      * @param region A Region holding the current transparency information,
19718      * where any parts of the region that are set are considered to be
19719      * transparent.  On return, this region will be modified to have the
19720      * transparency information reduced by the corresponding parts of the
19721      * Drawable that are not transparent.
19722      * {@hide}
19723      */
19724     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
19725         if (DBG) {
19726             Log.i("View", "Getting transparent region for: " + this);
19727         }
19728         final Region r = dr.getTransparentRegion();
19729         final Rect db = dr.getBounds();
19730         final AttachInfo attachInfo = mAttachInfo;
19731         if (r != null && attachInfo != null) {
19732             final int w = getRight()-getLeft();
19733             final int h = getBottom()-getTop();
19734             if (db.left > 0) {
19735                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
19736                 r.op(0, 0, db.left, h, Region.Op.UNION);
19737             }
19738             if (db.right < w) {
19739                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
19740                 r.op(db.right, 0, w, h, Region.Op.UNION);
19741             }
19742             if (db.top > 0) {
19743                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
19744                 r.op(0, 0, w, db.top, Region.Op.UNION);
19745             }
19746             if (db.bottom < h) {
19747                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
19748                 r.op(0, db.bottom, w, h, Region.Op.UNION);
19749             }
19750             final int[] location = attachInfo.mTransparentLocation;
19751             getLocationInWindow(location);
19752             r.translate(location[0], location[1]);
19753             region.op(r, Region.Op.INTERSECT);
19754         } else {
19755             region.op(db, Region.Op.DIFFERENCE);
19756         }
19757     }
19758 
19759     private void checkForLongClick(int delayOffset) {
19760         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
19761             mHasPerformedLongPress = false;
19762 
19763             if (mPendingCheckForLongPress == null) {
19764                 mPendingCheckForLongPress = new CheckForLongPress();
19765             }
19766             mPendingCheckForLongPress.rememberWindowAttachCount();
19767             postDelayed(mPendingCheckForLongPress,
19768                     ViewConfiguration.getLongPressTimeout() - delayOffset);
19769         }
19770     }
19771 
19772     /**
19773      * Inflate a view from an XML resource.  This convenience method wraps the {@link
19774      * LayoutInflater} class, which provides a full range of options for view inflation.
19775      *
19776      * @param context The Context object for your activity or application.
19777      * @param resource The resource ID to inflate
19778      * @param root A view group that will be the parent.  Used to properly inflate the
19779      * layout_* parameters.
19780      * @see LayoutInflater
19781      */
19782     public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
19783         LayoutInflater factory = LayoutInflater.from(context);
19784         return factory.inflate(resource, root);
19785     }
19786 
19787     /**
19788      * Scroll the view with standard behavior for scrolling beyond the normal
19789      * content boundaries. Views that call this method should override
19790      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
19791      * results of an over-scroll operation.
19792      *
19793      * Views can use this method to handle any touch or fling-based scrolling.
19794      *
19795      * @param deltaX Change in X in pixels
19796      * @param deltaY Change in Y in pixels
19797      * @param scrollX Current X scroll value in pixels before applying deltaX
19798      * @param scrollY Current Y scroll value in pixels before applying deltaY
19799      * @param scrollRangeX Maximum content scroll range along the X axis
19800      * @param scrollRangeY Maximum content scroll range along the Y axis
19801      * @param maxOverScrollX Number of pixels to overscroll by in either direction
19802      *          along the X axis.
19803      * @param maxOverScrollY Number of pixels to overscroll by in either direction
19804      *          along the Y axis.
19805      * @param isTouchEvent true if this scroll operation is the result of a touch event.
19806      * @return true if scrolling was clamped to an over-scroll boundary along either
19807      *          axis, false otherwise.
19808      */
19809     @SuppressWarnings({"UnusedParameters"})
19810     protected boolean overScrollBy(int deltaX, int deltaY,
19811             int scrollX, int scrollY,
19812             int scrollRangeX, int scrollRangeY,
19813             int maxOverScrollX, int maxOverScrollY,
19814             boolean isTouchEvent) {
19815         final int overScrollMode = mOverScrollMode;
19816         final boolean canScrollHorizontal =
19817                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
19818         final boolean canScrollVertical =
19819                 computeVerticalScrollRange() > computeVerticalScrollExtent();
19820         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
19821                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
19822         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
19823                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
19824 
19825         int newScrollX = scrollX + deltaX;
19826         if (!overScrollHorizontal) {
19827             maxOverScrollX = 0;
19828         }
19829 
19830         int newScrollY = scrollY + deltaY;
19831         if (!overScrollVertical) {
19832             maxOverScrollY = 0;
19833         }
19834 
19835         // Clamp values if at the limits and record
19836         final int left = -maxOverScrollX;
19837         final int right = maxOverScrollX + scrollRangeX;
19838         final int top = -maxOverScrollY;
19839         final int bottom = maxOverScrollY + scrollRangeY;
19840 
19841         boolean clampedX = false;
19842         if (newScrollX > right) {
19843             newScrollX = right;
19844             clampedX = true;
19845         } else if (newScrollX < left) {
19846             newScrollX = left;
19847             clampedX = true;
19848         }
19849 
19850         boolean clampedY = false;
19851         if (newScrollY > bottom) {
19852             newScrollY = bottom;
19853             clampedY = true;
19854         } else if (newScrollY < top) {
19855             newScrollY = top;
19856             clampedY = true;
19857         }
19858 
19859         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
19860 
19861         return clampedX || clampedY;
19862     }
19863 
19864     /**
19865      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
19866      * respond to the results of an over-scroll operation.
19867      *
19868      * @param scrollX New X scroll value in pixels
19869      * @param scrollY New Y scroll value in pixels
19870      * @param clampedX True if scrollX was clamped to an over-scroll boundary
19871      * @param clampedY True if scrollY was clamped to an over-scroll boundary
19872      */
19873     protected void onOverScrolled(int scrollX, int scrollY,
19874             boolean clampedX, boolean clampedY) {
19875         // Intentionally empty.
19876     }
19877 
19878     /**
19879      * Returns the over-scroll mode for this view. The result will be
19880      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19881      * (allow over-scrolling only if the view content is larger than the container),
19882      * or {@link #OVER_SCROLL_NEVER}.
19883      *
19884      * @return This view's over-scroll mode.
19885      */
19886     public int getOverScrollMode() {
19887         return mOverScrollMode;
19888     }
19889 
19890     /**
19891      * Set the over-scroll mode for this view. Valid over-scroll modes are
19892      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19893      * (allow over-scrolling only if the view content is larger than the container),
19894      * or {@link #OVER_SCROLL_NEVER}.
19895      *
19896      * Setting the over-scroll mode of a view will have an effect only if the
19897      * view is capable of scrolling.
19898      *
19899      * @param overScrollMode The new over-scroll mode for this view.
19900      */
19901     public void setOverScrollMode(int overScrollMode) {
19902         if (overScrollMode != OVER_SCROLL_ALWAYS &&
19903                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
19904                 overScrollMode != OVER_SCROLL_NEVER) {
19905             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
19906         }
19907         mOverScrollMode = overScrollMode;
19908     }
19909 
19910     /**
19911      * Enable or disable nested scrolling for this view.
19912      *
19913      * <p>If this property is set to true the view will be permitted to initiate nested
19914      * scrolling operations with a compatible parent view in the current hierarchy. If this
19915      * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
19916      * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
19917      * the nested scroll.</p>
19918      *
19919      * @param enabled true to enable nested scrolling, false to disable
19920      *
19921      * @see #isNestedScrollingEnabled()
19922      */
19923     public void setNestedScrollingEnabled(boolean enabled) {
19924         if (enabled) {
19925             mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
19926         } else {
19927             stopNestedScroll();
19928             mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
19929         }
19930     }
19931 
19932     /**
19933      * Returns true if nested scrolling is enabled for this view.
19934      *
19935      * <p>If nested scrolling is enabled and this View class implementation supports it,
19936      * this view will act as a nested scrolling child view when applicable, forwarding data
19937      * about the scroll operation in progress to a compatible and cooperating nested scrolling
19938      * parent.</p>
19939      *
19940      * @return true if nested scrolling is enabled
19941      *
19942      * @see #setNestedScrollingEnabled(boolean)
19943      */
19944     public boolean isNestedScrollingEnabled() {
19945         return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
19946                 PFLAG3_NESTED_SCROLLING_ENABLED;
19947     }
19948 
19949     /**
19950      * Begin a nestable scroll operation along the given axes.
19951      *
19952      * <p>A view starting a nested scroll promises to abide by the following contract:</p>
19953      *
19954      * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
19955      * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
19956      * In the case of touch scrolling the nested scroll will be terminated automatically in
19957      * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
19958      * In the event of programmatic scrolling the caller must explicitly call
19959      * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
19960      *
19961      * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
19962      * If it returns false the caller may ignore the rest of this contract until the next scroll.
19963      * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
19964      *
19965      * <p>At each incremental step of the scroll the caller should invoke
19966      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
19967      * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
19968      * parent at least partially consumed the scroll and the caller should adjust the amount it
19969      * scrolls by.</p>
19970      *
19971      * <p>After applying the remainder of the scroll delta the caller should invoke
19972      * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
19973      * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
19974      * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
19975      * </p>
19976      *
19977      * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
19978      *             {@link #SCROLL_AXIS_VERTICAL}.
19979      * @return true if a cooperative parent was found and nested scrolling has been enabled for
19980      *         the current gesture.
19981      *
19982      * @see #stopNestedScroll()
19983      * @see #dispatchNestedPreScroll(int, int, int[], int[])
19984      * @see #dispatchNestedScroll(int, int, int, int, int[])
19985      */
19986     public boolean startNestedScroll(int axes) {
19987         if (hasNestedScrollingParent()) {
19988             // Already in progress
19989             return true;
19990         }
19991         if (isNestedScrollingEnabled()) {
19992             ViewParent p = getParent();
19993             View child = this;
19994             while (p != null) {
19995                 try {
19996                     if (p.onStartNestedScroll(child, this, axes)) {
19997                         mNestedScrollingParent = p;
19998                         p.onNestedScrollAccepted(child, this, axes);
19999                         return true;
20000                     }
20001                 } catch (AbstractMethodError e) {
20002                     Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
20003                             "method onStartNestedScroll", e);
20004                     // Allow the search upward to continue
20005                 }
20006                 if (p instanceof View) {
20007                     child = (View) p;
20008                 }
20009                 p = p.getParent();
20010             }
20011         }
20012         return false;
20013     }
20014 
20015     /**
20016      * Stop a nested scroll in progress.
20017      *
20018      * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
20019      *
20020      * @see #startNestedScroll(int)
20021      */
20022     public void stopNestedScroll() {
20023         if (mNestedScrollingParent != null) {
20024             mNestedScrollingParent.onStopNestedScroll(this);
20025             mNestedScrollingParent = null;
20026         }
20027     }
20028 
20029     /**
20030      * Returns true if this view has a nested scrolling parent.
20031      *
20032      * <p>The presence of a nested scrolling parent indicates that this view has initiated
20033      * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
20034      *
20035      * @return whether this view has a nested scrolling parent
20036      */
20037     public boolean hasNestedScrollingParent() {
20038         return mNestedScrollingParent != null;
20039     }
20040 
20041     /**
20042      * Dispatch one step of a nested scroll in progress.
20043      *
20044      * <p>Implementations of views that support nested scrolling should call this to report
20045      * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
20046      * is not currently in progress or nested scrolling is not
20047      * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
20048      *
20049      * <p>Compatible View implementations should also call
20050      * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
20051      * consuming a component of the scroll event themselves.</p>
20052      *
20053      * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
20054      * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
20055      * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
20056      * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
20057      * @param offsetInWindow Optional. If not null, on return this will contain the offset
20058      *                       in local view coordinates of this view from before this operation
20059      *                       to after it completes. View implementations may use this to adjust
20060      *                       expected input coordinate tracking.
20061      * @return true if the event was dispatched, false if it could not be dispatched.
20062      * @see #dispatchNestedPreScroll(int, int, int[], int[])
20063      */
20064     public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
20065             int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
20066         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20067             if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
20068                 int startX = 0;
20069                 int startY = 0;
20070                 if (offsetInWindow != null) {
20071                     getLocationInWindow(offsetInWindow);
20072                     startX = offsetInWindow[0];
20073                     startY = offsetInWindow[1];
20074                 }
20075 
20076                 mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
20077                         dxUnconsumed, dyUnconsumed);
20078 
20079                 if (offsetInWindow != null) {
20080                     getLocationInWindow(offsetInWindow);
20081                     offsetInWindow[0] -= startX;
20082                     offsetInWindow[1] -= startY;
20083                 }
20084                 return true;
20085             } else if (offsetInWindow != null) {
20086                 // No motion, no dispatch. Keep offsetInWindow up to date.
20087                 offsetInWindow[0] = 0;
20088                 offsetInWindow[1] = 0;
20089             }
20090         }
20091         return false;
20092     }
20093 
20094     /**
20095      * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
20096      *
20097      * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
20098      * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
20099      * scrolling operation to consume some or all of the scroll operation before the child view
20100      * consumes it.</p>
20101      *
20102      * @param dx Horizontal scroll distance in pixels
20103      * @param dy Vertical scroll distance in pixels
20104      * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
20105      *                 and consumed[1] the consumed dy.
20106      * @param offsetInWindow Optional. If not null, on return this will contain the offset
20107      *                       in local view coordinates of this view from before this operation
20108      *                       to after it completes. View implementations may use this to adjust
20109      *                       expected input coordinate tracking.
20110      * @return true if the parent consumed some or all of the scroll delta
20111      * @see #dispatchNestedScroll(int, int, int, int, int[])
20112      */
20113     public boolean dispatchNestedPreScroll(int dx, int dy,
20114             @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
20115         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20116             if (dx != 0 || dy != 0) {
20117                 int startX = 0;
20118                 int startY = 0;
20119                 if (offsetInWindow != null) {
20120                     getLocationInWindow(offsetInWindow);
20121                     startX = offsetInWindow[0];
20122                     startY = offsetInWindow[1];
20123                 }
20124 
20125                 if (consumed == null) {
20126                     if (mTempNestedScrollConsumed == null) {
20127                         mTempNestedScrollConsumed = new int[2];
20128                     }
20129                     consumed = mTempNestedScrollConsumed;
20130                 }
20131                 consumed[0] = 0;
20132                 consumed[1] = 0;
20133                 mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
20134 
20135                 if (offsetInWindow != null) {
20136                     getLocationInWindow(offsetInWindow);
20137                     offsetInWindow[0] -= startX;
20138                     offsetInWindow[1] -= startY;
20139                 }
20140                 return consumed[0] != 0 || consumed[1] != 0;
20141             } else if (offsetInWindow != null) {
20142                 offsetInWindow[0] = 0;
20143                 offsetInWindow[1] = 0;
20144             }
20145         }
20146         return false;
20147     }
20148 
20149     /**
20150      * Dispatch a fling to a nested scrolling parent.
20151      *
20152      * <p>This method should be used to indicate that a nested scrolling child has detected
20153      * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
20154      * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
20155      * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
20156      * along a scrollable axis.</p>
20157      *
20158      * <p>If a nested scrolling child view would normally fling but it is at the edge of
20159      * its own content, it can use this method to delegate the fling to its nested scrolling
20160      * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
20161      *
20162      * @param velocityX Horizontal fling velocity in pixels per second
20163      * @param velocityY Vertical fling velocity in pixels per second
20164      * @param consumed true if the child consumed the fling, false otherwise
20165      * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
20166      */
20167     public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
20168         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20169             return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
20170         }
20171         return false;
20172     }
20173 
20174     /**
20175      * Dispatch a fling to a nested scrolling parent before it is processed by this view.
20176      *
20177      * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
20178      * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
20179      * offsets an opportunity for the parent view in a nested fling to fully consume the fling
20180      * before the child view consumes it. If this method returns <code>true</code>, a nested
20181      * parent view consumed the fling and this view should not scroll as a result.</p>
20182      *
20183      * <p>For a better user experience, only one view in a nested scrolling chain should consume
20184      * the fling at a time. If a parent view consumed the fling this method will return false.
20185      * Custom view implementations should account for this in two ways:</p>
20186      *
20187      * <ul>
20188      *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
20189      *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
20190      *     position regardless.</li>
20191      *     <li>If a nested parent does consume the fling, this view should not scroll at all,
20192      *     even to settle back to a valid idle position.</li>
20193      * </ul>
20194      *
20195      * <p>Views should also not offer fling velocities to nested parent views along an axis
20196      * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
20197      * should not offer a horizontal fling velocity to its parents since scrolling along that
20198      * axis is not permitted and carrying velocity along that motion does not make sense.</p>
20199      *
20200      * @param velocityX Horizontal fling velocity in pixels per second
20201      * @param velocityY Vertical fling velocity in pixels per second
20202      * @return true if a nested scrolling parent consumed the fling
20203      */
20204     public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
20205         if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20206             return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
20207         }
20208         return false;
20209     }
20210 
20211     /**
20212      * Gets a scale factor that determines the distance the view should scroll
20213      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
20214      * @return The vertical scroll scale factor.
20215      * @hide
20216      */
20217     protected float getVerticalScrollFactor() {
20218         if (mVerticalScrollFactor == 0) {
20219             TypedValue outValue = new TypedValue();
20220             if (!mContext.getTheme().resolveAttribute(
20221                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
20222                 throw new IllegalStateException(
20223                         "Expected theme to define listPreferredItemHeight.");
20224             }
20225             mVerticalScrollFactor = outValue.getDimension(
20226                     mContext.getResources().getDisplayMetrics());
20227         }
20228         return mVerticalScrollFactor;
20229     }
20230 
20231     /**
20232      * Gets a scale factor that determines the distance the view should scroll
20233      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
20234      * @return The horizontal scroll scale factor.
20235      * @hide
20236      */
20237     protected float getHorizontalScrollFactor() {
20238         // TODO: Should use something else.
20239         return getVerticalScrollFactor();
20240     }
20241 
20242     /**
20243      * Return the value specifying the text direction or policy that was set with
20244      * {@link #setTextDirection(int)}.
20245      *
20246      * @return the defined text direction. It can be one of:
20247      *
20248      * {@link #TEXT_DIRECTION_INHERIT},
20249      * {@link #TEXT_DIRECTION_FIRST_STRONG},
20250      * {@link #TEXT_DIRECTION_ANY_RTL},
20251      * {@link #TEXT_DIRECTION_LTR},
20252      * {@link #TEXT_DIRECTION_RTL},
20253      * {@link #TEXT_DIRECTION_LOCALE},
20254      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20255      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20256      *
20257      * @attr ref android.R.styleable#View_textDirection
20258      *
20259      * @hide
20260      */
20261     @ViewDebug.ExportedProperty(category = "text", mapping = {
20262             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20263             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20264             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20265             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20266             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20267             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20268             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20269             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20270     })
20271     public int getRawTextDirection() {
20272         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
20273     }
20274 
20275     /**
20276      * Set the text direction.
20277      *
20278      * @param textDirection the direction to set. Should be one of:
20279      *
20280      * {@link #TEXT_DIRECTION_INHERIT},
20281      * {@link #TEXT_DIRECTION_FIRST_STRONG},
20282      * {@link #TEXT_DIRECTION_ANY_RTL},
20283      * {@link #TEXT_DIRECTION_LTR},
20284      * {@link #TEXT_DIRECTION_RTL},
20285      * {@link #TEXT_DIRECTION_LOCALE}
20286      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20287      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
20288      *
20289      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
20290      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
20291      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
20292      *
20293      * @attr ref android.R.styleable#View_textDirection
20294      */
20295     public void setTextDirection(int textDirection) {
20296         if (getRawTextDirection() != textDirection) {
20297             // Reset the current text direction and the resolved one
20298             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
20299             resetResolvedTextDirection();
20300             // Set the new text direction
20301             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
20302             // Do resolution
20303             resolveTextDirection();
20304             // Notify change
20305             onRtlPropertiesChanged(getLayoutDirection());
20306             // Refresh
20307             requestLayout();
20308             invalidate(true);
20309         }
20310     }
20311 
20312     /**
20313      * Return the resolved text direction.
20314      *
20315      * @return the resolved text direction. Returns one of:
20316      *
20317      * {@link #TEXT_DIRECTION_FIRST_STRONG},
20318      * {@link #TEXT_DIRECTION_ANY_RTL},
20319      * {@link #TEXT_DIRECTION_LTR},
20320      * {@link #TEXT_DIRECTION_RTL},
20321      * {@link #TEXT_DIRECTION_LOCALE},
20322      * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20323      * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20324      *
20325      * @attr ref android.R.styleable#View_textDirection
20326      */
20327     @ViewDebug.ExportedProperty(category = "text", mapping = {
20328             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20329             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20330             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20331             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20332             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20333             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20334             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20335             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20336     })
20337     public int getTextDirection() {
20338         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
20339     }
20340 
20341     /**
20342      * Resolve the text direction.
20343      *
20344      * @return true if resolution has been done, false otherwise.
20345      *
20346      * @hide
20347      */
20348     public boolean resolveTextDirection() {
20349         // Reset any previous text direction resolution
20350         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20351 
20352         if (hasRtlSupport()) {
20353             // Set resolved text direction flag depending on text direction flag
20354             final int textDirection = getRawTextDirection();
20355             switch(textDirection) {
20356                 case TEXT_DIRECTION_INHERIT:
20357                     if (!canResolveTextDirection()) {
20358                         // We cannot do the resolution if there is no parent, so use the default one
20359                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20360                         // Resolution will need to happen again later
20361                         return false;
20362                     }
20363 
20364                     // Parent has not yet resolved, so we still return the default
20365                     try {
20366                         if (!mParent.isTextDirectionResolved()) {
20367                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20368                             // Resolution will need to happen again later
20369                             return false;
20370                         }
20371                     } catch (AbstractMethodError e) {
20372                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20373                                 " does not fully implement ViewParent", e);
20374                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
20375                                 PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20376                         return true;
20377                     }
20378 
20379                     // Set current resolved direction to the same value as the parent's one
20380                     int parentResolvedDirection;
20381                     try {
20382                         parentResolvedDirection = mParent.getTextDirection();
20383                     } catch (AbstractMethodError e) {
20384                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20385                                 " does not fully implement ViewParent", e);
20386                         parentResolvedDirection = TEXT_DIRECTION_LTR;
20387                     }
20388                     switch (parentResolvedDirection) {
20389                         case TEXT_DIRECTION_FIRST_STRONG:
20390                         case TEXT_DIRECTION_ANY_RTL:
20391                         case TEXT_DIRECTION_LTR:
20392                         case TEXT_DIRECTION_RTL:
20393                         case TEXT_DIRECTION_LOCALE:
20394                         case TEXT_DIRECTION_FIRST_STRONG_LTR:
20395                         case TEXT_DIRECTION_FIRST_STRONG_RTL:
20396                             mPrivateFlags2 |=
20397                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20398                             break;
20399                         default:
20400                             // Default resolved direction is "first strong" heuristic
20401                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20402                     }
20403                     break;
20404                 case TEXT_DIRECTION_FIRST_STRONG:
20405                 case TEXT_DIRECTION_ANY_RTL:
20406                 case TEXT_DIRECTION_LTR:
20407                 case TEXT_DIRECTION_RTL:
20408                 case TEXT_DIRECTION_LOCALE:
20409                 case TEXT_DIRECTION_FIRST_STRONG_LTR:
20410                 case TEXT_DIRECTION_FIRST_STRONG_RTL:
20411                     // Resolved direction is the same as text direction
20412                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20413                     break;
20414                 default:
20415                     // Default resolved direction is "first strong" heuristic
20416                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20417             }
20418         } else {
20419             // Default resolved direction is "first strong" heuristic
20420             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20421         }
20422 
20423         // Set to resolved
20424         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
20425         return true;
20426     }
20427 
20428     /**
20429      * Check if text direction resolution can be done.
20430      *
20431      * @return true if text direction resolution can be done otherwise return false.
20432      */
20433     public boolean canResolveTextDirection() {
20434         switch (getRawTextDirection()) {
20435             case TEXT_DIRECTION_INHERIT:
20436                 if (mParent != null) {
20437                     try {
20438                         return mParent.canResolveTextDirection();
20439                     } catch (AbstractMethodError e) {
20440                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20441                                 " does not fully implement ViewParent", e);
20442                     }
20443                 }
20444                 return false;
20445 
20446             default:
20447                 return true;
20448         }
20449     }
20450 
20451     /**
20452      * Reset resolved text direction. Text direction will be resolved during a call to
20453      * {@link #onMeasure(int, int)}.
20454      *
20455      * @hide
20456      */
20457     public void resetResolvedTextDirection() {
20458         // Reset any previous text direction resolution
20459         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20460         // Set to default value
20461         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20462     }
20463 
20464     /**
20465      * @return true if text direction is inherited.
20466      *
20467      * @hide
20468      */
20469     public boolean isTextDirectionInherited() {
20470         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
20471     }
20472 
20473     /**
20474      * @return true if text direction is resolved.
20475      */
20476     public boolean isTextDirectionResolved() {
20477         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
20478     }
20479 
20480     /**
20481      * Return the value specifying the text alignment or policy that was set with
20482      * {@link #setTextAlignment(int)}.
20483      *
20484      * @return the defined text alignment. It can be one of:
20485      *
20486      * {@link #TEXT_ALIGNMENT_INHERIT},
20487      * {@link #TEXT_ALIGNMENT_GRAVITY},
20488      * {@link #TEXT_ALIGNMENT_CENTER},
20489      * {@link #TEXT_ALIGNMENT_TEXT_START},
20490      * {@link #TEXT_ALIGNMENT_TEXT_END},
20491      * {@link #TEXT_ALIGNMENT_VIEW_START},
20492      * {@link #TEXT_ALIGNMENT_VIEW_END}
20493      *
20494      * @attr ref android.R.styleable#View_textAlignment
20495      *
20496      * @hide
20497      */
20498     @ViewDebug.ExportedProperty(category = "text", mapping = {
20499             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20500             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20501             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20502             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20503             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20504             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20505             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20506     })
20507     @TextAlignment
20508     public int getRawTextAlignment() {
20509         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
20510     }
20511 
20512     /**
20513      * Set the text alignment.
20514      *
20515      * @param textAlignment The text alignment to set. Should be one of
20516      *
20517      * {@link #TEXT_ALIGNMENT_INHERIT},
20518      * {@link #TEXT_ALIGNMENT_GRAVITY},
20519      * {@link #TEXT_ALIGNMENT_CENTER},
20520      * {@link #TEXT_ALIGNMENT_TEXT_START},
20521      * {@link #TEXT_ALIGNMENT_TEXT_END},
20522      * {@link #TEXT_ALIGNMENT_VIEW_START},
20523      * {@link #TEXT_ALIGNMENT_VIEW_END}
20524      *
20525      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
20526      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
20527      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
20528      *
20529      * @attr ref android.R.styleable#View_textAlignment
20530      */
20531     public void setTextAlignment(@TextAlignment int textAlignment) {
20532         if (textAlignment != getRawTextAlignment()) {
20533             // Reset the current and resolved text alignment
20534             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
20535             resetResolvedTextAlignment();
20536             // Set the new text alignment
20537             mPrivateFlags2 |=
20538                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
20539             // Do resolution
20540             resolveTextAlignment();
20541             // Notify change
20542             onRtlPropertiesChanged(getLayoutDirection());
20543             // Refresh
20544             requestLayout();
20545             invalidate(true);
20546         }
20547     }
20548 
20549     /**
20550      * Return the resolved text alignment.
20551      *
20552      * @return the resolved text alignment. Returns one of:
20553      *
20554      * {@link #TEXT_ALIGNMENT_GRAVITY},
20555      * {@link #TEXT_ALIGNMENT_CENTER},
20556      * {@link #TEXT_ALIGNMENT_TEXT_START},
20557      * {@link #TEXT_ALIGNMENT_TEXT_END},
20558      * {@link #TEXT_ALIGNMENT_VIEW_START},
20559      * {@link #TEXT_ALIGNMENT_VIEW_END}
20560      *
20561      * @attr ref android.R.styleable#View_textAlignment
20562      */
20563     @ViewDebug.ExportedProperty(category = "text", mapping = {
20564             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20565             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20566             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20567             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20568             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20569             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20570             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20571     })
20572     @TextAlignment
20573     public int getTextAlignment() {
20574         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
20575                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
20576     }
20577 
20578     /**
20579      * Resolve the text alignment.
20580      *
20581      * @return true if resolution has been done, false otherwise.
20582      *
20583      * @hide
20584      */
20585     public boolean resolveTextAlignment() {
20586         // Reset any previous text alignment resolution
20587         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20588 
20589         if (hasRtlSupport()) {
20590             // Set resolved text alignment flag depending on text alignment flag
20591             final int textAlignment = getRawTextAlignment();
20592             switch (textAlignment) {
20593                 case TEXT_ALIGNMENT_INHERIT:
20594                     // Check if we can resolve the text alignment
20595                     if (!canResolveTextAlignment()) {
20596                         // We cannot do the resolution if there is no parent so use the default
20597                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20598                         // Resolution will need to happen again later
20599                         return false;
20600                     }
20601 
20602                     // Parent has not yet resolved, so we still return the default
20603                     try {
20604                         if (!mParent.isTextAlignmentResolved()) {
20605                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20606                             // Resolution will need to happen again later
20607                             return false;
20608                         }
20609                     } catch (AbstractMethodError e) {
20610                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20611                                 " does not fully implement ViewParent", e);
20612                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
20613                                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20614                         return true;
20615                     }
20616 
20617                     int parentResolvedTextAlignment;
20618                     try {
20619                         parentResolvedTextAlignment = mParent.getTextAlignment();
20620                     } catch (AbstractMethodError e) {
20621                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20622                                 " does not fully implement ViewParent", e);
20623                         parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
20624                     }
20625                     switch (parentResolvedTextAlignment) {
20626                         case TEXT_ALIGNMENT_GRAVITY:
20627                         case TEXT_ALIGNMENT_TEXT_START:
20628                         case TEXT_ALIGNMENT_TEXT_END:
20629                         case TEXT_ALIGNMENT_CENTER:
20630                         case TEXT_ALIGNMENT_VIEW_START:
20631                         case TEXT_ALIGNMENT_VIEW_END:
20632                             // Resolved text alignment is the same as the parent resolved
20633                             // text alignment
20634                             mPrivateFlags2 |=
20635                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20636                             break;
20637                         default:
20638                             // Use default resolved text alignment
20639                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20640                     }
20641                     break;
20642                 case TEXT_ALIGNMENT_GRAVITY:
20643                 case TEXT_ALIGNMENT_TEXT_START:
20644                 case TEXT_ALIGNMENT_TEXT_END:
20645                 case TEXT_ALIGNMENT_CENTER:
20646                 case TEXT_ALIGNMENT_VIEW_START:
20647                 case TEXT_ALIGNMENT_VIEW_END:
20648                     // Resolved text alignment is the same as text alignment
20649                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20650                     break;
20651                 default:
20652                     // Use default resolved text alignment
20653                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20654             }
20655         } else {
20656             // Use default resolved text alignment
20657             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20658         }
20659 
20660         // Set the resolved
20661         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20662         return true;
20663     }
20664 
20665     /**
20666      * Check if text alignment resolution can be done.
20667      *
20668      * @return true if text alignment resolution can be done otherwise return false.
20669      */
20670     public boolean canResolveTextAlignment() {
20671         switch (getRawTextAlignment()) {
20672             case TEXT_DIRECTION_INHERIT:
20673                 if (mParent != null) {
20674                     try {
20675                         return mParent.canResolveTextAlignment();
20676                     } catch (AbstractMethodError e) {
20677                         Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20678                                 " does not fully implement ViewParent", e);
20679                     }
20680                 }
20681                 return false;
20682 
20683             default:
20684                 return true;
20685         }
20686     }
20687 
20688     /**
20689      * Reset resolved text alignment. Text alignment will be resolved during a call to
20690      * {@link #onMeasure(int, int)}.
20691      *
20692      * @hide
20693      */
20694     public void resetResolvedTextAlignment() {
20695         // Reset any previous text alignment resolution
20696         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20697         // Set to default
20698         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20699     }
20700 
20701     /**
20702      * @return true if text alignment is inherited.
20703      *
20704      * @hide
20705      */
20706     public boolean isTextAlignmentInherited() {
20707         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
20708     }
20709 
20710     /**
20711      * @return true if text alignment is resolved.
20712      */
20713     public boolean isTextAlignmentResolved() {
20714         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20715     }
20716 
20717     /**
20718      * Generate a value suitable for use in {@link #setId(int)}.
20719      * This value will not collide with ID values generated at build time by aapt for R.id.
20720      *
20721      * @return a generated ID value
20722      */
20723     public static int generateViewId() {
20724         for (;;) {
20725             final int result = sNextGeneratedId.get();
20726             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
20727             int newValue = result + 1;
20728             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
20729             if (sNextGeneratedId.compareAndSet(result, newValue)) {
20730                 return result;
20731             }
20732         }
20733     }
20734 
20735     /**
20736      * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
20737      * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
20738      *                           a normal View or a ViewGroup with
20739      *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
20740      * @hide
20741      */
20742     public void captureTransitioningViews(List<View> transitioningViews) {
20743         if (getVisibility() == View.VISIBLE) {
20744             transitioningViews.add(this);
20745         }
20746     }
20747 
20748     /**
20749      * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
20750      * @param namedElements Will contain all Views in the hierarchy having a transitionName.
20751      * @hide
20752      */
20753     public void findNamedViews(Map<String, View> namedElements) {
20754         if (getVisibility() == VISIBLE || mGhostView != null) {
20755             String transitionName = getTransitionName();
20756             if (transitionName != null) {
20757                 namedElements.put(transitionName, this);
20758             }
20759         }
20760     }
20761 
20762     //
20763     // Properties
20764     //
20765     /**
20766      * A Property wrapper around the <code>alpha</code> functionality handled by the
20767      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
20768      */
20769     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
20770         @Override
20771         public void setValue(View object, float value) {
20772             object.setAlpha(value);
20773         }
20774 
20775         @Override
20776         public Float get(View object) {
20777             return object.getAlpha();
20778         }
20779     };
20780 
20781     /**
20782      * A Property wrapper around the <code>translationX</code> functionality handled by the
20783      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
20784      */
20785     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
20786         @Override
20787         public void setValue(View object, float value) {
20788             object.setTranslationX(value);
20789         }
20790 
20791                 @Override
20792         public Float get(View object) {
20793             return object.getTranslationX();
20794         }
20795     };
20796 
20797     /**
20798      * A Property wrapper around the <code>translationY</code> functionality handled by the
20799      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
20800      */
20801     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
20802         @Override
20803         public void setValue(View object, float value) {
20804             object.setTranslationY(value);
20805         }
20806 
20807         @Override
20808         public Float get(View object) {
20809             return object.getTranslationY();
20810         }
20811     };
20812 
20813     /**
20814      * A Property wrapper around the <code>translationZ</code> functionality handled by the
20815      * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
20816      */
20817     public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
20818         @Override
20819         public void setValue(View object, float value) {
20820             object.setTranslationZ(value);
20821         }
20822 
20823         @Override
20824         public Float get(View object) {
20825             return object.getTranslationZ();
20826         }
20827     };
20828 
20829     /**
20830      * A Property wrapper around the <code>x</code> functionality handled by the
20831      * {@link View#setX(float)} and {@link View#getX()} methods.
20832      */
20833     public static final Property<View, Float> X = new FloatProperty<View>("x") {
20834         @Override
20835         public void setValue(View object, float value) {
20836             object.setX(value);
20837         }
20838 
20839         @Override
20840         public Float get(View object) {
20841             return object.getX();
20842         }
20843     };
20844 
20845     /**
20846      * A Property wrapper around the <code>y</code> functionality handled by the
20847      * {@link View#setY(float)} and {@link View#getY()} methods.
20848      */
20849     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
20850         @Override
20851         public void setValue(View object, float value) {
20852             object.setY(value);
20853         }
20854 
20855         @Override
20856         public Float get(View object) {
20857             return object.getY();
20858         }
20859     };
20860 
20861     /**
20862      * A Property wrapper around the <code>z</code> functionality handled by the
20863      * {@link View#setZ(float)} and {@link View#getZ()} methods.
20864      */
20865     public static final Property<View, Float> Z = new FloatProperty<View>("z") {
20866         @Override
20867         public void setValue(View object, float value) {
20868             object.setZ(value);
20869         }
20870 
20871         @Override
20872         public Float get(View object) {
20873             return object.getZ();
20874         }
20875     };
20876 
20877     /**
20878      * A Property wrapper around the <code>rotation</code> functionality handled by the
20879      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
20880      */
20881     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
20882         @Override
20883         public void setValue(View object, float value) {
20884             object.setRotation(value);
20885         }
20886 
20887         @Override
20888         public Float get(View object) {
20889             return object.getRotation();
20890         }
20891     };
20892 
20893     /**
20894      * A Property wrapper around the <code>rotationX</code> functionality handled by the
20895      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
20896      */
20897     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
20898         @Override
20899         public void setValue(View object, float value) {
20900             object.setRotationX(value);
20901         }
20902 
20903         @Override
20904         public Float get(View object) {
20905             return object.getRotationX();
20906         }
20907     };
20908 
20909     /**
20910      * A Property wrapper around the <code>rotationY</code> functionality handled by the
20911      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
20912      */
20913     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
20914         @Override
20915         public void setValue(View object, float value) {
20916             object.setRotationY(value);
20917         }
20918 
20919         @Override
20920         public Float get(View object) {
20921             return object.getRotationY();
20922         }
20923     };
20924 
20925     /**
20926      * A Property wrapper around the <code>scaleX</code> functionality handled by the
20927      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
20928      */
20929     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
20930         @Override
20931         public void setValue(View object, float value) {
20932             object.setScaleX(value);
20933         }
20934 
20935         @Override
20936         public Float get(View object) {
20937             return object.getScaleX();
20938         }
20939     };
20940 
20941     /**
20942      * A Property wrapper around the <code>scaleY</code> functionality handled by the
20943      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
20944      */
20945     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
20946         @Override
20947         public void setValue(View object, float value) {
20948             object.setScaleY(value);
20949         }
20950 
20951         @Override
20952         public Float get(View object) {
20953             return object.getScaleY();
20954         }
20955     };
20956 
20957     /**
20958      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
20959      * Each MeasureSpec represents a requirement for either the width or the height.
20960      * A MeasureSpec is comprised of a size and a mode. There are three possible
20961      * modes:
20962      * <dl>
20963      * <dt>UNSPECIFIED</dt>
20964      * <dd>
20965      * The parent has not imposed any constraint on the child. It can be whatever size
20966      * it wants.
20967      * </dd>
20968      *
20969      * <dt>EXACTLY</dt>
20970      * <dd>
20971      * The parent has determined an exact size for the child. The child is going to be
20972      * given those bounds regardless of how big it wants to be.
20973      * </dd>
20974      *
20975      * <dt>AT_MOST</dt>
20976      * <dd>
20977      * The child can be as large as it wants up to the specified size.
20978      * </dd>
20979      * </dl>
20980      *
20981      * MeasureSpecs are implemented as ints to reduce object allocation. This class
20982      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
20983      */
20984     public static class MeasureSpec {
20985         private static final int MODE_SHIFT = 30;
20986         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
20987 
20988         /**
20989          * Measure specification mode: The parent has not imposed any constraint
20990          * on the child. It can be whatever size it wants.
20991          */
20992         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
20993 
20994         /**
20995          * Measure specification mode: The parent has determined an exact size
20996          * for the child. The child is going to be given those bounds regardless
20997          * of how big it wants to be.
20998          */
20999         public static final int EXACTLY     = 1 << MODE_SHIFT;
21000 
21001         /**
21002          * Measure specification mode: The child can be as large as it wants up
21003          * to the specified size.
21004          */
21005         public static final int AT_MOST     = 2 << MODE_SHIFT;
21006 
21007         /**
21008          * Creates a measure specification based on the supplied size and mode.
21009          *
21010          * The mode must always be one of the following:
21011          * <ul>
21012          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
21013          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
21014          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
21015          * </ul>
21016          *
21017          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
21018          * implementation was such that the order of arguments did not matter
21019          * and overflow in either value could impact the resulting MeasureSpec.
21020          * {@link android.widget.RelativeLayout} was affected by this bug.
21021          * Apps targeting API levels greater than 17 will get the fixed, more strict
21022          * behavior.</p>
21023          *
21024          * @param size the size of the measure specification
21025          * @param mode the mode of the measure specification
21026          * @return the measure specification based on size and mode
21027          */
21028         public static int makeMeasureSpec(int size, int mode) {
21029             if (sUseBrokenMakeMeasureSpec) {
21030                 return size + mode;
21031             } else {
21032                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
21033             }
21034         }
21035 
21036         /**
21037          * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
21038          * will automatically get a size of 0. Older apps expect this.
21039          *
21040          * @hide internal use only for compatibility with system widgets and older apps
21041          */
21042         public static int makeSafeMeasureSpec(int size, int mode) {
21043             if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
21044                 return 0;
21045             }
21046             return makeMeasureSpec(size, mode);
21047         }
21048 
21049         /**
21050          * Extracts the mode from the supplied measure specification.
21051          *
21052          * @param measureSpec the measure specification to extract the mode from
21053          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
21054          *         {@link android.view.View.MeasureSpec#AT_MOST} or
21055          *         {@link android.view.View.MeasureSpec#EXACTLY}
21056          */
21057         public static int getMode(int measureSpec) {
21058             return (measureSpec & MODE_MASK);
21059         }
21060 
21061         /**
21062          * Extracts the size from the supplied measure specification.
21063          *
21064          * @param measureSpec the measure specification to extract the size from
21065          * @return the size in pixels defined in the supplied measure specification
21066          */
21067         public static int getSize(int measureSpec) {
21068             return (measureSpec & ~MODE_MASK);
21069         }
21070 
21071         static int adjust(int measureSpec, int delta) {
21072             final int mode = getMode(measureSpec);
21073             int size = getSize(measureSpec);
21074             if (mode == UNSPECIFIED) {
21075                 // No need to adjust size for UNSPECIFIED mode.
21076                 return makeMeasureSpec(size, UNSPECIFIED);
21077             }
21078             size += delta;
21079             if (size < 0) {
21080                 Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
21081                         ") spec: " + toString(measureSpec) + " delta: " + delta);
21082                 size = 0;
21083             }
21084             return makeMeasureSpec(size, mode);
21085         }
21086 
21087         /**
21088          * Returns a String representation of the specified measure
21089          * specification.
21090          *
21091          * @param measureSpec the measure specification to convert to a String
21092          * @return a String with the following format: "MeasureSpec: MODE SIZE"
21093          */
21094         public static String toString(int measureSpec) {
21095             int mode = getMode(measureSpec);
21096             int size = getSize(measureSpec);
21097 
21098             StringBuilder sb = new StringBuilder("MeasureSpec: ");
21099 
21100             if (mode == UNSPECIFIED)
21101                 sb.append("UNSPECIFIED ");
21102             else if (mode == EXACTLY)
21103                 sb.append("EXACTLY ");
21104             else if (mode == AT_MOST)
21105                 sb.append("AT_MOST ");
21106             else
21107                 sb.append(mode).append(" ");
21108 
21109             sb.append(size);
21110             return sb.toString();
21111         }
21112     }
21113 
21114     private final class CheckForLongPress implements Runnable {
21115         private int mOriginalWindowAttachCount;
21116 
21117         @Override
21118         public void run() {
21119             if (isPressed() && (mParent != null)
21120                     && mOriginalWindowAttachCount == mWindowAttachCount) {
21121                 if (performLongClick()) {
21122                     mHasPerformedLongPress = true;
21123                 }
21124             }
21125         }
21126 
21127         public void rememberWindowAttachCount() {
21128             mOriginalWindowAttachCount = mWindowAttachCount;
21129         }
21130     }
21131 
21132     private final class CheckForTap implements Runnable {
21133         public float x;
21134         public float y;
21135 
21136         @Override
21137         public void run() {
21138             mPrivateFlags &= ~PFLAG_PREPRESSED;
21139             setPressed(true, x, y);
21140             checkForLongClick(ViewConfiguration.getTapTimeout());
21141         }
21142     }
21143 
21144     private final class PerformClick implements Runnable {
21145         @Override
21146         public void run() {
21147             performClick();
21148         }
21149     }
21150 
21151     /** @hide */
21152     public void hackTurnOffWindowResizeAnim(boolean off) {
21153         mAttachInfo.mTurnOffWindowResizeAnim = off;
21154     }
21155 
21156     /**
21157      * This method returns a ViewPropertyAnimator object, which can be used to animate
21158      * specific properties on this View.
21159      *
21160      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
21161      */
21162     public ViewPropertyAnimator animate() {
21163         if (mAnimator == null) {
21164             mAnimator = new ViewPropertyAnimator(this);
21165         }
21166         return mAnimator;
21167     }
21168 
21169     /**
21170      * Sets the name of the View to be used to identify Views in Transitions.
21171      * Names should be unique in the View hierarchy.
21172      *
21173      * @param transitionName The name of the View to uniquely identify it for Transitions.
21174      */
21175     public final void setTransitionName(String transitionName) {
21176         mTransitionName = transitionName;
21177     }
21178 
21179     /**
21180      * Returns the name of the View to be used to identify Views in Transitions.
21181      * Names should be unique in the View hierarchy.
21182      *
21183      * <p>This returns null if the View has not been given a name.</p>
21184      *
21185      * @return The name used of the View to be used to identify Views in Transitions or null
21186      * if no name has been given.
21187      */
21188     @ViewDebug.ExportedProperty
21189     public String getTransitionName() {
21190         return mTransitionName;
21191     }
21192 
21193     /**
21194      * Interface definition for a callback to be invoked when a hardware key event is
21195      * dispatched to this view. The callback will be invoked before the key event is
21196      * given to the view. This is only useful for hardware keyboards; a software input
21197      * method has no obligation to trigger this listener.
21198      */
21199     public interface OnKeyListener {
21200         /**
21201          * Called when a hardware key is dispatched to a view. This allows listeners to
21202          * get a chance to respond before the target view.
21203          * <p>Key presses in software keyboards will generally NOT trigger this method,
21204          * although some may elect to do so in some situations. Do not assume a
21205          * software input method has to be key-based; even if it is, it may use key presses
21206          * in a different way than you expect, so there is no way to reliably catch soft
21207          * input key presses.
21208          *
21209          * @param v The view the key has been dispatched to.
21210          * @param keyCode The code for the physical key that was pressed
21211          * @param event The KeyEvent object containing full information about
21212          *        the event.
21213          * @return True if the listener has consumed the event, false otherwise.
21214          */
21215         boolean onKey(View v, int keyCode, KeyEvent event);
21216     }
21217 
21218     /**
21219      * Interface definition for a callback to be invoked when a touch event is
21220      * dispatched to this view. The callback will be invoked before the touch
21221      * event is given to the view.
21222      */
21223     public interface OnTouchListener {
21224         /**
21225          * Called when a touch event is dispatched to a view. This allows listeners to
21226          * get a chance to respond before the target view.
21227          *
21228          * @param v The view the touch event has been dispatched to.
21229          * @param event The MotionEvent object containing full information about
21230          *        the event.
21231          * @return True if the listener has consumed the event, false otherwise.
21232          */
21233         boolean onTouch(View v, MotionEvent event);
21234     }
21235 
21236     /**
21237      * Interface definition for a callback to be invoked when a hover event is
21238      * dispatched to this view. The callback will be invoked before the hover
21239      * event is given to the view.
21240      */
21241     public interface OnHoverListener {
21242         /**
21243          * Called when a hover event is dispatched to a view. This allows listeners to
21244          * get a chance to respond before the target view.
21245          *
21246          * @param v The view the hover event has been dispatched to.
21247          * @param event The MotionEvent object containing full information about
21248          *        the event.
21249          * @return True if the listener has consumed the event, false otherwise.
21250          */
21251         boolean onHover(View v, MotionEvent event);
21252     }
21253 
21254     /**
21255      * Interface definition for a callback to be invoked when a generic motion event is
21256      * dispatched to this view. The callback will be invoked before the generic motion
21257      * event is given to the view.
21258      */
21259     public interface OnGenericMotionListener {
21260         /**
21261          * Called when a generic motion event is dispatched to a view. This allows listeners to
21262          * get a chance to respond before the target view.
21263          *
21264          * @param v The view the generic motion event has been dispatched to.
21265          * @param event The MotionEvent object containing full information about
21266          *        the event.
21267          * @return True if the listener has consumed the event, false otherwise.
21268          */
21269         boolean onGenericMotion(View v, MotionEvent event);
21270     }
21271 
21272     /**
21273      * Interface definition for a callback to be invoked when a view has been clicked and held.
21274      */
21275     public interface OnLongClickListener {
21276         /**
21277          * Called when a view has been clicked and held.
21278          *
21279          * @param v The view that was clicked and held.
21280          *
21281          * @return true if the callback consumed the long click, false otherwise.
21282          */
21283         boolean onLongClick(View v);
21284     }
21285 
21286     /**
21287      * Interface definition for a callback to be invoked when a drag is being dispatched
21288      * to this view.  The callback will be invoked before the hosting view's own
21289      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
21290      * onDrag(event) behavior, it should return 'false' from this callback.
21291      *
21292      * <div class="special reference">
21293      * <h3>Developer Guides</h3>
21294      * <p>For a guide to implementing drag and drop features, read the
21295      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21296      * </div>
21297      */
21298     public interface OnDragListener {
21299         /**
21300          * Called when a drag event is dispatched to a view. This allows listeners
21301          * to get a chance to override base View behavior.
21302          *
21303          * @param v The View that received the drag event.
21304          * @param event The {@link android.view.DragEvent} object for the drag event.
21305          * @return {@code true} if the drag event was handled successfully, or {@code false}
21306          * if the drag event was not handled. Note that {@code false} will trigger the View
21307          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
21308          */
21309         boolean onDrag(View v, DragEvent event);
21310     }
21311 
21312     /**
21313      * Interface definition for a callback to be invoked when the focus state of
21314      * a view changed.
21315      */
21316     public interface OnFocusChangeListener {
21317         /**
21318          * Called when the focus state of a view has changed.
21319          *
21320          * @param v The view whose state has changed.
21321          * @param hasFocus The new focus state of v.
21322          */
21323         void onFocusChange(View v, boolean hasFocus);
21324     }
21325 
21326     /**
21327      * Interface definition for a callback to be invoked when a view is clicked.
21328      */
21329     public interface OnClickListener {
21330         /**
21331          * Called when a view has been clicked.
21332          *
21333          * @param v The view that was clicked.
21334          */
21335         void onClick(View v);
21336     }
21337 
21338     /**
21339      * Interface definition for a callback to be invoked when a view is context clicked.
21340      */
21341     public interface OnContextClickListener {
21342         /**
21343          * Called when a view is context clicked.
21344          *
21345          * @param v The view that has been context clicked.
21346          * @return true if the callback consumed the context click, false otherwise.
21347          */
21348         boolean onContextClick(View v);
21349     }
21350 
21351     /**
21352      * Interface definition for a callback to be invoked when the context menu
21353      * for this view is being built.
21354      */
21355     public interface OnCreateContextMenuListener {
21356         /**
21357          * Called when the context menu for this view is being built. It is not
21358          * safe to hold onto the menu after this method returns.
21359          *
21360          * @param menu The context menu that is being built
21361          * @param v The view for which the context menu is being built
21362          * @param menuInfo Extra information about the item for which the
21363          *            context menu should be shown. This information will vary
21364          *            depending on the class of v.
21365          */
21366         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
21367     }
21368 
21369     /**
21370      * Interface definition for a callback to be invoked when the status bar changes
21371      * visibility.  This reports <strong>global</strong> changes to the system UI
21372      * state, not what the application is requesting.
21373      *
21374      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
21375      */
21376     public interface OnSystemUiVisibilityChangeListener {
21377         /**
21378          * Called when the status bar changes visibility because of a call to
21379          * {@link View#setSystemUiVisibility(int)}.
21380          *
21381          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21382          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
21383          * This tells you the <strong>global</strong> state of these UI visibility
21384          * flags, not what your app is currently applying.
21385          */
21386         public void onSystemUiVisibilityChange(int visibility);
21387     }
21388 
21389     /**
21390      * Interface definition for a callback to be invoked when this view is attached
21391      * or detached from its window.
21392      */
21393     public interface OnAttachStateChangeListener {
21394         /**
21395          * Called when the view is attached to a window.
21396          * @param v The view that was attached
21397          */
21398         public void onViewAttachedToWindow(View v);
21399         /**
21400          * Called when the view is detached from a window.
21401          * @param v The view that was detached
21402          */
21403         public void onViewDetachedFromWindow(View v);
21404     }
21405 
21406     /**
21407      * Listener for applying window insets on a view in a custom way.
21408      *
21409      * <p>Apps may choose to implement this interface if they want to apply custom policy
21410      * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
21411      * is set, its
21412      * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
21413      * method will be called instead of the View's own
21414      * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
21415      * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
21416      * the View's normal behavior as part of its own.</p>
21417      */
21418     public interface OnApplyWindowInsetsListener {
21419         /**
21420          * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
21421          * on a View, this listener method will be called instead of the view's own
21422          * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
21423          *
21424          * @param v The view applying window insets
21425          * @param insets The insets to apply
21426          * @return The insets supplied, minus any insets that were consumed
21427          */
21428         public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
21429     }
21430 
21431     private final class UnsetPressedState implements Runnable {
21432         @Override
21433         public void run() {
21434             setPressed(false);
21435         }
21436     }
21437 
21438     /**
21439      * Base class for derived classes that want to save and restore their own
21440      * state in {@link android.view.View#onSaveInstanceState()}.
21441      */
21442     public static class BaseSavedState extends AbsSavedState {
21443         String mStartActivityRequestWhoSaved;
21444 
21445         /**
21446          * Constructor used when reading from a parcel. Reads the state of the superclass.
21447          *
21448          * @param source
21449          */
21450         public BaseSavedState(Parcel source) {
21451             super(source);
21452             mStartActivityRequestWhoSaved = source.readString();
21453         }
21454 
21455         /**
21456          * Constructor called by derived classes when creating their SavedState objects
21457          *
21458          * @param superState The state of the superclass of this view
21459          */
21460         public BaseSavedState(Parcelable superState) {
21461             super(superState);
21462         }
21463 
21464         @Override
21465         public void writeToParcel(Parcel out, int flags) {
21466             super.writeToParcel(out, flags);
21467             out.writeString(mStartActivityRequestWhoSaved);
21468         }
21469 
21470         public static final Parcelable.Creator<BaseSavedState> CREATOR =
21471                 new Parcelable.Creator<BaseSavedState>() {
21472             public BaseSavedState createFromParcel(Parcel in) {
21473                 return new BaseSavedState(in);
21474             }
21475 
21476             public BaseSavedState[] newArray(int size) {
21477                 return new BaseSavedState[size];
21478             }
21479         };
21480     }
21481 
21482     /**
21483      * A set of information given to a view when it is attached to its parent
21484      * window.
21485      */
21486     final static class AttachInfo {
21487         interface Callbacks {
21488             void playSoundEffect(int effectId);
21489             boolean performHapticFeedback(int effectId, boolean always);
21490         }
21491 
21492         /**
21493          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
21494          * to a Handler. This class contains the target (View) to invalidate and
21495          * the coordinates of the dirty rectangle.
21496          *
21497          * For performance purposes, this class also implements a pool of up to
21498          * POOL_LIMIT objects that get reused. This reduces memory allocations
21499          * whenever possible.
21500          */
21501         static class InvalidateInfo {
21502             private static final int POOL_LIMIT = 10;
21503 
21504             private static final SynchronizedPool<InvalidateInfo> sPool =
21505                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
21506 
21507             View target;
21508 
21509             int left;
21510             int top;
21511             int right;
21512             int bottom;
21513 
21514             public static InvalidateInfo obtain() {
21515                 InvalidateInfo instance = sPool.acquire();
21516                 return (instance != null) ? instance : new InvalidateInfo();
21517             }
21518 
21519             public void recycle() {
21520                 target = null;
21521                 sPool.release(this);
21522             }
21523         }
21524 
21525         final IWindowSession mSession;
21526 
21527         final IWindow mWindow;
21528 
21529         final IBinder mWindowToken;
21530 
21531         final Display mDisplay;
21532 
21533         final Callbacks mRootCallbacks;
21534 
21535         IWindowId mIWindowId;
21536         WindowId mWindowId;
21537 
21538         /**
21539          * The top view of the hierarchy.
21540          */
21541         View mRootView;
21542 
21543         IBinder mPanelParentWindowToken;
21544 
21545         boolean mHardwareAccelerated;
21546         boolean mHardwareAccelerationRequested;
21547         HardwareRenderer mHardwareRenderer;
21548         List<RenderNode> mPendingAnimatingRenderNodes;
21549 
21550         /**
21551          * The state of the display to which the window is attached, as reported
21552          * by {@link Display#getState()}.  Note that the display state constants
21553          * declared by {@link Display} do not exactly line up with the screen state
21554          * constants declared by {@link View} (there are more display states than
21555          * screen states).
21556          */
21557         int mDisplayState = Display.STATE_UNKNOWN;
21558 
21559         /**
21560          * Scale factor used by the compatibility mode
21561          */
21562         float mApplicationScale;
21563 
21564         /**
21565          * Indicates whether the application is in compatibility mode
21566          */
21567         boolean mScalingRequired;
21568 
21569         /**
21570          * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
21571          */
21572         boolean mTurnOffWindowResizeAnim;
21573 
21574         /**
21575          * Left position of this view's window
21576          */
21577         int mWindowLeft;
21578 
21579         /**
21580          * Top position of this view's window
21581          */
21582         int mWindowTop;
21583 
21584         /**
21585          * Indicates whether views need to use 32-bit drawing caches
21586          */
21587         boolean mUse32BitDrawingCache;
21588 
21589         /**
21590          * For windows that are full-screen but using insets to layout inside
21591          * of the screen areas, these are the current insets to appear inside
21592          * the overscan area of the display.
21593          */
21594         final Rect mOverscanInsets = new Rect();
21595 
21596         /**
21597          * For windows that are full-screen but using insets to layout inside
21598          * of the screen decorations, these are the current insets for the
21599          * content of the window.
21600          */
21601         final Rect mContentInsets = new Rect();
21602 
21603         /**
21604          * For windows that are full-screen but using insets to layout inside
21605          * of the screen decorations, these are the current insets for the
21606          * actual visible parts of the window.
21607          */
21608         final Rect mVisibleInsets = new Rect();
21609 
21610         /**
21611          * For windows that are full-screen but using insets to layout inside
21612          * of the screen decorations, these are the current insets for the
21613          * stable system windows.
21614          */
21615         final Rect mStableInsets = new Rect();
21616 
21617         /**
21618          * For windows that include areas that are not covered by real surface these are the outsets
21619          * for real surface.
21620          */
21621         final Rect mOutsets = new Rect();
21622 
21623         /**
21624          * The internal insets given by this window.  This value is
21625          * supplied by the client (through
21626          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
21627          * be given to the window manager when changed to be used in laying
21628          * out windows behind it.
21629          */
21630         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
21631                 = new ViewTreeObserver.InternalInsetsInfo();
21632 
21633         /**
21634          * Set to true when mGivenInternalInsets is non-empty.
21635          */
21636         boolean mHasNonEmptyGivenInternalInsets;
21637 
21638         /**
21639          * All views in the window's hierarchy that serve as scroll containers,
21640          * used to determine if the window can be resized or must be panned
21641          * to adjust for a soft input area.
21642          */
21643         final ArrayList<View> mScrollContainers = new ArrayList<View>();
21644 
21645         final KeyEvent.DispatcherState mKeyDispatchState
21646                 = new KeyEvent.DispatcherState();
21647 
21648         /**
21649          * Indicates whether the view's window currently has the focus.
21650          */
21651         boolean mHasWindowFocus;
21652 
21653         /**
21654          * The current visibility of the window.
21655          */
21656         int mWindowVisibility;
21657 
21658         /**
21659          * Indicates the time at which drawing started to occur.
21660          */
21661         long mDrawingTime;
21662 
21663         /**
21664          * Indicates whether or not ignoring the DIRTY_MASK flags.
21665          */
21666         boolean mIgnoreDirtyState;
21667 
21668         /**
21669          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
21670          * to avoid clearing that flag prematurely.
21671          */
21672         boolean mSetIgnoreDirtyState = false;
21673 
21674         /**
21675          * Indicates whether the view's window is currently in touch mode.
21676          */
21677         boolean mInTouchMode;
21678 
21679         /**
21680          * Indicates whether the view has requested unbuffered input dispatching for the current
21681          * event stream.
21682          */
21683         boolean mUnbufferedDispatchRequested;
21684 
21685         /**
21686          * Indicates that ViewAncestor should trigger a global layout change
21687          * the next time it performs a traversal
21688          */
21689         boolean mRecomputeGlobalAttributes;
21690 
21691         /**
21692          * Always report new attributes at next traversal.
21693          */
21694         boolean mForceReportNewAttributes;
21695 
21696         /**
21697          * Set during a traveral if any views want to keep the screen on.
21698          */
21699         boolean mKeepScreenOn;
21700 
21701         /**
21702          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
21703          */
21704         int mSystemUiVisibility;
21705 
21706         /**
21707          * Hack to force certain system UI visibility flags to be cleared.
21708          */
21709         int mDisabledSystemUiVisibility;
21710 
21711         /**
21712          * Last global system UI visibility reported by the window manager.
21713          */
21714         int mGlobalSystemUiVisibility;
21715 
21716         /**
21717          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
21718          * attached.
21719          */
21720         boolean mHasSystemUiListeners;
21721 
21722         /**
21723          * Set if the window has requested to extend into the overscan region
21724          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
21725          */
21726         boolean mOverscanRequested;
21727 
21728         /**
21729          * Set if the visibility of any views has changed.
21730          */
21731         boolean mViewVisibilityChanged;
21732 
21733         /**
21734          * Set to true if a view has been scrolled.
21735          */
21736         boolean mViewScrollChanged;
21737 
21738         /**
21739          * Set to true if high contrast mode enabled
21740          */
21741         boolean mHighContrastText;
21742 
21743         /**
21744          * Global to the view hierarchy used as a temporary for dealing with
21745          * x/y points in the transparent region computations.
21746          */
21747         final int[] mTransparentLocation = new int[2];
21748 
21749         /**
21750          * Global to the view hierarchy used as a temporary for dealing with
21751          * x/y points in the ViewGroup.invalidateChild implementation.
21752          */
21753         final int[] mInvalidateChildLocation = new int[2];
21754 
21755         /**
21756          * Global to the view hierarchy used as a temporary for dealng with
21757          * computing absolute on-screen location.
21758          */
21759         final int[] mTmpLocation = new int[2];
21760 
21761         /**
21762          * Global to the view hierarchy used as a temporary for dealing with
21763          * x/y location when view is transformed.
21764          */
21765         final float[] mTmpTransformLocation = new float[2];
21766 
21767         /**
21768          * The view tree observer used to dispatch global events like
21769          * layout, pre-draw, touch mode change, etc.
21770          */
21771         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
21772 
21773         /**
21774          * A Canvas used by the view hierarchy to perform bitmap caching.
21775          */
21776         Canvas mCanvas;
21777 
21778         /**
21779          * The view root impl.
21780          */
21781         final ViewRootImpl mViewRootImpl;
21782 
21783         /**
21784          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
21785          * handler can be used to pump events in the UI events queue.
21786          */
21787         final Handler mHandler;
21788 
21789         /**
21790          * Temporary for use in computing invalidate rectangles while
21791          * calling up the hierarchy.
21792          */
21793         final Rect mTmpInvalRect = new Rect();
21794 
21795         /**
21796          * Temporary for use in computing hit areas with transformed views
21797          */
21798         final RectF mTmpTransformRect = new RectF();
21799 
21800         /**
21801          * Temporary for use in computing hit areas with transformed views
21802          */
21803         final RectF mTmpTransformRect1 = new RectF();
21804 
21805         /**
21806          * Temporary list of rectanges.
21807          */
21808         final List<RectF> mTmpRectList = new ArrayList<>();
21809 
21810         /**
21811          * Temporary for use in transforming invalidation rect
21812          */
21813         final Matrix mTmpMatrix = new Matrix();
21814 
21815         /**
21816          * Temporary for use in transforming invalidation rect
21817          */
21818         final Transformation mTmpTransformation = new Transformation();
21819 
21820         /**
21821          * Temporary for use in querying outlines from OutlineProviders
21822          */
21823         final Outline mTmpOutline = new Outline();
21824 
21825         /**
21826          * Temporary list for use in collecting focusable descendents of a view.
21827          */
21828         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
21829 
21830         /**
21831          * The id of the window for accessibility purposes.
21832          */
21833         int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
21834 
21835         /**
21836          * Flags related to accessibility processing.
21837          *
21838          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
21839          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
21840          */
21841         int mAccessibilityFetchFlags;
21842 
21843         /**
21844          * The drawable for highlighting accessibility focus.
21845          */
21846         Drawable mAccessibilityFocusDrawable;
21847 
21848         /**
21849          * Show where the margins, bounds and layout bounds are for each view.
21850          */
21851         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
21852 
21853         /**
21854          * Point used to compute visible regions.
21855          */
21856         final Point mPoint = new Point();
21857 
21858         /**
21859          * Used to track which View originated a requestLayout() call, used when
21860          * requestLayout() is called during layout.
21861          */
21862         View mViewRequestingLayout;
21863 
21864         /**
21865          * Creates a new set of attachment information with the specified
21866          * events handler and thread.
21867          *
21868          * @param handler the events handler the view must use
21869          */
21870         AttachInfo(IWindowSession session, IWindow window, Display display,
21871                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
21872             mSession = session;
21873             mWindow = window;
21874             mWindowToken = window.asBinder();
21875             mDisplay = display;
21876             mViewRootImpl = viewRootImpl;
21877             mHandler = handler;
21878             mRootCallbacks = effectPlayer;
21879         }
21880     }
21881 
21882     /**
21883      * <p>ScrollabilityCache holds various fields used by a View when scrolling
21884      * is supported. This avoids keeping too many unused fields in most
21885      * instances of View.</p>
21886      */
21887     private static class ScrollabilityCache implements Runnable {
21888 
21889         /**
21890          * Scrollbars are not visible
21891          */
21892         public static final int OFF = 0;
21893 
21894         /**
21895          * Scrollbars are visible
21896          */
21897         public static final int ON = 1;
21898 
21899         /**
21900          * Scrollbars are fading away
21901          */
21902         public static final int FADING = 2;
21903 
21904         public boolean fadeScrollBars;
21905 
21906         public int fadingEdgeLength;
21907         public int scrollBarDefaultDelayBeforeFade;
21908         public int scrollBarFadeDuration;
21909 
21910         public int scrollBarSize;
21911         public ScrollBarDrawable scrollBar;
21912         public float[] interpolatorValues;
21913         public View host;
21914 
21915         public final Paint paint;
21916         public final Matrix matrix;
21917         public Shader shader;
21918 
21919         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
21920 
21921         private static final float[] OPAQUE = { 255 };
21922         private static final float[] TRANSPARENT = { 0.0f };
21923 
21924         /**
21925          * When fading should start. This time moves into the future every time
21926          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
21927          */
21928         public long fadeStartTime;
21929 
21930 
21931         /**
21932          * The current state of the scrollbars: ON, OFF, or FADING
21933          */
21934         public int state = OFF;
21935 
21936         private int mLastColor;
21937 
21938         public ScrollabilityCache(ViewConfiguration configuration, View host) {
21939             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
21940             scrollBarSize = configuration.getScaledScrollBarSize();
21941             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
21942             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
21943 
21944             paint = new Paint();
21945             matrix = new Matrix();
21946             // use use a height of 1, and then wack the matrix each time we
21947             // actually use it.
21948             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21949             paint.setShader(shader);
21950             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21951 
21952             this.host = host;
21953         }
21954 
21955         public void setFadeColor(int color) {
21956             if (color != mLastColor) {
21957                 mLastColor = color;
21958 
21959                 if (color != 0) {
21960                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
21961                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
21962                     paint.setShader(shader);
21963                     // Restore the default transfer mode (src_over)
21964                     paint.setXfermode(null);
21965                 } else {
21966                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21967                     paint.setShader(shader);
21968                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21969                 }
21970             }
21971         }
21972 
21973         public void run() {
21974             long now = AnimationUtils.currentAnimationTimeMillis();
21975             if (now >= fadeStartTime) {
21976 
21977                 // the animation fades the scrollbars out by changing
21978                 // the opacity (alpha) from fully opaque to fully
21979                 // transparent
21980                 int nextFrame = (int) now;
21981                 int framesCount = 0;
21982 
21983                 Interpolator interpolator = scrollBarInterpolator;
21984 
21985                 // Start opaque
21986                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
21987 
21988                 // End transparent
21989                 nextFrame += scrollBarFadeDuration;
21990                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
21991 
21992                 state = FADING;
21993 
21994                 // Kick off the fade animation
21995                 host.invalidate(true);
21996             }
21997         }
21998     }
21999 
22000     /**
22001      * Resuable callback for sending
22002      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
22003      */
22004     private class SendViewScrolledAccessibilityEvent implements Runnable {
22005         public volatile boolean mIsPending;
22006 
22007         public void run() {
22008             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
22009             mIsPending = false;
22010         }
22011     }
22012 
22013     /**
22014      * <p>
22015      * This class represents a delegate that can be registered in a {@link View}
22016      * to enhance accessibility support via composition rather via inheritance.
22017      * It is specifically targeted to widget developers that extend basic View
22018      * classes i.e. classes in package android.view, that would like their
22019      * applications to be backwards compatible.
22020      * </p>
22021      * <div class="special reference">
22022      * <h3>Developer Guides</h3>
22023      * <p>For more information about making applications accessible, read the
22024      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
22025      * developer guide.</p>
22026      * </div>
22027      * <p>
22028      * A scenario in which a developer would like to use an accessibility delegate
22029      * is overriding a method introduced in a later API version then the minimal API
22030      * version supported by the application. For example, the method
22031      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
22032      * in API version 4 when the accessibility APIs were first introduced. If a
22033      * developer would like his application to run on API version 4 devices (assuming
22034      * all other APIs used by the application are version 4 or lower) and take advantage
22035      * of this method, instead of overriding the method which would break the application's
22036      * backwards compatibility, he can override the corresponding method in this
22037      * delegate and register the delegate in the target View if the API version of
22038      * the system is high enough i.e. the API version is same or higher to the API
22039      * version that introduced
22040      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
22041      * </p>
22042      * <p>
22043      * Here is an example implementation:
22044      * </p>
22045      * <code><pre><p>
22046      * if (Build.VERSION.SDK_INT >= 14) {
22047      *     // If the API version is equal of higher than the version in
22048      *     // which onInitializeAccessibilityNodeInfo was introduced we
22049      *     // register a delegate with a customized implementation.
22050      *     View view = findViewById(R.id.view_id);
22051      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
22052      *         public void onInitializeAccessibilityNodeInfo(View host,
22053      *                 AccessibilityNodeInfo info) {
22054      *             // Let the default implementation populate the info.
22055      *             super.onInitializeAccessibilityNodeInfo(host, info);
22056      *             // Set some other information.
22057      *             info.setEnabled(host.isEnabled());
22058      *         }
22059      *     });
22060      * }
22061      * </code></pre></p>
22062      * <p>
22063      * This delegate contains methods that correspond to the accessibility methods
22064      * in View. If a delegate has been specified the implementation in View hands
22065      * off handling to the corresponding method in this delegate. The default
22066      * implementation the delegate methods behaves exactly as the corresponding
22067      * method in View for the case of no accessibility delegate been set. Hence,
22068      * to customize the behavior of a View method, clients can override only the
22069      * corresponding delegate method without altering the behavior of the rest
22070      * accessibility related methods of the host view.
22071      * </p>
22072      */
22073     public static class AccessibilityDelegate {
22074 
22075         /**
22076          * Sends an accessibility event of the given type. If accessibility is not
22077          * enabled this method has no effect.
22078          * <p>
22079          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
22080          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
22081          * been set.
22082          * </p>
22083          *
22084          * @param host The View hosting the delegate.
22085          * @param eventType The type of the event to send.
22086          *
22087          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
22088          */
22089         public void sendAccessibilityEvent(View host, int eventType) {
22090             host.sendAccessibilityEventInternal(eventType);
22091         }
22092 
22093         /**
22094          * Performs the specified accessibility action on the view. For
22095          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
22096          * <p>
22097          * The default implementation behaves as
22098          * {@link View#performAccessibilityAction(int, Bundle)
22099          *  View#performAccessibilityAction(int, Bundle)} for the case of
22100          *  no accessibility delegate been set.
22101          * </p>
22102          *
22103          * @param action The action to perform.
22104          * @return Whether the action was performed.
22105          *
22106          * @see View#performAccessibilityAction(int, Bundle)
22107          *      View#performAccessibilityAction(int, Bundle)
22108          */
22109         public boolean performAccessibilityAction(View host, int action, Bundle args) {
22110             return host.performAccessibilityActionInternal(action, args);
22111         }
22112 
22113         /**
22114          * Sends an accessibility event. This method behaves exactly as
22115          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
22116          * empty {@link AccessibilityEvent} and does not perform a check whether
22117          * accessibility is enabled.
22118          * <p>
22119          * The default implementation behaves as
22120          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22121          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
22122          * the case of no accessibility delegate been set.
22123          * </p>
22124          *
22125          * @param host The View hosting the delegate.
22126          * @param event The event to send.
22127          *
22128          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22129          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22130          */
22131         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
22132             host.sendAccessibilityEventUncheckedInternal(event);
22133         }
22134 
22135         /**
22136          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
22137          * to its children for adding their text content to the event.
22138          * <p>
22139          * The default implementation behaves as
22140          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22141          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
22142          * the case of no accessibility delegate been set.
22143          * </p>
22144          *
22145          * @param host The View hosting the delegate.
22146          * @param event The event.
22147          * @return True if the event population was completed.
22148          *
22149          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22150          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22151          */
22152         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22153             return host.dispatchPopulateAccessibilityEventInternal(event);
22154         }
22155 
22156         /**
22157          * Gives a chance to the host View to populate the accessibility event with its
22158          * text content.
22159          * <p>
22160          * The default implementation behaves as
22161          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
22162          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
22163          * the case of no accessibility delegate been set.
22164          * </p>
22165          *
22166          * @param host The View hosting the delegate.
22167          * @param event The accessibility event which to populate.
22168          *
22169          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
22170          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
22171          */
22172         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22173             host.onPopulateAccessibilityEventInternal(event);
22174         }
22175 
22176         /**
22177          * Initializes an {@link AccessibilityEvent} with information about the
22178          * the host View which is the event source.
22179          * <p>
22180          * The default implementation behaves as
22181          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
22182          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
22183          * the case of no accessibility delegate been set.
22184          * </p>
22185          *
22186          * @param host The View hosting the delegate.
22187          * @param event The event to initialize.
22188          *
22189          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
22190          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
22191          */
22192         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
22193             host.onInitializeAccessibilityEventInternal(event);
22194         }
22195 
22196         /**
22197          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
22198          * <p>
22199          * The default implementation behaves as
22200          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22201          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
22202          * the case of no accessibility delegate been set.
22203          * </p>
22204          *
22205          * @param host The View hosting the delegate.
22206          * @param info The instance to initialize.
22207          *
22208          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22209          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22210          */
22211         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
22212             host.onInitializeAccessibilityNodeInfoInternal(info);
22213         }
22214 
22215         /**
22216          * Called when a child of the host View has requested sending an
22217          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
22218          * to augment the event.
22219          * <p>
22220          * The default implementation behaves as
22221          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22222          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
22223          * the case of no accessibility delegate been set.
22224          * </p>
22225          *
22226          * @param host The View hosting the delegate.
22227          * @param child The child which requests sending the event.
22228          * @param event The event to be sent.
22229          * @return True if the event should be sent
22230          *
22231          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22232          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22233          */
22234         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
22235                 AccessibilityEvent event) {
22236             return host.onRequestSendAccessibilityEventInternal(child, event);
22237         }
22238 
22239         /**
22240          * Gets the provider for managing a virtual view hierarchy rooted at this View
22241          * and reported to {@link android.accessibilityservice.AccessibilityService}s
22242          * that explore the window content.
22243          * <p>
22244          * The default implementation behaves as
22245          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
22246          * the case of no accessibility delegate been set.
22247          * </p>
22248          *
22249          * @return The provider.
22250          *
22251          * @see AccessibilityNodeProvider
22252          */
22253         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
22254             return null;
22255         }
22256 
22257         /**
22258          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
22259          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
22260          * This method is responsible for obtaining an accessibility node info from a
22261          * pool of reusable instances and calling
22262          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
22263          * view to initialize the former.
22264          * <p>
22265          * <strong>Note:</strong> The client is responsible for recycling the obtained
22266          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
22267          * creation.
22268          * </p>
22269          * <p>
22270          * The default implementation behaves as
22271          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
22272          * the case of no accessibility delegate been set.
22273          * </p>
22274          * @return A populated {@link AccessibilityNodeInfo}.
22275          *
22276          * @see AccessibilityNodeInfo
22277          *
22278          * @hide
22279          */
22280         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
22281             return host.createAccessibilityNodeInfoInternal();
22282         }
22283     }
22284 
22285     private class MatchIdPredicate implements Predicate<View> {
22286         public int mId;
22287 
22288         @Override
22289         public boolean apply(View view) {
22290             return (view.mID == mId);
22291         }
22292     }
22293 
22294     private class MatchLabelForPredicate implements Predicate<View> {
22295         private int mLabeledId;
22296 
22297         @Override
22298         public boolean apply(View view) {
22299             return (view.mLabelForId == mLabeledId);
22300         }
22301     }
22302 
22303     private class SendViewStateChangedAccessibilityEvent implements Runnable {
22304         private int mChangeTypes = 0;
22305         private boolean mPosted;
22306         private boolean mPostedWithDelay;
22307         private long mLastEventTimeMillis;
22308 
22309         @Override
22310         public void run() {
22311             mPosted = false;
22312             mPostedWithDelay = false;
22313             mLastEventTimeMillis = SystemClock.uptimeMillis();
22314             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
22315                 final AccessibilityEvent event = AccessibilityEvent.obtain();
22316                 event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
22317                 event.setContentChangeTypes(mChangeTypes);
22318                 sendAccessibilityEventUnchecked(event);
22319             }
22320             mChangeTypes = 0;
22321         }
22322 
22323         public void runOrPost(int changeType) {
22324             mChangeTypes |= changeType;
22325 
22326             // If this is a live region or the child of a live region, collect
22327             // all events from this frame and send them on the next frame.
22328             if (inLiveRegion()) {
22329                 // If we're already posted with a delay, remove that.
22330                 if (mPostedWithDelay) {
22331                     removeCallbacks(this);
22332                     mPostedWithDelay = false;
22333                 }
22334                 // Only post if we're not already posted.
22335                 if (!mPosted) {
22336                     post(this);
22337                     mPosted = true;
22338                 }
22339                 return;
22340             }
22341 
22342             if (mPosted) {
22343                 return;
22344             }
22345 
22346             final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
22347             final long minEventIntevalMillis =
22348                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
22349             if (timeSinceLastMillis >= minEventIntevalMillis) {
22350                 removeCallbacks(this);
22351                 run();
22352             } else {
22353                 postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
22354                 mPostedWithDelay = true;
22355             }
22356         }
22357     }
22358 
22359     private boolean inLiveRegion() {
22360         if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22361             return true;
22362         }
22363 
22364         ViewParent parent = getParent();
22365         while (parent instanceof View) {
22366             if (((View) parent).getAccessibilityLiveRegion()
22367                     != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22368                 return true;
22369             }
22370             parent = parent.getParent();
22371         }
22372 
22373         return false;
22374     }
22375 
22376     /**
22377      * Dump all private flags in readable format, useful for documentation and
22378      * sanity checking.
22379      */
22380     private static void dumpFlags() {
22381         final HashMap<String, String> found = Maps.newHashMap();
22382         try {
22383             for (Field field : View.class.getDeclaredFields()) {
22384                 final int modifiers = field.getModifiers();
22385                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
22386                     if (field.getType().equals(int.class)) {
22387                         final int value = field.getInt(null);
22388                         dumpFlag(found, field.getName(), value);
22389                     } else if (field.getType().equals(int[].class)) {
22390                         final int[] values = (int[]) field.get(null);
22391                         for (int i = 0; i < values.length; i++) {
22392                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
22393                         }
22394                     }
22395                 }
22396             }
22397         } catch (IllegalAccessException e) {
22398             throw new RuntimeException(e);
22399         }
22400 
22401         final ArrayList<String> keys = Lists.newArrayList();
22402         keys.addAll(found.keySet());
22403         Collections.sort(keys);
22404         for (String key : keys) {
22405             Log.d(VIEW_LOG_TAG, found.get(key));
22406         }
22407     }
22408 
22409     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
22410         // Sort flags by prefix, then by bits, always keeping unique keys
22411         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
22412         final int prefix = name.indexOf('_');
22413         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
22414         final String output = bits + " " + name;
22415         found.put(key, output);
22416     }
22417 
22418     /** {@hide} */
22419     public void encode(@NonNull ViewHierarchyEncoder stream) {
22420         stream.beginObject(this);
22421         encodeProperties(stream);
22422         stream.endObject();
22423     }
22424 
22425     /** {@hide} */
22426     @CallSuper
22427     protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
22428         Object resolveId = ViewDebug.resolveId(getContext(), mID);
22429         if (resolveId instanceof String) {
22430             stream.addProperty("id", (String) resolveId);
22431         } else {
22432             stream.addProperty("id", mID);
22433         }
22434 
22435         stream.addProperty("misc:transformation.alpha",
22436                 mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
22437         stream.addProperty("misc:transitionName", getTransitionName());
22438 
22439         // layout
22440         stream.addProperty("layout:left", mLeft);
22441         stream.addProperty("layout:right", mRight);
22442         stream.addProperty("layout:top", mTop);
22443         stream.addProperty("layout:bottom", mBottom);
22444         stream.addProperty("layout:width", getWidth());
22445         stream.addProperty("layout:height", getHeight());
22446         stream.addProperty("layout:layoutDirection", getLayoutDirection());
22447         stream.addProperty("layout:layoutRtl", isLayoutRtl());
22448         stream.addProperty("layout:hasTransientState", hasTransientState());
22449         stream.addProperty("layout:baseline", getBaseline());
22450 
22451         // layout params
22452         ViewGroup.LayoutParams layoutParams = getLayoutParams();
22453         if (layoutParams != null) {
22454             stream.addPropertyKey("layoutParams");
22455             layoutParams.encode(stream);
22456         }
22457 
22458         // scrolling
22459         stream.addProperty("scrolling:scrollX", mScrollX);
22460         stream.addProperty("scrolling:scrollY", mScrollY);
22461 
22462         // padding
22463         stream.addProperty("padding:paddingLeft", mPaddingLeft);
22464         stream.addProperty("padding:paddingRight", mPaddingRight);
22465         stream.addProperty("padding:paddingTop", mPaddingTop);
22466         stream.addProperty("padding:paddingBottom", mPaddingBottom);
22467         stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
22468         stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
22469         stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
22470         stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
22471         stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
22472 
22473         // measurement
22474         stream.addProperty("measurement:minHeight", mMinHeight);
22475         stream.addProperty("measurement:minWidth", mMinWidth);
22476         stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
22477         stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
22478 
22479         // drawing
22480         stream.addProperty("drawing:elevation", getElevation());
22481         stream.addProperty("drawing:translationX", getTranslationX());
22482         stream.addProperty("drawing:translationY", getTranslationY());
22483         stream.addProperty("drawing:translationZ", getTranslationZ());
22484         stream.addProperty("drawing:rotation", getRotation());
22485         stream.addProperty("drawing:rotationX", getRotationX());
22486         stream.addProperty("drawing:rotationY", getRotationY());
22487         stream.addProperty("drawing:scaleX", getScaleX());
22488         stream.addProperty("drawing:scaleY", getScaleY());
22489         stream.addProperty("drawing:pivotX", getPivotX());
22490         stream.addProperty("drawing:pivotY", getPivotY());
22491         stream.addProperty("drawing:opaque", isOpaque());
22492         stream.addProperty("drawing:alpha", getAlpha());
22493         stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
22494         stream.addProperty("drawing:shadow", hasShadow());
22495         stream.addProperty("drawing:solidColor", getSolidColor());
22496         stream.addProperty("drawing:layerType", mLayerType);
22497         stream.addProperty("drawing:willNotDraw", willNotDraw());
22498         stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
22499         stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
22500         stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
22501         stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
22502 
22503         // focus
22504         stream.addProperty("focus:hasFocus", hasFocus());
22505         stream.addProperty("focus:isFocused", isFocused());
22506         stream.addProperty("focus:isFocusable", isFocusable());
22507         stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
22508 
22509         stream.addProperty("misc:clickable", isClickable());
22510         stream.addProperty("misc:pressed", isPressed());
22511         stream.addProperty("misc:selected", isSelected());
22512         stream.addProperty("misc:touchMode", isInTouchMode());
22513         stream.addProperty("misc:hovered", isHovered());
22514         stream.addProperty("misc:activated", isActivated());
22515 
22516         stream.addProperty("misc:visibility", getVisibility());
22517         stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
22518         stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
22519 
22520         stream.addProperty("misc:enabled", isEnabled());
22521         stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
22522         stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
22523 
22524         // theme attributes
22525         Resources.Theme theme = getContext().getTheme();
22526         if (theme != null) {
22527             stream.addPropertyKey("theme");
22528             theme.encode(stream);
22529         }
22530 
22531         // view attribute information
22532         int n = mAttributes != null ? mAttributes.length : 0;
22533         stream.addProperty("meta:__attrCount__", n/2);
22534         for (int i = 0; i < n; i += 2) {
22535             stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
22536         }
22537 
22538         stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
22539 
22540         // text
22541         stream.addProperty("text:textDirection", getTextDirection());
22542         stream.addProperty("text:textAlignment", getTextAlignment());
22543 
22544         // accessibility
22545         CharSequence contentDescription = getContentDescription();
22546         stream.addProperty("accessibility:contentDescription",
22547                 contentDescription == null ? "" : contentDescription.toString());
22548         stream.addProperty("accessibility:labelFor", getLabelFor());
22549         stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
22550     }
22551 }
22552