• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.view;
18 
19 import android.content.ClipData;
20 import android.content.Context;
21 import android.content.res.Configuration;
22 import android.content.res.Resources;
23 import android.content.res.TypedArray;
24 import android.graphics.Bitmap;
25 import android.graphics.Camera;
26 import android.graphics.Canvas;
27 import android.graphics.Insets;
28 import android.graphics.Interpolator;
29 import android.graphics.LinearGradient;
30 import android.graphics.Matrix;
31 import android.graphics.Paint;
32 import android.graphics.PixelFormat;
33 import android.graphics.Point;
34 import android.graphics.PorterDuff;
35 import android.graphics.PorterDuffXfermode;
36 import android.graphics.Rect;
37 import android.graphics.RectF;
38 import android.graphics.Region;
39 import android.graphics.Shader;
40 import android.graphics.drawable.ColorDrawable;
41 import android.graphics.drawable.Drawable;
42 import android.hardware.display.DisplayManagerGlobal;
43 import android.os.Bundle;
44 import android.os.Handler;
45 import android.os.IBinder;
46 import android.os.Parcel;
47 import android.os.Parcelable;
48 import android.os.RemoteException;
49 import android.os.SystemClock;
50 import android.os.SystemProperties;
51 import android.text.TextUtils;
52 import android.util.AttributeSet;
53 import android.util.FloatProperty;
54 import android.util.Log;
55 import android.util.Pool;
56 import android.util.Poolable;
57 import android.util.PoolableManager;
58 import android.util.Pools;
59 import android.util.Property;
60 import android.util.SparseArray;
61 import android.util.TypedValue;
62 import android.view.ContextMenu.ContextMenuInfo;
63 import android.view.AccessibilityIterators.TextSegmentIterator;
64 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
65 import android.view.AccessibilityIterators.WordTextSegmentIterator;
66 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
67 import android.view.accessibility.AccessibilityEvent;
68 import android.view.accessibility.AccessibilityEventSource;
69 import android.view.accessibility.AccessibilityManager;
70 import android.view.accessibility.AccessibilityNodeInfo;
71 import android.view.accessibility.AccessibilityNodeProvider;
72 import android.view.animation.Animation;
73 import android.view.animation.AnimationUtils;
74 import android.view.animation.Transformation;
75 import android.view.inputmethod.EditorInfo;
76 import android.view.inputmethod.InputConnection;
77 import android.view.inputmethod.InputMethodManager;
78 import android.widget.ScrollBarDrawable;
79 
80 import static android.os.Build.VERSION_CODES.*;
81 import static java.lang.Math.max;
82 
83 import com.android.internal.R;
84 import com.android.internal.util.Predicate;
85 import com.android.internal.view.menu.MenuBuilder;
86 import com.google.android.collect.Lists;
87 import com.google.android.collect.Maps;
88 
89 import java.lang.ref.WeakReference;
90 import java.lang.reflect.Field;
91 import java.lang.reflect.InvocationTargetException;
92 import java.lang.reflect.Method;
93 import java.lang.reflect.Modifier;
94 import java.util.ArrayList;
95 import java.util.Arrays;
96 import java.util.Collections;
97 import java.util.HashMap;
98 import java.util.Locale;
99 import java.util.concurrent.CopyOnWriteArrayList;
100 import java.util.concurrent.atomic.AtomicInteger;
101 
102 /**
103  * <p>
104  * This class represents the basic building block for user interface components. A View
105  * occupies a rectangular area on the screen and is responsible for drawing and
106  * event handling. View is the base class for <em>widgets</em>, which are
107  * used to create interactive UI components (buttons, text fields, etc.). The
108  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
109  * are invisible containers that hold other Views (or other ViewGroups) and define
110  * their layout properties.
111  * </p>
112  *
113  * <div class="special reference">
114  * <h3>Developer Guides</h3>
115  * <p>For information about using this class to develop your application's user interface,
116  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
117  * </div>
118  *
119  * <a name="Using"></a>
120  * <h3>Using Views</h3>
121  * <p>
122  * All of the views in a window are arranged in a single tree. You can add views
123  * either from code or by specifying a tree of views in one or more XML layout
124  * files. There are many specialized subclasses of views that act as controls or
125  * are capable of displaying text, images, or other content.
126  * </p>
127  * <p>
128  * Once you have created a tree of views, there are typically a few types of
129  * common operations you may wish to perform:
130  * <ul>
131  * <li><strong>Set properties:</strong> for example setting the text of a
132  * {@link android.widget.TextView}. The available properties and the methods
133  * that set them will vary among the different subclasses of views. Note that
134  * properties that are known at build time can be set in the XML layout
135  * files.</li>
136  * <li><strong>Set focus:</strong> The framework will handled moving focus in
137  * response to user input. To force focus to a specific view, call
138  * {@link #requestFocus}.</li>
139  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
140  * that will be notified when something interesting happens to the view. For
141  * example, all views will let you set a listener to be notified when the view
142  * gains or loses focus. You can register such a listener using
143  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
144  * Other view subclasses offer more specialized listeners. For example, a Button
145  * exposes a listener to notify clients when the button is clicked.</li>
146  * <li><strong>Set visibility:</strong> You can hide or show views using
147  * {@link #setVisibility(int)}.</li>
148  * </ul>
149  * </p>
150  * <p><em>
151  * Note: The Android framework is responsible for measuring, laying out and
152  * drawing views. You should not call methods that perform these actions on
153  * views yourself unless you are actually implementing a
154  * {@link android.view.ViewGroup}.
155  * </em></p>
156  *
157  * <a name="Lifecycle"></a>
158  * <h3>Implementing a Custom View</h3>
159  *
160  * <p>
161  * To implement a custom view, you will usually begin by providing overrides for
162  * some of the standard methods that the framework calls on all views. You do
163  * not need to override all of these methods. In fact, you can start by just
164  * overriding {@link #onDraw(android.graphics.Canvas)}.
165  * <table border="2" width="85%" align="center" cellpadding="5">
166  *     <thead>
167  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
168  *     </thead>
169  *
170  *     <tbody>
171  *     <tr>
172  *         <td rowspan="2">Creation</td>
173  *         <td>Constructors</td>
174  *         <td>There is a form of the constructor that are called when the view
175  *         is created from code and a form that is called when the view is
176  *         inflated from a layout file. The second form should parse and apply
177  *         any attributes defined in the layout file.
178  *         </td>
179  *     </tr>
180  *     <tr>
181  *         <td><code>{@link #onFinishInflate()}</code></td>
182  *         <td>Called after a view and all of its children has been inflated
183  *         from XML.</td>
184  *     </tr>
185  *
186  *     <tr>
187  *         <td rowspan="3">Layout</td>
188  *         <td><code>{@link #onMeasure(int, int)}</code></td>
189  *         <td>Called to determine the size requirements for this view and all
190  *         of its children.
191  *         </td>
192  *     </tr>
193  *     <tr>
194  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
195  *         <td>Called when this view should assign a size and position to all
196  *         of its children.
197  *         </td>
198  *     </tr>
199  *     <tr>
200  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
201  *         <td>Called when the size of this view has changed.
202  *         </td>
203  *     </tr>
204  *
205  *     <tr>
206  *         <td>Drawing</td>
207  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
208  *         <td>Called when the view should render its content.
209  *         </td>
210  *     </tr>
211  *
212  *     <tr>
213  *         <td rowspan="4">Event processing</td>
214  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
215  *         <td>Called when a new hardware key event occurs.
216  *         </td>
217  *     </tr>
218  *     <tr>
219  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
220  *         <td>Called when a hardware key up event occurs.
221  *         </td>
222  *     </tr>
223  *     <tr>
224  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
225  *         <td>Called when a trackball motion event occurs.
226  *         </td>
227  *     </tr>
228  *     <tr>
229  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
230  *         <td>Called when a touch screen motion event occurs.
231  *         </td>
232  *     </tr>
233  *
234  *     <tr>
235  *         <td rowspan="2">Focus</td>
236  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
237  *         <td>Called when the view gains or loses focus.
238  *         </td>
239  *     </tr>
240  *
241  *     <tr>
242  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
243  *         <td>Called when the window containing the view gains or loses focus.
244  *         </td>
245  *     </tr>
246  *
247  *     <tr>
248  *         <td rowspan="3">Attaching</td>
249  *         <td><code>{@link #onAttachedToWindow()}</code></td>
250  *         <td>Called when the view is attached to a window.
251  *         </td>
252  *     </tr>
253  *
254  *     <tr>
255  *         <td><code>{@link #onDetachedFromWindow}</code></td>
256  *         <td>Called when the view is detached from its window.
257  *         </td>
258  *     </tr>
259  *
260  *     <tr>
261  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
262  *         <td>Called when the visibility of the window containing the view
263  *         has changed.
264  *         </td>
265  *     </tr>
266  *     </tbody>
267  *
268  * </table>
269  * </p>
270  *
271  * <a name="IDs"></a>
272  * <h3>IDs</h3>
273  * Views may have an integer id associated with them. These ids are typically
274  * assigned in the layout XML files, and are used to find specific views within
275  * the view tree. A common pattern is to:
276  * <ul>
277  * <li>Define a Button in the layout file and assign it a unique ID.
278  * <pre>
279  * &lt;Button
280  *     android:id="@+id/my_button"
281  *     android:layout_width="wrap_content"
282  *     android:layout_height="wrap_content"
283  *     android:text="@string/my_button_text"/&gt;
284  * </pre></li>
285  * <li>From the onCreate method of an Activity, find the Button
286  * <pre class="prettyprint">
287  *      Button myButton = (Button) findViewById(R.id.my_button);
288  * </pre></li>
289  * </ul>
290  * <p>
291  * View IDs need not be unique throughout the tree, but it is good practice to
292  * ensure that they are at least unique within the part of the tree you are
293  * searching.
294  * </p>
295  *
296  * <a name="Position"></a>
297  * <h3>Position</h3>
298  * <p>
299  * The geometry of a view is that of a rectangle. A view has a location,
300  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
301  * two dimensions, expressed as a width and a height. The unit for location
302  * and dimensions is the pixel.
303  * </p>
304  *
305  * <p>
306  * It is possible to retrieve the location of a view by invoking the methods
307  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
308  * coordinate of the rectangle representing the view. The latter returns the
309  * top, or Y, coordinate of the rectangle representing the view. These methods
310  * both return the location of the view relative to its parent. For instance,
311  * when getLeft() returns 20, that means the view is located 20 pixels to the
312  * right of the left edge of its direct parent.
313  * </p>
314  *
315  * <p>
316  * In addition, several convenience methods are offered to avoid unnecessary
317  * computations, namely {@link #getRight()} and {@link #getBottom()}.
318  * These methods return the coordinates of the right and bottom edges of the
319  * rectangle representing the view. For instance, calling {@link #getRight()}
320  * is similar to the following computation: <code>getLeft() + getWidth()</code>
321  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
322  * </p>
323  *
324  * <a name="SizePaddingMargins"></a>
325  * <h3>Size, padding and margins</h3>
326  * <p>
327  * The size of a view is expressed with a width and a height. A view actually
328  * possess two pairs of width and height values.
329  * </p>
330  *
331  * <p>
332  * The first pair is known as <em>measured width</em> and
333  * <em>measured height</em>. These dimensions define how big a view wants to be
334  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
335  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
336  * and {@link #getMeasuredHeight()}.
337  * </p>
338  *
339  * <p>
340  * The second pair is simply known as <em>width</em> and <em>height</em>, or
341  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
342  * dimensions define the actual size of the view on screen, at drawing time and
343  * after layout. These values may, but do not have to, be different from the
344  * measured width and height. The width and height can be obtained by calling
345  * {@link #getWidth()} and {@link #getHeight()}.
346  * </p>
347  *
348  * <p>
349  * To measure its dimensions, a view takes into account its padding. The padding
350  * is expressed in pixels for the left, top, right and bottom parts of the view.
351  * Padding can be used to offset the content of the view by a specific amount of
352  * pixels. For instance, a left padding of 2 will push the view's content by
353  * 2 pixels to the right of the left edge. Padding can be set using the
354  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
355  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
356  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
357  * {@link #getPaddingEnd()}.
358  * </p>
359  *
360  * <p>
361  * Even though a view can define a padding, it does not provide any support for
362  * margins. However, view groups provide such a support. Refer to
363  * {@link android.view.ViewGroup} and
364  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
365  * </p>
366  *
367  * <a name="Layout"></a>
368  * <h3>Layout</h3>
369  * <p>
370  * Layout is a two pass process: a measure pass and a layout pass. The measuring
371  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
372  * of the view tree. Each view pushes dimension specifications down the tree
373  * during the recursion. At the end of the measure pass, every view has stored
374  * its measurements. The second pass happens in
375  * {@link #layout(int,int,int,int)} and is also top-down. During
376  * this pass each parent is responsible for positioning all of its children
377  * using the sizes computed in the measure pass.
378  * </p>
379  *
380  * <p>
381  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
382  * {@link #getMeasuredHeight()} values must be set, along with those for all of
383  * that view's descendants. A view's measured width and measured height values
384  * must respect the constraints imposed by the view's parents. This guarantees
385  * that at the end of the measure pass, all parents accept all of their
386  * children's measurements. A parent view may call measure() more than once on
387  * its children. For example, the parent may measure each child once with
388  * unspecified dimensions to find out how big they want to be, then call
389  * measure() on them again with actual numbers if the sum of all the children's
390  * unconstrained sizes is too big or too small.
391  * </p>
392  *
393  * <p>
394  * The measure pass uses two classes to communicate dimensions. The
395  * {@link MeasureSpec} class is used by views to tell their parents how they
396  * want to be measured and positioned. The base LayoutParams class just
397  * describes how big the view wants to be for both width and height. For each
398  * dimension, it can specify one of:
399  * <ul>
400  * <li> an exact number
401  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
402  * (minus padding)
403  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
404  * enclose its content (plus padding).
405  * </ul>
406  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
407  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
408  * an X and Y value.
409  * </p>
410  *
411  * <p>
412  * MeasureSpecs are used to push requirements down the tree from parent to
413  * child. A MeasureSpec can be in one of three modes:
414  * <ul>
415  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
416  * of a child view. For example, a LinearLayout may call measure() on its child
417  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
418  * tall the child view wants to be given a width of 240 pixels.
419  * <li>EXACTLY: This is used by the parent to impose an exact size on the
420  * child. The child must use this size, and guarantee that all of its
421  * descendants will fit within this size.
422  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
423  * child. The child must gurantee that it and all of its descendants will fit
424  * within this size.
425  * </ul>
426  * </p>
427  *
428  * <p>
429  * To intiate a layout, call {@link #requestLayout}. This method is typically
430  * called by a view on itself when it believes that is can no longer fit within
431  * its current bounds.
432  * </p>
433  *
434  * <a name="Drawing"></a>
435  * <h3>Drawing</h3>
436  * <p>
437  * Drawing is handled by walking the tree and rendering each view that
438  * intersects the invalid region. Because the tree is traversed in-order,
439  * this means that parents will draw before (i.e., behind) their children, with
440  * siblings drawn in the order they appear in the tree.
441  * If you set a background drawable for a View, then the View will draw it for you
442  * before calling back to its <code>onDraw()</code> method.
443  * </p>
444  *
445  * <p>
446  * Note that the framework will not draw views that are not in the invalid region.
447  * </p>
448  *
449  * <p>
450  * To force a view to draw, call {@link #invalidate()}.
451  * </p>
452  *
453  * <a name="EventHandlingThreading"></a>
454  * <h3>Event Handling and Threading</h3>
455  * <p>
456  * The basic cycle of a view is as follows:
457  * <ol>
458  * <li>An event comes in and is dispatched to the appropriate view. The view
459  * handles the event and notifies any listeners.</li>
460  * <li>If in the course of processing the event, the view's bounds may need
461  * to be changed, the view will call {@link #requestLayout()}.</li>
462  * <li>Similarly, if in the course of processing the event the view's appearance
463  * may need to be changed, the view will call {@link #invalidate()}.</li>
464  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
465  * the framework will take care of measuring, laying out, and drawing the tree
466  * as appropriate.</li>
467  * </ol>
468  * </p>
469  *
470  * <p><em>Note: The entire view tree is single threaded. You must always be on
471  * the UI thread when calling any method on any view.</em>
472  * If you are doing work on other threads and want to update the state of a view
473  * from that thread, you should use a {@link Handler}.
474  * </p>
475  *
476  * <a name="FocusHandling"></a>
477  * <h3>Focus Handling</h3>
478  * <p>
479  * The framework will handle routine focus movement in response to user input.
480  * This includes changing the focus as views are removed or hidden, or as new
481  * views become available. Views indicate their willingness to take focus
482  * through the {@link #isFocusable} method. To change whether a view can take
483  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
484  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
485  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
486  * </p>
487  * <p>
488  * Focus movement is based on an algorithm which finds the nearest neighbor in a
489  * given direction. In rare cases, the default algorithm may not match the
490  * intended behavior of the developer. In these situations, you can provide
491  * explicit overrides by using these XML attributes in the layout file:
492  * <pre>
493  * nextFocusDown
494  * nextFocusLeft
495  * nextFocusRight
496  * nextFocusUp
497  * </pre>
498  * </p>
499  *
500  *
501  * <p>
502  * To get a particular view to take focus, call {@link #requestFocus()}.
503  * </p>
504  *
505  * <a name="TouchMode"></a>
506  * <h3>Touch Mode</h3>
507  * <p>
508  * When a user is navigating a user interface via directional keys such as a D-pad, it is
509  * necessary to give focus to actionable items such as buttons so the user can see
510  * what will take input.  If the device has touch capabilities, however, and the user
511  * begins interacting with the interface by touching it, it is no longer necessary to
512  * always highlight, or give focus to, a particular view.  This motivates a mode
513  * for interaction named 'touch mode'.
514  * </p>
515  * <p>
516  * For a touch capable device, once the user touches the screen, the device
517  * will enter touch mode.  From this point onward, only views for which
518  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
519  * Other views that are touchable, like buttons, will not take focus when touched; they will
520  * only fire the on click listeners.
521  * </p>
522  * <p>
523  * Any time a user hits a directional key, such as a D-pad direction, the view device will
524  * exit touch mode, and find a view to take focus, so that the user may resume interacting
525  * with the user interface without touching the screen again.
526  * </p>
527  * <p>
528  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
529  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
530  * </p>
531  *
532  * <a name="Scrolling"></a>
533  * <h3>Scrolling</h3>
534  * <p>
535  * The framework provides basic support for views that wish to internally
536  * scroll their content. This includes keeping track of the X and Y scroll
537  * offset as well as mechanisms for drawing scrollbars. See
538  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
539  * {@link #awakenScrollBars()} for more details.
540  * </p>
541  *
542  * <a name="Tags"></a>
543  * <h3>Tags</h3>
544  * <p>
545  * Unlike IDs, tags are not used to identify views. Tags are essentially an
546  * extra piece of information that can be associated with a view. They are most
547  * often used as a convenience to store data related to views in the views
548  * themselves rather than by putting them in a separate structure.
549  * </p>
550  *
551  * <a name="Properties"></a>
552  * <h3>Properties</h3>
553  * <p>
554  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
555  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
556  * available both in the {@link Property} form as well as in similarly-named setter/getter
557  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
558  * be used to set persistent state associated with these rendering-related properties on the view.
559  * The properties and methods can also be used in conjunction with
560  * {@link android.animation.Animator Animator}-based animations, described more in the
561  * <a href="#Animation">Animation</a> section.
562  * </p>
563  *
564  * <a name="Animation"></a>
565  * <h3>Animation</h3>
566  * <p>
567  * Starting with Android 3.0, the preferred way of animating views is to use the
568  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
569  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
570  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
571  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
572  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
573  * makes animating these View properties particularly easy and efficient.
574  * </p>
575  * <p>
576  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
577  * You can attach an {@link Animation} object to a view using
578  * {@link #setAnimation(Animation)} or
579  * {@link #startAnimation(Animation)}. The animation can alter the scale,
580  * rotation, translation and alpha of a view over time. If the animation is
581  * attached to a view that has children, the animation will affect the entire
582  * subtree rooted by that node. When an animation is started, the framework will
583  * take care of redrawing the appropriate views until the animation completes.
584  * </p>
585  *
586  * <a name="Security"></a>
587  * <h3>Security</h3>
588  * <p>
589  * Sometimes it is essential that an application be able to verify that an action
590  * is being performed with the full knowledge and consent of the user, such as
591  * granting a permission request, making a purchase or clicking on an advertisement.
592  * Unfortunately, a malicious application could try to spoof the user into
593  * performing these actions, unaware, by concealing the intended purpose of the view.
594  * As a remedy, the framework offers a touch filtering mechanism that can be used to
595  * improve the security of views that provide access to sensitive functionality.
596  * </p><p>
597  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
598  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
599  * will discard touches that are received whenever the view's window is obscured by
600  * another visible window.  As a result, the view will not receive touches whenever a
601  * toast, dialog or other window appears above the view's window.
602  * </p><p>
603  * For more fine-grained control over security, consider overriding the
604  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
605  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
606  * </p>
607  *
608  * @attr ref android.R.styleable#View_alpha
609  * @attr ref android.R.styleable#View_background
610  * @attr ref android.R.styleable#View_clickable
611  * @attr ref android.R.styleable#View_contentDescription
612  * @attr ref android.R.styleable#View_drawingCacheQuality
613  * @attr ref android.R.styleable#View_duplicateParentState
614  * @attr ref android.R.styleable#View_id
615  * @attr ref android.R.styleable#View_requiresFadingEdge
616  * @attr ref android.R.styleable#View_fadeScrollbars
617  * @attr ref android.R.styleable#View_fadingEdgeLength
618  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
619  * @attr ref android.R.styleable#View_fitsSystemWindows
620  * @attr ref android.R.styleable#View_isScrollContainer
621  * @attr ref android.R.styleable#View_focusable
622  * @attr ref android.R.styleable#View_focusableInTouchMode
623  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
624  * @attr ref android.R.styleable#View_keepScreenOn
625  * @attr ref android.R.styleable#View_layerType
626  * @attr ref android.R.styleable#View_layoutDirection
627  * @attr ref android.R.styleable#View_longClickable
628  * @attr ref android.R.styleable#View_minHeight
629  * @attr ref android.R.styleable#View_minWidth
630  * @attr ref android.R.styleable#View_nextFocusDown
631  * @attr ref android.R.styleable#View_nextFocusLeft
632  * @attr ref android.R.styleable#View_nextFocusRight
633  * @attr ref android.R.styleable#View_nextFocusUp
634  * @attr ref android.R.styleable#View_onClick
635  * @attr ref android.R.styleable#View_padding
636  * @attr ref android.R.styleable#View_paddingBottom
637  * @attr ref android.R.styleable#View_paddingLeft
638  * @attr ref android.R.styleable#View_paddingRight
639  * @attr ref android.R.styleable#View_paddingTop
640  * @attr ref android.R.styleable#View_paddingStart
641  * @attr ref android.R.styleable#View_paddingEnd
642  * @attr ref android.R.styleable#View_saveEnabled
643  * @attr ref android.R.styleable#View_rotation
644  * @attr ref android.R.styleable#View_rotationX
645  * @attr ref android.R.styleable#View_rotationY
646  * @attr ref android.R.styleable#View_scaleX
647  * @attr ref android.R.styleable#View_scaleY
648  * @attr ref android.R.styleable#View_scrollX
649  * @attr ref android.R.styleable#View_scrollY
650  * @attr ref android.R.styleable#View_scrollbarSize
651  * @attr ref android.R.styleable#View_scrollbarStyle
652  * @attr ref android.R.styleable#View_scrollbars
653  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
654  * @attr ref android.R.styleable#View_scrollbarFadeDuration
655  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
656  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
657  * @attr ref android.R.styleable#View_scrollbarThumbVertical
658  * @attr ref android.R.styleable#View_scrollbarTrackVertical
659  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
660  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
661  * @attr ref android.R.styleable#View_soundEffectsEnabled
662  * @attr ref android.R.styleable#View_tag
663  * @attr ref android.R.styleable#View_textAlignment
664  * @attr ref android.R.styleable#View_textDirection
665  * @attr ref android.R.styleable#View_transformPivotX
666  * @attr ref android.R.styleable#View_transformPivotY
667  * @attr ref android.R.styleable#View_translationX
668  * @attr ref android.R.styleable#View_translationY
669  * @attr ref android.R.styleable#View_visibility
670  *
671  * @see android.view.ViewGroup
672  */
673 public class View implements Drawable.Callback, KeyEvent.Callback,
674         AccessibilityEventSource {
675     private static final boolean DBG = false;
676 
677     /**
678      * The logging tag used by this class with android.util.Log.
679      */
680     protected static final String VIEW_LOG_TAG = "View";
681 
682     /**
683      * When set to true, apps will draw debugging information about their layouts.
684      *
685      * @hide
686      */
687     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
688 
689     /**
690      * Used to mark a View that has no ID.
691      */
692     public static final int NO_ID = -1;
693 
694     /**
695      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
696      * calling setFlags.
697      */
698     private static final int NOT_FOCUSABLE = 0x00000000;
699 
700     /**
701      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
702      * setFlags.
703      */
704     private static final int FOCUSABLE = 0x00000001;
705 
706     /**
707      * Mask for use with setFlags indicating bits used for focus.
708      */
709     private static final int FOCUSABLE_MASK = 0x00000001;
710 
711     /**
712      * This view will adjust its padding to fit sytem windows (e.g. status bar)
713      */
714     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
715 
716     /**
717      * This view is visible.
718      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
719      * android:visibility}.
720      */
721     public static final int VISIBLE = 0x00000000;
722 
723     /**
724      * This view is invisible, but it still takes up space for layout purposes.
725      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
726      * android:visibility}.
727      */
728     public static final int INVISIBLE = 0x00000004;
729 
730     /**
731      * This view is invisible, and it doesn't take any space for layout
732      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
733      * android:visibility}.
734      */
735     public static final int GONE = 0x00000008;
736 
737     /**
738      * Mask for use with setFlags indicating bits used for visibility.
739      * {@hide}
740      */
741     static final int VISIBILITY_MASK = 0x0000000C;
742 
743     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
744 
745     /**
746      * This view is enabled. Interpretation varies by subclass.
747      * Use with ENABLED_MASK when calling setFlags.
748      * {@hide}
749      */
750     static final int ENABLED = 0x00000000;
751 
752     /**
753      * This view is disabled. Interpretation varies by subclass.
754      * Use with ENABLED_MASK when calling setFlags.
755      * {@hide}
756      */
757     static final int DISABLED = 0x00000020;
758 
759    /**
760     * Mask for use with setFlags indicating bits used for indicating whether
761     * this view is enabled
762     * {@hide}
763     */
764     static final int ENABLED_MASK = 0x00000020;
765 
766     /**
767      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
768      * called and further optimizations will be performed. It is okay to have
769      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
770      * {@hide}
771      */
772     static final int WILL_NOT_DRAW = 0x00000080;
773 
774     /**
775      * Mask for use with setFlags indicating bits used for indicating whether
776      * this view is will draw
777      * {@hide}
778      */
779     static final int DRAW_MASK = 0x00000080;
780 
781     /**
782      * <p>This view doesn't show scrollbars.</p>
783      * {@hide}
784      */
785     static final int SCROLLBARS_NONE = 0x00000000;
786 
787     /**
788      * <p>This view shows horizontal scrollbars.</p>
789      * {@hide}
790      */
791     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
792 
793     /**
794      * <p>This view shows vertical scrollbars.</p>
795      * {@hide}
796      */
797     static final int SCROLLBARS_VERTICAL = 0x00000200;
798 
799     /**
800      * <p>Mask for use with setFlags indicating bits used for indicating which
801      * scrollbars are enabled.</p>
802      * {@hide}
803      */
804     static final int SCROLLBARS_MASK = 0x00000300;
805 
806     /**
807      * Indicates that the view should filter touches when its window is obscured.
808      * Refer to the class comments for more information about this security feature.
809      * {@hide}
810      */
811     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
812 
813     /**
814      * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
815      * that they are optional and should be skipped if the window has
816      * requested system UI flags that ignore those insets for layout.
817      */
818     static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
819 
820     /**
821      * <p>This view doesn't show fading edges.</p>
822      * {@hide}
823      */
824     static final int FADING_EDGE_NONE = 0x00000000;
825 
826     /**
827      * <p>This view shows horizontal fading edges.</p>
828      * {@hide}
829      */
830     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
831 
832     /**
833      * <p>This view shows vertical fading edges.</p>
834      * {@hide}
835      */
836     static final int FADING_EDGE_VERTICAL = 0x00002000;
837 
838     /**
839      * <p>Mask for use with setFlags indicating bits used for indicating which
840      * fading edges are enabled.</p>
841      * {@hide}
842      */
843     static final int FADING_EDGE_MASK = 0x00003000;
844 
845     /**
846      * <p>Indicates this view can be clicked. When clickable, a View reacts
847      * to clicks by notifying the OnClickListener.<p>
848      * {@hide}
849      */
850     static final int CLICKABLE = 0x00004000;
851 
852     /**
853      * <p>Indicates this view is caching its drawing into a bitmap.</p>
854      * {@hide}
855      */
856     static final int DRAWING_CACHE_ENABLED = 0x00008000;
857 
858     /**
859      * <p>Indicates that no icicle should be saved for this view.<p>
860      * {@hide}
861      */
862     static final int SAVE_DISABLED = 0x000010000;
863 
864     /**
865      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
866      * property.</p>
867      * {@hide}
868      */
869     static final int SAVE_DISABLED_MASK = 0x000010000;
870 
871     /**
872      * <p>Indicates that no drawing cache should ever be created for this view.<p>
873      * {@hide}
874      */
875     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
876 
877     /**
878      * <p>Indicates this view can take / keep focus when int touch mode.</p>
879      * {@hide}
880      */
881     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
882 
883     /**
884      * <p>Enables low quality mode for the drawing cache.</p>
885      */
886     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
887 
888     /**
889      * <p>Enables high quality mode for the drawing cache.</p>
890      */
891     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
892 
893     /**
894      * <p>Enables automatic quality mode for the drawing cache.</p>
895      */
896     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
897 
898     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
899             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
900     };
901 
902     /**
903      * <p>Mask for use with setFlags indicating bits used for the cache
904      * quality property.</p>
905      * {@hide}
906      */
907     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
908 
909     /**
910      * <p>
911      * Indicates this view can be long clicked. When long clickable, a View
912      * reacts to long clicks by notifying the OnLongClickListener or showing a
913      * context menu.
914      * </p>
915      * {@hide}
916      */
917     static final int LONG_CLICKABLE = 0x00200000;
918 
919     /**
920      * <p>Indicates that this view gets its drawable states from its direct parent
921      * and ignores its original internal states.</p>
922      *
923      * @hide
924      */
925     static final int DUPLICATE_PARENT_STATE = 0x00400000;
926 
927     /**
928      * The scrollbar style to display the scrollbars inside the content area,
929      * without increasing the padding. The scrollbars will be overlaid with
930      * translucency on the view's content.
931      */
932     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
933 
934     /**
935      * The scrollbar style to display the scrollbars inside the padded area,
936      * increasing the padding of the view. The scrollbars will not overlap the
937      * content area of the view.
938      */
939     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
940 
941     /**
942      * The scrollbar style to display the scrollbars at the edge of the view,
943      * without increasing the padding. The scrollbars will be overlaid with
944      * translucency.
945      */
946     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
947 
948     /**
949      * The scrollbar style to display the scrollbars at the edge of the view,
950      * increasing the padding of the view. The scrollbars will only overlap the
951      * background, if any.
952      */
953     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
954 
955     /**
956      * Mask to check if the scrollbar style is overlay or inset.
957      * {@hide}
958      */
959     static final int SCROLLBARS_INSET_MASK = 0x01000000;
960 
961     /**
962      * Mask to check if the scrollbar style is inside or outside.
963      * {@hide}
964      */
965     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
966 
967     /**
968      * Mask for scrollbar style.
969      * {@hide}
970      */
971     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
972 
973     /**
974      * View flag indicating that the screen should remain on while the
975      * window containing this view is visible to the user.  This effectively
976      * takes care of automatically setting the WindowManager's
977      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
978      */
979     public static final int KEEP_SCREEN_ON = 0x04000000;
980 
981     /**
982      * View flag indicating whether this view should have sound effects enabled
983      * for events such as clicking and touching.
984      */
985     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
986 
987     /**
988      * View flag indicating whether this view should have haptic feedback
989      * enabled for events such as long presses.
990      */
991     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
992 
993     /**
994      * <p>Indicates that the view hierarchy should stop saving state when
995      * it reaches this view.  If state saving is initiated immediately at
996      * the view, it will be allowed.
997      * {@hide}
998      */
999     static final int PARENT_SAVE_DISABLED = 0x20000000;
1000 
1001     /**
1002      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1003      * {@hide}
1004      */
1005     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1006 
1007     /**
1008      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1009      * should add all focusable Views regardless if they are focusable in touch mode.
1010      */
1011     public static final int FOCUSABLES_ALL = 0x00000000;
1012 
1013     /**
1014      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1015      * should add only Views focusable in touch mode.
1016      */
1017     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1018 
1019     /**
1020      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1021      * item.
1022      */
1023     public static final int FOCUS_BACKWARD = 0x00000001;
1024 
1025     /**
1026      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1027      * item.
1028      */
1029     public static final int FOCUS_FORWARD = 0x00000002;
1030 
1031     /**
1032      * Use with {@link #focusSearch(int)}. Move focus to the left.
1033      */
1034     public static final int FOCUS_LEFT = 0x00000011;
1035 
1036     /**
1037      * Use with {@link #focusSearch(int)}. Move focus up.
1038      */
1039     public static final int FOCUS_UP = 0x00000021;
1040 
1041     /**
1042      * Use with {@link #focusSearch(int)}. Move focus to the right.
1043      */
1044     public static final int FOCUS_RIGHT = 0x00000042;
1045 
1046     /**
1047      * Use with {@link #focusSearch(int)}. Move focus down.
1048      */
1049     public static final int FOCUS_DOWN = 0x00000082;
1050 
1051     /**
1052      * Bits of {@link #getMeasuredWidthAndState()} and
1053      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1054      */
1055     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1056 
1057     /**
1058      * Bits of {@link #getMeasuredWidthAndState()} and
1059      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1060      */
1061     public static final int MEASURED_STATE_MASK = 0xff000000;
1062 
1063     /**
1064      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1065      * for functions that combine both width and height into a single int,
1066      * such as {@link #getMeasuredState()} and the childState argument of
1067      * {@link #resolveSizeAndState(int, int, int)}.
1068      */
1069     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1070 
1071     /**
1072      * Bit of {@link #getMeasuredWidthAndState()} and
1073      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1074      * is smaller that the space the view would like to have.
1075      */
1076     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1077 
1078     /**
1079      * Base View state sets
1080      */
1081     // Singles
1082     /**
1083      * Indicates the view has no states set. States are used with
1084      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1085      * view depending on its state.
1086      *
1087      * @see android.graphics.drawable.Drawable
1088      * @see #getDrawableState()
1089      */
1090     protected static final int[] EMPTY_STATE_SET;
1091     /**
1092      * Indicates the view is enabled. States are used with
1093      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1094      * view depending on its state.
1095      *
1096      * @see android.graphics.drawable.Drawable
1097      * @see #getDrawableState()
1098      */
1099     protected static final int[] ENABLED_STATE_SET;
1100     /**
1101      * Indicates the view is focused. States are used with
1102      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1103      * view depending on its state.
1104      *
1105      * @see android.graphics.drawable.Drawable
1106      * @see #getDrawableState()
1107      */
1108     protected static final int[] FOCUSED_STATE_SET;
1109     /**
1110      * Indicates the view is selected. States are used with
1111      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1112      * view depending on its state.
1113      *
1114      * @see android.graphics.drawable.Drawable
1115      * @see #getDrawableState()
1116      */
1117     protected static final int[] SELECTED_STATE_SET;
1118     /**
1119      * Indicates the view is pressed. States are used with
1120      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1121      * view depending on its state.
1122      *
1123      * @see android.graphics.drawable.Drawable
1124      * @see #getDrawableState()
1125      * @hide
1126      */
1127     protected static final int[] PRESSED_STATE_SET;
1128     /**
1129      * Indicates the view's window has focus. States are used with
1130      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1131      * view depending on its state.
1132      *
1133      * @see android.graphics.drawable.Drawable
1134      * @see #getDrawableState()
1135      */
1136     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1137     // Doubles
1138     /**
1139      * Indicates the view is enabled and has the focus.
1140      *
1141      * @see #ENABLED_STATE_SET
1142      * @see #FOCUSED_STATE_SET
1143      */
1144     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1145     /**
1146      * Indicates the view is enabled and selected.
1147      *
1148      * @see #ENABLED_STATE_SET
1149      * @see #SELECTED_STATE_SET
1150      */
1151     protected static final int[] ENABLED_SELECTED_STATE_SET;
1152     /**
1153      * Indicates the view is enabled and that its window has focus.
1154      *
1155      * @see #ENABLED_STATE_SET
1156      * @see #WINDOW_FOCUSED_STATE_SET
1157      */
1158     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1159     /**
1160      * Indicates the view is focused and selected.
1161      *
1162      * @see #FOCUSED_STATE_SET
1163      * @see #SELECTED_STATE_SET
1164      */
1165     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1166     /**
1167      * Indicates the view has the focus and that its window has the focus.
1168      *
1169      * @see #FOCUSED_STATE_SET
1170      * @see #WINDOW_FOCUSED_STATE_SET
1171      */
1172     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1173     /**
1174      * Indicates the view is selected and that its window has the focus.
1175      *
1176      * @see #SELECTED_STATE_SET
1177      * @see #WINDOW_FOCUSED_STATE_SET
1178      */
1179     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1180     // Triples
1181     /**
1182      * Indicates the view is enabled, focused and selected.
1183      *
1184      * @see #ENABLED_STATE_SET
1185      * @see #FOCUSED_STATE_SET
1186      * @see #SELECTED_STATE_SET
1187      */
1188     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1189     /**
1190      * Indicates the view is enabled, focused and its window has the focus.
1191      *
1192      * @see #ENABLED_STATE_SET
1193      * @see #FOCUSED_STATE_SET
1194      * @see #WINDOW_FOCUSED_STATE_SET
1195      */
1196     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1197     /**
1198      * Indicates the view is enabled, selected and its window has the focus.
1199      *
1200      * @see #ENABLED_STATE_SET
1201      * @see #SELECTED_STATE_SET
1202      * @see #WINDOW_FOCUSED_STATE_SET
1203      */
1204     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1205     /**
1206      * Indicates the view is focused, selected and its window has the focus.
1207      *
1208      * @see #FOCUSED_STATE_SET
1209      * @see #SELECTED_STATE_SET
1210      * @see #WINDOW_FOCUSED_STATE_SET
1211      */
1212     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1213     /**
1214      * Indicates the view is enabled, focused, selected and its window
1215      * has the focus.
1216      *
1217      * @see #ENABLED_STATE_SET
1218      * @see #FOCUSED_STATE_SET
1219      * @see #SELECTED_STATE_SET
1220      * @see #WINDOW_FOCUSED_STATE_SET
1221      */
1222     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1223     /**
1224      * Indicates the view is pressed and its window has the focus.
1225      *
1226      * @see #PRESSED_STATE_SET
1227      * @see #WINDOW_FOCUSED_STATE_SET
1228      */
1229     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1230     /**
1231      * Indicates the view is pressed and selected.
1232      *
1233      * @see #PRESSED_STATE_SET
1234      * @see #SELECTED_STATE_SET
1235      */
1236     protected static final int[] PRESSED_SELECTED_STATE_SET;
1237     /**
1238      * Indicates the view is pressed, selected and its window has the focus.
1239      *
1240      * @see #PRESSED_STATE_SET
1241      * @see #SELECTED_STATE_SET
1242      * @see #WINDOW_FOCUSED_STATE_SET
1243      */
1244     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1245     /**
1246      * Indicates the view is pressed and focused.
1247      *
1248      * @see #PRESSED_STATE_SET
1249      * @see #FOCUSED_STATE_SET
1250      */
1251     protected static final int[] PRESSED_FOCUSED_STATE_SET;
1252     /**
1253      * Indicates the view is pressed, focused and its window has the focus.
1254      *
1255      * @see #PRESSED_STATE_SET
1256      * @see #FOCUSED_STATE_SET
1257      * @see #WINDOW_FOCUSED_STATE_SET
1258      */
1259     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1260     /**
1261      * Indicates the view is pressed, focused and selected.
1262      *
1263      * @see #PRESSED_STATE_SET
1264      * @see #SELECTED_STATE_SET
1265      * @see #FOCUSED_STATE_SET
1266      */
1267     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1268     /**
1269      * Indicates the view is pressed, focused, selected and its window has the focus.
1270      *
1271      * @see #PRESSED_STATE_SET
1272      * @see #FOCUSED_STATE_SET
1273      * @see #SELECTED_STATE_SET
1274      * @see #WINDOW_FOCUSED_STATE_SET
1275      */
1276     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1277     /**
1278      * Indicates the view is pressed and enabled.
1279      *
1280      * @see #PRESSED_STATE_SET
1281      * @see #ENABLED_STATE_SET
1282      */
1283     protected static final int[] PRESSED_ENABLED_STATE_SET;
1284     /**
1285      * Indicates the view is pressed, enabled and its window has the focus.
1286      *
1287      * @see #PRESSED_STATE_SET
1288      * @see #ENABLED_STATE_SET
1289      * @see #WINDOW_FOCUSED_STATE_SET
1290      */
1291     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1292     /**
1293      * Indicates the view is pressed, enabled and selected.
1294      *
1295      * @see #PRESSED_STATE_SET
1296      * @see #ENABLED_STATE_SET
1297      * @see #SELECTED_STATE_SET
1298      */
1299     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1300     /**
1301      * Indicates the view is pressed, enabled, selected and its window has the
1302      * focus.
1303      *
1304      * @see #PRESSED_STATE_SET
1305      * @see #ENABLED_STATE_SET
1306      * @see #SELECTED_STATE_SET
1307      * @see #WINDOW_FOCUSED_STATE_SET
1308      */
1309     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1310     /**
1311      * Indicates the view is pressed, enabled and focused.
1312      *
1313      * @see #PRESSED_STATE_SET
1314      * @see #ENABLED_STATE_SET
1315      * @see #FOCUSED_STATE_SET
1316      */
1317     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1318     /**
1319      * Indicates the view is pressed, enabled, focused and its window has the
1320      * focus.
1321      *
1322      * @see #PRESSED_STATE_SET
1323      * @see #ENABLED_STATE_SET
1324      * @see #FOCUSED_STATE_SET
1325      * @see #WINDOW_FOCUSED_STATE_SET
1326      */
1327     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1328     /**
1329      * Indicates the view is pressed, enabled, focused and selected.
1330      *
1331      * @see #PRESSED_STATE_SET
1332      * @see #ENABLED_STATE_SET
1333      * @see #SELECTED_STATE_SET
1334      * @see #FOCUSED_STATE_SET
1335      */
1336     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1337     /**
1338      * Indicates the view is pressed, enabled, focused, selected and its window
1339      * has the focus.
1340      *
1341      * @see #PRESSED_STATE_SET
1342      * @see #ENABLED_STATE_SET
1343      * @see #SELECTED_STATE_SET
1344      * @see #FOCUSED_STATE_SET
1345      * @see #WINDOW_FOCUSED_STATE_SET
1346      */
1347     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1348 
1349     /**
1350      * The order here is very important to {@link #getDrawableState()}
1351      */
1352     private static final int[][] VIEW_STATE_SETS;
1353 
1354     static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1355     static final int VIEW_STATE_SELECTED = 1 << 1;
1356     static final int VIEW_STATE_FOCUSED = 1 << 2;
1357     static final int VIEW_STATE_ENABLED = 1 << 3;
1358     static final int VIEW_STATE_PRESSED = 1 << 4;
1359     static final int VIEW_STATE_ACTIVATED = 1 << 5;
1360     static final int VIEW_STATE_ACCELERATED = 1 << 6;
1361     static final int VIEW_STATE_HOVERED = 1 << 7;
1362     static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1363     static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
1364 
1365     static final int[] VIEW_STATE_IDS = new int[] {
1366         R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
1367         R.attr.state_selected,          VIEW_STATE_SELECTED,
1368         R.attr.state_focused,           VIEW_STATE_FOCUSED,
1369         R.attr.state_enabled,           VIEW_STATE_ENABLED,
1370         R.attr.state_pressed,           VIEW_STATE_PRESSED,
1371         R.attr.state_activated,         VIEW_STATE_ACTIVATED,
1372         R.attr.state_accelerated,       VIEW_STATE_ACCELERATED,
1373         R.attr.state_hovered,           VIEW_STATE_HOVERED,
1374         R.attr.state_drag_can_accept,   VIEW_STATE_DRAG_CAN_ACCEPT,
1375         R.attr.state_drag_hovered,      VIEW_STATE_DRAG_HOVERED
1376     };
1377 
1378     static {
1379         if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1380             throw new IllegalStateException(
1381                     "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1382         }
1383         int[] orderedIds = new int[VIEW_STATE_IDS.length];
1384         for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
1385             int viewState = R.styleable.ViewDrawableStates[i];
1386             for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
1387                 if (VIEW_STATE_IDS[j] == viewState) {
1388                     orderedIds[i * 2] = viewState;
1389                     orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
1390                 }
1391             }
1392         }
1393         final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1394         VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1395         for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
1396             int numBits = Integer.bitCount(i);
1397             int[] set = new int[numBits];
1398             int pos = 0;
1399             for (int j = 0; j < orderedIds.length; j += 2) {
1400                 if ((i & orderedIds[j+1]) != 0) {
1401                     set[pos++] = orderedIds[j];
1402                 }
1403             }
1404             VIEW_STATE_SETS[i] = set;
1405         }
1406 
1407         EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1408         WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1409         SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1410         SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1411                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1412         FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1413         FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1414                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1415         FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1416                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1417         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1418                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1419                 | VIEW_STATE_FOCUSED];
1420         ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1421         ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1422                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1423         ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1424                 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1425         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1426                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1427                 | VIEW_STATE_ENABLED];
1428         ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1429                 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1430         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1431                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1432                 | VIEW_STATE_ENABLED];
1433         ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1434                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1435                 | VIEW_STATE_ENABLED];
1436         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1437                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1438                 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1439 
1440         PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1441         PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1442                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1443         PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1444                 VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1445         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1446                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1447                 | VIEW_STATE_PRESSED];
1448         PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1449                 VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1450         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1451                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1452                 | VIEW_STATE_PRESSED];
1453         PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1454                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1455                 | VIEW_STATE_PRESSED];
1456         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1457                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1458                 | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1459         PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1460                 VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1461         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1462                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1463                 | VIEW_STATE_PRESSED];
1464         PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1465                 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1466                 | VIEW_STATE_PRESSED];
1467         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1468                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1469                 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1470         PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1471                 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1472                 | VIEW_STATE_PRESSED];
1473         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1474                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1475                 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1476         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1477                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1478                 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1479         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1480                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1481                 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1482                 | VIEW_STATE_PRESSED];
1483     }
1484 
1485     /**
1486      * Accessibility event types that are dispatched for text population.
1487      */
1488     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1489             AccessibilityEvent.TYPE_VIEW_CLICKED
1490             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1491             | AccessibilityEvent.TYPE_VIEW_SELECTED
1492             | AccessibilityEvent.TYPE_VIEW_FOCUSED
1493             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1494             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1495             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1496             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1497             | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1498             | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1499             | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1500 
1501     /**
1502      * Temporary Rect currently for use in setBackground().  This will probably
1503      * be extended in the future to hold our own class with more than just
1504      * a Rect. :)
1505      */
1506     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1507 
1508     /**
1509      * Map used to store views' tags.
1510      */
1511     private SparseArray<Object> mKeyedTags;
1512 
1513     /**
1514      * The next available accessibility id.
1515      */
1516     private static int sNextAccessibilityViewId;
1517 
1518     /**
1519      * The animation currently associated with this view.
1520      * @hide
1521      */
1522     protected Animation mCurrentAnimation = null;
1523 
1524     /**
1525      * Width as measured during measure pass.
1526      * {@hide}
1527      */
1528     @ViewDebug.ExportedProperty(category = "measurement")
1529     int mMeasuredWidth;
1530 
1531     /**
1532      * Height as measured during measure pass.
1533      * {@hide}
1534      */
1535     @ViewDebug.ExportedProperty(category = "measurement")
1536     int mMeasuredHeight;
1537 
1538     /**
1539      * Flag to indicate that this view was marked INVALIDATED, or had its display list
1540      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1541      * its display list. This flag, used only when hw accelerated, allows us to clear the
1542      * flag while retaining this information until it's needed (at getDisplayList() time and
1543      * in drawChild(), when we decide to draw a view's children's display lists into our own).
1544      *
1545      * {@hide}
1546      */
1547     boolean mRecreateDisplayList = false;
1548 
1549     /**
1550      * The view's identifier.
1551      * {@hide}
1552      *
1553      * @see #setId(int)
1554      * @see #getId()
1555      */
1556     @ViewDebug.ExportedProperty(resolveId = true)
1557     int mID = NO_ID;
1558 
1559     /**
1560      * The stable ID of this view for accessibility purposes.
1561      */
1562     int mAccessibilityViewId = NO_ID;
1563 
1564     /**
1565      * @hide
1566      */
1567     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1568 
1569     /**
1570      * The view's tag.
1571      * {@hide}
1572      *
1573      * @see #setTag(Object)
1574      * @see #getTag()
1575      */
1576     protected Object mTag;
1577 
1578     // for mPrivateFlags:
1579     /** {@hide} */
1580     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1581     /** {@hide} */
1582     static final int PFLAG_FOCUSED                     = 0x00000002;
1583     /** {@hide} */
1584     static final int PFLAG_SELECTED                    = 0x00000004;
1585     /** {@hide} */
1586     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1587     /** {@hide} */
1588     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1589     /** {@hide} */
1590     static final int PFLAG_DRAWN                       = 0x00000020;
1591     /**
1592      * When this flag is set, this view is running an animation on behalf of its
1593      * children and should therefore not cancel invalidate requests, even if they
1594      * lie outside of this view's bounds.
1595      *
1596      * {@hide}
1597      */
1598     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1599     /** {@hide} */
1600     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1601     /** {@hide} */
1602     static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
1603     /** {@hide} */
1604     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1605     /** {@hide} */
1606     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1607     /** {@hide} */
1608     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1609     /** {@hide} */
1610     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1611     /** {@hide} */
1612     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1613 
1614     private static final int PFLAG_PRESSED             = 0x00004000;
1615 
1616     /** {@hide} */
1617     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1618     /**
1619      * Flag used to indicate that this view should be drawn once more (and only once
1620      * more) after its animation has completed.
1621      * {@hide}
1622      */
1623     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1624 
1625     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1626 
1627     /**
1628      * Indicates that the View returned true when onSetAlpha() was called and that
1629      * the alpha must be restored.
1630      * {@hide}
1631      */
1632     static final int PFLAG_ALPHA_SET                   = 0x00040000;
1633 
1634     /**
1635      * Set by {@link #setScrollContainer(boolean)}.
1636      */
1637     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1638 
1639     /**
1640      * Set by {@link #setScrollContainer(boolean)}.
1641      */
1642     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1643 
1644     /**
1645      * View flag indicating whether this view was invalidated (fully or partially.)
1646      *
1647      * @hide
1648      */
1649     static final int PFLAG_DIRTY                       = 0x00200000;
1650 
1651     /**
1652      * View flag indicating whether this view was invalidated by an opaque
1653      * invalidate request.
1654      *
1655      * @hide
1656      */
1657     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1658 
1659     /**
1660      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1661      *
1662      * @hide
1663      */
1664     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1665 
1666     /**
1667      * Indicates whether the background is opaque.
1668      *
1669      * @hide
1670      */
1671     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1672 
1673     /**
1674      * Indicates whether the scrollbars are opaque.
1675      *
1676      * @hide
1677      */
1678     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1679 
1680     /**
1681      * Indicates whether the view is opaque.
1682      *
1683      * @hide
1684      */
1685     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1686 
1687     /**
1688      * Indicates a prepressed state;
1689      * the short time between ACTION_DOWN and recognizing
1690      * a 'real' press. Prepressed is used to recognize quick taps
1691      * even when they are shorter than ViewConfiguration.getTapTimeout().
1692      *
1693      * @hide
1694      */
1695     private static final int PFLAG_PREPRESSED          = 0x02000000;
1696 
1697     /**
1698      * Indicates whether the view is temporarily detached.
1699      *
1700      * @hide
1701      */
1702     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1703 
1704     /**
1705      * Indicates that we should awaken scroll bars once attached
1706      *
1707      * @hide
1708      */
1709     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1710 
1711     /**
1712      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1713      * @hide
1714      */
1715     private static final int PFLAG_HOVERED             = 0x10000000;
1716 
1717     /**
1718      * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
1719      * for transform operations
1720      *
1721      * @hide
1722      */
1723     private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000;
1724 
1725     /** {@hide} */
1726     static final int PFLAG_ACTIVATED                   = 0x40000000;
1727 
1728     /**
1729      * Indicates that this view was specifically invalidated, not just dirtied because some
1730      * child view was invalidated. The flag is used to determine when we need to recreate
1731      * a view's display list (as opposed to just returning a reference to its existing
1732      * display list).
1733      *
1734      * @hide
1735      */
1736     static final int PFLAG_INVALIDATED                 = 0x80000000;
1737 
1738     /**
1739      * Masks for mPrivateFlags2, as generated by dumpFlags():
1740      *
1741      * -------|-------|-------|-------|
1742      *                                  PFLAG2_TEXT_ALIGNMENT_FLAGS[0]
1743      *                                  PFLAG2_TEXT_DIRECTION_FLAGS[0]
1744      *                                1 PFLAG2_DRAG_CAN_ACCEPT
1745      *                               1  PFLAG2_DRAG_HOVERED
1746      *                               1  PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT
1747      *                              11  PFLAG2_TEXT_DIRECTION_MASK_SHIFT
1748      *                             1 1  PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT
1749      *                             11   PFLAG2_LAYOUT_DIRECTION_MASK
1750      *                             11 1 PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
1751      *                            1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1752      *                            1   1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT
1753      *                            1 1   PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT
1754      *                           1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1755      *                           11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1756      *                          1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1757      *                         1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1758      *                         11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1759      *                        1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1760      *                        1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1761      *                        111       PFLAG2_TEXT_DIRECTION_MASK
1762      *                       1          PFLAG2_TEXT_DIRECTION_RESOLVED
1763      *                      1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1764      *                    111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1765      *                   1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1766      *                  1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1767      *                  11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1768      *                 1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1769      *                 1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1770      *                 11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1771      *                 111              PFLAG2_TEXT_ALIGNMENT_MASK
1772      *                1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1773      *               1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1774      *             111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1775      *           11                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1776      *          1                       PFLAG2_HAS_TRANSIENT_STATE
1777      *      1                           PFLAG2_ACCESSIBILITY_FOCUSED
1778      *     1                            PFLAG2_ACCESSIBILITY_STATE_CHANGED
1779      *    1                             PFLAG2_VIEW_QUICK_REJECTED
1780      *   1                              PFLAG2_PADDING_RESOLVED
1781      * -------|-------|-------|-------|
1782      */
1783 
1784     /**
1785      * Indicates that this view has reported that it can accept the current drag's content.
1786      * Cleared when the drag operation concludes.
1787      * @hide
1788      */
1789     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1790 
1791     /**
1792      * Indicates that this view is currently directly under the drag location in a
1793      * drag-and-drop operation involving content that it can accept.  Cleared when
1794      * the drag exits the view, or when the drag operation concludes.
1795      * @hide
1796      */
1797     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1798 
1799     /**
1800      * Horizontal layout direction of this view is from Left to Right.
1801      * Use with {@link #setLayoutDirection}.
1802      */
1803     public static final int LAYOUT_DIRECTION_LTR = 0;
1804 
1805     /**
1806      * Horizontal layout direction of this view is from Right to Left.
1807      * Use with {@link #setLayoutDirection}.
1808      */
1809     public static final int LAYOUT_DIRECTION_RTL = 1;
1810 
1811     /**
1812      * Horizontal layout direction of this view is inherited from its parent.
1813      * Use with {@link #setLayoutDirection}.
1814      */
1815     public static final int LAYOUT_DIRECTION_INHERIT = 2;
1816 
1817     /**
1818      * Horizontal layout direction of this view is from deduced from the default language
1819      * script for the locale. Use with {@link #setLayoutDirection}.
1820      */
1821     public static final int LAYOUT_DIRECTION_LOCALE = 3;
1822 
1823     /**
1824      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1825      * @hide
1826      */
1827     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1828 
1829     /**
1830      * Mask for use with private flags indicating bits used for horizontal layout direction.
1831      * @hide
1832      */
1833     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1834 
1835     /**
1836      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1837      * right-to-left direction.
1838      * @hide
1839      */
1840     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1841 
1842     /**
1843      * Indicates whether the view horizontal layout direction has been resolved.
1844      * @hide
1845      */
1846     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1847 
1848     /**
1849      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1850      * @hide
1851      */
1852     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1853             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1854 
1855     /*
1856      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1857      * flag value.
1858      * @hide
1859      */
1860     private static final int[] LAYOUT_DIRECTION_FLAGS = {
1861             LAYOUT_DIRECTION_LTR,
1862             LAYOUT_DIRECTION_RTL,
1863             LAYOUT_DIRECTION_INHERIT,
1864             LAYOUT_DIRECTION_LOCALE
1865     };
1866 
1867     /**
1868      * Default horizontal layout direction.
1869      */
1870     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1871 
1872     /**
1873      * Indicates that the view is tracking some sort of transient state
1874      * that the app should not need to be aware of, but that the framework
1875      * should take special care to preserve.
1876      *
1877      * @hide
1878      */
1879     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x1 << 22;
1880 
1881     /**
1882      * Text direction is inherited thru {@link ViewGroup}
1883      */
1884     public static final int TEXT_DIRECTION_INHERIT = 0;
1885 
1886     /**
1887      * Text direction is using "first strong algorithm". The first strong directional character
1888      * determines the paragraph direction. If there is no strong directional character, the
1889      * paragraph direction is the view's resolved layout direction.
1890      */
1891     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1892 
1893     /**
1894      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1895      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1896      * If there are neither, the paragraph direction is the view's resolved layout direction.
1897      */
1898     public static final int TEXT_DIRECTION_ANY_RTL = 2;
1899 
1900     /**
1901      * Text direction is forced to LTR.
1902      */
1903     public static final int TEXT_DIRECTION_LTR = 3;
1904 
1905     /**
1906      * Text direction is forced to RTL.
1907      */
1908     public static final int TEXT_DIRECTION_RTL = 4;
1909 
1910     /**
1911      * Text direction is coming from the system Locale.
1912      */
1913     public static final int TEXT_DIRECTION_LOCALE = 5;
1914 
1915     /**
1916      * Default text direction is inherited
1917      */
1918     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
1919 
1920     /**
1921      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
1922      * @hide
1923      */
1924     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
1925 
1926     /**
1927      * Mask for use with private flags indicating bits used for text direction.
1928      * @hide
1929      */
1930     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
1931             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
1932 
1933     /**
1934      * Array of text direction flags for mapping attribute "textDirection" to correct
1935      * flag value.
1936      * @hide
1937      */
1938     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
1939             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1940             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1941             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1942             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1943             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1944             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
1945     };
1946 
1947     /**
1948      * Indicates whether the view text direction has been resolved.
1949      * @hide
1950      */
1951     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
1952             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
1953 
1954     /**
1955      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1956      * @hide
1957      */
1958     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
1959 
1960     /**
1961      * Mask for use with private flags indicating bits used for resolved text direction.
1962      * @hide
1963      */
1964     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
1965             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
1966 
1967     /**
1968      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
1969      * @hide
1970      */
1971     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
1972             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
1973 
1974     /*
1975      * Default text alignment. The text alignment of this View is inherited from its parent.
1976      * Use with {@link #setTextAlignment(int)}
1977      */
1978     public static final int TEXT_ALIGNMENT_INHERIT = 0;
1979 
1980     /**
1981      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
1982      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
1983      *
1984      * Use with {@link #setTextAlignment(int)}
1985      */
1986     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
1987 
1988     /**
1989      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
1990      *
1991      * Use with {@link #setTextAlignment(int)}
1992      */
1993     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
1994 
1995     /**
1996      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
1997      *
1998      * Use with {@link #setTextAlignment(int)}
1999      */
2000     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2001 
2002     /**
2003      * Center the paragraph, e.g. ALIGN_CENTER.
2004      *
2005      * Use with {@link #setTextAlignment(int)}
2006      */
2007     public static final int TEXT_ALIGNMENT_CENTER = 4;
2008 
2009     /**
2010      * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2011      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2012      *
2013      * Use with {@link #setTextAlignment(int)}
2014      */
2015     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2016 
2017     /**
2018      * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2019      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2020      *
2021      * Use with {@link #setTextAlignment(int)}
2022      */
2023     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2024 
2025     /**
2026      * Default text alignment is inherited
2027      */
2028     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2029 
2030     /**
2031       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2032       * @hide
2033       */
2034     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2035 
2036     /**
2037       * Mask for use with private flags indicating bits used for text alignment.
2038       * @hide
2039       */
2040     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2041 
2042     /**
2043      * Array of text direction flags for mapping attribute "textAlignment" to correct
2044      * flag value.
2045      * @hide
2046      */
2047     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2048             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2049             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2050             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2051             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2052             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2053             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2054             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2055     };
2056 
2057     /**
2058      * Indicates whether the view text alignment has been resolved.
2059      * @hide
2060      */
2061     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2062 
2063     /**
2064      * Bit shift to get the resolved text alignment.
2065      * @hide
2066      */
2067     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2068 
2069     /**
2070      * Mask for use with private flags indicating bits used for text alignment.
2071      * @hide
2072      */
2073     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2074             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2075 
2076     /**
2077      * Indicates whether if the view text alignment has been resolved to gravity
2078      */
2079     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2080             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2081 
2082     // Accessiblity constants for mPrivateFlags2
2083 
2084     /**
2085      * Shift for the bits in {@link #mPrivateFlags2} related to the
2086      * "importantForAccessibility" attribute.
2087      */
2088     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2089 
2090     /**
2091      * Automatically determine whether a view is important for accessibility.
2092      */
2093     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2094 
2095     /**
2096      * The view is important for accessibility.
2097      */
2098     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2099 
2100     /**
2101      * The view is not important for accessibility.
2102      */
2103     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2104 
2105     /**
2106      * The default whether the view is important for accessibility.
2107      */
2108     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2109 
2110     /**
2111      * Mask for obtainig the bits which specify how to determine
2112      * whether a view is important for accessibility.
2113      */
2114     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2115         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO)
2116         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2117 
2118     /**
2119      * Flag indicating whether a view has accessibility focus.
2120      */
2121     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x00000040 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2122 
2123     /**
2124      * Flag indicating whether a view state for accessibility has changed.
2125      */
2126     static final int PFLAG2_ACCESSIBILITY_STATE_CHANGED = 0x00000080
2127             << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2128 
2129     /**
2130      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2131      * is used to check whether later changes to the view's transform should invalidate the
2132      * view to force the quickReject test to run again.
2133      */
2134     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2135 
2136     /**
2137      * Flag indicating that start/end padding has been resolved into left/right padding
2138      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2139      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2140      * during measurement. In some special cases this is required such as when an adapter-based
2141      * view measures prospective children without attaching them to a window.
2142      */
2143     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2144 
2145     /**
2146      * Flag indicating that the start/end drawables has been resolved into left/right ones.
2147      */
2148     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2149 
2150     /**
2151      * Group of bits indicating that RTL properties resolution is done.
2152      */
2153     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2154             PFLAG2_TEXT_DIRECTION_RESOLVED |
2155             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2156             PFLAG2_PADDING_RESOLVED |
2157             PFLAG2_DRAWABLE_RESOLVED;
2158 
2159     // There are a couple of flags left in mPrivateFlags2
2160 
2161     /* End of masks for mPrivateFlags2 */
2162 
2163     /* Masks for mPrivateFlags3 */
2164 
2165     /**
2166      * Flag indicating that view has a transform animation set on it. This is used to track whether
2167      * an animation is cleared between successive frames, in order to tell the associated
2168      * DisplayList to clear its animation matrix.
2169      */
2170     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2171 
2172     /**
2173      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2174      * animation is cleared between successive frames, in order to tell the associated
2175      * DisplayList to restore its alpha value.
2176      */
2177     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2178 
2179 
2180     /* End of masks for mPrivateFlags3 */
2181 
2182     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2183 
2184     /**
2185      * Always allow a user to over-scroll this view, provided it is a
2186      * view that can scroll.
2187      *
2188      * @see #getOverScrollMode()
2189      * @see #setOverScrollMode(int)
2190      */
2191     public static final int OVER_SCROLL_ALWAYS = 0;
2192 
2193     /**
2194      * Allow a user to over-scroll this view only if the content is large
2195      * enough to meaningfully scroll, provided it is a view that can scroll.
2196      *
2197      * @see #getOverScrollMode()
2198      * @see #setOverScrollMode(int)
2199      */
2200     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2201 
2202     /**
2203      * Never allow a user to over-scroll this view.
2204      *
2205      * @see #getOverScrollMode()
2206      * @see #setOverScrollMode(int)
2207      */
2208     public static final int OVER_SCROLL_NEVER = 2;
2209 
2210     /**
2211      * Special constant for {@link #setSystemUiVisibility(int)}: View has
2212      * requested the system UI (status bar) to be visible (the default).
2213      *
2214      * @see #setSystemUiVisibility(int)
2215      */
2216     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2217 
2218     /**
2219      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2220      * system UI to enter an unobtrusive "low profile" mode.
2221      *
2222      * <p>This is for use in games, book readers, video players, or any other
2223      * "immersive" application where the usual system chrome is deemed too distracting.
2224      *
2225      * <p>In low profile mode, the status bar and/or navigation icons may dim.
2226      *
2227      * @see #setSystemUiVisibility(int)
2228      */
2229     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2230 
2231     /**
2232      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2233      * system navigation be temporarily hidden.
2234      *
2235      * <p>This is an even less obtrusive state than that called for by
2236      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2237      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2238      * those to disappear. This is useful (in conjunction with the
2239      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2240      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2241      * window flags) for displaying content using every last pixel on the display.
2242      *
2243      * <p>There is a limitation: because navigation controls are so important, the least user
2244      * interaction will cause them to reappear immediately.  When this happens, both
2245      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2246      * so that both elements reappear at the same time.
2247      *
2248      * @see #setSystemUiVisibility(int)
2249      */
2250     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2251 
2252     /**
2253      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2254      * into the normal fullscreen mode so that its content can take over the screen
2255      * while still allowing the user to interact with the application.
2256      *
2257      * <p>This has the same visual effect as
2258      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2259      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2260      * meaning that non-critical screen decorations (such as the status bar) will be
2261      * hidden while the user is in the View's window, focusing the experience on
2262      * that content.  Unlike the window flag, if you are using ActionBar in
2263      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2264      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2265      * hide the action bar.
2266      *
2267      * <p>This approach to going fullscreen is best used over the window flag when
2268      * it is a transient state -- that is, the application does this at certain
2269      * points in its user interaction where it wants to allow the user to focus
2270      * on content, but not as a continuous state.  For situations where the application
2271      * would like to simply stay full screen the entire time (such as a game that
2272      * wants to take over the screen), the
2273      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2274      * is usually a better approach.  The state set here will be removed by the system
2275      * in various situations (such as the user moving to another application) like
2276      * the other system UI states.
2277      *
2278      * <p>When using this flag, the application should provide some easy facility
2279      * for the user to go out of it.  A common example would be in an e-book
2280      * reader, where tapping on the screen brings back whatever screen and UI
2281      * decorations that had been hidden while the user was immersed in reading
2282      * the book.
2283      *
2284      * @see #setSystemUiVisibility(int)
2285      */
2286     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2287 
2288     /**
2289      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2290      * flags, we would like a stable view of the content insets given to
2291      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2292      * will always represent the worst case that the application can expect
2293      * as a continuous state.  In the stock Android UI this is the space for
2294      * the system bar, nav bar, and status bar, but not more transient elements
2295      * such as an input method.
2296      *
2297      * The stable layout your UI sees is based on the system UI modes you can
2298      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2299      * then you will get a stable layout for changes of the
2300      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2301      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2302      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2303      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2304      * with a stable layout.  (Note that you should avoid using
2305      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2306      *
2307      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2308      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2309      * then a hidden status bar will be considered a "stable" state for purposes
2310      * here.  This allows your UI to continually hide the status bar, while still
2311      * using the system UI flags to hide the action bar while still retaining
2312      * a stable layout.  Note that changing the window fullscreen flag will never
2313      * provide a stable layout for a clean transition.
2314      *
2315      * <p>If you are using ActionBar in
2316      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2317      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2318      * insets it adds to those given to the application.
2319      */
2320     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2321 
2322     /**
2323      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2324      * to be layed out as if it has requested
2325      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2326      * allows it to avoid artifacts when switching in and out of that mode, at
2327      * the expense that some of its user interface may be covered by screen
2328      * decorations when they are shown.  You can perform layout of your inner
2329      * UI elements to account for the navagation system UI through the
2330      * {@link #fitSystemWindows(Rect)} method.
2331      */
2332     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2333 
2334     /**
2335      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2336      * to be layed out as if it has requested
2337      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2338      * allows it to avoid artifacts when switching in and out of that mode, at
2339      * the expense that some of its user interface may be covered by screen
2340      * decorations when they are shown.  You can perform layout of your inner
2341      * UI elements to account for non-fullscreen system UI through the
2342      * {@link #fitSystemWindows(Rect)} method.
2343      */
2344     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2345 
2346     /**
2347      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2348      */
2349     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2350 
2351     /**
2352      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2353      */
2354     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2355 
2356     /**
2357      * @hide
2358      *
2359      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2360      * out of the public fields to keep the undefined bits out of the developer's way.
2361      *
2362      * Flag to make the status bar not expandable.  Unless you also
2363      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2364      */
2365     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2366 
2367     /**
2368      * @hide
2369      *
2370      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2371      * out of the public fields to keep the undefined bits out of the developer's way.
2372      *
2373      * Flag to hide notification icons and scrolling ticker text.
2374      */
2375     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2376 
2377     /**
2378      * @hide
2379      *
2380      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2381      * out of the public fields to keep the undefined bits out of the developer's way.
2382      *
2383      * Flag to disable incoming notification alerts.  This will not block
2384      * icons, but it will block sound, vibrating and other visual or aural notifications.
2385      */
2386     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2387 
2388     /**
2389      * @hide
2390      *
2391      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2392      * out of the public fields to keep the undefined bits out of the developer's way.
2393      *
2394      * Flag to hide only the scrolling ticker.  Note that
2395      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2396      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2397      */
2398     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2399 
2400     /**
2401      * @hide
2402      *
2403      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2404      * out of the public fields to keep the undefined bits out of the developer's way.
2405      *
2406      * Flag to hide the center system info area.
2407      */
2408     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2409 
2410     /**
2411      * @hide
2412      *
2413      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2414      * out of the public fields to keep the undefined bits out of the developer's way.
2415      *
2416      * Flag to hide only the home button.  Don't use this
2417      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2418      */
2419     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2420 
2421     /**
2422      * @hide
2423      *
2424      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2425      * out of the public fields to keep the undefined bits out of the developer's way.
2426      *
2427      * Flag to hide only the back button. Don't use this
2428      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2429      */
2430     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2431 
2432     /**
2433      * @hide
2434      *
2435      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2436      * out of the public fields to keep the undefined bits out of the developer's way.
2437      *
2438      * Flag to hide only the clock.  You might use this if your activity has
2439      * its own clock making the status bar's clock redundant.
2440      */
2441     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2442 
2443     /**
2444      * @hide
2445      *
2446      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2447      * out of the public fields to keep the undefined bits out of the developer's way.
2448      *
2449      * Flag to hide only the recent apps button. Don't use this
2450      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2451      */
2452     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2453 
2454     /**
2455      * @hide
2456      *
2457      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2458      * out of the public fields to keep the undefined bits out of the developer's way.
2459      *
2460      * Flag to disable the global search gesture. Don't use this
2461      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2462      */
2463     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2464 
2465     /**
2466      * @hide
2467      */
2468     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
2469 
2470     /**
2471      * These are the system UI flags that can be cleared by events outside
2472      * of an application.  Currently this is just the ability to tap on the
2473      * screen while hiding the navigation bar to have it return.
2474      * @hide
2475      */
2476     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2477             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2478             | SYSTEM_UI_FLAG_FULLSCREEN;
2479 
2480     /**
2481      * Flags that can impact the layout in relation to system UI.
2482      */
2483     public static final int SYSTEM_UI_LAYOUT_FLAGS =
2484             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2485             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2486 
2487     /**
2488      * Find views that render the specified text.
2489      *
2490      * @see #findViewsWithText(ArrayList, CharSequence, int)
2491      */
2492     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2493 
2494     /**
2495      * Find find views that contain the specified content description.
2496      *
2497      * @see #findViewsWithText(ArrayList, CharSequence, int)
2498      */
2499     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2500 
2501     /**
2502      * Find views that contain {@link AccessibilityNodeProvider}. Such
2503      * a View is a root of virtual view hierarchy and may contain the searched
2504      * text. If this flag is set Views with providers are automatically
2505      * added and it is a responsibility of the client to call the APIs of
2506      * the provider to determine whether the virtual tree rooted at this View
2507      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2508      * represeting the virtual views with this text.
2509      *
2510      * @see #findViewsWithText(ArrayList, CharSequence, int)
2511      *
2512      * @hide
2513      */
2514     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2515 
2516     /**
2517      * The undefined cursor position.
2518      */
2519     private static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2520 
2521     /**
2522      * Indicates that the screen has changed state and is now off.
2523      *
2524      * @see #onScreenStateChanged(int)
2525      */
2526     public static final int SCREEN_STATE_OFF = 0x0;
2527 
2528     /**
2529      * Indicates that the screen has changed state and is now on.
2530      *
2531      * @see #onScreenStateChanged(int)
2532      */
2533     public static final int SCREEN_STATE_ON = 0x1;
2534 
2535     /**
2536      * Controls the over-scroll mode for this view.
2537      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2538      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2539      * and {@link #OVER_SCROLL_NEVER}.
2540      */
2541     private int mOverScrollMode;
2542 
2543     /**
2544      * The parent this view is attached to.
2545      * {@hide}
2546      *
2547      * @see #getParent()
2548      */
2549     protected ViewParent mParent;
2550 
2551     /**
2552      * {@hide}
2553      */
2554     AttachInfo mAttachInfo;
2555 
2556     /**
2557      * {@hide}
2558      */
2559     @ViewDebug.ExportedProperty(flagMapping = {
2560         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2561                 name = "FORCE_LAYOUT"),
2562         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2563                 name = "LAYOUT_REQUIRED"),
2564         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2565             name = "DRAWING_CACHE_INVALID", outputIf = false),
2566         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2567         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2568         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2569         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2570     })
2571     int mPrivateFlags;
2572     int mPrivateFlags2;
2573     int mPrivateFlags3;
2574 
2575     /**
2576      * This view's request for the visibility of the status bar.
2577      * @hide
2578      */
2579     @ViewDebug.ExportedProperty(flagMapping = {
2580         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2581                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2582                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2583         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2584                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2585                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2586         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2587                                 equals = SYSTEM_UI_FLAG_VISIBLE,
2588                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2589     })
2590     int mSystemUiVisibility;
2591 
2592     /**
2593      * Reference count for transient state.
2594      * @see #setHasTransientState(boolean)
2595      */
2596     int mTransientStateCount = 0;
2597 
2598     /**
2599      * Count of how many windows this view has been attached to.
2600      */
2601     int mWindowAttachCount;
2602 
2603     /**
2604      * The layout parameters associated with this view and used by the parent
2605      * {@link android.view.ViewGroup} to determine how this view should be
2606      * laid out.
2607      * {@hide}
2608      */
2609     protected ViewGroup.LayoutParams mLayoutParams;
2610 
2611     /**
2612      * The view flags hold various views states.
2613      * {@hide}
2614      */
2615     @ViewDebug.ExportedProperty
2616     int mViewFlags;
2617 
2618     static class TransformationInfo {
2619         /**
2620          * The transform matrix for the View. This transform is calculated internally
2621          * based on the rotation, scaleX, and scaleY properties. The identity matrix
2622          * is used by default. Do *not* use this variable directly; instead call
2623          * getMatrix(), which will automatically recalculate the matrix if necessary
2624          * to get the correct matrix based on the latest rotation and scale properties.
2625          */
2626         private final Matrix mMatrix = new Matrix();
2627 
2628         /**
2629          * The transform matrix for the View. This transform is calculated internally
2630          * based on the rotation, scaleX, and scaleY properties. The identity matrix
2631          * is used by default. Do *not* use this variable directly; instead call
2632          * getInverseMatrix(), which will automatically recalculate the matrix if necessary
2633          * to get the correct matrix based on the latest rotation and scale properties.
2634          */
2635         private Matrix mInverseMatrix;
2636 
2637         /**
2638          * An internal variable that tracks whether we need to recalculate the
2639          * transform matrix, based on whether the rotation or scaleX/Y properties
2640          * have changed since the matrix was last calculated.
2641          */
2642         boolean mMatrixDirty = false;
2643 
2644         /**
2645          * An internal variable that tracks whether we need to recalculate the
2646          * transform matrix, based on whether the rotation or scaleX/Y properties
2647          * have changed since the matrix was last calculated.
2648          */
2649         private boolean mInverseMatrixDirty = true;
2650 
2651         /**
2652          * A variable that tracks whether we need to recalculate the
2653          * transform matrix, based on whether the rotation or scaleX/Y properties
2654          * have changed since the matrix was last calculated. This variable
2655          * is only valid after a call to updateMatrix() or to a function that
2656          * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
2657          */
2658         private boolean mMatrixIsIdentity = true;
2659 
2660         /**
2661          * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
2662          */
2663         private Camera mCamera = null;
2664 
2665         /**
2666          * This matrix is used when computing the matrix for 3D rotations.
2667          */
2668         private Matrix matrix3D = null;
2669 
2670         /**
2671          * These prev values are used to recalculate a centered pivot point when necessary. The
2672          * pivot point is only used in matrix operations (when rotation, scale, or translation are
2673          * set), so thes values are only used then as well.
2674          */
2675         private int mPrevWidth = -1;
2676         private int mPrevHeight = -1;
2677 
2678         /**
2679          * The degrees rotation around the vertical axis through the pivot point.
2680          */
2681         @ViewDebug.ExportedProperty
2682         float mRotationY = 0f;
2683 
2684         /**
2685          * The degrees rotation around the horizontal axis through the pivot point.
2686          */
2687         @ViewDebug.ExportedProperty
2688         float mRotationX = 0f;
2689 
2690         /**
2691          * The degrees rotation around the pivot point.
2692          */
2693         @ViewDebug.ExportedProperty
2694         float mRotation = 0f;
2695 
2696         /**
2697          * The amount of translation of the object away from its left property (post-layout).
2698          */
2699         @ViewDebug.ExportedProperty
2700         float mTranslationX = 0f;
2701 
2702         /**
2703          * The amount of translation of the object away from its top property (post-layout).
2704          */
2705         @ViewDebug.ExportedProperty
2706         float mTranslationY = 0f;
2707 
2708         /**
2709          * The amount of scale in the x direction around the pivot point. A
2710          * value of 1 means no scaling is applied.
2711          */
2712         @ViewDebug.ExportedProperty
2713         float mScaleX = 1f;
2714 
2715         /**
2716          * The amount of scale in the y direction around the pivot point. A
2717          * value of 1 means no scaling is applied.
2718          */
2719         @ViewDebug.ExportedProperty
2720         float mScaleY = 1f;
2721 
2722         /**
2723          * The x location of the point around which the view is rotated and scaled.
2724          */
2725         @ViewDebug.ExportedProperty
2726         float mPivotX = 0f;
2727 
2728         /**
2729          * The y location of the point around which the view is rotated and scaled.
2730          */
2731         @ViewDebug.ExportedProperty
2732         float mPivotY = 0f;
2733 
2734         /**
2735          * The opacity of the View. This is a value from 0 to 1, where 0 means
2736          * completely transparent and 1 means completely opaque.
2737          */
2738         @ViewDebug.ExportedProperty
2739         float mAlpha = 1f;
2740     }
2741 
2742     TransformationInfo mTransformationInfo;
2743 
2744     private boolean mLastIsOpaque;
2745 
2746     /**
2747      * Convenience value to check for float values that are close enough to zero to be considered
2748      * zero.
2749      */
2750     private static final float NONZERO_EPSILON = .001f;
2751 
2752     /**
2753      * The distance in pixels from the left edge of this view's parent
2754      * to the left edge of this view.
2755      * {@hide}
2756      */
2757     @ViewDebug.ExportedProperty(category = "layout")
2758     protected int mLeft;
2759     /**
2760      * The distance in pixels from the left edge of this view's parent
2761      * to the right edge of this view.
2762      * {@hide}
2763      */
2764     @ViewDebug.ExportedProperty(category = "layout")
2765     protected int mRight;
2766     /**
2767      * The distance in pixels from the top edge of this view's parent
2768      * to the top edge of this view.
2769      * {@hide}
2770      */
2771     @ViewDebug.ExportedProperty(category = "layout")
2772     protected int mTop;
2773     /**
2774      * The distance in pixels from the top edge of this view's parent
2775      * to the bottom edge of this view.
2776      * {@hide}
2777      */
2778     @ViewDebug.ExportedProperty(category = "layout")
2779     protected int mBottom;
2780 
2781     /**
2782      * The offset, in pixels, by which the content of this view is scrolled
2783      * horizontally.
2784      * {@hide}
2785      */
2786     @ViewDebug.ExportedProperty(category = "scrolling")
2787     protected int mScrollX;
2788     /**
2789      * The offset, in pixels, by which the content of this view is scrolled
2790      * vertically.
2791      * {@hide}
2792      */
2793     @ViewDebug.ExportedProperty(category = "scrolling")
2794     protected int mScrollY;
2795 
2796     /**
2797      * The left padding in pixels, that is the distance in pixels between the
2798      * left edge of this view and the left edge of its content.
2799      * {@hide}
2800      */
2801     @ViewDebug.ExportedProperty(category = "padding")
2802     protected int mPaddingLeft = 0;
2803     /**
2804      * The right padding in pixels, that is the distance in pixels between the
2805      * right edge of this view and the right edge of its content.
2806      * {@hide}
2807      */
2808     @ViewDebug.ExportedProperty(category = "padding")
2809     protected int mPaddingRight = 0;
2810     /**
2811      * The top padding in pixels, that is the distance in pixels between the
2812      * top edge of this view and the top edge of its content.
2813      * {@hide}
2814      */
2815     @ViewDebug.ExportedProperty(category = "padding")
2816     protected int mPaddingTop;
2817     /**
2818      * The bottom padding in pixels, that is the distance in pixels between the
2819      * bottom edge of this view and the bottom edge of its content.
2820      * {@hide}
2821      */
2822     @ViewDebug.ExportedProperty(category = "padding")
2823     protected int mPaddingBottom;
2824 
2825     /**
2826      * The layout insets in pixels, that is the distance in pixels between the
2827      * visible edges of this view its bounds.
2828      */
2829     private Insets mLayoutInsets;
2830 
2831     /**
2832      * Briefly describes the view and is primarily used for accessibility support.
2833      */
2834     private CharSequence mContentDescription;
2835 
2836     /**
2837      * Specifies the id of a view for which this view serves as a label for
2838      * accessibility purposes.
2839      */
2840     private int mLabelForId = View.NO_ID;
2841 
2842     /**
2843      * Predicate for matching labeled view id with its label for
2844      * accessibility purposes.
2845      */
2846     private MatchLabelForPredicate mMatchLabelForPredicate;
2847 
2848     /**
2849      * Predicate for matching a view by its id.
2850      */
2851     private MatchIdPredicate mMatchIdPredicate;
2852 
2853     /**
2854      * Cache the paddingRight set by the user to append to the scrollbar's size.
2855      *
2856      * @hide
2857      */
2858     @ViewDebug.ExportedProperty(category = "padding")
2859     protected int mUserPaddingRight;
2860 
2861     /**
2862      * Cache the paddingBottom set by the user to append to the scrollbar's size.
2863      *
2864      * @hide
2865      */
2866     @ViewDebug.ExportedProperty(category = "padding")
2867     protected int mUserPaddingBottom;
2868 
2869     /**
2870      * Cache the paddingLeft set by the user to append to the scrollbar's size.
2871      *
2872      * @hide
2873      */
2874     @ViewDebug.ExportedProperty(category = "padding")
2875     protected int mUserPaddingLeft;
2876 
2877     /**
2878      * Cache the paddingStart set by the user to append to the scrollbar's size.
2879      *
2880      */
2881     @ViewDebug.ExportedProperty(category = "padding")
2882     int mUserPaddingStart;
2883 
2884     /**
2885      * Cache the paddingEnd set by the user to append to the scrollbar's size.
2886      *
2887      */
2888     @ViewDebug.ExportedProperty(category = "padding")
2889     int mUserPaddingEnd;
2890 
2891     /**
2892      * Cache initial left padding.
2893      *
2894      * @hide
2895      */
2896     int mUserPaddingLeftInitial = 0;
2897 
2898     /**
2899      * Cache initial right padding.
2900      *
2901      * @hide
2902      */
2903     int mUserPaddingRightInitial = 0;
2904 
2905     /**
2906      * Default undefined padding
2907      */
2908     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
2909 
2910     /**
2911      * @hide
2912      */
2913     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
2914     /**
2915      * @hide
2916      */
2917     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
2918 
2919     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
2920     private Drawable mBackground;
2921 
2922     private int mBackgroundResource;
2923     private boolean mBackgroundSizeChanged;
2924 
2925     static class ListenerInfo {
2926         /**
2927          * Listener used to dispatch focus change events.
2928          * This field should be made private, so it is hidden from the SDK.
2929          * {@hide}
2930          */
2931         protected OnFocusChangeListener mOnFocusChangeListener;
2932 
2933         /**
2934          * Listeners for layout change events.
2935          */
2936         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
2937 
2938         /**
2939          * Listeners for attach events.
2940          */
2941         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
2942 
2943         /**
2944          * Listener used to dispatch click events.
2945          * This field should be made private, so it is hidden from the SDK.
2946          * {@hide}
2947          */
2948         public OnClickListener mOnClickListener;
2949 
2950         /**
2951          * Listener used to dispatch long click events.
2952          * This field should be made private, so it is hidden from the SDK.
2953          * {@hide}
2954          */
2955         protected OnLongClickListener mOnLongClickListener;
2956 
2957         /**
2958          * Listener used to build the context menu.
2959          * This field should be made private, so it is hidden from the SDK.
2960          * {@hide}
2961          */
2962         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
2963 
2964         private OnKeyListener mOnKeyListener;
2965 
2966         private OnTouchListener mOnTouchListener;
2967 
2968         private OnHoverListener mOnHoverListener;
2969 
2970         private OnGenericMotionListener mOnGenericMotionListener;
2971 
2972         private OnDragListener mOnDragListener;
2973 
2974         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
2975     }
2976 
2977     ListenerInfo mListenerInfo;
2978 
2979     /**
2980      * The application environment this view lives in.
2981      * This field should be made private, so it is hidden from the SDK.
2982      * {@hide}
2983      */
2984     protected Context mContext;
2985 
2986     private final Resources mResources;
2987 
2988     private ScrollabilityCache mScrollCache;
2989 
2990     private int[] mDrawableState = null;
2991 
2992     /**
2993      * Set to true when drawing cache is enabled and cannot be created.
2994      *
2995      * @hide
2996      */
2997     public boolean mCachingFailed;
2998 
2999     private Bitmap mDrawingCache;
3000     private Bitmap mUnscaledDrawingCache;
3001     private HardwareLayer mHardwareLayer;
3002     DisplayList mDisplayList;
3003 
3004     /**
3005      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3006      * the user may specify which view to go to next.
3007      */
3008     private int mNextFocusLeftId = View.NO_ID;
3009 
3010     /**
3011      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3012      * the user may specify which view to go to next.
3013      */
3014     private int mNextFocusRightId = View.NO_ID;
3015 
3016     /**
3017      * When this view has focus and the next focus is {@link #FOCUS_UP},
3018      * the user may specify which view to go to next.
3019      */
3020     private int mNextFocusUpId = View.NO_ID;
3021 
3022     /**
3023      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3024      * the user may specify which view to go to next.
3025      */
3026     private int mNextFocusDownId = View.NO_ID;
3027 
3028     /**
3029      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3030      * the user may specify which view to go to next.
3031      */
3032     int mNextFocusForwardId = View.NO_ID;
3033 
3034     private CheckForLongPress mPendingCheckForLongPress;
3035     private CheckForTap mPendingCheckForTap = null;
3036     private PerformClick mPerformClick;
3037     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3038 
3039     private UnsetPressedState mUnsetPressedState;
3040 
3041     /**
3042      * Whether the long press's action has been invoked.  The tap's action is invoked on the
3043      * up event while a long press is invoked as soon as the long press duration is reached, so
3044      * a long press could be performed before the tap is checked, in which case the tap's action
3045      * should not be invoked.
3046      */
3047     private boolean mHasPerformedLongPress;
3048 
3049     /**
3050      * The minimum height of the view. We'll try our best to have the height
3051      * of this view to at least this amount.
3052      */
3053     @ViewDebug.ExportedProperty(category = "measurement")
3054     private int mMinHeight;
3055 
3056     /**
3057      * The minimum width of the view. We'll try our best to have the width
3058      * of this view to at least this amount.
3059      */
3060     @ViewDebug.ExportedProperty(category = "measurement")
3061     private int mMinWidth;
3062 
3063     /**
3064      * The delegate to handle touch events that are physically in this view
3065      * but should be handled by another view.
3066      */
3067     private TouchDelegate mTouchDelegate = null;
3068 
3069     /**
3070      * Solid color to use as a background when creating the drawing cache. Enables
3071      * the cache to use 16 bit bitmaps instead of 32 bit.
3072      */
3073     private int mDrawingCacheBackgroundColor = 0;
3074 
3075     /**
3076      * Special tree observer used when mAttachInfo is null.
3077      */
3078     private ViewTreeObserver mFloatingTreeObserver;
3079 
3080     /**
3081      * Cache the touch slop from the context that created the view.
3082      */
3083     private int mTouchSlop;
3084 
3085     /**
3086      * Object that handles automatic animation of view properties.
3087      */
3088     private ViewPropertyAnimator mAnimator = null;
3089 
3090     /**
3091      * Flag indicating that a drag can cross window boundaries.  When
3092      * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3093      * with this flag set, all visible applications will be able to participate
3094      * in the drag operation and receive the dragged content.
3095      *
3096      * @hide
3097      */
3098     public static final int DRAG_FLAG_GLOBAL = 1;
3099 
3100     /**
3101      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3102      */
3103     private float mVerticalScrollFactor;
3104 
3105     /**
3106      * Position of the vertical scroll bar.
3107      */
3108     private int mVerticalScrollbarPosition;
3109 
3110     /**
3111      * Position the scroll bar at the default position as determined by the system.
3112      */
3113     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3114 
3115     /**
3116      * Position the scroll bar along the left edge.
3117      */
3118     public static final int SCROLLBAR_POSITION_LEFT = 1;
3119 
3120     /**
3121      * Position the scroll bar along the right edge.
3122      */
3123     public static final int SCROLLBAR_POSITION_RIGHT = 2;
3124 
3125     /**
3126      * Indicates that the view does not have a layer.
3127      *
3128      * @see #getLayerType()
3129      * @see #setLayerType(int, android.graphics.Paint)
3130      * @see #LAYER_TYPE_SOFTWARE
3131      * @see #LAYER_TYPE_HARDWARE
3132      */
3133     public static final int LAYER_TYPE_NONE = 0;
3134 
3135     /**
3136      * <p>Indicates that the view has a software layer. A software layer is backed
3137      * by a bitmap and causes the view to be rendered using Android's software
3138      * rendering pipeline, even if hardware acceleration is enabled.</p>
3139      *
3140      * <p>Software layers have various usages:</p>
3141      * <p>When the application is not using hardware acceleration, a software layer
3142      * is useful to apply a specific color filter and/or blending mode and/or
3143      * translucency to a view and all its children.</p>
3144      * <p>When the application is using hardware acceleration, a software layer
3145      * is useful to render drawing primitives not supported by the hardware
3146      * accelerated pipeline. It can also be used to cache a complex view tree
3147      * into a texture and reduce the complexity of drawing operations. For instance,
3148      * when animating a complex view tree with a translation, a software layer can
3149      * be used to render the view tree only once.</p>
3150      * <p>Software layers should be avoided when the affected view tree updates
3151      * often. Every update will require to re-render the software layer, which can
3152      * potentially be slow (particularly when hardware acceleration is turned on
3153      * since the layer will have to be uploaded into a hardware texture after every
3154      * update.)</p>
3155      *
3156      * @see #getLayerType()
3157      * @see #setLayerType(int, android.graphics.Paint)
3158      * @see #LAYER_TYPE_NONE
3159      * @see #LAYER_TYPE_HARDWARE
3160      */
3161     public static final int LAYER_TYPE_SOFTWARE = 1;
3162 
3163     /**
3164      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3165      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3166      * OpenGL hardware) and causes the view to be rendered using Android's hardware
3167      * rendering pipeline, but only if hardware acceleration is turned on for the
3168      * view hierarchy. When hardware acceleration is turned off, hardware layers
3169      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3170      *
3171      * <p>A hardware layer is useful to apply a specific color filter and/or
3172      * blending mode and/or translucency to a view and all its children.</p>
3173      * <p>A hardware layer can be used to cache a complex view tree into a
3174      * texture and reduce the complexity of drawing operations. For instance,
3175      * when animating a complex view tree with a translation, a hardware layer can
3176      * be used to render the view tree only once.</p>
3177      * <p>A hardware layer can also be used to increase the rendering quality when
3178      * rotation transformations are applied on a view. It can also be used to
3179      * prevent potential clipping issues when applying 3D transforms on a view.</p>
3180      *
3181      * @see #getLayerType()
3182      * @see #setLayerType(int, android.graphics.Paint)
3183      * @see #LAYER_TYPE_NONE
3184      * @see #LAYER_TYPE_SOFTWARE
3185      */
3186     public static final int LAYER_TYPE_HARDWARE = 2;
3187 
3188     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3189             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3190             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3191             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3192     })
3193     int mLayerType = LAYER_TYPE_NONE;
3194     Paint mLayerPaint;
3195     Rect mLocalDirtyRect;
3196 
3197     /**
3198      * Set to true when the view is sending hover accessibility events because it
3199      * is the innermost hovered view.
3200      */
3201     private boolean mSendingHoverAccessibilityEvents;
3202 
3203     /**
3204      * Delegate for injecting accessibility functionality.
3205      */
3206     AccessibilityDelegate mAccessibilityDelegate;
3207 
3208     /**
3209      * Consistency verifier for debugging purposes.
3210      * @hide
3211      */
3212     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3213             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3214                     new InputEventConsistencyVerifier(this, 0) : null;
3215 
3216     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3217 
3218     /**
3219      * Simple constructor to use when creating a view from code.
3220      *
3221      * @param context The Context the view is running in, through which it can
3222      *        access the current theme, resources, etc.
3223      */
View(Context context)3224     public View(Context context) {
3225         mContext = context;
3226         mResources = context != null ? context.getResources() : null;
3227         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3228         // Set some flags defaults
3229         mPrivateFlags2 =
3230                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3231                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3232                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3233                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3234                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3235                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3236         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3237         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3238         mUserPaddingStart = UNDEFINED_PADDING;
3239         mUserPaddingEnd = UNDEFINED_PADDING;
3240     }
3241 
3242     /**
3243      * Constructor that is called when inflating a view from XML. This is called
3244      * when a view is being constructed from an XML file, supplying attributes
3245      * that were specified in the XML file. This version uses a default style of
3246      * 0, so the only attribute values applied are those in the Context's Theme
3247      * and the given AttributeSet.
3248      *
3249      * <p>
3250      * The method onFinishInflate() will be called after all children have been
3251      * added.
3252      *
3253      * @param context The Context the view is running in, through which it can
3254      *        access the current theme, resources, etc.
3255      * @param attrs The attributes of the XML tag that is inflating the view.
3256      * @see #View(Context, AttributeSet, int)
3257      */
View(Context context, AttributeSet attrs)3258     public View(Context context, AttributeSet attrs) {
3259         this(context, attrs, 0);
3260     }
3261 
3262     /**
3263      * Perform inflation from XML and apply a class-specific base style. This
3264      * constructor of View allows subclasses to use their own base style when
3265      * they are inflating. For example, a Button class's constructor would call
3266      * this version of the super class constructor and supply
3267      * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
3268      * the theme's button style to modify all of the base view attributes (in
3269      * particular its background) as well as the Button class's attributes.
3270      *
3271      * @param context The Context the view is running in, through which it can
3272      *        access the current theme, resources, etc.
3273      * @param attrs The attributes of the XML tag that is inflating the view.
3274      * @param defStyle The default style to apply to this view. If 0, no style
3275      *        will be applied (beyond what is included in the theme). This may
3276      *        either be an attribute resource, whose value will be retrieved
3277      *        from the current theme, or an explicit style resource.
3278      * @see #View(Context, AttributeSet)
3279      */
View(Context context, AttributeSet attrs, int defStyle)3280     public View(Context context, AttributeSet attrs, int defStyle) {
3281         this(context);
3282 
3283         TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
3284                 defStyle, 0);
3285 
3286         Drawable background = null;
3287 
3288         int leftPadding = -1;
3289         int topPadding = -1;
3290         int rightPadding = -1;
3291         int bottomPadding = -1;
3292         int startPadding = UNDEFINED_PADDING;
3293         int endPadding = UNDEFINED_PADDING;
3294 
3295         int padding = -1;
3296 
3297         int viewFlagValues = 0;
3298         int viewFlagMasks = 0;
3299 
3300         boolean setScrollContainer = false;
3301 
3302         int x = 0;
3303         int y = 0;
3304 
3305         float tx = 0;
3306         float ty = 0;
3307         float rotation = 0;
3308         float rotationX = 0;
3309         float rotationY = 0;
3310         float sx = 1f;
3311         float sy = 1f;
3312         boolean transformSet = false;
3313 
3314         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3315         int overScrollMode = mOverScrollMode;
3316         boolean initializeScrollbars = false;
3317 
3318         boolean leftPaddingDefined = false;
3319         boolean rightPaddingDefined = false;
3320         boolean startPaddingDefined = false;
3321         boolean endPaddingDefined = false;
3322 
3323         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3324 
3325         final int N = a.getIndexCount();
3326         for (int i = 0; i < N; i++) {
3327             int attr = a.getIndex(i);
3328             switch (attr) {
3329                 case com.android.internal.R.styleable.View_background:
3330                     background = a.getDrawable(attr);
3331                     break;
3332                 case com.android.internal.R.styleable.View_padding:
3333                     padding = a.getDimensionPixelSize(attr, -1);
3334                     mUserPaddingLeftInitial = padding;
3335                     mUserPaddingRightInitial = padding;
3336                     leftPaddingDefined = true;
3337                     rightPaddingDefined = true;
3338                     break;
3339                  case com.android.internal.R.styleable.View_paddingLeft:
3340                     leftPadding = a.getDimensionPixelSize(attr, -1);
3341                     mUserPaddingLeftInitial = leftPadding;
3342                     leftPaddingDefined = true;
3343                     break;
3344                 case com.android.internal.R.styleable.View_paddingTop:
3345                     topPadding = a.getDimensionPixelSize(attr, -1);
3346                     break;
3347                 case com.android.internal.R.styleable.View_paddingRight:
3348                     rightPadding = a.getDimensionPixelSize(attr, -1);
3349                     mUserPaddingRightInitial = rightPadding;
3350                     rightPaddingDefined = true;
3351                     break;
3352                 case com.android.internal.R.styleable.View_paddingBottom:
3353                     bottomPadding = a.getDimensionPixelSize(attr, -1);
3354                     break;
3355                 case com.android.internal.R.styleable.View_paddingStart:
3356                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3357                     startPaddingDefined = true;
3358                     break;
3359                 case com.android.internal.R.styleable.View_paddingEnd:
3360                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3361                     endPaddingDefined = true;
3362                     break;
3363                 case com.android.internal.R.styleable.View_scrollX:
3364                     x = a.getDimensionPixelOffset(attr, 0);
3365                     break;
3366                 case com.android.internal.R.styleable.View_scrollY:
3367                     y = a.getDimensionPixelOffset(attr, 0);
3368                     break;
3369                 case com.android.internal.R.styleable.View_alpha:
3370                     setAlpha(a.getFloat(attr, 1f));
3371                     break;
3372                 case com.android.internal.R.styleable.View_transformPivotX:
3373                     setPivotX(a.getDimensionPixelOffset(attr, 0));
3374                     break;
3375                 case com.android.internal.R.styleable.View_transformPivotY:
3376                     setPivotY(a.getDimensionPixelOffset(attr, 0));
3377                     break;
3378                 case com.android.internal.R.styleable.View_translationX:
3379                     tx = a.getDimensionPixelOffset(attr, 0);
3380                     transformSet = true;
3381                     break;
3382                 case com.android.internal.R.styleable.View_translationY:
3383                     ty = a.getDimensionPixelOffset(attr, 0);
3384                     transformSet = true;
3385                     break;
3386                 case com.android.internal.R.styleable.View_rotation:
3387                     rotation = a.getFloat(attr, 0);
3388                     transformSet = true;
3389                     break;
3390                 case com.android.internal.R.styleable.View_rotationX:
3391                     rotationX = a.getFloat(attr, 0);
3392                     transformSet = true;
3393                     break;
3394                 case com.android.internal.R.styleable.View_rotationY:
3395                     rotationY = a.getFloat(attr, 0);
3396                     transformSet = true;
3397                     break;
3398                 case com.android.internal.R.styleable.View_scaleX:
3399                     sx = a.getFloat(attr, 1f);
3400                     transformSet = true;
3401                     break;
3402                 case com.android.internal.R.styleable.View_scaleY:
3403                     sy = a.getFloat(attr, 1f);
3404                     transformSet = true;
3405                     break;
3406                 case com.android.internal.R.styleable.View_id:
3407                     mID = a.getResourceId(attr, NO_ID);
3408                     break;
3409                 case com.android.internal.R.styleable.View_tag:
3410                     mTag = a.getText(attr);
3411                     break;
3412                 case com.android.internal.R.styleable.View_fitsSystemWindows:
3413                     if (a.getBoolean(attr, false)) {
3414                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
3415                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3416                     }
3417                     break;
3418                 case com.android.internal.R.styleable.View_focusable:
3419                     if (a.getBoolean(attr, false)) {
3420                         viewFlagValues |= FOCUSABLE;
3421                         viewFlagMasks |= FOCUSABLE_MASK;
3422                     }
3423                     break;
3424                 case com.android.internal.R.styleable.View_focusableInTouchMode:
3425                     if (a.getBoolean(attr, false)) {
3426                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3427                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3428                     }
3429                     break;
3430                 case com.android.internal.R.styleable.View_clickable:
3431                     if (a.getBoolean(attr, false)) {
3432                         viewFlagValues |= CLICKABLE;
3433                         viewFlagMasks |= CLICKABLE;
3434                     }
3435                     break;
3436                 case com.android.internal.R.styleable.View_longClickable:
3437                     if (a.getBoolean(attr, false)) {
3438                         viewFlagValues |= LONG_CLICKABLE;
3439                         viewFlagMasks |= LONG_CLICKABLE;
3440                     }
3441                     break;
3442                 case com.android.internal.R.styleable.View_saveEnabled:
3443                     if (!a.getBoolean(attr, true)) {
3444                         viewFlagValues |= SAVE_DISABLED;
3445                         viewFlagMasks |= SAVE_DISABLED_MASK;
3446                     }
3447                     break;
3448                 case com.android.internal.R.styleable.View_duplicateParentState:
3449                     if (a.getBoolean(attr, false)) {
3450                         viewFlagValues |= DUPLICATE_PARENT_STATE;
3451                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
3452                     }
3453                     break;
3454                 case com.android.internal.R.styleable.View_visibility:
3455                     final int visibility = a.getInt(attr, 0);
3456                     if (visibility != 0) {
3457                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
3458                         viewFlagMasks |= VISIBILITY_MASK;
3459                     }
3460                     break;
3461                 case com.android.internal.R.styleable.View_layoutDirection:
3462                     // Clear any layout direction flags (included resolved bits) already set
3463                     mPrivateFlags2 &=
3464                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3465                     // Set the layout direction flags depending on the value of the attribute
3466                     final int layoutDirection = a.getInt(attr, -1);
3467                     final int value = (layoutDirection != -1) ?
3468                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3469                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3470                     break;
3471                 case com.android.internal.R.styleable.View_drawingCacheQuality:
3472                     final int cacheQuality = a.getInt(attr, 0);
3473                     if (cacheQuality != 0) {
3474                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3475                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3476                     }
3477                     break;
3478                 case com.android.internal.R.styleable.View_contentDescription:
3479                     setContentDescription(a.getString(attr));
3480                     break;
3481                 case com.android.internal.R.styleable.View_labelFor:
3482                     setLabelFor(a.getResourceId(attr, NO_ID));
3483                     break;
3484                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
3485                     if (!a.getBoolean(attr, true)) {
3486                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3487                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3488                     }
3489                     break;
3490                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3491                     if (!a.getBoolean(attr, true)) {
3492                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3493                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3494                     }
3495                     break;
3496                 case R.styleable.View_scrollbars:
3497                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3498                     if (scrollbars != SCROLLBARS_NONE) {
3499                         viewFlagValues |= scrollbars;
3500                         viewFlagMasks |= SCROLLBARS_MASK;
3501                         initializeScrollbars = true;
3502                     }
3503                     break;
3504                 //noinspection deprecation
3505                 case R.styleable.View_fadingEdge:
3506                     if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3507                         // Ignore the attribute starting with ICS
3508                         break;
3509                     }
3510                     // With builds < ICS, fall through and apply fading edges
3511                 case R.styleable.View_requiresFadingEdge:
3512                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3513                     if (fadingEdge != FADING_EDGE_NONE) {
3514                         viewFlagValues |= fadingEdge;
3515                         viewFlagMasks |= FADING_EDGE_MASK;
3516                         initializeFadingEdge(a);
3517                     }
3518                     break;
3519                 case R.styleable.View_scrollbarStyle:
3520                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3521                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3522                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3523                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3524                     }
3525                     break;
3526                 case R.styleable.View_isScrollContainer:
3527                     setScrollContainer = true;
3528                     if (a.getBoolean(attr, false)) {
3529                         setScrollContainer(true);
3530                     }
3531                     break;
3532                 case com.android.internal.R.styleable.View_keepScreenOn:
3533                     if (a.getBoolean(attr, false)) {
3534                         viewFlagValues |= KEEP_SCREEN_ON;
3535                         viewFlagMasks |= KEEP_SCREEN_ON;
3536                     }
3537                     break;
3538                 case R.styleable.View_filterTouchesWhenObscured:
3539                     if (a.getBoolean(attr, false)) {
3540                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3541                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3542                     }
3543                     break;
3544                 case R.styleable.View_nextFocusLeft:
3545                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3546                     break;
3547                 case R.styleable.View_nextFocusRight:
3548                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3549                     break;
3550                 case R.styleable.View_nextFocusUp:
3551                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3552                     break;
3553                 case R.styleable.View_nextFocusDown:
3554                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3555                     break;
3556                 case R.styleable.View_nextFocusForward:
3557                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3558                     break;
3559                 case R.styleable.View_minWidth:
3560                     mMinWidth = a.getDimensionPixelSize(attr, 0);
3561                     break;
3562                 case R.styleable.View_minHeight:
3563                     mMinHeight = a.getDimensionPixelSize(attr, 0);
3564                     break;
3565                 case R.styleable.View_onClick:
3566                     if (context.isRestricted()) {
3567                         throw new IllegalStateException("The android:onClick attribute cannot "
3568                                 + "be used within a restricted context");
3569                     }
3570 
3571                     final String handlerName = a.getString(attr);
3572                     if (handlerName != null) {
3573                         setOnClickListener(new OnClickListener() {
3574                             private Method mHandler;
3575 
3576                             public void onClick(View v) {
3577                                 if (mHandler == null) {
3578                                     try {
3579                                         mHandler = getContext().getClass().getMethod(handlerName,
3580                                                 View.class);
3581                                     } catch (NoSuchMethodException e) {
3582                                         int id = getId();
3583                                         String idText = id == NO_ID ? "" : " with id '"
3584                                                 + getContext().getResources().getResourceEntryName(
3585                                                     id) + "'";
3586                                         throw new IllegalStateException("Could not find a method " +
3587                                                 handlerName + "(View) in the activity "
3588                                                 + getContext().getClass() + " for onClick handler"
3589                                                 + " on view " + View.this.getClass() + idText, e);
3590                                     }
3591                                 }
3592 
3593                                 try {
3594                                     mHandler.invoke(getContext(), View.this);
3595                                 } catch (IllegalAccessException e) {
3596                                     throw new IllegalStateException("Could not execute non "
3597                                             + "public method of the activity", e);
3598                                 } catch (InvocationTargetException e) {
3599                                     throw new IllegalStateException("Could not execute "
3600                                             + "method of the activity", e);
3601                                 }
3602                             }
3603                         });
3604                     }
3605                     break;
3606                 case R.styleable.View_overScrollMode:
3607                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3608                     break;
3609                 case R.styleable.View_verticalScrollbarPosition:
3610                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3611                     break;
3612                 case R.styleable.View_layerType:
3613                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3614                     break;
3615                 case R.styleable.View_textDirection:
3616                     // Clear any text direction flag already set
3617                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
3618                     // Set the text direction flags depending on the value of the attribute
3619                     final int textDirection = a.getInt(attr, -1);
3620                     if (textDirection != -1) {
3621                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
3622                     }
3623                     break;
3624                 case R.styleable.View_textAlignment:
3625                     // Clear any text alignment flag already set
3626                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
3627                     // Set the text alignment flag depending on the value of the attribute
3628                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
3629                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
3630                     break;
3631                 case R.styleable.View_importantForAccessibility:
3632                     setImportantForAccessibility(a.getInt(attr,
3633                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
3634                     break;
3635             }
3636         }
3637 
3638         setOverScrollMode(overScrollMode);
3639 
3640         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
3641         // the resolved layout direction). Those cached values will be used later during padding
3642         // resolution.
3643         mUserPaddingStart = startPadding;
3644         mUserPaddingEnd = endPadding;
3645 
3646         if (background != null) {
3647             setBackground(background);
3648         }
3649 
3650         if (padding >= 0) {
3651             leftPadding = padding;
3652             topPadding = padding;
3653             rightPadding = padding;
3654             bottomPadding = padding;
3655             mUserPaddingLeftInitial = padding;
3656             mUserPaddingRightInitial = padding;
3657         }
3658 
3659         if (isRtlCompatibilityMode()) {
3660             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
3661             // left / right padding are used if defined (meaning here nothing to do). If they are not
3662             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
3663             // start / end and resolve them as left / right (layout direction is not taken into account).
3664             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
3665             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
3666             // defined.
3667             if (!leftPaddingDefined && startPaddingDefined) {
3668                 leftPadding = startPadding;
3669             }
3670             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
3671             if (!rightPaddingDefined && endPaddingDefined) {
3672                 rightPadding = endPadding;
3673             }
3674             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
3675         } else {
3676             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
3677             // values defined. Otherwise, left /right values are used.
3678             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
3679             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
3680             // defined.
3681             if (leftPaddingDefined) {
3682                 mUserPaddingLeftInitial = leftPadding;
3683             }
3684             if (rightPaddingDefined) {
3685                 mUserPaddingRightInitial = rightPadding;
3686             }
3687         }
3688 
3689         internalSetPadding(
3690                 mUserPaddingLeftInitial,
3691                 topPadding >= 0 ? topPadding : mPaddingTop,
3692                 mUserPaddingRightInitial,
3693                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
3694 
3695         if (viewFlagMasks != 0) {
3696             setFlags(viewFlagValues, viewFlagMasks);
3697         }
3698 
3699         if (initializeScrollbars) {
3700             initializeScrollbars(a);
3701         }
3702 
3703         a.recycle();
3704 
3705         // Needs to be called after mViewFlags is set
3706         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3707             recomputePadding();
3708         }
3709 
3710         if (x != 0 || y != 0) {
3711             scrollTo(x, y);
3712         }
3713 
3714         if (transformSet) {
3715             setTranslationX(tx);
3716             setTranslationY(ty);
3717             setRotation(rotation);
3718             setRotationX(rotationX);
3719             setRotationY(rotationY);
3720             setScaleX(sx);
3721             setScaleY(sy);
3722         }
3723 
3724         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
3725             setScrollContainer(true);
3726         }
3727 
3728         computeOpaqueFlags();
3729     }
3730 
3731     /**
3732      * Non-public constructor for use in testing
3733      */
View()3734     View() {
3735         mResources = null;
3736     }
3737 
toString()3738     public String toString() {
3739         StringBuilder out = new StringBuilder(128);
3740         out.append(getClass().getName());
3741         out.append('{');
3742         out.append(Integer.toHexString(System.identityHashCode(this)));
3743         out.append(' ');
3744         switch (mViewFlags&VISIBILITY_MASK) {
3745             case VISIBLE: out.append('V'); break;
3746             case INVISIBLE: out.append('I'); break;
3747             case GONE: out.append('G'); break;
3748             default: out.append('.'); break;
3749         }
3750         out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
3751         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
3752         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
3753         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
3754         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
3755         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
3756         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
3757         out.append(' ');
3758         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
3759         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
3760         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
3761         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
3762             out.append('p');
3763         } else {
3764             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
3765         }
3766         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
3767         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
3768         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
3769         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
3770         out.append(' ');
3771         out.append(mLeft);
3772         out.append(',');
3773         out.append(mTop);
3774         out.append('-');
3775         out.append(mRight);
3776         out.append(',');
3777         out.append(mBottom);
3778         final int id = getId();
3779         if (id != NO_ID) {
3780             out.append(" #");
3781             out.append(Integer.toHexString(id));
3782             final Resources r = mResources;
3783             if (id != 0 && r != null) {
3784                 try {
3785                     String pkgname;
3786                     switch (id&0xff000000) {
3787                         case 0x7f000000:
3788                             pkgname="app";
3789                             break;
3790                         case 0x01000000:
3791                             pkgname="android";
3792                             break;
3793                         default:
3794                             pkgname = r.getResourcePackageName(id);
3795                             break;
3796                     }
3797                     String typename = r.getResourceTypeName(id);
3798                     String entryname = r.getResourceEntryName(id);
3799                     out.append(" ");
3800                     out.append(pkgname);
3801                     out.append(":");
3802                     out.append(typename);
3803                     out.append("/");
3804                     out.append(entryname);
3805                 } catch (Resources.NotFoundException e) {
3806                 }
3807             }
3808         }
3809         out.append("}");
3810         return out.toString();
3811     }
3812 
3813     /**
3814      * <p>
3815      * Initializes the fading edges from a given set of styled attributes. This
3816      * method should be called by subclasses that need fading edges and when an
3817      * instance of these subclasses is created programmatically rather than
3818      * being inflated from XML. This method is automatically called when the XML
3819      * is inflated.
3820      * </p>
3821      *
3822      * @param a the styled attributes set to initialize the fading edges from
3823      */
initializeFadingEdge(TypedArray a)3824     protected void initializeFadingEdge(TypedArray a) {
3825         initScrollCache();
3826 
3827         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
3828                 R.styleable.View_fadingEdgeLength,
3829                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
3830     }
3831 
3832     /**
3833      * Returns the size of the vertical faded edges used to indicate that more
3834      * content in this view is visible.
3835      *
3836      * @return The size in pixels of the vertical faded edge or 0 if vertical
3837      *         faded edges are not enabled for this view.
3838      * @attr ref android.R.styleable#View_fadingEdgeLength
3839      */
getVerticalFadingEdgeLength()3840     public int getVerticalFadingEdgeLength() {
3841         if (isVerticalFadingEdgeEnabled()) {
3842             ScrollabilityCache cache = mScrollCache;
3843             if (cache != null) {
3844                 return cache.fadingEdgeLength;
3845             }
3846         }
3847         return 0;
3848     }
3849 
3850     /**
3851      * Set the size of the faded edge used to indicate that more content in this
3852      * view is available.  Will not change whether the fading edge is enabled; use
3853      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
3854      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
3855      * for the vertical or horizontal fading edges.
3856      *
3857      * @param length The size in pixels of the faded edge used to indicate that more
3858      *        content in this view is visible.
3859      */
setFadingEdgeLength(int length)3860     public void setFadingEdgeLength(int length) {
3861         initScrollCache();
3862         mScrollCache.fadingEdgeLength = length;
3863     }
3864 
3865     /**
3866      * Returns the size of the horizontal faded edges used to indicate that more
3867      * content in this view is visible.
3868      *
3869      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
3870      *         faded edges are not enabled for this view.
3871      * @attr ref android.R.styleable#View_fadingEdgeLength
3872      */
getHorizontalFadingEdgeLength()3873     public int getHorizontalFadingEdgeLength() {
3874         if (isHorizontalFadingEdgeEnabled()) {
3875             ScrollabilityCache cache = mScrollCache;
3876             if (cache != null) {
3877                 return cache.fadingEdgeLength;
3878             }
3879         }
3880         return 0;
3881     }
3882 
3883     /**
3884      * Returns the width of the vertical scrollbar.
3885      *
3886      * @return The width in pixels of the vertical scrollbar or 0 if there
3887      *         is no vertical scrollbar.
3888      */
getVerticalScrollbarWidth()3889     public int getVerticalScrollbarWidth() {
3890         ScrollabilityCache cache = mScrollCache;
3891         if (cache != null) {
3892             ScrollBarDrawable scrollBar = cache.scrollBar;
3893             if (scrollBar != null) {
3894                 int size = scrollBar.getSize(true);
3895                 if (size <= 0) {
3896                     size = cache.scrollBarSize;
3897                 }
3898                 return size;
3899             }
3900             return 0;
3901         }
3902         return 0;
3903     }
3904 
3905     /**
3906      * Returns the height of the horizontal scrollbar.
3907      *
3908      * @return The height in pixels of the horizontal scrollbar or 0 if
3909      *         there is no horizontal scrollbar.
3910      */
getHorizontalScrollbarHeight()3911     protected int getHorizontalScrollbarHeight() {
3912         ScrollabilityCache cache = mScrollCache;
3913         if (cache != null) {
3914             ScrollBarDrawable scrollBar = cache.scrollBar;
3915             if (scrollBar != null) {
3916                 int size = scrollBar.getSize(false);
3917                 if (size <= 0) {
3918                     size = cache.scrollBarSize;
3919                 }
3920                 return size;
3921             }
3922             return 0;
3923         }
3924         return 0;
3925     }
3926 
3927     /**
3928      * <p>
3929      * Initializes the scrollbars from a given set of styled attributes. This
3930      * method should be called by subclasses that need scrollbars and when an
3931      * instance of these subclasses is created programmatically rather than
3932      * being inflated from XML. This method is automatically called when the XML
3933      * is inflated.
3934      * </p>
3935      *
3936      * @param a the styled attributes set to initialize the scrollbars from
3937      */
initializeScrollbars(TypedArray a)3938     protected void initializeScrollbars(TypedArray a) {
3939         initScrollCache();
3940 
3941         final ScrollabilityCache scrollabilityCache = mScrollCache;
3942 
3943         if (scrollabilityCache.scrollBar == null) {
3944             scrollabilityCache.scrollBar = new ScrollBarDrawable();
3945         }
3946 
3947         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
3948 
3949         if (!fadeScrollbars) {
3950             scrollabilityCache.state = ScrollabilityCache.ON;
3951         }
3952         scrollabilityCache.fadeScrollBars = fadeScrollbars;
3953 
3954 
3955         scrollabilityCache.scrollBarFadeDuration = a.getInt(
3956                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
3957                         .getScrollBarFadeDuration());
3958         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
3959                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
3960                 ViewConfiguration.getScrollDefaultDelay());
3961 
3962 
3963         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
3964                 com.android.internal.R.styleable.View_scrollbarSize,
3965                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
3966 
3967         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
3968         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
3969 
3970         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
3971         if (thumb != null) {
3972             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
3973         }
3974 
3975         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
3976                 false);
3977         if (alwaysDraw) {
3978             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
3979         }
3980 
3981         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
3982         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
3983 
3984         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
3985         if (thumb != null) {
3986             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
3987         }
3988 
3989         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
3990                 false);
3991         if (alwaysDraw) {
3992             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
3993         }
3994 
3995         // Apply layout direction to the new Drawables if needed
3996         final int layoutDirection = getLayoutDirection();
3997         if (track != null) {
3998             track.setLayoutDirection(layoutDirection);
3999         }
4000         if (thumb != null) {
4001             thumb.setLayoutDirection(layoutDirection);
4002         }
4003 
4004         // Re-apply user/background padding so that scrollbar(s) get added
4005         resolvePadding();
4006     }
4007 
4008     /**
4009      * <p>
4010      * Initalizes the scrollability cache if necessary.
4011      * </p>
4012      */
initScrollCache()4013     private void initScrollCache() {
4014         if (mScrollCache == null) {
4015             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4016         }
4017     }
4018 
getScrollCache()4019     private ScrollabilityCache getScrollCache() {
4020         initScrollCache();
4021         return mScrollCache;
4022     }
4023 
4024     /**
4025      * Set the position of the vertical scroll bar. Should be one of
4026      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4027      * {@link #SCROLLBAR_POSITION_RIGHT}.
4028      *
4029      * @param position Where the vertical scroll bar should be positioned.
4030      */
setVerticalScrollbarPosition(int position)4031     public void setVerticalScrollbarPosition(int position) {
4032         if (mVerticalScrollbarPosition != position) {
4033             mVerticalScrollbarPosition = position;
4034             computeOpaqueFlags();
4035             resolvePadding();
4036         }
4037     }
4038 
4039     /**
4040      * @return The position where the vertical scroll bar will show, if applicable.
4041      * @see #setVerticalScrollbarPosition(int)
4042      */
getVerticalScrollbarPosition()4043     public int getVerticalScrollbarPosition() {
4044         return mVerticalScrollbarPosition;
4045     }
4046 
getListenerInfo()4047     ListenerInfo getListenerInfo() {
4048         if (mListenerInfo != null) {
4049             return mListenerInfo;
4050         }
4051         mListenerInfo = new ListenerInfo();
4052         return mListenerInfo;
4053     }
4054 
4055     /**
4056      * Register a callback to be invoked when focus of this view changed.
4057      *
4058      * @param l The callback that will run.
4059      */
setOnFocusChangeListener(OnFocusChangeListener l)4060     public void setOnFocusChangeListener(OnFocusChangeListener l) {
4061         getListenerInfo().mOnFocusChangeListener = l;
4062     }
4063 
4064     /**
4065      * Add a listener that will be called when the bounds of the view change due to
4066      * layout processing.
4067      *
4068      * @param listener The listener that will be called when layout bounds change.
4069      */
addOnLayoutChangeListener(OnLayoutChangeListener listener)4070     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4071         ListenerInfo li = getListenerInfo();
4072         if (li.mOnLayoutChangeListeners == null) {
4073             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4074         }
4075         if (!li.mOnLayoutChangeListeners.contains(listener)) {
4076             li.mOnLayoutChangeListeners.add(listener);
4077         }
4078     }
4079 
4080     /**
4081      * Remove a listener for layout changes.
4082      *
4083      * @param listener The listener for layout bounds change.
4084      */
removeOnLayoutChangeListener(OnLayoutChangeListener listener)4085     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4086         ListenerInfo li = mListenerInfo;
4087         if (li == null || li.mOnLayoutChangeListeners == null) {
4088             return;
4089         }
4090         li.mOnLayoutChangeListeners.remove(listener);
4091     }
4092 
4093     /**
4094      * Add a listener for attach state changes.
4095      *
4096      * This listener will be called whenever this view is attached or detached
4097      * from a window. Remove the listener using
4098      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4099      *
4100      * @param listener Listener to attach
4101      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4102      */
addOnAttachStateChangeListener(OnAttachStateChangeListener listener)4103     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4104         ListenerInfo li = getListenerInfo();
4105         if (li.mOnAttachStateChangeListeners == null) {
4106             li.mOnAttachStateChangeListeners
4107                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4108         }
4109         li.mOnAttachStateChangeListeners.add(listener);
4110     }
4111 
4112     /**
4113      * Remove a listener for attach state changes. The listener will receive no further
4114      * notification of window attach/detach events.
4115      *
4116      * @param listener Listener to remove
4117      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4118      */
removeOnAttachStateChangeListener(OnAttachStateChangeListener listener)4119     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4120         ListenerInfo li = mListenerInfo;
4121         if (li == null || li.mOnAttachStateChangeListeners == null) {
4122             return;
4123         }
4124         li.mOnAttachStateChangeListeners.remove(listener);
4125     }
4126 
4127     /**
4128      * Returns the focus-change callback registered for this view.
4129      *
4130      * @return The callback, or null if one is not registered.
4131      */
getOnFocusChangeListener()4132     public OnFocusChangeListener getOnFocusChangeListener() {
4133         ListenerInfo li = mListenerInfo;
4134         return li != null ? li.mOnFocusChangeListener : null;
4135     }
4136 
4137     /**
4138      * Register a callback to be invoked when this view is clicked. If this view is not
4139      * clickable, it becomes clickable.
4140      *
4141      * @param l The callback that will run
4142      *
4143      * @see #setClickable(boolean)
4144      */
setOnClickListener(OnClickListener l)4145     public void setOnClickListener(OnClickListener l) {
4146         if (!isClickable()) {
4147             setClickable(true);
4148         }
4149         getListenerInfo().mOnClickListener = l;
4150     }
4151 
4152     /**
4153      * Return whether this view has an attached OnClickListener.  Returns
4154      * true if there is a listener, false if there is none.
4155      */
hasOnClickListeners()4156     public boolean hasOnClickListeners() {
4157         ListenerInfo li = mListenerInfo;
4158         return (li != null && li.mOnClickListener != null);
4159     }
4160 
4161     /**
4162      * Register a callback to be invoked when this view is clicked and held. If this view is not
4163      * long clickable, it becomes long clickable.
4164      *
4165      * @param l The callback that will run
4166      *
4167      * @see #setLongClickable(boolean)
4168      */
setOnLongClickListener(OnLongClickListener l)4169     public void setOnLongClickListener(OnLongClickListener l) {
4170         if (!isLongClickable()) {
4171             setLongClickable(true);
4172         }
4173         getListenerInfo().mOnLongClickListener = l;
4174     }
4175 
4176     /**
4177      * Register a callback to be invoked when the context menu for this view is
4178      * being built. If this view is not long clickable, it becomes long clickable.
4179      *
4180      * @param l The callback that will run
4181      *
4182      */
setOnCreateContextMenuListener(OnCreateContextMenuListener l)4183     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4184         if (!isLongClickable()) {
4185             setLongClickable(true);
4186         }
4187         getListenerInfo().mOnCreateContextMenuListener = l;
4188     }
4189 
4190     /**
4191      * Call this view's OnClickListener, if it is defined.  Performs all normal
4192      * actions associated with clicking: reporting accessibility event, playing
4193      * a sound, etc.
4194      *
4195      * @return True there was an assigned OnClickListener that was called, false
4196      *         otherwise is returned.
4197      */
performClick()4198     public boolean performClick() {
4199         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4200 
4201         ListenerInfo li = mListenerInfo;
4202         if (li != null && li.mOnClickListener != null) {
4203             playSoundEffect(SoundEffectConstants.CLICK);
4204             li.mOnClickListener.onClick(this);
4205             return true;
4206         }
4207 
4208         return false;
4209     }
4210 
4211     /**
4212      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
4213      * this only calls the listener, and does not do any associated clicking
4214      * actions like reporting an accessibility event.
4215      *
4216      * @return True there was an assigned OnClickListener that was called, false
4217      *         otherwise is returned.
4218      */
callOnClick()4219     public boolean callOnClick() {
4220         ListenerInfo li = mListenerInfo;
4221         if (li != null && li.mOnClickListener != null) {
4222             li.mOnClickListener.onClick(this);
4223             return true;
4224         }
4225         return false;
4226     }
4227 
4228     /**
4229      * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4230      * OnLongClickListener did not consume the event.
4231      *
4232      * @return True if one of the above receivers consumed the event, false otherwise.
4233      */
performLongClick()4234     public boolean performLongClick() {
4235         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4236 
4237         boolean handled = false;
4238         ListenerInfo li = mListenerInfo;
4239         if (li != null && li.mOnLongClickListener != null) {
4240             handled = li.mOnLongClickListener.onLongClick(View.this);
4241         }
4242         if (!handled) {
4243             handled = showContextMenu();
4244         }
4245         if (handled) {
4246             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4247         }
4248         return handled;
4249     }
4250 
4251     /**
4252      * Performs button-related actions during a touch down event.
4253      *
4254      * @param event The event.
4255      * @return True if the down was consumed.
4256      *
4257      * @hide
4258      */
performButtonActionOnTouchDown(MotionEvent event)4259     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4260         if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4261             if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4262                 return true;
4263             }
4264         }
4265         return false;
4266     }
4267 
4268     /**
4269      * Bring up the context menu for this view.
4270      *
4271      * @return Whether a context menu was displayed.
4272      */
showContextMenu()4273     public boolean showContextMenu() {
4274         return getParent().showContextMenuForChild(this);
4275     }
4276 
4277     /**
4278      * Bring up the context menu for this view, referring to the item under the specified point.
4279      *
4280      * @param x The referenced x coordinate.
4281      * @param y The referenced y coordinate.
4282      * @param metaState The keyboard modifiers that were pressed.
4283      * @return Whether a context menu was displayed.
4284      *
4285      * @hide
4286      */
showContextMenu(float x, float y, int metaState)4287     public boolean showContextMenu(float x, float y, int metaState) {
4288         return showContextMenu();
4289     }
4290 
4291     /**
4292      * Start an action mode.
4293      *
4294      * @param callback Callback that will control the lifecycle of the action mode
4295      * @return The new action mode if it is started, null otherwise
4296      *
4297      * @see ActionMode
4298      */
startActionMode(ActionMode.Callback callback)4299     public ActionMode startActionMode(ActionMode.Callback callback) {
4300         ViewParent parent = getParent();
4301         if (parent == null) return null;
4302         return parent.startActionModeForChild(this, callback);
4303     }
4304 
4305     /**
4306      * Register a callback to be invoked when a hardware key is pressed in this view.
4307      * Key presses in software input methods will generally not trigger the methods of
4308      * this listener.
4309      * @param l the key listener to attach to this view
4310      */
setOnKeyListener(OnKeyListener l)4311     public void setOnKeyListener(OnKeyListener l) {
4312         getListenerInfo().mOnKeyListener = l;
4313     }
4314 
4315     /**
4316      * Register a callback to be invoked when a touch event is sent to this view.
4317      * @param l the touch listener to attach to this view
4318      */
setOnTouchListener(OnTouchListener l)4319     public void setOnTouchListener(OnTouchListener l) {
4320         getListenerInfo().mOnTouchListener = l;
4321     }
4322 
4323     /**
4324      * Register a callback to be invoked when a generic motion event is sent to this view.
4325      * @param l the generic motion listener to attach to this view
4326      */
setOnGenericMotionListener(OnGenericMotionListener l)4327     public void setOnGenericMotionListener(OnGenericMotionListener l) {
4328         getListenerInfo().mOnGenericMotionListener = l;
4329     }
4330 
4331     /**
4332      * Register a callback to be invoked when a hover event is sent to this view.
4333      * @param l the hover listener to attach to this view
4334      */
setOnHoverListener(OnHoverListener l)4335     public void setOnHoverListener(OnHoverListener l) {
4336         getListenerInfo().mOnHoverListener = l;
4337     }
4338 
4339     /**
4340      * Register a drag event listener callback object for this View. The parameter is
4341      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4342      * View, the system calls the
4343      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4344      * @param l An implementation of {@link android.view.View.OnDragListener}.
4345      */
setOnDragListener(OnDragListener l)4346     public void setOnDragListener(OnDragListener l) {
4347         getListenerInfo().mOnDragListener = l;
4348     }
4349 
4350     /**
4351      * Give this view focus. This will cause
4352      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
4353      *
4354      * Note: this does not check whether this {@link View} should get focus, it just
4355      * gives it focus no matter what.  It should only be called internally by framework
4356      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4357      *
4358      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4359      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
4360      *        focus moved when requestFocus() is called. It may not always
4361      *        apply, in which case use the default View.FOCUS_DOWN.
4362      * @param previouslyFocusedRect The rectangle of the view that had focus
4363      *        prior in this View's coordinate system.
4364      */
handleFocusGainInternal(int direction, Rect previouslyFocusedRect)4365     void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
4366         if (DBG) {
4367             System.out.println(this + " requestFocus()");
4368         }
4369 
4370         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4371             mPrivateFlags |= PFLAG_FOCUSED;
4372 
4373             if (mParent != null) {
4374                 mParent.requestChildFocus(this, this);
4375             }
4376 
4377             onFocusChanged(true, direction, previouslyFocusedRect);
4378             refreshDrawableState();
4379 
4380             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4381                 notifyAccessibilityStateChanged();
4382             }
4383         }
4384     }
4385 
4386     /**
4387      * Request that a rectangle of this view be visible on the screen,
4388      * scrolling if necessary just enough.
4389      *
4390      * <p>A View should call this if it maintains some notion of which part
4391      * of its content is interesting.  For example, a text editing view
4392      * should call this when its cursor moves.
4393      *
4394      * @param rectangle The rectangle.
4395      * @return Whether any parent scrolled.
4396      */
requestRectangleOnScreen(Rect rectangle)4397     public boolean requestRectangleOnScreen(Rect rectangle) {
4398         return requestRectangleOnScreen(rectangle, false);
4399     }
4400 
4401     /**
4402      * Request that a rectangle of this view be visible on the screen,
4403      * scrolling if necessary just enough.
4404      *
4405      * <p>A View should call this if it maintains some notion of which part
4406      * of its content is interesting.  For example, a text editing view
4407      * should call this when its cursor moves.
4408      *
4409      * <p>When <code>immediate</code> is set to true, scrolling will not be
4410      * animated.
4411      *
4412      * @param rectangle The rectangle.
4413      * @param immediate True to forbid animated scrolling, false otherwise
4414      * @return Whether any parent scrolled.
4415      */
requestRectangleOnScreen(Rect rectangle, boolean immediate)4416     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
4417         if (mParent == null) {
4418             return false;
4419         }
4420 
4421         View child = this;
4422 
4423         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
4424         position.set(rectangle);
4425 
4426         ViewParent parent = mParent;
4427         boolean scrolled = false;
4428         while (parent != null) {
4429             rectangle.set((int) position.left, (int) position.top,
4430                     (int) position.right, (int) position.bottom);
4431 
4432             scrolled |= parent.requestChildRectangleOnScreen(child,
4433                     rectangle, immediate);
4434 
4435             if (!child.hasIdentityMatrix()) {
4436                 child.getMatrix().mapRect(position);
4437             }
4438 
4439             position.offset(child.mLeft, child.mTop);
4440 
4441             if (!(parent instanceof View)) {
4442                 break;
4443             }
4444 
4445             View parentView = (View) parent;
4446 
4447             position.offset(-parentView.getScrollX(), -parentView.getScrollY());
4448 
4449             child = parentView;
4450             parent = child.getParent();
4451         }
4452 
4453         return scrolled;
4454     }
4455 
4456     /**
4457      * Called when this view wants to give up focus. If focus is cleared
4458      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
4459      * <p>
4460      * <strong>Note:</strong> When a View clears focus the framework is trying
4461      * to give focus to the first focusable View from the top. Hence, if this
4462      * View is the first from the top that can take focus, then all callbacks
4463      * related to clearing focus will be invoked after wich the framework will
4464      * give focus to this view.
4465      * </p>
4466      */
clearFocus()4467     public void clearFocus() {
4468         if (DBG) {
4469             System.out.println(this + " clearFocus()");
4470         }
4471 
4472         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4473             mPrivateFlags &= ~PFLAG_FOCUSED;
4474 
4475             if (mParent != null) {
4476                 mParent.clearChildFocus(this);
4477             }
4478 
4479             onFocusChanged(false, 0, null);
4480 
4481             refreshDrawableState();
4482 
4483             ensureInputFocusOnFirstFocusable();
4484 
4485             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4486                 notifyAccessibilityStateChanged();
4487             }
4488         }
4489     }
4490 
ensureInputFocusOnFirstFocusable()4491     void ensureInputFocusOnFirstFocusable() {
4492         View root = getRootView();
4493         if (root != null) {
4494             root.requestFocus();
4495         }
4496     }
4497 
4498     /**
4499      * Called internally by the view system when a new view is getting focus.
4500      * This is what clears the old focus.
4501      */
unFocus()4502     void unFocus() {
4503         if (DBG) {
4504             System.out.println(this + " unFocus()");
4505         }
4506 
4507         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4508             mPrivateFlags &= ~PFLAG_FOCUSED;
4509 
4510             onFocusChanged(false, 0, null);
4511             refreshDrawableState();
4512 
4513             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4514                 notifyAccessibilityStateChanged();
4515             }
4516         }
4517     }
4518 
4519     /**
4520      * Returns true if this view has focus iteself, or is the ancestor of the
4521      * view that has focus.
4522      *
4523      * @return True if this view has or contains focus, false otherwise.
4524      */
4525     @ViewDebug.ExportedProperty(category = "focus")
hasFocus()4526     public boolean hasFocus() {
4527         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
4528     }
4529 
4530     /**
4531      * Returns true if this view is focusable or if it contains a reachable View
4532      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
4533      * is a View whose parents do not block descendants focus.
4534      *
4535      * Only {@link #VISIBLE} views are considered focusable.
4536      *
4537      * @return True if the view is focusable or if the view contains a focusable
4538      *         View, false otherwise.
4539      *
4540      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
4541      */
hasFocusable()4542     public boolean hasFocusable() {
4543         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
4544     }
4545 
4546     /**
4547      * Called by the view system when the focus state of this view changes.
4548      * When the focus change event is caused by directional navigation, direction
4549      * and previouslyFocusedRect provide insight into where the focus is coming from.
4550      * When overriding, be sure to call up through to the super class so that
4551      * the standard focus handling will occur.
4552      *
4553      * @param gainFocus True if the View has focus; false otherwise.
4554      * @param direction The direction focus has moved when requestFocus()
4555      *                  is called to give this view focus. Values are
4556      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
4557      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
4558      *                  It may not always apply, in which case use the default.
4559      * @param previouslyFocusedRect The rectangle, in this view's coordinate
4560      *        system, of the previously focused view.  If applicable, this will be
4561      *        passed in as finer grained information about where the focus is coming
4562      *        from (in addition to direction).  Will be <code>null</code> otherwise.
4563      */
onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect)4564     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
4565         if (gainFocus) {
4566             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4567                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
4568             }
4569         }
4570 
4571         InputMethodManager imm = InputMethodManager.peekInstance();
4572         if (!gainFocus) {
4573             if (isPressed()) {
4574                 setPressed(false);
4575             }
4576             if (imm != null && mAttachInfo != null
4577                     && mAttachInfo.mHasWindowFocus) {
4578                 imm.focusOut(this);
4579             }
4580             onFocusLost();
4581         } else if (imm != null && mAttachInfo != null
4582                 && mAttachInfo.mHasWindowFocus) {
4583             imm.focusIn(this);
4584         }
4585 
4586         invalidate(true);
4587         ListenerInfo li = mListenerInfo;
4588         if (li != null && li.mOnFocusChangeListener != null) {
4589             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
4590         }
4591 
4592         if (mAttachInfo != null) {
4593             mAttachInfo.mKeyDispatchState.reset(this);
4594         }
4595     }
4596 
4597     /**
4598      * Sends an accessibility event of the given type. If accessibility is
4599      * not enabled this method has no effect. The default implementation calls
4600      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
4601      * to populate information about the event source (this View), then calls
4602      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
4603      * populate the text content of the event source including its descendants,
4604      * and last calls
4605      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
4606      * on its parent to resuest sending of the event to interested parties.
4607      * <p>
4608      * If an {@link AccessibilityDelegate} has been specified via calling
4609      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4610      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
4611      * responsible for handling this call.
4612      * </p>
4613      *
4614      * @param eventType The type of the event to send, as defined by several types from
4615      * {@link android.view.accessibility.AccessibilityEvent}, such as
4616      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
4617      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
4618      *
4619      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4620      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4621      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
4622      * @see AccessibilityDelegate
4623      */
sendAccessibilityEvent(int eventType)4624     public void sendAccessibilityEvent(int eventType) {
4625         if (mAccessibilityDelegate != null) {
4626             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
4627         } else {
4628             sendAccessibilityEventInternal(eventType);
4629         }
4630     }
4631 
4632     /**
4633      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
4634      * {@link AccessibilityEvent} to make an announcement which is related to some
4635      * sort of a context change for which none of the events representing UI transitions
4636      * is a good fit. For example, announcing a new page in a book. If accessibility
4637      * is not enabled this method does nothing.
4638      *
4639      * @param text The announcement text.
4640      */
announceForAccessibility(CharSequence text)4641     public void announceForAccessibility(CharSequence text) {
4642         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
4643             AccessibilityEvent event = AccessibilityEvent.obtain(
4644                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
4645             onInitializeAccessibilityEvent(event);
4646             event.getText().add(text);
4647             event.setContentDescription(null);
4648             mParent.requestSendAccessibilityEvent(this, event);
4649         }
4650     }
4651 
4652     /**
4653      * @see #sendAccessibilityEvent(int)
4654      *
4655      * Note: Called from the default {@link AccessibilityDelegate}.
4656      */
sendAccessibilityEventInternal(int eventType)4657     void sendAccessibilityEventInternal(int eventType) {
4658         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4659             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
4660         }
4661     }
4662 
4663     /**
4664      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
4665      * takes as an argument an empty {@link AccessibilityEvent} and does not
4666      * perform a check whether accessibility is enabled.
4667      * <p>
4668      * If an {@link AccessibilityDelegate} has been specified via calling
4669      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4670      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
4671      * is responsible for handling this call.
4672      * </p>
4673      *
4674      * @param event The event to send.
4675      *
4676      * @see #sendAccessibilityEvent(int)
4677      */
sendAccessibilityEventUnchecked(AccessibilityEvent event)4678     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
4679         if (mAccessibilityDelegate != null) {
4680             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
4681         } else {
4682             sendAccessibilityEventUncheckedInternal(event);
4683         }
4684     }
4685 
4686     /**
4687      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
4688      *
4689      * Note: Called from the default {@link AccessibilityDelegate}.
4690      */
sendAccessibilityEventUncheckedInternal(AccessibilityEvent event)4691     void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
4692         if (!isShown()) {
4693             return;
4694         }
4695         onInitializeAccessibilityEvent(event);
4696         // Only a subset of accessibility events populates text content.
4697         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
4698             dispatchPopulateAccessibilityEvent(event);
4699         }
4700         // In the beginning we called #isShown(), so we know that getParent() is not null.
4701         getParent().requestSendAccessibilityEvent(this, event);
4702     }
4703 
4704     /**
4705      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
4706      * to its children for adding their text content to the event. Note that the
4707      * event text is populated in a separate dispatch path since we add to the
4708      * event not only the text of the source but also the text of all its descendants.
4709      * A typical implementation will call
4710      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
4711      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4712      * on each child. Override this method if custom population of the event text
4713      * content is required.
4714      * <p>
4715      * If an {@link AccessibilityDelegate} has been specified via calling
4716      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4717      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
4718      * is responsible for handling this call.
4719      * </p>
4720      * <p>
4721      * <em>Note:</em> Accessibility events of certain types are not dispatched for
4722      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
4723      * </p>
4724      *
4725      * @param event The event.
4726      *
4727      * @return True if the event population was completed.
4728      */
dispatchPopulateAccessibilityEvent(AccessibilityEvent event)4729     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
4730         if (mAccessibilityDelegate != null) {
4731             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
4732         } else {
4733             return dispatchPopulateAccessibilityEventInternal(event);
4734         }
4735     }
4736 
4737     /**
4738      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4739      *
4740      * Note: Called from the default {@link AccessibilityDelegate}.
4741      */
dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event)4742     boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4743         onPopulateAccessibilityEvent(event);
4744         return false;
4745     }
4746 
4747     /**
4748      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4749      * giving a chance to this View to populate the accessibility event with its
4750      * text content. While this method is free to modify event
4751      * attributes other than text content, doing so should normally be performed in
4752      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
4753      * <p>
4754      * Example: Adding formatted date string to an accessibility event in addition
4755      *          to the text added by the super implementation:
4756      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
4757      *     super.onPopulateAccessibilityEvent(event);
4758      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
4759      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
4760      *         mCurrentDate.getTimeInMillis(), flags);
4761      *     event.getText().add(selectedDateUtterance);
4762      * }</pre>
4763      * <p>
4764      * If an {@link AccessibilityDelegate} has been specified via calling
4765      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4766      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
4767      * is responsible for handling this call.
4768      * </p>
4769      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4770      * information to the event, in case the default implementation has basic information to add.
4771      * </p>
4772      *
4773      * @param event The accessibility event which to populate.
4774      *
4775      * @see #sendAccessibilityEvent(int)
4776      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4777      */
onPopulateAccessibilityEvent(AccessibilityEvent event)4778     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
4779         if (mAccessibilityDelegate != null) {
4780             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
4781         } else {
4782             onPopulateAccessibilityEventInternal(event);
4783         }
4784     }
4785 
4786     /**
4787      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
4788      *
4789      * Note: Called from the default {@link AccessibilityDelegate}.
4790      */
onPopulateAccessibilityEventInternal(AccessibilityEvent event)4791     void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4792 
4793     }
4794 
4795     /**
4796      * Initializes an {@link AccessibilityEvent} with information about
4797      * this View which is the event source. In other words, the source of
4798      * an accessibility event is the view whose state change triggered firing
4799      * the event.
4800      * <p>
4801      * Example: Setting the password property of an event in addition
4802      *          to properties set by the super implementation:
4803      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4804      *     super.onInitializeAccessibilityEvent(event);
4805      *     event.setPassword(true);
4806      * }</pre>
4807      * <p>
4808      * If an {@link AccessibilityDelegate} has been specified via calling
4809      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4810      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
4811      * is responsible for handling this call.
4812      * </p>
4813      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4814      * information to the event, in case the default implementation has basic information to add.
4815      * </p>
4816      * @param event The event to initialize.
4817      *
4818      * @see #sendAccessibilityEvent(int)
4819      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4820      */
onInitializeAccessibilityEvent(AccessibilityEvent event)4821     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4822         if (mAccessibilityDelegate != null) {
4823             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
4824         } else {
4825             onInitializeAccessibilityEventInternal(event);
4826         }
4827     }
4828 
4829     /**
4830      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4831      *
4832      * Note: Called from the default {@link AccessibilityDelegate}.
4833      */
onInitializeAccessibilityEventInternal(AccessibilityEvent event)4834     void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
4835         event.setSource(this);
4836         event.setClassName(View.class.getName());
4837         event.setPackageName(getContext().getPackageName());
4838         event.setEnabled(isEnabled());
4839         event.setContentDescription(mContentDescription);
4840 
4841         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
4842             ArrayList<View> focusablesTempList = mAttachInfo.mTempArrayList;
4843             getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
4844                     FOCUSABLES_ALL);
4845             event.setItemCount(focusablesTempList.size());
4846             event.setCurrentItemIndex(focusablesTempList.indexOf(this));
4847             focusablesTempList.clear();
4848         }
4849     }
4850 
4851     /**
4852      * Returns an {@link AccessibilityNodeInfo} representing this view from the
4853      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
4854      * This method is responsible for obtaining an accessibility node info from a
4855      * pool of reusable instances and calling
4856      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
4857      * initialize the former.
4858      * <p>
4859      * Note: The client is responsible for recycling the obtained instance by calling
4860      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
4861      * </p>
4862      *
4863      * @return A populated {@link AccessibilityNodeInfo}.
4864      *
4865      * @see AccessibilityNodeInfo
4866      */
createAccessibilityNodeInfo()4867     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
4868         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
4869         if (provider != null) {
4870             return provider.createAccessibilityNodeInfo(View.NO_ID);
4871         } else {
4872             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
4873             onInitializeAccessibilityNodeInfo(info);
4874             return info;
4875         }
4876     }
4877 
4878     /**
4879      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
4880      * The base implementation sets:
4881      * <ul>
4882      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
4883      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
4884      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
4885      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
4886      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
4887      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
4888      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
4889      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
4890      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
4891      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
4892      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
4893      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
4894      * </ul>
4895      * <p>
4896      * Subclasses should override this method, call the super implementation,
4897      * and set additional attributes.
4898      * </p>
4899      * <p>
4900      * If an {@link AccessibilityDelegate} has been specified via calling
4901      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4902      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
4903      * is responsible for handling this call.
4904      * </p>
4905      *
4906      * @param info The instance to initialize.
4907      */
onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)4908     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
4909         if (mAccessibilityDelegate != null) {
4910             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
4911         } else {
4912             onInitializeAccessibilityNodeInfoInternal(info);
4913         }
4914     }
4915 
4916     /**
4917      * Gets the location of this view in screen coordintates.
4918      *
4919      * @param outRect The output location
4920      */
getBoundsOnScreen(Rect outRect)4921     void getBoundsOnScreen(Rect outRect) {
4922         if (mAttachInfo == null) {
4923             return;
4924         }
4925 
4926         RectF position = mAttachInfo.mTmpTransformRect;
4927         position.set(0, 0, mRight - mLeft, mBottom - mTop);
4928 
4929         if (!hasIdentityMatrix()) {
4930             getMatrix().mapRect(position);
4931         }
4932 
4933         position.offset(mLeft, mTop);
4934 
4935         ViewParent parent = mParent;
4936         while (parent instanceof View) {
4937             View parentView = (View) parent;
4938 
4939             position.offset(-parentView.mScrollX, -parentView.mScrollY);
4940 
4941             if (!parentView.hasIdentityMatrix()) {
4942                 parentView.getMatrix().mapRect(position);
4943             }
4944 
4945             position.offset(parentView.mLeft, parentView.mTop);
4946 
4947             parent = parentView.mParent;
4948         }
4949 
4950         if (parent instanceof ViewRootImpl) {
4951             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
4952             position.offset(0, -viewRootImpl.mCurScrollY);
4953         }
4954 
4955         position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
4956 
4957         outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
4958                 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
4959     }
4960 
4961     /**
4962      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
4963      *
4964      * Note: Called from the default {@link AccessibilityDelegate}.
4965      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)4966     void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
4967         Rect bounds = mAttachInfo.mTmpInvalRect;
4968 
4969         getDrawingRect(bounds);
4970         info.setBoundsInParent(bounds);
4971 
4972         getBoundsOnScreen(bounds);
4973         info.setBoundsInScreen(bounds);
4974 
4975         ViewParent parent = getParentForAccessibility();
4976         if (parent instanceof View) {
4977             info.setParent((View) parent);
4978         }
4979 
4980         if (mID != View.NO_ID) {
4981             View rootView = getRootView();
4982             if (rootView == null) {
4983                 rootView = this;
4984             }
4985             View label = rootView.findLabelForView(this, mID);
4986             if (label != null) {
4987                 info.setLabeledBy(label);
4988             }
4989         }
4990 
4991         if (mLabelForId != View.NO_ID) {
4992             View rootView = getRootView();
4993             if (rootView == null) {
4994                 rootView = this;
4995             }
4996             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
4997             if (labeled != null) {
4998                 info.setLabelFor(labeled);
4999             }
5000         }
5001 
5002         info.setVisibleToUser(isVisibleToUser());
5003 
5004         info.setPackageName(mContext.getPackageName());
5005         info.setClassName(View.class.getName());
5006         info.setContentDescription(getContentDescription());
5007 
5008         info.setEnabled(isEnabled());
5009         info.setClickable(isClickable());
5010         info.setFocusable(isFocusable());
5011         info.setFocused(isFocused());
5012         info.setAccessibilityFocused(isAccessibilityFocused());
5013         info.setSelected(isSelected());
5014         info.setLongClickable(isLongClickable());
5015 
5016         // TODO: These make sense only if we are in an AdapterView but all
5017         // views can be selected. Maybe from accessibility perspective
5018         // we should report as selectable view in an AdapterView.
5019         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
5020         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
5021 
5022         if (isFocusable()) {
5023             if (isFocused()) {
5024                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
5025             } else {
5026                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
5027             }
5028         }
5029 
5030         if (!isAccessibilityFocused()) {
5031             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
5032         } else {
5033             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
5034         }
5035 
5036         if (isClickable() && isEnabled()) {
5037             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
5038         }
5039 
5040         if (isLongClickable() && isEnabled()) {
5041             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
5042         }
5043 
5044         if (mContentDescription != null && mContentDescription.length() > 0) {
5045             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
5046             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
5047             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
5048                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
5049                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
5050         }
5051     }
5052 
findLabelForView(View view, int labeledId)5053     private View findLabelForView(View view, int labeledId) {
5054         if (mMatchLabelForPredicate == null) {
5055             mMatchLabelForPredicate = new MatchLabelForPredicate();
5056         }
5057         mMatchLabelForPredicate.mLabeledId = labeledId;
5058         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
5059     }
5060 
5061     /**
5062      * Computes whether this view is visible to the user. Such a view is
5063      * attached, visible, all its predecessors are visible, it is not clipped
5064      * entirely by its predecessors, and has an alpha greater than zero.
5065      *
5066      * @return Whether the view is visible on the screen.
5067      *
5068      * @hide
5069      */
isVisibleToUser()5070     protected boolean isVisibleToUser() {
5071         return isVisibleToUser(null);
5072     }
5073 
5074     /**
5075      * Computes whether the given portion of this view is visible to the user.
5076      * Such a view is attached, visible, all its predecessors are visible,
5077      * has an alpha greater than zero, and the specified portion is not
5078      * clipped entirely by its predecessors.
5079      *
5080      * @param boundInView the portion of the view to test; coordinates should be relative; may be
5081      *                    <code>null</code>, and the entire view will be tested in this case.
5082      *                    When <code>true</code> is returned by the function, the actual visible
5083      *                    region will be stored in this parameter; that is, if boundInView is fully
5084      *                    contained within the view, no modification will be made, otherwise regions
5085      *                    outside of the visible area of the view will be clipped.
5086      *
5087      * @return Whether the specified portion of the view is visible on the screen.
5088      *
5089      * @hide
5090      */
isVisibleToUser(Rect boundInView)5091     protected boolean isVisibleToUser(Rect boundInView) {
5092         if (mAttachInfo != null) {
5093             // Attached to invisible window means this view is not visible.
5094             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
5095                 return false;
5096             }
5097             // An invisible predecessor or one with alpha zero means
5098             // that this view is not visible to the user.
5099             Object current = this;
5100             while (current instanceof View) {
5101                 View view = (View) current;
5102                 // We have attach info so this view is attached and there is no
5103                 // need to check whether we reach to ViewRootImpl on the way up.
5104                 if (view.getAlpha() <= 0 || view.getVisibility() != VISIBLE) {
5105                     return false;
5106                 }
5107                 current = view.mParent;
5108             }
5109             // Check if the view is entirely covered by its predecessors.
5110             Rect visibleRect = mAttachInfo.mTmpInvalRect;
5111             Point offset = mAttachInfo.mPoint;
5112             if (!getGlobalVisibleRect(visibleRect, offset)) {
5113                 return false;
5114             }
5115             // Check if the visible portion intersects the rectangle of interest.
5116             if (boundInView != null) {
5117                 visibleRect.offset(-offset.x, -offset.y);
5118                 return boundInView.intersect(visibleRect);
5119             }
5120             return true;
5121         }
5122         return false;
5123     }
5124 
5125     /**
5126      * Returns the delegate for implementing accessibility support via
5127      * composition. For more details see {@link AccessibilityDelegate}.
5128      *
5129      * @return The delegate, or null if none set.
5130      *
5131      * @hide
5132      */
getAccessibilityDelegate()5133     public AccessibilityDelegate getAccessibilityDelegate() {
5134         return mAccessibilityDelegate;
5135     }
5136 
5137     /**
5138      * Sets a delegate for implementing accessibility support via composition as
5139      * opposed to inheritance. The delegate's primary use is for implementing
5140      * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
5141      *
5142      * @param delegate The delegate instance.
5143      *
5144      * @see AccessibilityDelegate
5145      */
setAccessibilityDelegate(AccessibilityDelegate delegate)5146     public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
5147         mAccessibilityDelegate = delegate;
5148     }
5149 
5150     /**
5151      * Gets the provider for managing a virtual view hierarchy rooted at this View
5152      * and reported to {@link android.accessibilityservice.AccessibilityService}s
5153      * that explore the window content.
5154      * <p>
5155      * If this method returns an instance, this instance is responsible for managing
5156      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
5157      * View including the one representing the View itself. Similarly the returned
5158      * instance is responsible for performing accessibility actions on any virtual
5159      * view or the root view itself.
5160      * </p>
5161      * <p>
5162      * If an {@link AccessibilityDelegate} has been specified via calling
5163      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5164      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
5165      * is responsible for handling this call.
5166      * </p>
5167      *
5168      * @return The provider.
5169      *
5170      * @see AccessibilityNodeProvider
5171      */
getAccessibilityNodeProvider()5172     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
5173         if (mAccessibilityDelegate != null) {
5174             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
5175         } else {
5176             return null;
5177         }
5178     }
5179 
5180     /**
5181      * Gets the unique identifier of this view on the screen for accessibility purposes.
5182      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
5183      *
5184      * @return The view accessibility id.
5185      *
5186      * @hide
5187      */
getAccessibilityViewId()5188     public int getAccessibilityViewId() {
5189         if (mAccessibilityViewId == NO_ID) {
5190             mAccessibilityViewId = sNextAccessibilityViewId++;
5191         }
5192         return mAccessibilityViewId;
5193     }
5194 
5195     /**
5196      * Gets the unique identifier of the window in which this View reseides.
5197      *
5198      * @return The window accessibility id.
5199      *
5200      * @hide
5201      */
getAccessibilityWindowId()5202     public int getAccessibilityWindowId() {
5203         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
5204     }
5205 
5206     /**
5207      * Gets the {@link View} description. It briefly describes the view and is
5208      * primarily used for accessibility support. Set this property to enable
5209      * better accessibility support for your application. This is especially
5210      * true for views that do not have textual representation (For example,
5211      * ImageButton).
5212      *
5213      * @return The content description.
5214      *
5215      * @attr ref android.R.styleable#View_contentDescription
5216      */
5217     @ViewDebug.ExportedProperty(category = "accessibility")
getContentDescription()5218     public CharSequence getContentDescription() {
5219         return mContentDescription;
5220     }
5221 
5222     /**
5223      * Sets the {@link View} description. It briefly describes the view and is
5224      * primarily used for accessibility support. Set this property to enable
5225      * better accessibility support for your application. This is especially
5226      * true for views that do not have textual representation (For example,
5227      * ImageButton).
5228      *
5229      * @param contentDescription The content description.
5230      *
5231      * @attr ref android.R.styleable#View_contentDescription
5232      */
5233     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)5234     public void setContentDescription(CharSequence contentDescription) {
5235         if (mContentDescription == null) {
5236             if (contentDescription == null) {
5237                 return;
5238             }
5239         } else if (mContentDescription.equals(contentDescription)) {
5240             return;
5241         }
5242         mContentDescription = contentDescription;
5243         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
5244         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
5245              setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
5246         }
5247         notifyAccessibilityStateChanged();
5248     }
5249 
5250     /**
5251      * Gets the id of a view for which this view serves as a label for
5252      * accessibility purposes.
5253      *
5254      * @return The labeled view id.
5255      */
5256     @ViewDebug.ExportedProperty(category = "accessibility")
getLabelFor()5257     public int getLabelFor() {
5258         return mLabelForId;
5259     }
5260 
5261     /**
5262      * Sets the id of a view for which this view serves as a label for
5263      * accessibility purposes.
5264      *
5265      * @param id The labeled view id.
5266      */
5267     @RemotableViewMethod
setLabelFor(int id)5268     public void setLabelFor(int id) {
5269         mLabelForId = id;
5270         if (mLabelForId != View.NO_ID
5271                 && mID == View.NO_ID) {
5272             mID = generateViewId();
5273         }
5274     }
5275 
5276     /**
5277      * Invoked whenever this view loses focus, either by losing window focus or by losing
5278      * focus within its window. This method can be used to clear any state tied to the
5279      * focus. For instance, if a button is held pressed with the trackball and the window
5280      * loses focus, this method can be used to cancel the press.
5281      *
5282      * Subclasses of View overriding this method should always call super.onFocusLost().
5283      *
5284      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
5285      * @see #onWindowFocusChanged(boolean)
5286      *
5287      * @hide pending API council approval
5288      */
onFocusLost()5289     protected void onFocusLost() {
5290         resetPressedState();
5291     }
5292 
resetPressedState()5293     private void resetPressedState() {
5294         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
5295             return;
5296         }
5297 
5298         if (isPressed()) {
5299             setPressed(false);
5300 
5301             if (!mHasPerformedLongPress) {
5302                 removeLongPressCallback();
5303             }
5304         }
5305     }
5306 
5307     /**
5308      * Returns true if this view has focus
5309      *
5310      * @return True if this view has focus, false otherwise.
5311      */
5312     @ViewDebug.ExportedProperty(category = "focus")
isFocused()5313     public boolean isFocused() {
5314         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5315     }
5316 
5317     /**
5318      * Find the view in the hierarchy rooted at this view that currently has
5319      * focus.
5320      *
5321      * @return The view that currently has focus, or null if no focused view can
5322      *         be found.
5323      */
findFocus()5324     public View findFocus() {
5325         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
5326     }
5327 
5328     /**
5329      * Indicates whether this view is one of the set of scrollable containers in
5330      * its window.
5331      *
5332      * @return whether this view is one of the set of scrollable containers in
5333      * its window
5334      *
5335      * @attr ref android.R.styleable#View_isScrollContainer
5336      */
isScrollContainer()5337     public boolean isScrollContainer() {
5338         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
5339     }
5340 
5341     /**
5342      * Change whether this view is one of the set of scrollable containers in
5343      * its window.  This will be used to determine whether the window can
5344      * resize or must pan when a soft input area is open -- scrollable
5345      * containers allow the window to use resize mode since the container
5346      * will appropriately shrink.
5347      *
5348      * @attr ref android.R.styleable#View_isScrollContainer
5349      */
setScrollContainer(boolean isScrollContainer)5350     public void setScrollContainer(boolean isScrollContainer) {
5351         if (isScrollContainer) {
5352             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
5353                 mAttachInfo.mScrollContainers.add(this);
5354                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
5355             }
5356             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
5357         } else {
5358             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
5359                 mAttachInfo.mScrollContainers.remove(this);
5360             }
5361             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
5362         }
5363     }
5364 
5365     /**
5366      * Returns the quality of the drawing cache.
5367      *
5368      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5369      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5370      *
5371      * @see #setDrawingCacheQuality(int)
5372      * @see #setDrawingCacheEnabled(boolean)
5373      * @see #isDrawingCacheEnabled()
5374      *
5375      * @attr ref android.R.styleable#View_drawingCacheQuality
5376      */
getDrawingCacheQuality()5377     public int getDrawingCacheQuality() {
5378         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
5379     }
5380 
5381     /**
5382      * Set the drawing cache quality of this view. This value is used only when the
5383      * drawing cache is enabled
5384      *
5385      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5386      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5387      *
5388      * @see #getDrawingCacheQuality()
5389      * @see #setDrawingCacheEnabled(boolean)
5390      * @see #isDrawingCacheEnabled()
5391      *
5392      * @attr ref android.R.styleable#View_drawingCacheQuality
5393      */
setDrawingCacheQuality(int quality)5394     public void setDrawingCacheQuality(int quality) {
5395         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
5396     }
5397 
5398     /**
5399      * Returns whether the screen should remain on, corresponding to the current
5400      * value of {@link #KEEP_SCREEN_ON}.
5401      *
5402      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
5403      *
5404      * @see #setKeepScreenOn(boolean)
5405      *
5406      * @attr ref android.R.styleable#View_keepScreenOn
5407      */
getKeepScreenOn()5408     public boolean getKeepScreenOn() {
5409         return (mViewFlags & KEEP_SCREEN_ON) != 0;
5410     }
5411 
5412     /**
5413      * Controls whether the screen should remain on, modifying the
5414      * value of {@link #KEEP_SCREEN_ON}.
5415      *
5416      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
5417      *
5418      * @see #getKeepScreenOn()
5419      *
5420      * @attr ref android.R.styleable#View_keepScreenOn
5421      */
setKeepScreenOn(boolean keepScreenOn)5422     public void setKeepScreenOn(boolean keepScreenOn) {
5423         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
5424     }
5425 
5426     /**
5427      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5428      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5429      *
5430      * @attr ref android.R.styleable#View_nextFocusLeft
5431      */
getNextFocusLeftId()5432     public int getNextFocusLeftId() {
5433         return mNextFocusLeftId;
5434     }
5435 
5436     /**
5437      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5438      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
5439      * decide automatically.
5440      *
5441      * @attr ref android.R.styleable#View_nextFocusLeft
5442      */
setNextFocusLeftId(int nextFocusLeftId)5443     public void setNextFocusLeftId(int nextFocusLeftId) {
5444         mNextFocusLeftId = nextFocusLeftId;
5445     }
5446 
5447     /**
5448      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5449      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5450      *
5451      * @attr ref android.R.styleable#View_nextFocusRight
5452      */
getNextFocusRightId()5453     public int getNextFocusRightId() {
5454         return mNextFocusRightId;
5455     }
5456 
5457     /**
5458      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5459      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
5460      * decide automatically.
5461      *
5462      * @attr ref android.R.styleable#View_nextFocusRight
5463      */
setNextFocusRightId(int nextFocusRightId)5464     public void setNextFocusRightId(int nextFocusRightId) {
5465         mNextFocusRightId = nextFocusRightId;
5466     }
5467 
5468     /**
5469      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5470      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5471      *
5472      * @attr ref android.R.styleable#View_nextFocusUp
5473      */
getNextFocusUpId()5474     public int getNextFocusUpId() {
5475         return mNextFocusUpId;
5476     }
5477 
5478     /**
5479      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5480      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
5481      * decide automatically.
5482      *
5483      * @attr ref android.R.styleable#View_nextFocusUp
5484      */
setNextFocusUpId(int nextFocusUpId)5485     public void setNextFocusUpId(int nextFocusUpId) {
5486         mNextFocusUpId = nextFocusUpId;
5487     }
5488 
5489     /**
5490      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5491      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5492      *
5493      * @attr ref android.R.styleable#View_nextFocusDown
5494      */
getNextFocusDownId()5495     public int getNextFocusDownId() {
5496         return mNextFocusDownId;
5497     }
5498 
5499     /**
5500      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5501      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
5502      * decide automatically.
5503      *
5504      * @attr ref android.R.styleable#View_nextFocusDown
5505      */
setNextFocusDownId(int nextFocusDownId)5506     public void setNextFocusDownId(int nextFocusDownId) {
5507         mNextFocusDownId = nextFocusDownId;
5508     }
5509 
5510     /**
5511      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5512      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5513      *
5514      * @attr ref android.R.styleable#View_nextFocusForward
5515      */
getNextFocusForwardId()5516     public int getNextFocusForwardId() {
5517         return mNextFocusForwardId;
5518     }
5519 
5520     /**
5521      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5522      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
5523      * decide automatically.
5524      *
5525      * @attr ref android.R.styleable#View_nextFocusForward
5526      */
setNextFocusForwardId(int nextFocusForwardId)5527     public void setNextFocusForwardId(int nextFocusForwardId) {
5528         mNextFocusForwardId = nextFocusForwardId;
5529     }
5530 
5531     /**
5532      * Returns the visibility of this view and all of its ancestors
5533      *
5534      * @return True if this view and all of its ancestors are {@link #VISIBLE}
5535      */
isShown()5536     public boolean isShown() {
5537         View current = this;
5538         //noinspection ConstantConditions
5539         do {
5540             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
5541                 return false;
5542             }
5543             ViewParent parent = current.mParent;
5544             if (parent == null) {
5545                 return false; // We are not attached to the view root
5546             }
5547             if (!(parent instanceof View)) {
5548                 return true;
5549             }
5550             current = (View) parent;
5551         } while (current != null);
5552 
5553         return false;
5554     }
5555 
5556     /**
5557      * Called by the view hierarchy when the content insets for a window have
5558      * changed, to allow it to adjust its content to fit within those windows.
5559      * The content insets tell you the space that the status bar, input method,
5560      * and other system windows infringe on the application's window.
5561      *
5562      * <p>You do not normally need to deal with this function, since the default
5563      * window decoration given to applications takes care of applying it to the
5564      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
5565      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
5566      * and your content can be placed under those system elements.  You can then
5567      * use this method within your view hierarchy if you have parts of your UI
5568      * which you would like to ensure are not being covered.
5569      *
5570      * <p>The default implementation of this method simply applies the content
5571      * inset's to the view's padding, consuming that content (modifying the
5572      * insets to be 0), and returning true.  This behavior is off by default, but can
5573      * be enabled through {@link #setFitsSystemWindows(boolean)}.
5574      *
5575      * <p>This function's traversal down the hierarchy is depth-first.  The same content
5576      * insets object is propagated down the hierarchy, so any changes made to it will
5577      * be seen by all following views (including potentially ones above in
5578      * the hierarchy since this is a depth-first traversal).  The first view
5579      * that returns true will abort the entire traversal.
5580      *
5581      * <p>The default implementation works well for a situation where it is
5582      * used with a container that covers the entire window, allowing it to
5583      * apply the appropriate insets to its content on all edges.  If you need
5584      * a more complicated layout (such as two different views fitting system
5585      * windows, one on the top of the window, and one on the bottom),
5586      * you can override the method and handle the insets however you would like.
5587      * Note that the insets provided by the framework are always relative to the
5588      * far edges of the window, not accounting for the location of the called view
5589      * within that window.  (In fact when this method is called you do not yet know
5590      * where the layout will place the view, as it is done before layout happens.)
5591      *
5592      * <p>Note: unlike many View methods, there is no dispatch phase to this
5593      * call.  If you are overriding it in a ViewGroup and want to allow the
5594      * call to continue to your children, you must be sure to call the super
5595      * implementation.
5596      *
5597      * <p>Here is a sample layout that makes use of fitting system windows
5598      * to have controls for a video view placed inside of the window decorations
5599      * that it hides and shows.  This can be used with code like the second
5600      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
5601      *
5602      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
5603      *
5604      * @param insets Current content insets of the window.  Prior to
5605      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
5606      * the insets or else you and Android will be unhappy.
5607      *
5608      * @return Return true if this view applied the insets and it should not
5609      * continue propagating further down the hierarchy, false otherwise.
5610      * @see #getFitsSystemWindows()
5611      * @see #setFitsSystemWindows(boolean)
5612      * @see #setSystemUiVisibility(int)
5613      */
fitSystemWindows(Rect insets)5614     protected boolean fitSystemWindows(Rect insets) {
5615         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
5616             mUserPaddingStart = UNDEFINED_PADDING;
5617             mUserPaddingEnd = UNDEFINED_PADDING;
5618             if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
5619                     || mAttachInfo == null
5620                     || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
5621                 internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
5622                 return true;
5623             } else {
5624                 internalSetPadding(0, 0, 0, 0);
5625                 return false;
5626             }
5627         }
5628         return false;
5629     }
5630 
5631     /**
5632      * Sets whether or not this view should account for system screen decorations
5633      * such as the status bar and inset its content; that is, controlling whether
5634      * the default implementation of {@link #fitSystemWindows(Rect)} will be
5635      * executed.  See that method for more details.
5636      *
5637      * <p>Note that if you are providing your own implementation of
5638      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
5639      * flag to true -- your implementation will be overriding the default
5640      * implementation that checks this flag.
5641      *
5642      * @param fitSystemWindows If true, then the default implementation of
5643      * {@link #fitSystemWindows(Rect)} will be executed.
5644      *
5645      * @attr ref android.R.styleable#View_fitsSystemWindows
5646      * @see #getFitsSystemWindows()
5647      * @see #fitSystemWindows(Rect)
5648      * @see #setSystemUiVisibility(int)
5649      */
setFitsSystemWindows(boolean fitSystemWindows)5650     public void setFitsSystemWindows(boolean fitSystemWindows) {
5651         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
5652     }
5653 
5654     /**
5655      * Check for state of {@link #setFitsSystemWindows(boolean). If this method
5656      * returns true, the default implementation of {@link #fitSystemWindows(Rect)}
5657      * will be executed.
5658      *
5659      * @return Returns true if the default implementation of
5660      * {@link #fitSystemWindows(Rect)} will be executed.
5661      *
5662      * @attr ref android.R.styleable#View_fitsSystemWindows
5663      * @see #setFitsSystemWindows()
5664      * @see #fitSystemWindows(Rect)
5665      * @see #setSystemUiVisibility(int)
5666      */
getFitsSystemWindows()5667     public boolean getFitsSystemWindows() {
5668         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
5669     }
5670 
5671     /** @hide */
fitsSystemWindows()5672     public boolean fitsSystemWindows() {
5673         return getFitsSystemWindows();
5674     }
5675 
5676     /**
5677      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
5678      */
requestFitSystemWindows()5679     public void requestFitSystemWindows() {
5680         if (mParent != null) {
5681             mParent.requestFitSystemWindows();
5682         }
5683     }
5684 
5685     /**
5686      * For use by PhoneWindow to make its own system window fitting optional.
5687      * @hide
5688      */
makeOptionalFitsSystemWindows()5689     public void makeOptionalFitsSystemWindows() {
5690         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
5691     }
5692 
5693     /**
5694      * Returns the visibility status for this view.
5695      *
5696      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5697      * @attr ref android.R.styleable#View_visibility
5698      */
5699     @ViewDebug.ExportedProperty(mapping = {
5700         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
5701         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
5702         @ViewDebug.IntToString(from = GONE,      to = "GONE")
5703     })
getVisibility()5704     public int getVisibility() {
5705         return mViewFlags & VISIBILITY_MASK;
5706     }
5707 
5708     /**
5709      * Set the enabled state of this view.
5710      *
5711      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5712      * @attr ref android.R.styleable#View_visibility
5713      */
5714     @RemotableViewMethod
setVisibility(int visibility)5715     public void setVisibility(int visibility) {
5716         setFlags(visibility, VISIBILITY_MASK);
5717         if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
5718     }
5719 
5720     /**
5721      * Returns the enabled status for this view. The interpretation of the
5722      * enabled state varies by subclass.
5723      *
5724      * @return True if this view is enabled, false otherwise.
5725      */
5726     @ViewDebug.ExportedProperty
isEnabled()5727     public boolean isEnabled() {
5728         return (mViewFlags & ENABLED_MASK) == ENABLED;
5729     }
5730 
5731     /**
5732      * Set the enabled state of this view. The interpretation of the enabled
5733      * state varies by subclass.
5734      *
5735      * @param enabled True if this view is enabled, false otherwise.
5736      */
5737     @RemotableViewMethod
setEnabled(boolean enabled)5738     public void setEnabled(boolean enabled) {
5739         if (enabled == isEnabled()) return;
5740 
5741         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
5742 
5743         /*
5744          * The View most likely has to change its appearance, so refresh
5745          * the drawable state.
5746          */
5747         refreshDrawableState();
5748 
5749         // Invalidate too, since the default behavior for views is to be
5750         // be drawn at 50% alpha rather than to change the drawable.
5751         invalidate(true);
5752     }
5753 
5754     /**
5755      * Set whether this view can receive the focus.
5756      *
5757      * Setting this to false will also ensure that this view is not focusable
5758      * in touch mode.
5759      *
5760      * @param focusable If true, this view can receive the focus.
5761      *
5762      * @see #setFocusableInTouchMode(boolean)
5763      * @attr ref android.R.styleable#View_focusable
5764      */
setFocusable(boolean focusable)5765     public void setFocusable(boolean focusable) {
5766         if (!focusable) {
5767             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
5768         }
5769         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
5770     }
5771 
5772     /**
5773      * Set whether this view can receive focus while in touch mode.
5774      *
5775      * Setting this to true will also ensure that this view is focusable.
5776      *
5777      * @param focusableInTouchMode If true, this view can receive the focus while
5778      *   in touch mode.
5779      *
5780      * @see #setFocusable(boolean)
5781      * @attr ref android.R.styleable#View_focusableInTouchMode
5782      */
setFocusableInTouchMode(boolean focusableInTouchMode)5783     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
5784         // Focusable in touch mode should always be set before the focusable flag
5785         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
5786         // which, in touch mode, will not successfully request focus on this view
5787         // because the focusable in touch mode flag is not set
5788         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
5789         if (focusableInTouchMode) {
5790             setFlags(FOCUSABLE, FOCUSABLE_MASK);
5791         }
5792     }
5793 
5794     /**
5795      * Set whether this view should have sound effects enabled for events such as
5796      * clicking and touching.
5797      *
5798      * <p>You may wish to disable sound effects for a view if you already play sounds,
5799      * for instance, a dial key that plays dtmf tones.
5800      *
5801      * @param soundEffectsEnabled whether sound effects are enabled for this view.
5802      * @see #isSoundEffectsEnabled()
5803      * @see #playSoundEffect(int)
5804      * @attr ref android.R.styleable#View_soundEffectsEnabled
5805      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)5806     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
5807         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
5808     }
5809 
5810     /**
5811      * @return whether this view should have sound effects enabled for events such as
5812      *     clicking and touching.
5813      *
5814      * @see #setSoundEffectsEnabled(boolean)
5815      * @see #playSoundEffect(int)
5816      * @attr ref android.R.styleable#View_soundEffectsEnabled
5817      */
5818     @ViewDebug.ExportedProperty
isSoundEffectsEnabled()5819     public boolean isSoundEffectsEnabled() {
5820         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
5821     }
5822 
5823     /**
5824      * Set whether this view should have haptic feedback for events such as
5825      * long presses.
5826      *
5827      * <p>You may wish to disable haptic feedback if your view already controls
5828      * its own haptic feedback.
5829      *
5830      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
5831      * @see #isHapticFeedbackEnabled()
5832      * @see #performHapticFeedback(int)
5833      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5834      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)5835     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
5836         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
5837     }
5838 
5839     /**
5840      * @return whether this view should have haptic feedback enabled for events
5841      * long presses.
5842      *
5843      * @see #setHapticFeedbackEnabled(boolean)
5844      * @see #performHapticFeedback(int)
5845      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5846      */
5847     @ViewDebug.ExportedProperty
isHapticFeedbackEnabled()5848     public boolean isHapticFeedbackEnabled() {
5849         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
5850     }
5851 
5852     /**
5853      * Returns the layout direction for this view.
5854      *
5855      * @return One of {@link #LAYOUT_DIRECTION_LTR},
5856      *   {@link #LAYOUT_DIRECTION_RTL},
5857      *   {@link #LAYOUT_DIRECTION_INHERIT} or
5858      *   {@link #LAYOUT_DIRECTION_LOCALE}.
5859      *
5860      * @attr ref android.R.styleable#View_layoutDirection
5861      *
5862      * @hide
5863      */
5864     @ViewDebug.ExportedProperty(category = "layout", mapping = {
5865         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
5866         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
5867         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
5868         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
5869     })
getRawLayoutDirection()5870     public int getRawLayoutDirection() {
5871         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
5872     }
5873 
5874     /**
5875      * Set the layout direction for this view. This will propagate a reset of layout direction
5876      * resolution to the view's children and resolve layout direction for this view.
5877      *
5878      * @param layoutDirection the layout direction to set. Should be one of:
5879      *
5880      * {@link #LAYOUT_DIRECTION_LTR},
5881      * {@link #LAYOUT_DIRECTION_RTL},
5882      * {@link #LAYOUT_DIRECTION_INHERIT},
5883      * {@link #LAYOUT_DIRECTION_LOCALE}.
5884      *
5885      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
5886      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
5887      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
5888      *
5889      * @attr ref android.R.styleable#View_layoutDirection
5890      */
5891     @RemotableViewMethod
setLayoutDirection(int layoutDirection)5892     public void setLayoutDirection(int layoutDirection) {
5893         if (getRawLayoutDirection() != layoutDirection) {
5894             // Reset the current layout direction and the resolved one
5895             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
5896             resetRtlProperties();
5897             // Set the new layout direction (filtered)
5898             mPrivateFlags2 |=
5899                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
5900             // We need to resolve all RTL properties as they all depend on layout direction
5901             resolveRtlPropertiesIfNeeded();
5902             requestLayout();
5903             invalidate(true);
5904         }
5905     }
5906 
5907     /**
5908      * Returns the resolved layout direction for this view.
5909      *
5910      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
5911      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
5912      *
5913      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
5914      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
5915      *
5916      * @attr ref android.R.styleable#View_layoutDirection
5917      */
5918     @ViewDebug.ExportedProperty(category = "layout", mapping = {
5919         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
5920         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
5921     })
getLayoutDirection()5922     public int getLayoutDirection() {
5923         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
5924         if (targetSdkVersion < JELLY_BEAN_MR1) {
5925             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
5926             return LAYOUT_DIRECTION_LTR;
5927         }
5928         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
5929                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
5930     }
5931 
5932     /**
5933      * Indicates whether or not this view's layout is right-to-left. This is resolved from
5934      * layout attribute and/or the inherited value from the parent
5935      *
5936      * @return true if the layout is right-to-left.
5937      *
5938      * @hide
5939      */
5940     @ViewDebug.ExportedProperty(category = "layout")
isLayoutRtl()5941     public boolean isLayoutRtl() {
5942         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
5943     }
5944 
5945     /**
5946      * Indicates whether the view is currently tracking transient state that the
5947      * app should not need to concern itself with saving and restoring, but that
5948      * the framework should take special note to preserve when possible.
5949      *
5950      * <p>A view with transient state cannot be trivially rebound from an external
5951      * data source, such as an adapter binding item views in a list. This may be
5952      * because the view is performing an animation, tracking user selection
5953      * of content, or similar.</p>
5954      *
5955      * @return true if the view has transient state
5956      */
5957     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()5958     public boolean hasTransientState() {
5959         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
5960     }
5961 
5962     /**
5963      * Set whether this view is currently tracking transient state that the
5964      * framework should attempt to preserve when possible. This flag is reference counted,
5965      * so every call to setHasTransientState(true) should be paired with a later call
5966      * to setHasTransientState(false).
5967      *
5968      * <p>A view with transient state cannot be trivially rebound from an external
5969      * data source, such as an adapter binding item views in a list. This may be
5970      * because the view is performing an animation, tracking user selection
5971      * of content, or similar.</p>
5972      *
5973      * @param hasTransientState true if this view has transient state
5974      */
setHasTransientState(boolean hasTransientState)5975     public void setHasTransientState(boolean hasTransientState) {
5976         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
5977                 mTransientStateCount - 1;
5978         if (mTransientStateCount < 0) {
5979             mTransientStateCount = 0;
5980             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
5981                     "unmatched pair of setHasTransientState calls");
5982         }
5983         if ((hasTransientState && mTransientStateCount == 1) ||
5984                 (!hasTransientState && mTransientStateCount == 0)) {
5985             // update flag if we've just incremented up from 0 or decremented down to 0
5986             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
5987                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
5988             if (mParent != null) {
5989                 try {
5990                     mParent.childHasTransientStateChanged(this, hasTransientState);
5991                 } catch (AbstractMethodError e) {
5992                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
5993                             " does not fully implement ViewParent", e);
5994                 }
5995             }
5996         }
5997     }
5998 
5999     /**
6000      * If this view doesn't do any drawing on its own, set this flag to
6001      * allow further optimizations. By default, this flag is not set on
6002      * View, but could be set on some View subclasses such as ViewGroup.
6003      *
6004      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
6005      * you should clear this flag.
6006      *
6007      * @param willNotDraw whether or not this View draw on its own
6008      */
setWillNotDraw(boolean willNotDraw)6009     public void setWillNotDraw(boolean willNotDraw) {
6010         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
6011     }
6012 
6013     /**
6014      * Returns whether or not this View draws on its own.
6015      *
6016      * @return true if this view has nothing to draw, false otherwise
6017      */
6018     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()6019     public boolean willNotDraw() {
6020         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
6021     }
6022 
6023     /**
6024      * When a View's drawing cache is enabled, drawing is redirected to an
6025      * offscreen bitmap. Some views, like an ImageView, must be able to
6026      * bypass this mechanism if they already draw a single bitmap, to avoid
6027      * unnecessary usage of the memory.
6028      *
6029      * @param willNotCacheDrawing true if this view does not cache its
6030      *        drawing, false otherwise
6031      */
setWillNotCacheDrawing(boolean willNotCacheDrawing)6032     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
6033         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
6034     }
6035 
6036     /**
6037      * Returns whether or not this View can cache its drawing or not.
6038      *
6039      * @return true if this view does not cache its drawing, false otherwise
6040      */
6041     @ViewDebug.ExportedProperty(category = "drawing")
willNotCacheDrawing()6042     public boolean willNotCacheDrawing() {
6043         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
6044     }
6045 
6046     /**
6047      * Indicates whether this view reacts to click events or not.
6048      *
6049      * @return true if the view is clickable, false otherwise
6050      *
6051      * @see #setClickable(boolean)
6052      * @attr ref android.R.styleable#View_clickable
6053      */
6054     @ViewDebug.ExportedProperty
isClickable()6055     public boolean isClickable() {
6056         return (mViewFlags & CLICKABLE) == CLICKABLE;
6057     }
6058 
6059     /**
6060      * Enables or disables click events for this view. When a view
6061      * is clickable it will change its state to "pressed" on every click.
6062      * Subclasses should set the view clickable to visually react to
6063      * user's clicks.
6064      *
6065      * @param clickable true to make the view clickable, false otherwise
6066      *
6067      * @see #isClickable()
6068      * @attr ref android.R.styleable#View_clickable
6069      */
setClickable(boolean clickable)6070     public void setClickable(boolean clickable) {
6071         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
6072     }
6073 
6074     /**
6075      * Indicates whether this view reacts to long click events or not.
6076      *
6077      * @return true if the view is long clickable, false otherwise
6078      *
6079      * @see #setLongClickable(boolean)
6080      * @attr ref android.R.styleable#View_longClickable
6081      */
isLongClickable()6082     public boolean isLongClickable() {
6083         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
6084     }
6085 
6086     /**
6087      * Enables or disables long click events for this view. When a view is long
6088      * clickable it reacts to the user holding down the button for a longer
6089      * duration than a tap. This event can either launch the listener or a
6090      * context menu.
6091      *
6092      * @param longClickable true to make the view long clickable, false otherwise
6093      * @see #isLongClickable()
6094      * @attr ref android.R.styleable#View_longClickable
6095      */
setLongClickable(boolean longClickable)6096     public void setLongClickable(boolean longClickable) {
6097         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
6098     }
6099 
6100     /**
6101      * Sets the pressed state for this view.
6102      *
6103      * @see #isClickable()
6104      * @see #setClickable(boolean)
6105      *
6106      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
6107      *        the View's internal state from a previously set "pressed" state.
6108      */
setPressed(boolean pressed)6109     public void setPressed(boolean pressed) {
6110         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
6111 
6112         if (pressed) {
6113             mPrivateFlags |= PFLAG_PRESSED;
6114         } else {
6115             mPrivateFlags &= ~PFLAG_PRESSED;
6116         }
6117 
6118         if (needsRefresh) {
6119             refreshDrawableState();
6120         }
6121         dispatchSetPressed(pressed);
6122     }
6123 
6124     /**
6125      * Dispatch setPressed to all of this View's children.
6126      *
6127      * @see #setPressed(boolean)
6128      *
6129      * @param pressed The new pressed state
6130      */
dispatchSetPressed(boolean pressed)6131     protected void dispatchSetPressed(boolean pressed) {
6132     }
6133 
6134     /**
6135      * Indicates whether the view is currently in pressed state. Unless
6136      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
6137      * the pressed state.
6138      *
6139      * @see #setPressed(boolean)
6140      * @see #isClickable()
6141      * @see #setClickable(boolean)
6142      *
6143      * @return true if the view is currently pressed, false otherwise
6144      */
isPressed()6145     public boolean isPressed() {
6146         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
6147     }
6148 
6149     /**
6150      * Indicates whether this view will save its state (that is,
6151      * whether its {@link #onSaveInstanceState} method will be called).
6152      *
6153      * @return Returns true if the view state saving is enabled, else false.
6154      *
6155      * @see #setSaveEnabled(boolean)
6156      * @attr ref android.R.styleable#View_saveEnabled
6157      */
isSaveEnabled()6158     public boolean isSaveEnabled() {
6159         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
6160     }
6161 
6162     /**
6163      * Controls whether the saving of this view's state is
6164      * enabled (that is, whether its {@link #onSaveInstanceState} method
6165      * will be called).  Note that even if freezing is enabled, the
6166      * view still must have an id assigned to it (via {@link #setId(int)})
6167      * for its state to be saved.  This flag can only disable the
6168      * saving of this view; any child views may still have their state saved.
6169      *
6170      * @param enabled Set to false to <em>disable</em> state saving, or true
6171      * (the default) to allow it.
6172      *
6173      * @see #isSaveEnabled()
6174      * @see #setId(int)
6175      * @see #onSaveInstanceState()
6176      * @attr ref android.R.styleable#View_saveEnabled
6177      */
setSaveEnabled(boolean enabled)6178     public void setSaveEnabled(boolean enabled) {
6179         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
6180     }
6181 
6182     /**
6183      * Gets whether the framework should discard touches when the view's
6184      * window is obscured by another visible window.
6185      * Refer to the {@link View} security documentation for more details.
6186      *
6187      * @return True if touch filtering is enabled.
6188      *
6189      * @see #setFilterTouchesWhenObscured(boolean)
6190      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
6191      */
6192     @ViewDebug.ExportedProperty
getFilterTouchesWhenObscured()6193     public boolean getFilterTouchesWhenObscured() {
6194         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
6195     }
6196 
6197     /**
6198      * Sets whether the framework should discard touches when the view's
6199      * window is obscured by another visible window.
6200      * Refer to the {@link View} security documentation for more details.
6201      *
6202      * @param enabled True if touch filtering should be enabled.
6203      *
6204      * @see #getFilterTouchesWhenObscured
6205      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
6206      */
setFilterTouchesWhenObscured(boolean enabled)6207     public void setFilterTouchesWhenObscured(boolean enabled) {
6208         setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
6209                 FILTER_TOUCHES_WHEN_OBSCURED);
6210     }
6211 
6212     /**
6213      * Indicates whether the entire hierarchy under this view will save its
6214      * state when a state saving traversal occurs from its parent.  The default
6215      * is true; if false, these views will not be saved unless
6216      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
6217      *
6218      * @return Returns true if the view state saving from parent is enabled, else false.
6219      *
6220      * @see #setSaveFromParentEnabled(boolean)
6221      */
isSaveFromParentEnabled()6222     public boolean isSaveFromParentEnabled() {
6223         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
6224     }
6225 
6226     /**
6227      * Controls whether the entire hierarchy under this view will save its
6228      * state when a state saving traversal occurs from its parent.  The default
6229      * is true; if false, these views will not be saved unless
6230      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
6231      *
6232      * @param enabled Set to false to <em>disable</em> state saving, or true
6233      * (the default) to allow it.
6234      *
6235      * @see #isSaveFromParentEnabled()
6236      * @see #setId(int)
6237      * @see #onSaveInstanceState()
6238      */
setSaveFromParentEnabled(boolean enabled)6239     public void setSaveFromParentEnabled(boolean enabled) {
6240         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
6241     }
6242 
6243 
6244     /**
6245      * Returns whether this View is able to take focus.
6246      *
6247      * @return True if this view can take focus, or false otherwise.
6248      * @attr ref android.R.styleable#View_focusable
6249      */
6250     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()6251     public final boolean isFocusable() {
6252         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
6253     }
6254 
6255     /**
6256      * When a view is focusable, it may not want to take focus when in touch mode.
6257      * For example, a button would like focus when the user is navigating via a D-pad
6258      * so that the user can click on it, but once the user starts touching the screen,
6259      * the button shouldn't take focus
6260      * @return Whether the view is focusable in touch mode.
6261      * @attr ref android.R.styleable#View_focusableInTouchMode
6262      */
6263     @ViewDebug.ExportedProperty
isFocusableInTouchMode()6264     public final boolean isFocusableInTouchMode() {
6265         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
6266     }
6267 
6268     /**
6269      * Find the nearest view in the specified direction that can take focus.
6270      * This does not actually give focus to that view.
6271      *
6272      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6273      *
6274      * @return The nearest focusable in the specified direction, or null if none
6275      *         can be found.
6276      */
focusSearch(int direction)6277     public View focusSearch(int direction) {
6278         if (mParent != null) {
6279             return mParent.focusSearch(this, direction);
6280         } else {
6281             return null;
6282         }
6283     }
6284 
6285     /**
6286      * This method is the last chance for the focused view and its ancestors to
6287      * respond to an arrow key. This is called when the focused view did not
6288      * consume the key internally, nor could the view system find a new view in
6289      * the requested direction to give focus to.
6290      *
6291      * @param focused The currently focused view.
6292      * @param direction The direction focus wants to move. One of FOCUS_UP,
6293      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
6294      * @return True if the this view consumed this unhandled move.
6295      */
dispatchUnhandledMove(View focused, int direction)6296     public boolean dispatchUnhandledMove(View focused, int direction) {
6297         return false;
6298     }
6299 
6300     /**
6301      * If a user manually specified the next view id for a particular direction,
6302      * use the root to look up the view.
6303      * @param root The root view of the hierarchy containing this view.
6304      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
6305      * or FOCUS_BACKWARD.
6306      * @return The user specified next view, or null if there is none.
6307      */
findUserSetNextFocus(View root, int direction)6308     View findUserSetNextFocus(View root, int direction) {
6309         switch (direction) {
6310             case FOCUS_LEFT:
6311                 if (mNextFocusLeftId == View.NO_ID) return null;
6312                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
6313             case FOCUS_RIGHT:
6314                 if (mNextFocusRightId == View.NO_ID) return null;
6315                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
6316             case FOCUS_UP:
6317                 if (mNextFocusUpId == View.NO_ID) return null;
6318                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
6319             case FOCUS_DOWN:
6320                 if (mNextFocusDownId == View.NO_ID) return null;
6321                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
6322             case FOCUS_FORWARD:
6323                 if (mNextFocusForwardId == View.NO_ID) return null;
6324                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
6325             case FOCUS_BACKWARD: {
6326                 if (mID == View.NO_ID) return null;
6327                 final int id = mID;
6328                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
6329                     @Override
6330                     public boolean apply(View t) {
6331                         return t.mNextFocusForwardId == id;
6332                     }
6333                 });
6334             }
6335         }
6336         return null;
6337     }
6338 
6339     private View findViewInsideOutShouldExist(View root, int id) {
6340         if (mMatchIdPredicate == null) {
6341             mMatchIdPredicate = new MatchIdPredicate();
6342         }
6343         mMatchIdPredicate.mId = id;
6344         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
6345         if (result == null) {
6346             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
6347         }
6348         return result;
6349     }
6350 
6351     /**
6352      * Find and return all focusable views that are descendants of this view,
6353      * possibly including this view if it is focusable itself.
6354      *
6355      * @param direction The direction of the focus
6356      * @return A list of focusable views
6357      */
6358     public ArrayList<View> getFocusables(int direction) {
6359         ArrayList<View> result = new ArrayList<View>(24);
6360         addFocusables(result, direction);
6361         return result;
6362     }
6363 
6364     /**
6365      * Add any focusable views that are descendants of this view (possibly
6366      * including this view if it is focusable itself) to views.  If we are in touch mode,
6367      * only add views that are also focusable in touch mode.
6368      *
6369      * @param views Focusable views found so far
6370      * @param direction The direction of the focus
6371      */
6372     public void addFocusables(ArrayList<View> views, int direction) {
6373         addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
6374     }
6375 
6376     /**
6377      * Adds any focusable views that are descendants of this view (possibly
6378      * including this view if it is focusable itself) to views. This method
6379      * adds all focusable views regardless if we are in touch mode or
6380      * only views focusable in touch mode if we are in touch mode or
6381      * only views that can take accessibility focus if accessibility is enabeld
6382      * depending on the focusable mode paramater.
6383      *
6384      * @param views Focusable views found so far or null if all we are interested is
6385      *        the number of focusables.
6386      * @param direction The direction of the focus.
6387      * @param focusableMode The type of focusables to be added.
6388      *
6389      * @see #FOCUSABLES_ALL
6390      * @see #FOCUSABLES_TOUCH_MODE
6391      */
6392     public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
6393         if (views == null) {
6394             return;
6395         }
6396         if (!isFocusable()) {
6397             return;
6398         }
6399         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
6400                 && isInTouchMode() && !isFocusableInTouchMode()) {
6401             return;
6402         }
6403         views.add(this);
6404     }
6405 
6406     /**
6407      * Finds the Views that contain given text. The containment is case insensitive.
6408      * The search is performed by either the text that the View renders or the content
6409      * description that describes the view for accessibility purposes and the view does
6410      * not render or both. Clients can specify how the search is to be performed via
6411      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
6412      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
6413      *
6414      * @param outViews The output list of matching Views.
6415      * @param searched The text to match against.
6416      *
6417      * @see #FIND_VIEWS_WITH_TEXT
6418      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
6419      * @see #setContentDescription(CharSequence)
6420      */
6421     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
6422         if (getAccessibilityNodeProvider() != null) {
6423             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
6424                 outViews.add(this);
6425             }
6426         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
6427                 && (searched != null && searched.length() > 0)
6428                 && (mContentDescription != null && mContentDescription.length() > 0)) {
6429             String searchedLowerCase = searched.toString().toLowerCase();
6430             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
6431             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
6432                 outViews.add(this);
6433             }
6434         }
6435     }
6436 
6437     /**
6438      * Find and return all touchable views that are descendants of this view,
6439      * possibly including this view if it is touchable itself.
6440      *
6441      * @return A list of touchable views
6442      */
6443     public ArrayList<View> getTouchables() {
6444         ArrayList<View> result = new ArrayList<View>();
6445         addTouchables(result);
6446         return result;
6447     }
6448 
6449     /**
6450      * Add any touchable views that are descendants of this view (possibly
6451      * including this view if it is touchable itself) to views.
6452      *
6453      * @param views Touchable views found so far
6454      */
6455     public void addTouchables(ArrayList<View> views) {
6456         final int viewFlags = mViewFlags;
6457 
6458         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
6459                 && (viewFlags & ENABLED_MASK) == ENABLED) {
6460             views.add(this);
6461         }
6462     }
6463 
6464     /**
6465      * Returns whether this View is accessibility focused.
6466      *
6467      * @return True if this View is accessibility focused.
6468      */
6469     boolean isAccessibilityFocused() {
6470         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
6471     }
6472 
6473     /**
6474      * Call this to try to give accessibility focus to this view.
6475      *
6476      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
6477      * returns false or the view is no visible or the view already has accessibility
6478      * focus.
6479      *
6480      * See also {@link #focusSearch(int)}, which is what you call to say that you
6481      * have focus, and you want your parent to look for the next one.
6482      *
6483      * @return Whether this view actually took accessibility focus.
6484      *
6485      * @hide
6486      */
6487     public boolean requestAccessibilityFocus() {
6488         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
6489         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
6490             return false;
6491         }
6492         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6493             return false;
6494         }
6495         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
6496             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
6497             ViewRootImpl viewRootImpl = getViewRootImpl();
6498             if (viewRootImpl != null) {
6499                 viewRootImpl.setAccessibilityFocus(this, null);
6500             }
6501             invalidate();
6502             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
6503             notifyAccessibilityStateChanged();
6504             return true;
6505         }
6506         return false;
6507     }
6508 
6509     /**
6510      * Call this to try to clear accessibility focus of this view.
6511      *
6512      * See also {@link #focusSearch(int)}, which is what you call to say that you
6513      * have focus, and you want your parent to look for the next one.
6514      *
6515      * @hide
6516      */
6517     public void clearAccessibilityFocus() {
6518         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
6519             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
6520             invalidate();
6521             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
6522             notifyAccessibilityStateChanged();
6523         }
6524         // Clear the global reference of accessibility focus if this
6525         // view or any of its descendants had accessibility focus.
6526         ViewRootImpl viewRootImpl = getViewRootImpl();
6527         if (viewRootImpl != null) {
6528             View focusHost = viewRootImpl.getAccessibilityFocusedHost();
6529             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
6530                 viewRootImpl.setAccessibilityFocus(null, null);
6531             }
6532         }
6533     }
6534 
6535     private void sendAccessibilityHoverEvent(int eventType) {
6536         // Since we are not delivering to a client accessibility events from not
6537         // important views (unless the clinet request that) we need to fire the
6538         // event from the deepest view exposed to the client. As a consequence if
6539         // the user crosses a not exposed view the client will see enter and exit
6540         // of the exposed predecessor followed by and enter and exit of that same
6541         // predecessor when entering and exiting the not exposed descendant. This
6542         // is fine since the client has a clear idea which view is hovered at the
6543         // price of a couple more events being sent. This is a simple and
6544         // working solution.
6545         View source = this;
6546         while (true) {
6547             if (source.includeForAccessibility()) {
6548                 source.sendAccessibilityEvent(eventType);
6549                 return;
6550             }
6551             ViewParent parent = source.getParent();
6552             if (parent instanceof View) {
6553                 source = (View) parent;
6554             } else {
6555                 return;
6556             }
6557         }
6558     }
6559 
6560     /**
6561      * Clears accessibility focus without calling any callback methods
6562      * normally invoked in {@link #clearAccessibilityFocus()}. This method
6563      * is used for clearing accessibility focus when giving this focus to
6564      * another view.
6565      */
6566     void clearAccessibilityFocusNoCallbacks() {
6567         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
6568             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
6569             invalidate();
6570         }
6571     }
6572 
6573     /**
6574      * Call this to try to give focus to a specific view or to one of its
6575      * descendants.
6576      *
6577      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6578      * false), or if it is focusable and it is not focusable in touch mode
6579      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
6580      *
6581      * See also {@link #focusSearch(int)}, which is what you call to say that you
6582      * have focus, and you want your parent to look for the next one.
6583      *
6584      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
6585      * {@link #FOCUS_DOWN} and <code>null</code>.
6586      *
6587      * @return Whether this view or one of its descendants actually took focus.
6588      */
6589     public final boolean requestFocus() {
6590         return requestFocus(View.FOCUS_DOWN);
6591     }
6592 
6593     /**
6594      * Call this to try to give focus to a specific view or to one of its
6595      * descendants and give it a hint about what direction focus is heading.
6596      *
6597      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6598      * false), or if it is focusable and it is not focusable in touch mode
6599      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
6600      *
6601      * See also {@link #focusSearch(int)}, which is what you call to say that you
6602      * have focus, and you want your parent to look for the next one.
6603      *
6604      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
6605      * <code>null</code> set for the previously focused rectangle.
6606      *
6607      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6608      * @return Whether this view or one of its descendants actually took focus.
6609      */
6610     public final boolean requestFocus(int direction) {
6611         return requestFocus(direction, null);
6612     }
6613 
6614     /**
6615      * Call this to try to give focus to a specific view or to one of its descendants
6616      * and give it hints about the direction and a specific rectangle that the focus
6617      * is coming from.  The rectangle can help give larger views a finer grained hint
6618      * about where focus is coming from, and therefore, where to show selection, or
6619      * forward focus change internally.
6620      *
6621      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6622      * false), or if it is focusable and it is not focusable in touch mode
6623      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
6624      *
6625      * A View will not take focus if it is not visible.
6626      *
6627      * A View will not take focus if one of its parents has
6628      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
6629      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
6630      *
6631      * See also {@link #focusSearch(int)}, which is what you call to say that you
6632      * have focus, and you want your parent to look for the next one.
6633      *
6634      * You may wish to override this method if your custom {@link View} has an internal
6635      * {@link View} that it wishes to forward the request to.
6636      *
6637      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6638      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
6639      *        to give a finer grained hint about where focus is coming from.  May be null
6640      *        if there is no hint.
6641      * @return Whether this view or one of its descendants actually took focus.
6642      */
6643     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
6644         return requestFocusNoSearch(direction, previouslyFocusedRect);
6645     }
6646 
6647     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
6648         // need to be focusable
6649         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
6650                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6651             return false;
6652         }
6653 
6654         // need to be focusable in touch mode if in touch mode
6655         if (isInTouchMode() &&
6656             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
6657                return false;
6658         }
6659 
6660         // need to not have any parents blocking us
6661         if (hasAncestorThatBlocksDescendantFocus()) {
6662             return false;
6663         }
6664 
6665         handleFocusGainInternal(direction, previouslyFocusedRect);
6666         return true;
6667     }
6668 
6669     /**
6670      * Call this to try to give focus to a specific view or to one of its descendants. This is a
6671      * special variant of {@link #requestFocus() } that will allow views that are not focuable in
6672      * touch mode to request focus when they are touched.
6673      *
6674      * @return Whether this view or one of its descendants actually took focus.
6675      *
6676      * @see #isInTouchMode()
6677      *
6678      */
6679     public final boolean requestFocusFromTouch() {
6680         // Leave touch mode if we need to
6681         if (isInTouchMode()) {
6682             ViewRootImpl viewRoot = getViewRootImpl();
6683             if (viewRoot != null) {
6684                 viewRoot.ensureTouchMode(false);
6685             }
6686         }
6687         return requestFocus(View.FOCUS_DOWN);
6688     }
6689 
6690     /**
6691      * @return Whether any ancestor of this view blocks descendant focus.
6692      */
6693     private boolean hasAncestorThatBlocksDescendantFocus() {
6694         ViewParent ancestor = mParent;
6695         while (ancestor instanceof ViewGroup) {
6696             final ViewGroup vgAncestor = (ViewGroup) ancestor;
6697             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
6698                 return true;
6699             } else {
6700                 ancestor = vgAncestor.getParent();
6701             }
6702         }
6703         return false;
6704     }
6705 
6706     /**
6707      * Gets the mode for determining whether this View is important for accessibility
6708      * which is if it fires accessibility events and if it is reported to
6709      * accessibility services that query the screen.
6710      *
6711      * @return The mode for determining whether a View is important for accessibility.
6712      *
6713      * @attr ref android.R.styleable#View_importantForAccessibility
6714      *
6715      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6716      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6717      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6718      */
6719     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
6720             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
6721             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
6722             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
6723         })
6724     public int getImportantForAccessibility() {
6725         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
6726                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
6727     }
6728 
6729     /**
6730      * Sets how to determine whether this view is important for accessibility
6731      * which is if it fires accessibility events and if it is reported to
6732      * accessibility services that query the screen.
6733      *
6734      * @param mode How to determine whether this view is important for accessibility.
6735      *
6736      * @attr ref android.R.styleable#View_importantForAccessibility
6737      *
6738      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6739      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6740      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6741      */
6742     public void setImportantForAccessibility(int mode) {
6743         if (mode != getImportantForAccessibility()) {
6744             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
6745             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
6746                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
6747             notifyAccessibilityStateChanged();
6748         }
6749     }
6750 
6751     /**
6752      * Gets whether this view should be exposed for accessibility.
6753      *
6754      * @return Whether the view is exposed for accessibility.
6755      *
6756      * @hide
6757      */
6758     public boolean isImportantForAccessibility() {
6759         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
6760                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
6761         switch (mode) {
6762             case IMPORTANT_FOR_ACCESSIBILITY_YES:
6763                 return true;
6764             case IMPORTANT_FOR_ACCESSIBILITY_NO:
6765                 return false;
6766             case IMPORTANT_FOR_ACCESSIBILITY_AUTO:
6767                 return isActionableForAccessibility() || hasListenersForAccessibility()
6768                         || getAccessibilityNodeProvider() != null;
6769             default:
6770                 throw new IllegalArgumentException("Unknow important for accessibility mode: "
6771                         + mode);
6772         }
6773     }
6774 
6775     /**
6776      * Gets the parent for accessibility purposes. Note that the parent for
6777      * accessibility is not necessary the immediate parent. It is the first
6778      * predecessor that is important for accessibility.
6779      *
6780      * @return The parent for accessibility purposes.
6781      */
6782     public ViewParent getParentForAccessibility() {
6783         if (mParent instanceof View) {
6784             View parentView = (View) mParent;
6785             if (parentView.includeForAccessibility()) {
6786                 return mParent;
6787             } else {
6788                 return mParent.getParentForAccessibility();
6789             }
6790         }
6791         return null;
6792     }
6793 
6794     /**
6795      * Adds the children of a given View for accessibility. Since some Views are
6796      * not important for accessibility the children for accessibility are not
6797      * necessarily direct children of the riew, rather they are the first level of
6798      * descendants important for accessibility.
6799      *
6800      * @param children The list of children for accessibility.
6801      */
6802     public void addChildrenForAccessibility(ArrayList<View> children) {
6803         if (includeForAccessibility()) {
6804             children.add(this);
6805         }
6806     }
6807 
6808     /**
6809      * Whether to regard this view for accessibility. A view is regarded for
6810      * accessibility if it is important for accessibility or the querying
6811      * accessibility service has explicitly requested that view not
6812      * important for accessibility are regarded.
6813      *
6814      * @return Whether to regard the view for accessibility.
6815      *
6816      * @hide
6817      */
6818     public boolean includeForAccessibility() {
6819         if (mAttachInfo != null) {
6820             return mAttachInfo.mIncludeNotImportantViews || isImportantForAccessibility();
6821         }
6822         return false;
6823     }
6824 
6825     /**
6826      * Returns whether the View is considered actionable from
6827      * accessibility perspective. Such view are important for
6828      * accessibility.
6829      *
6830      * @return True if the view is actionable for accessibility.
6831      *
6832      * @hide
6833      */
6834     public boolean isActionableForAccessibility() {
6835         return (isClickable() || isLongClickable() || isFocusable());
6836     }
6837 
6838     /**
6839      * Returns whether the View has registered callbacks wich makes it
6840      * important for accessibility.
6841      *
6842      * @return True if the view is actionable for accessibility.
6843      */
6844     private boolean hasListenersForAccessibility() {
6845         ListenerInfo info = getListenerInfo();
6846         return mTouchDelegate != null || info.mOnKeyListener != null
6847                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
6848                 || info.mOnHoverListener != null || info.mOnDragListener != null;
6849     }
6850 
6851     /**
6852      * Notifies accessibility services that some view's important for
6853      * accessibility state has changed. Note that such notifications
6854      * are made at most once every
6855      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
6856      * to avoid unnecessary load to the system. Also once a view has
6857      * made a notifucation this method is a NOP until the notification has
6858      * been sent to clients.
6859      *
6860      * @hide
6861      *
6862      * TODO: Makse sure this method is called for any view state change
6863      *       that is interesting for accessilility purposes.
6864      */
6865     public void notifyAccessibilityStateChanged() {
6866         if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
6867             return;
6868         }
6869         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_STATE_CHANGED) == 0) {
6870             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_STATE_CHANGED;
6871             if (mParent != null) {
6872                 mParent.childAccessibilityStateChanged(this);
6873             }
6874         }
6875     }
6876 
6877     /**
6878      * Reset the state indicating the this view has requested clients
6879      * interested in its accessibility state to be notified.
6880      *
6881      * @hide
6882      */
6883     public void resetAccessibilityStateChanged() {
6884         mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_STATE_CHANGED;
6885     }
6886 
6887     /**
6888      * Performs the specified accessibility action on the view. For
6889      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
6890      * <p>
6891      * If an {@link AccessibilityDelegate} has been specified via calling
6892      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6893      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
6894      * is responsible for handling this call.
6895      * </p>
6896      *
6897      * @param action The action to perform.
6898      * @param arguments Optional action arguments.
6899      * @return Whether the action was performed.
6900      */
6901     public boolean performAccessibilityAction(int action, Bundle arguments) {
6902       if (mAccessibilityDelegate != null) {
6903           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
6904       } else {
6905           return performAccessibilityActionInternal(action, arguments);
6906       }
6907     }
6908 
6909    /**
6910     * @see #performAccessibilityAction(int, Bundle)
6911     *
6912     * Note: Called from the default {@link AccessibilityDelegate}.
6913     */
6914     boolean performAccessibilityActionInternal(int action, Bundle arguments) {
6915         switch (action) {
6916             case AccessibilityNodeInfo.ACTION_CLICK: {
6917                 if (isClickable()) {
6918                     performClick();
6919                     return true;
6920                 }
6921             } break;
6922             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
6923                 if (isLongClickable()) {
6924                     performLongClick();
6925                     return true;
6926                 }
6927             } break;
6928             case AccessibilityNodeInfo.ACTION_FOCUS: {
6929                 if (!hasFocus()) {
6930                     // Get out of touch mode since accessibility
6931                     // wants to move focus around.
6932                     getViewRootImpl().ensureTouchMode(false);
6933                     return requestFocus();
6934                 }
6935             } break;
6936             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
6937                 if (hasFocus()) {
6938                     clearFocus();
6939                     return !isFocused();
6940                 }
6941             } break;
6942             case AccessibilityNodeInfo.ACTION_SELECT: {
6943                 if (!isSelected()) {
6944                     setSelected(true);
6945                     return isSelected();
6946                 }
6947             } break;
6948             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
6949                 if (isSelected()) {
6950                     setSelected(false);
6951                     return !isSelected();
6952                 }
6953             } break;
6954             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
6955                 if (!isAccessibilityFocused()) {
6956                     return requestAccessibilityFocus();
6957                 }
6958             } break;
6959             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
6960                 if (isAccessibilityFocused()) {
6961                     clearAccessibilityFocus();
6962                     return true;
6963                 }
6964             } break;
6965             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
6966                 if (arguments != null) {
6967                     final int granularity = arguments.getInt(
6968                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
6969                     return nextAtGranularity(granularity);
6970                 }
6971             } break;
6972             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
6973                 if (arguments != null) {
6974                     final int granularity = arguments.getInt(
6975                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
6976                     return previousAtGranularity(granularity);
6977                 }
6978             } break;
6979         }
6980         return false;
6981     }
6982 
6983     private boolean nextAtGranularity(int granularity) {
6984         CharSequence text = getIterableTextForAccessibility();
6985         if (text == null || text.length() == 0) {
6986             return false;
6987         }
6988         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
6989         if (iterator == null) {
6990             return false;
6991         }
6992         final int current = getAccessibilityCursorPosition();
6993         final int[] range = iterator.following(current);
6994         if (range == null) {
6995             return false;
6996         }
6997         final int start = range[0];
6998         final int end = range[1];
6999         setAccessibilityCursorPosition(end);
7000         sendViewTextTraversedAtGranularityEvent(
7001                 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
7002                 granularity, start, end);
7003         return true;
7004     }
7005 
7006     private boolean previousAtGranularity(int granularity) {
7007         CharSequence text = getIterableTextForAccessibility();
7008         if (text == null || text.length() == 0) {
7009             return false;
7010         }
7011         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
7012         if (iterator == null) {
7013             return false;
7014         }
7015         int current = getAccessibilityCursorPosition();
7016         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
7017             current = text.length();
7018             setAccessibilityCursorPosition(current);
7019         } else if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
7020             // When traversing by character we always put the cursor after the character
7021             // to ease edit and have to compensate before asking the for previous segment.
7022             current--;
7023             setAccessibilityCursorPosition(current);
7024         }
7025         final int[] range = iterator.preceding(current);
7026         if (range == null) {
7027             return false;
7028         }
7029         final int start = range[0];
7030         final int end = range[1];
7031         // Always put the cursor after the character to ease edit.
7032         if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
7033             setAccessibilityCursorPosition(end);
7034         } else {
7035             setAccessibilityCursorPosition(start);
7036         }
7037         sendViewTextTraversedAtGranularityEvent(
7038                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
7039                 granularity, start, end);
7040         return true;
7041     }
7042 
7043     /**
7044      * Gets the text reported for accessibility purposes.
7045      *
7046      * @return The accessibility text.
7047      *
7048      * @hide
7049      */
7050     public CharSequence getIterableTextForAccessibility() {
7051         return getContentDescription();
7052     }
7053 
7054     /**
7055      * @hide
7056      */
7057     public int getAccessibilityCursorPosition() {
7058         return mAccessibilityCursorPosition;
7059     }
7060 
7061     /**
7062      * @hide
7063      */
7064     public void setAccessibilityCursorPosition(int position) {
7065         mAccessibilityCursorPosition = position;
7066     }
7067 
7068     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
7069             int fromIndex, int toIndex) {
7070         if (mParent == null) {
7071             return;
7072         }
7073         AccessibilityEvent event = AccessibilityEvent.obtain(
7074                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
7075         onInitializeAccessibilityEvent(event);
7076         onPopulateAccessibilityEvent(event);
7077         event.setFromIndex(fromIndex);
7078         event.setToIndex(toIndex);
7079         event.setAction(action);
7080         event.setMovementGranularity(granularity);
7081         mParent.requestSendAccessibilityEvent(this, event);
7082     }
7083 
7084     /**
7085      * @hide
7086      */
7087     public TextSegmentIterator getIteratorForGranularity(int granularity) {
7088         switch (granularity) {
7089             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
7090                 CharSequence text = getIterableTextForAccessibility();
7091                 if (text != null && text.length() > 0) {
7092                     CharacterTextSegmentIterator iterator =
7093                         CharacterTextSegmentIterator.getInstance(
7094                                 mContext.getResources().getConfiguration().locale);
7095                     iterator.initialize(text.toString());
7096                     return iterator;
7097                 }
7098             } break;
7099             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
7100                 CharSequence text = getIterableTextForAccessibility();
7101                 if (text != null && text.length() > 0) {
7102                     WordTextSegmentIterator iterator =
7103                         WordTextSegmentIterator.getInstance(
7104                                 mContext.getResources().getConfiguration().locale);
7105                     iterator.initialize(text.toString());
7106                     return iterator;
7107                 }
7108             } break;
7109             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
7110                 CharSequence text = getIterableTextForAccessibility();
7111                 if (text != null && text.length() > 0) {
7112                     ParagraphTextSegmentIterator iterator =
7113                         ParagraphTextSegmentIterator.getInstance();
7114                     iterator.initialize(text.toString());
7115                     return iterator;
7116                 }
7117             } break;
7118         }
7119         return null;
7120     }
7121 
7122     /**
7123      * @hide
7124      */
7125     public void dispatchStartTemporaryDetach() {
7126         clearAccessibilityFocus();
7127         clearDisplayList();
7128 
7129         onStartTemporaryDetach();
7130     }
7131 
7132     /**
7133      * This is called when a container is going to temporarily detach a child, with
7134      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
7135      * It will either be followed by {@link #onFinishTemporaryDetach()} or
7136      * {@link #onDetachedFromWindow()} when the container is done.
7137      */
7138     public void onStartTemporaryDetach() {
7139         removeUnsetPressCallback();
7140         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
7141     }
7142 
7143     /**
7144      * @hide
7145      */
7146     public void dispatchFinishTemporaryDetach() {
7147         onFinishTemporaryDetach();
7148     }
7149 
7150     /**
7151      * Called after {@link #onStartTemporaryDetach} when the container is done
7152      * changing the view.
7153      */
7154     public void onFinishTemporaryDetach() {
7155     }
7156 
7157     /**
7158      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
7159      * for this view's window.  Returns null if the view is not currently attached
7160      * to the window.  Normally you will not need to use this directly, but
7161      * just use the standard high-level event callbacks like
7162      * {@link #onKeyDown(int, KeyEvent)}.
7163      */
7164     public KeyEvent.DispatcherState getKeyDispatcherState() {
7165         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
7166     }
7167 
7168     /**
7169      * Dispatch a key event before it is processed by any input method
7170      * associated with the view hierarchy.  This can be used to intercept
7171      * key events in special situations before the IME consumes them; a
7172      * typical example would be handling the BACK key to update the application's
7173      * UI instead of allowing the IME to see it and close itself.
7174      *
7175      * @param event The key event to be dispatched.
7176      * @return True if the event was handled, false otherwise.
7177      */
7178     public boolean dispatchKeyEventPreIme(KeyEvent event) {
7179         return onKeyPreIme(event.getKeyCode(), event);
7180     }
7181 
7182     /**
7183      * Dispatch a key event to the next view on the focus path. This path runs
7184      * from the top of the view tree down to the currently focused view. If this
7185      * view has focus, it will dispatch to itself. Otherwise it will dispatch
7186      * the next node down the focus path. This method also fires any key
7187      * listeners.
7188      *
7189      * @param event The key event to be dispatched.
7190      * @return True if the event was handled, false otherwise.
7191      */
7192     public boolean dispatchKeyEvent(KeyEvent event) {
7193         if (mInputEventConsistencyVerifier != null) {
7194             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
7195         }
7196 
7197         // Give any attached key listener a first crack at the event.
7198         //noinspection SimplifiableIfStatement
7199         ListenerInfo li = mListenerInfo;
7200         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
7201                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
7202             return true;
7203         }
7204 
7205         if (event.dispatch(this, mAttachInfo != null
7206                 ? mAttachInfo.mKeyDispatchState : null, this)) {
7207             return true;
7208         }
7209 
7210         if (mInputEventConsistencyVerifier != null) {
7211             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7212         }
7213         return false;
7214     }
7215 
7216     /**
7217      * Dispatches a key shortcut event.
7218      *
7219      * @param event The key event to be dispatched.
7220      * @return True if the event was handled by the view, false otherwise.
7221      */
7222     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7223         return onKeyShortcut(event.getKeyCode(), event);
7224     }
7225 
7226     /**
7227      * Pass the touch screen motion event down to the target view, or this
7228      * view if it is the target.
7229      *
7230      * @param event The motion event to be dispatched.
7231      * @return True if the event was handled by the view, false otherwise.
7232      */
7233     public boolean dispatchTouchEvent(MotionEvent event) {
7234         if (mInputEventConsistencyVerifier != null) {
7235             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
7236         }
7237 
7238         if (onFilterTouchEventForSecurity(event)) {
7239             //noinspection SimplifiableIfStatement
7240             ListenerInfo li = mListenerInfo;
7241             if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
7242                     && li.mOnTouchListener.onTouch(this, event)) {
7243                 return true;
7244             }
7245 
7246             if (onTouchEvent(event)) {
7247                 return true;
7248             }
7249         }
7250 
7251         if (mInputEventConsistencyVerifier != null) {
7252             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7253         }
7254         return false;
7255     }
7256 
7257     /**
7258      * Filter the touch event to apply security policies.
7259      *
7260      * @param event The motion event to be filtered.
7261      * @return True if the event should be dispatched, false if the event should be dropped.
7262      *
7263      * @see #getFilterTouchesWhenObscured
7264      */
7265     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
7266         //noinspection RedundantIfStatement
7267         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
7268                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
7269             // Window is obscured, drop this touch.
7270             return false;
7271         }
7272         return true;
7273     }
7274 
7275     /**
7276      * Pass a trackball motion event down to the focused view.
7277      *
7278      * @param event The motion event to be dispatched.
7279      * @return True if the event was handled by the view, false otherwise.
7280      */
7281     public boolean dispatchTrackballEvent(MotionEvent event) {
7282         if (mInputEventConsistencyVerifier != null) {
7283             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
7284         }
7285 
7286         return onTrackballEvent(event);
7287     }
7288 
7289     /**
7290      * Dispatch a generic motion event.
7291      * <p>
7292      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
7293      * are delivered to the view under the pointer.  All other generic motion events are
7294      * delivered to the focused view.  Hover events are handled specially and are delivered
7295      * to {@link #onHoverEvent(MotionEvent)}.
7296      * </p>
7297      *
7298      * @param event The motion event to be dispatched.
7299      * @return True if the event was handled by the view, false otherwise.
7300      */
7301     public boolean dispatchGenericMotionEvent(MotionEvent event) {
7302         if (mInputEventConsistencyVerifier != null) {
7303             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
7304         }
7305 
7306         final int source = event.getSource();
7307         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
7308             final int action = event.getAction();
7309             if (action == MotionEvent.ACTION_HOVER_ENTER
7310                     || action == MotionEvent.ACTION_HOVER_MOVE
7311                     || action == MotionEvent.ACTION_HOVER_EXIT) {
7312                 if (dispatchHoverEvent(event)) {
7313                     return true;
7314                 }
7315             } else if (dispatchGenericPointerEvent(event)) {
7316                 return true;
7317             }
7318         } else if (dispatchGenericFocusedEvent(event)) {
7319             return true;
7320         }
7321 
7322         if (dispatchGenericMotionEventInternal(event)) {
7323             return true;
7324         }
7325 
7326         if (mInputEventConsistencyVerifier != null) {
7327             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7328         }
7329         return false;
7330     }
7331 
7332     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
7333         //noinspection SimplifiableIfStatement
7334         ListenerInfo li = mListenerInfo;
7335         if (li != null && li.mOnGenericMotionListener != null
7336                 && (mViewFlags & ENABLED_MASK) == ENABLED
7337                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
7338             return true;
7339         }
7340 
7341         if (onGenericMotionEvent(event)) {
7342             return true;
7343         }
7344 
7345         if (mInputEventConsistencyVerifier != null) {
7346             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7347         }
7348         return false;
7349     }
7350 
7351     /**
7352      * Dispatch a hover event.
7353      * <p>
7354      * Do not call this method directly.
7355      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
7356      * </p>
7357      *
7358      * @param event The motion event to be dispatched.
7359      * @return True if the event was handled by the view, false otherwise.
7360      */
7361     protected boolean dispatchHoverEvent(MotionEvent event) {
7362         //noinspection SimplifiableIfStatement
7363         ListenerInfo li = mListenerInfo;
7364         if (li != null && li.mOnHoverListener != null
7365                 && (mViewFlags & ENABLED_MASK) == ENABLED
7366                 && li.mOnHoverListener.onHover(this, event)) {
7367             return true;
7368         }
7369 
7370         return onHoverEvent(event);
7371     }
7372 
7373     /**
7374      * Returns true if the view has a child to which it has recently sent
7375      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
7376      * it does not have a hovered child, then it must be the innermost hovered view.
7377      * @hide
7378      */
7379     protected boolean hasHoveredChild() {
7380         return false;
7381     }
7382 
7383     /**
7384      * Dispatch a generic motion event to the view under the first pointer.
7385      * <p>
7386      * Do not call this method directly.
7387      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
7388      * </p>
7389      *
7390      * @param event The motion event to be dispatched.
7391      * @return True if the event was handled by the view, false otherwise.
7392      */
7393     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
7394         return false;
7395     }
7396 
7397     /**
7398      * Dispatch a generic motion event to the currently focused view.
7399      * <p>
7400      * Do not call this method directly.
7401      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
7402      * </p>
7403      *
7404      * @param event The motion event to be dispatched.
7405      * @return True if the event was handled by the view, false otherwise.
7406      */
7407     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
7408         return false;
7409     }
7410 
7411     /**
7412      * Dispatch a pointer event.
7413      * <p>
7414      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
7415      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
7416      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
7417      * and should not be expected to handle other pointing device features.
7418      * </p>
7419      *
7420      * @param event The motion event to be dispatched.
7421      * @return True if the event was handled by the view, false otherwise.
7422      * @hide
7423      */
7424     public final boolean dispatchPointerEvent(MotionEvent event) {
7425         if (event.isTouchEvent()) {
7426             return dispatchTouchEvent(event);
7427         } else {
7428             return dispatchGenericMotionEvent(event);
7429         }
7430     }
7431 
7432     /**
7433      * Called when the window containing this view gains or loses window focus.
7434      * ViewGroups should override to route to their children.
7435      *
7436      * @param hasFocus True if the window containing this view now has focus,
7437      *        false otherwise.
7438      */
7439     public void dispatchWindowFocusChanged(boolean hasFocus) {
7440         onWindowFocusChanged(hasFocus);
7441     }
7442 
7443     /**
7444      * Called when the window containing this view gains or loses focus.  Note
7445      * that this is separate from view focus: to receive key events, both
7446      * your view and its window must have focus.  If a window is displayed
7447      * on top of yours that takes input focus, then your own window will lose
7448      * focus but the view focus will remain unchanged.
7449      *
7450      * @param hasWindowFocus True if the window containing this view now has
7451      *        focus, false otherwise.
7452      */
7453     public void onWindowFocusChanged(boolean hasWindowFocus) {
7454         InputMethodManager imm = InputMethodManager.peekInstance();
7455         if (!hasWindowFocus) {
7456             if (isPressed()) {
7457                 setPressed(false);
7458             }
7459             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
7460                 imm.focusOut(this);
7461             }
7462             removeLongPressCallback();
7463             removeTapCallback();
7464             onFocusLost();
7465         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
7466             imm.focusIn(this);
7467         }
7468         refreshDrawableState();
7469     }
7470 
7471     /**
7472      * Returns true if this view is in a window that currently has window focus.
7473      * Note that this is not the same as the view itself having focus.
7474      *
7475      * @return True if this view is in a window that currently has window focus.
7476      */
7477     public boolean hasWindowFocus() {
7478         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
7479     }
7480 
7481     /**
7482      * Dispatch a view visibility change down the view hierarchy.
7483      * ViewGroups should override to route to their children.
7484      * @param changedView The view whose visibility changed. Could be 'this' or
7485      * an ancestor view.
7486      * @param visibility The new visibility of changedView: {@link #VISIBLE},
7487      * {@link #INVISIBLE} or {@link #GONE}.
7488      */
7489     protected void dispatchVisibilityChanged(View changedView, int visibility) {
7490         onVisibilityChanged(changedView, visibility);
7491     }
7492 
7493     /**
7494      * Called when the visibility of the view or an ancestor of the view is changed.
7495      * @param changedView The view whose visibility changed. Could be 'this' or
7496      * an ancestor view.
7497      * @param visibility The new visibility of changedView: {@link #VISIBLE},
7498      * {@link #INVISIBLE} or {@link #GONE}.
7499      */
7500     protected void onVisibilityChanged(View changedView, int visibility) {
7501         if (visibility == VISIBLE) {
7502             if (mAttachInfo != null) {
7503                 initialAwakenScrollBars();
7504             } else {
7505                 mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
7506             }
7507         }
7508     }
7509 
7510     /**
7511      * Dispatch a hint about whether this view is displayed. For instance, when
7512      * a View moves out of the screen, it might receives a display hint indicating
7513      * the view is not displayed. Applications should not <em>rely</em> on this hint
7514      * as there is no guarantee that they will receive one.
7515      *
7516      * @param hint A hint about whether or not this view is displayed:
7517      * {@link #VISIBLE} or {@link #INVISIBLE}.
7518      */
7519     public void dispatchDisplayHint(int hint) {
7520         onDisplayHint(hint);
7521     }
7522 
7523     /**
7524      * Gives this view a hint about whether is displayed or not. For instance, when
7525      * a View moves out of the screen, it might receives a display hint indicating
7526      * the view is not displayed. Applications should not <em>rely</em> on this hint
7527      * as there is no guarantee that they will receive one.
7528      *
7529      * @param hint A hint about whether or not this view is displayed:
7530      * {@link #VISIBLE} or {@link #INVISIBLE}.
7531      */
7532     protected void onDisplayHint(int hint) {
7533     }
7534 
7535     /**
7536      * Dispatch a window visibility change down the view hierarchy.
7537      * ViewGroups should override to route to their children.
7538      *
7539      * @param visibility The new visibility of the window.
7540      *
7541      * @see #onWindowVisibilityChanged(int)
7542      */
7543     public void dispatchWindowVisibilityChanged(int visibility) {
7544         onWindowVisibilityChanged(visibility);
7545     }
7546 
7547     /**
7548      * Called when the window containing has change its visibility
7549      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
7550      * that this tells you whether or not your window is being made visible
7551      * to the window manager; this does <em>not</em> tell you whether or not
7552      * your window is obscured by other windows on the screen, even if it
7553      * is itself visible.
7554      *
7555      * @param visibility The new visibility of the window.
7556      */
7557     protected void onWindowVisibilityChanged(int visibility) {
7558         if (visibility == VISIBLE) {
7559             initialAwakenScrollBars();
7560         }
7561     }
7562 
7563     /**
7564      * Returns the current visibility of the window this view is attached to
7565      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
7566      *
7567      * @return Returns the current visibility of the view's window.
7568      */
7569     public int getWindowVisibility() {
7570         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
7571     }
7572 
7573     /**
7574      * Retrieve the overall visible display size in which the window this view is
7575      * attached to has been positioned in.  This takes into account screen
7576      * decorations above the window, for both cases where the window itself
7577      * is being position inside of them or the window is being placed under
7578      * then and covered insets are used for the window to position its content
7579      * inside.  In effect, this tells you the available area where content can
7580      * be placed and remain visible to users.
7581      *
7582      * <p>This function requires an IPC back to the window manager to retrieve
7583      * the requested information, so should not be used in performance critical
7584      * code like drawing.
7585      *
7586      * @param outRect Filled in with the visible display frame.  If the view
7587      * is not attached to a window, this is simply the raw display size.
7588      */
7589     public void getWindowVisibleDisplayFrame(Rect outRect) {
7590         if (mAttachInfo != null) {
7591             try {
7592                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
7593             } catch (RemoteException e) {
7594                 return;
7595             }
7596             // XXX This is really broken, and probably all needs to be done
7597             // in the window manager, and we need to know more about whether
7598             // we want the area behind or in front of the IME.
7599             final Rect insets = mAttachInfo.mVisibleInsets;
7600             outRect.left += insets.left;
7601             outRect.top += insets.top;
7602             outRect.right -= insets.right;
7603             outRect.bottom -= insets.bottom;
7604             return;
7605         }
7606         // The view is not attached to a display so we don't have a context.
7607         // Make a best guess about the display size.
7608         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
7609         d.getRectSize(outRect);
7610     }
7611 
7612     /**
7613      * Dispatch a notification about a resource configuration change down
7614      * the view hierarchy.
7615      * ViewGroups should override to route to their children.
7616      *
7617      * @param newConfig The new resource configuration.
7618      *
7619      * @see #onConfigurationChanged(android.content.res.Configuration)
7620      */
7621     public void dispatchConfigurationChanged(Configuration newConfig) {
7622         onConfigurationChanged(newConfig);
7623     }
7624 
7625     /**
7626      * Called when the current configuration of the resources being used
7627      * by the application have changed.  You can use this to decide when
7628      * to reload resources that can changed based on orientation and other
7629      * configuration characterstics.  You only need to use this if you are
7630      * not relying on the normal {@link android.app.Activity} mechanism of
7631      * recreating the activity instance upon a configuration change.
7632      *
7633      * @param newConfig The new resource configuration.
7634      */
7635     protected void onConfigurationChanged(Configuration newConfig) {
7636     }
7637 
7638     /**
7639      * Private function to aggregate all per-view attributes in to the view
7640      * root.
7641      */
7642     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7643         performCollectViewAttributes(attachInfo, visibility);
7644     }
7645 
7646     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7647         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
7648             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
7649                 attachInfo.mKeepScreenOn = true;
7650             }
7651             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
7652             ListenerInfo li = mListenerInfo;
7653             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
7654                 attachInfo.mHasSystemUiListeners = true;
7655             }
7656         }
7657     }
7658 
7659     void needGlobalAttributesUpdate(boolean force) {
7660         final AttachInfo ai = mAttachInfo;
7661         if (ai != null && !ai.mRecomputeGlobalAttributes) {
7662             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
7663                     || ai.mHasSystemUiListeners) {
7664                 ai.mRecomputeGlobalAttributes = true;
7665             }
7666         }
7667     }
7668 
7669     /**
7670      * Returns whether the device is currently in touch mode.  Touch mode is entered
7671      * once the user begins interacting with the device by touch, and affects various
7672      * things like whether focus is always visible to the user.
7673      *
7674      * @return Whether the device is in touch mode.
7675      */
7676     @ViewDebug.ExportedProperty
7677     public boolean isInTouchMode() {
7678         if (mAttachInfo != null) {
7679             return mAttachInfo.mInTouchMode;
7680         } else {
7681             return ViewRootImpl.isInTouchMode();
7682         }
7683     }
7684 
7685     /**
7686      * Returns the context the view is running in, through which it can
7687      * access the current theme, resources, etc.
7688      *
7689      * @return The view's Context.
7690      */
7691     @ViewDebug.CapturedViewProperty
7692     public final Context getContext() {
7693         return mContext;
7694     }
7695 
7696     /**
7697      * Handle a key event before it is processed by any input method
7698      * associated with the view hierarchy.  This can be used to intercept
7699      * key events in special situations before the IME consumes them; a
7700      * typical example would be handling the BACK key to update the application's
7701      * UI instead of allowing the IME to see it and close itself.
7702      *
7703      * @param keyCode The value in event.getKeyCode().
7704      * @param event Description of the key event.
7705      * @return If you handled the event, return true. If you want to allow the
7706      *         event to be handled by the next receiver, return false.
7707      */
7708     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
7709         return false;
7710     }
7711 
7712     /**
7713      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
7714      * KeyEvent.Callback.onKeyDown()}: perform press of the view
7715      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
7716      * is released, if the view is enabled and clickable.
7717      *
7718      * <p>Key presses in software keyboards will generally NOT trigger this listener,
7719      * although some may elect to do so in some situations. Do not rely on this to
7720      * catch software key presses.
7721      *
7722      * @param keyCode A key code that represents the button pressed, from
7723      *                {@link android.view.KeyEvent}.
7724      * @param event   The KeyEvent object that defines the button action.
7725      */
7726     public boolean onKeyDown(int keyCode, KeyEvent event) {
7727         boolean result = false;
7728 
7729         switch (keyCode) {
7730             case KeyEvent.KEYCODE_DPAD_CENTER:
7731             case KeyEvent.KEYCODE_ENTER: {
7732                 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7733                     return true;
7734                 }
7735                 // Long clickable items don't necessarily have to be clickable
7736                 if (((mViewFlags & CLICKABLE) == CLICKABLE ||
7737                         (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
7738                         (event.getRepeatCount() == 0)) {
7739                     setPressed(true);
7740                     checkForLongClick(0);
7741                     return true;
7742                 }
7743                 break;
7744             }
7745         }
7746         return result;
7747     }
7748 
7749     /**
7750      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
7751      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
7752      * the event).
7753      * <p>Key presses in software keyboards will generally NOT trigger this listener,
7754      * although some may elect to do so in some situations. Do not rely on this to
7755      * catch software key presses.
7756      */
7757     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
7758         return false;
7759     }
7760 
7761     /**
7762      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
7763      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
7764      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
7765      * {@link KeyEvent#KEYCODE_ENTER} is released.
7766      * <p>Key presses in software keyboards will generally NOT trigger this listener,
7767      * although some may elect to do so in some situations. Do not rely on this to
7768      * catch software key presses.
7769      *
7770      * @param keyCode A key code that represents the button pressed, from
7771      *                {@link android.view.KeyEvent}.
7772      * @param event   The KeyEvent object that defines the button action.
7773      */
7774     public boolean onKeyUp(int keyCode, KeyEvent event) {
7775         boolean result = false;
7776 
7777         switch (keyCode) {
7778             case KeyEvent.KEYCODE_DPAD_CENTER:
7779             case KeyEvent.KEYCODE_ENTER: {
7780                 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7781                     return true;
7782                 }
7783                 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
7784                     setPressed(false);
7785 
7786                     if (!mHasPerformedLongPress) {
7787                         // This is a tap, so remove the longpress check
7788                         removeLongPressCallback();
7789 
7790                         result = performClick();
7791                     }
7792                 }
7793                 break;
7794             }
7795         }
7796         return result;
7797     }
7798 
7799     /**
7800      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
7801      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
7802      * the event).
7803      * <p>Key presses in software keyboards will generally NOT trigger this listener,
7804      * although some may elect to do so in some situations. Do not rely on this to
7805      * catch software key presses.
7806      *
7807      * @param keyCode     A key code that represents the button pressed, from
7808      *                    {@link android.view.KeyEvent}.
7809      * @param repeatCount The number of times the action was made.
7810      * @param event       The KeyEvent object that defines the button action.
7811      */
7812     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
7813         return false;
7814     }
7815 
7816     /**
7817      * Called on the focused view when a key shortcut event is not handled.
7818      * Override this method to implement local key shortcuts for the View.
7819      * Key shortcuts can also be implemented by setting the
7820      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
7821      *
7822      * @param keyCode The value in event.getKeyCode().
7823      * @param event Description of the key event.
7824      * @return If you handled the event, return true. If you want to allow the
7825      *         event to be handled by the next receiver, return false.
7826      */
7827     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
7828         return false;
7829     }
7830 
7831     /**
7832      * Check whether the called view is a text editor, in which case it
7833      * would make sense to automatically display a soft input window for
7834      * it.  Subclasses should override this if they implement
7835      * {@link #onCreateInputConnection(EditorInfo)} to return true if
7836      * a call on that method would return a non-null InputConnection, and
7837      * they are really a first-class editor that the user would normally
7838      * start typing on when the go into a window containing your view.
7839      *
7840      * <p>The default implementation always returns false.  This does
7841      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
7842      * will not be called or the user can not otherwise perform edits on your
7843      * view; it is just a hint to the system that this is not the primary
7844      * purpose of this view.
7845      *
7846      * @return Returns true if this view is a text editor, else false.
7847      */
7848     public boolean onCheckIsTextEditor() {
7849         return false;
7850     }
7851 
7852     /**
7853      * Create a new InputConnection for an InputMethod to interact
7854      * with the view.  The default implementation returns null, since it doesn't
7855      * support input methods.  You can override this to implement such support.
7856      * This is only needed for views that take focus and text input.
7857      *
7858      * <p>When implementing this, you probably also want to implement
7859      * {@link #onCheckIsTextEditor()} to indicate you will return a
7860      * non-null InputConnection.
7861      *
7862      * @param outAttrs Fill in with attribute information about the connection.
7863      */
7864     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
7865         return null;
7866     }
7867 
7868     /**
7869      * Called by the {@link android.view.inputmethod.InputMethodManager}
7870      * when a view who is not the current
7871      * input connection target is trying to make a call on the manager.  The
7872      * default implementation returns false; you can override this to return
7873      * true for certain views if you are performing InputConnection proxying
7874      * to them.
7875      * @param view The View that is making the InputMethodManager call.
7876      * @return Return true to allow the call, false to reject.
7877      */
7878     public boolean checkInputConnectionProxy(View view) {
7879         return false;
7880     }
7881 
7882     /**
7883      * Show the context menu for this view. It is not safe to hold on to the
7884      * menu after returning from this method.
7885      *
7886      * You should normally not overload this method. Overload
7887      * {@link #onCreateContextMenu(ContextMenu)} or define an
7888      * {@link OnCreateContextMenuListener} to add items to the context menu.
7889      *
7890      * @param menu The context menu to populate
7891      */
7892     public void createContextMenu(ContextMenu menu) {
7893         ContextMenuInfo menuInfo = getContextMenuInfo();
7894 
7895         // Sets the current menu info so all items added to menu will have
7896         // my extra info set.
7897         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
7898 
7899         onCreateContextMenu(menu);
7900         ListenerInfo li = mListenerInfo;
7901         if (li != null && li.mOnCreateContextMenuListener != null) {
7902             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
7903         }
7904 
7905         // Clear the extra information so subsequent items that aren't mine don't
7906         // have my extra info.
7907         ((MenuBuilder)menu).setCurrentMenuInfo(null);
7908 
7909         if (mParent != null) {
7910             mParent.createContextMenu(menu);
7911         }
7912     }
7913 
7914     /**
7915      * Views should implement this if they have extra information to associate
7916      * with the context menu. The return result is supplied as a parameter to
7917      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
7918      * callback.
7919      *
7920      * @return Extra information about the item for which the context menu
7921      *         should be shown. This information will vary across different
7922      *         subclasses of View.
7923      */
7924     protected ContextMenuInfo getContextMenuInfo() {
7925         return null;
7926     }
7927 
7928     /**
7929      * Views should implement this if the view itself is going to add items to
7930      * the context menu.
7931      *
7932      * @param menu the context menu to populate
7933      */
7934     protected void onCreateContextMenu(ContextMenu menu) {
7935     }
7936 
7937     /**
7938      * Implement this method to handle trackball motion events.  The
7939      * <em>relative</em> movement of the trackball since the last event
7940      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
7941      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
7942      * that a movement of 1 corresponds to the user pressing one DPAD key (so
7943      * they will often be fractional values, representing the more fine-grained
7944      * movement information available from a trackball).
7945      *
7946      * @param event The motion event.
7947      * @return True if the event was handled, false otherwise.
7948      */
7949     public boolean onTrackballEvent(MotionEvent event) {
7950         return false;
7951     }
7952 
7953     /**
7954      * Implement this method to handle generic motion events.
7955      * <p>
7956      * Generic motion events describe joystick movements, mouse hovers, track pad
7957      * touches, scroll wheel movements and other input events.  The
7958      * {@link MotionEvent#getSource() source} of the motion event specifies
7959      * the class of input that was received.  Implementations of this method
7960      * must examine the bits in the source before processing the event.
7961      * The following code example shows how this is done.
7962      * </p><p>
7963      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
7964      * are delivered to the view under the pointer.  All other generic motion events are
7965      * delivered to the focused view.
7966      * </p>
7967      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
7968      *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
7969      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
7970      *             // process the joystick movement...
7971      *             return true;
7972      *         }
7973      *     }
7974      *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_POINTER) != 0) {
7975      *         switch (event.getAction()) {
7976      *             case MotionEvent.ACTION_HOVER_MOVE:
7977      *                 // process the mouse hover movement...
7978      *                 return true;
7979      *             case MotionEvent.ACTION_SCROLL:
7980      *                 // process the scroll wheel movement...
7981      *                 return true;
7982      *         }
7983      *     }
7984      *     return super.onGenericMotionEvent(event);
7985      * }</pre>
7986      *
7987      * @param event The generic motion event being processed.
7988      * @return True if the event was handled, false otherwise.
7989      */
7990     public boolean onGenericMotionEvent(MotionEvent event) {
7991         return false;
7992     }
7993 
7994     /**
7995      * Implement this method to handle hover events.
7996      * <p>
7997      * This method is called whenever a pointer is hovering into, over, or out of the
7998      * bounds of a view and the view is not currently being touched.
7999      * Hover events are represented as pointer events with action
8000      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
8001      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
8002      * </p>
8003      * <ul>
8004      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
8005      * when the pointer enters the bounds of the view.</li>
8006      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
8007      * when the pointer has already entered the bounds of the view and has moved.</li>
8008      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
8009      * when the pointer has exited the bounds of the view or when the pointer is
8010      * about to go down due to a button click, tap, or similar user action that
8011      * causes the view to be touched.</li>
8012      * </ul>
8013      * <p>
8014      * The view should implement this method to return true to indicate that it is
8015      * handling the hover event, such as by changing its drawable state.
8016      * </p><p>
8017      * The default implementation calls {@link #setHovered} to update the hovered state
8018      * of the view when a hover enter or hover exit event is received, if the view
8019      * is enabled and is clickable.  The default implementation also sends hover
8020      * accessibility events.
8021      * </p>
8022      *
8023      * @param event The motion event that describes the hover.
8024      * @return True if the view handled the hover event.
8025      *
8026      * @see #isHovered
8027      * @see #setHovered
8028      * @see #onHoverChanged
8029      */
8030     public boolean onHoverEvent(MotionEvent event) {
8031         // The root view may receive hover (or touch) events that are outside the bounds of
8032         // the window.  This code ensures that we only send accessibility events for
8033         // hovers that are actually within the bounds of the root view.
8034         final int action = event.getActionMasked();
8035         if (!mSendingHoverAccessibilityEvents) {
8036             if ((action == MotionEvent.ACTION_HOVER_ENTER
8037                     || action == MotionEvent.ACTION_HOVER_MOVE)
8038                     && !hasHoveredChild()
8039                     && pointInView(event.getX(), event.getY())) {
8040                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
8041                 mSendingHoverAccessibilityEvents = true;
8042             }
8043         } else {
8044             if (action == MotionEvent.ACTION_HOVER_EXIT
8045                     || (action == MotionEvent.ACTION_MOVE
8046                             && !pointInView(event.getX(), event.getY()))) {
8047                 mSendingHoverAccessibilityEvents = false;
8048                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
8049                 // If the window does not have input focus we take away accessibility
8050                 // focus as soon as the user stop hovering over the view.
8051                 if (mAttachInfo != null && !mAttachInfo.mHasWindowFocus) {
8052                     getViewRootImpl().setAccessibilityFocus(null, null);
8053                 }
8054             }
8055         }
8056 
8057         if (isHoverable()) {
8058             switch (action) {
8059                 case MotionEvent.ACTION_HOVER_ENTER:
8060                     setHovered(true);
8061                     break;
8062                 case MotionEvent.ACTION_HOVER_EXIT:
8063                     setHovered(false);
8064                     break;
8065             }
8066 
8067             // Dispatch the event to onGenericMotionEvent before returning true.
8068             // This is to provide compatibility with existing applications that
8069             // handled HOVER_MOVE events in onGenericMotionEvent and that would
8070             // break because of the new default handling for hoverable views
8071             // in onHoverEvent.
8072             // Note that onGenericMotionEvent will be called by default when
8073             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
8074             dispatchGenericMotionEventInternal(event);
8075             return true;
8076         }
8077 
8078         return false;
8079     }
8080 
8081     /**
8082      * Returns true if the view should handle {@link #onHoverEvent}
8083      * by calling {@link #setHovered} to change its hovered state.
8084      *
8085      * @return True if the view is hoverable.
8086      */
8087     private boolean isHoverable() {
8088         final int viewFlags = mViewFlags;
8089         if ((viewFlags & ENABLED_MASK) == DISABLED) {
8090             return false;
8091         }
8092 
8093         return (viewFlags & CLICKABLE) == CLICKABLE
8094                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8095     }
8096 
8097     /**
8098      * Returns true if the view is currently hovered.
8099      *
8100      * @return True if the view is currently hovered.
8101      *
8102      * @see #setHovered
8103      * @see #onHoverChanged
8104      */
8105     @ViewDebug.ExportedProperty
8106     public boolean isHovered() {
8107         return (mPrivateFlags & PFLAG_HOVERED) != 0;
8108     }
8109 
8110     /**
8111      * Sets whether the view is currently hovered.
8112      * <p>
8113      * Calling this method also changes the drawable state of the view.  This
8114      * enables the view to react to hover by using different drawable resources
8115      * to change its appearance.
8116      * </p><p>
8117      * The {@link #onHoverChanged} method is called when the hovered state changes.
8118      * </p>
8119      *
8120      * @param hovered True if the view is hovered.
8121      *
8122      * @see #isHovered
8123      * @see #onHoverChanged
8124      */
8125     public void setHovered(boolean hovered) {
8126         if (hovered) {
8127             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
8128                 mPrivateFlags |= PFLAG_HOVERED;
8129                 refreshDrawableState();
8130                 onHoverChanged(true);
8131             }
8132         } else {
8133             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
8134                 mPrivateFlags &= ~PFLAG_HOVERED;
8135                 refreshDrawableState();
8136                 onHoverChanged(false);
8137             }
8138         }
8139     }
8140 
8141     /**
8142      * Implement this method to handle hover state changes.
8143      * <p>
8144      * This method is called whenever the hover state changes as a result of a
8145      * call to {@link #setHovered}.
8146      * </p>
8147      *
8148      * @param hovered The current hover state, as returned by {@link #isHovered}.
8149      *
8150      * @see #isHovered
8151      * @see #setHovered
8152      */
8153     public void onHoverChanged(boolean hovered) {
8154     }
8155 
8156     /**
8157      * Implement this method to handle touch screen motion events.
8158      *
8159      * @param event The motion event.
8160      * @return True if the event was handled, false otherwise.
8161      */
8162     public boolean onTouchEvent(MotionEvent event) {
8163         final int viewFlags = mViewFlags;
8164 
8165         if ((viewFlags & ENABLED_MASK) == DISABLED) {
8166             if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
8167                 setPressed(false);
8168             }
8169             // A disabled view that is clickable still consumes the touch
8170             // events, it just doesn't respond to them.
8171             return (((viewFlags & CLICKABLE) == CLICKABLE ||
8172                     (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
8173         }
8174 
8175         if (mTouchDelegate != null) {
8176             if (mTouchDelegate.onTouchEvent(event)) {
8177                 return true;
8178             }
8179         }
8180 
8181         if (((viewFlags & CLICKABLE) == CLICKABLE ||
8182                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
8183             switch (event.getAction()) {
8184                 case MotionEvent.ACTION_UP:
8185                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
8186                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
8187                         // take focus if we don't have it already and we should in
8188                         // touch mode.
8189                         boolean focusTaken = false;
8190                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
8191                             focusTaken = requestFocus();
8192                         }
8193 
8194                         if (prepressed) {
8195                             // The button is being released before we actually
8196                             // showed it as pressed.  Make it show the pressed
8197                             // state now (before scheduling the click) to ensure
8198                             // the user sees it.
8199                             setPressed(true);
8200                        }
8201 
8202                         if (!mHasPerformedLongPress) {
8203                             // This is a tap, so remove the longpress check
8204                             removeLongPressCallback();
8205 
8206                             // Only perform take click actions if we were in the pressed state
8207                             if (!focusTaken) {
8208                                 // Use a Runnable and post this rather than calling
8209                                 // performClick directly. This lets other visual state
8210                                 // of the view update before click actions start.
8211                                 if (mPerformClick == null) {
8212                                     mPerformClick = new PerformClick();
8213                                 }
8214                                 if (!post(mPerformClick)) {
8215                                     performClick();
8216                                 }
8217                             }
8218                         }
8219 
8220                         if (mUnsetPressedState == null) {
8221                             mUnsetPressedState = new UnsetPressedState();
8222                         }
8223 
8224                         if (prepressed) {
8225                             postDelayed(mUnsetPressedState,
8226                                     ViewConfiguration.getPressedStateDuration());
8227                         } else if (!post(mUnsetPressedState)) {
8228                             // If the post failed, unpress right now
8229                             mUnsetPressedState.run();
8230                         }
8231                         removeTapCallback();
8232                     }
8233                     break;
8234 
8235                 case MotionEvent.ACTION_DOWN:
8236                     mHasPerformedLongPress = false;
8237 
8238                     if (performButtonActionOnTouchDown(event)) {
8239                         break;
8240                     }
8241 
8242                     // Walk up the hierarchy to determine if we're inside a scrolling container.
8243                     boolean isInScrollingContainer = isInScrollingContainer();
8244 
8245                     // For views inside a scrolling container, delay the pressed feedback for
8246                     // a short period in case this is a scroll.
8247                     if (isInScrollingContainer) {
8248                         mPrivateFlags |= PFLAG_PREPRESSED;
8249                         if (mPendingCheckForTap == null) {
8250                             mPendingCheckForTap = new CheckForTap();
8251                         }
8252                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
8253                     } else {
8254                         // Not inside a scrolling container, so show the feedback right away
8255                         setPressed(true);
8256                         checkForLongClick(0);
8257                     }
8258                     break;
8259 
8260                 case MotionEvent.ACTION_CANCEL:
8261                     setPressed(false);
8262                     removeTapCallback();
8263                     removeLongPressCallback();
8264                     break;
8265 
8266                 case MotionEvent.ACTION_MOVE:
8267                     final int x = (int) event.getX();
8268                     final int y = (int) event.getY();
8269 
8270                     // Be lenient about moving outside of buttons
8271                     if (!pointInView(x, y, mTouchSlop)) {
8272                         // Outside button
8273                         removeTapCallback();
8274                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
8275                             // Remove any future long press/tap checks
8276                             removeLongPressCallback();
8277 
8278                             setPressed(false);
8279                         }
8280                     }
8281                     break;
8282             }
8283             return true;
8284         }
8285 
8286         return false;
8287     }
8288 
8289     /**
8290      * @hide
8291      */
8292     public boolean isInScrollingContainer() {
8293         ViewParent p = getParent();
8294         while (p != null && p instanceof ViewGroup) {
8295             if (((ViewGroup) p).shouldDelayChildPressedState()) {
8296                 return true;
8297             }
8298             p = p.getParent();
8299         }
8300         return false;
8301     }
8302 
8303     /**
8304      * Remove the longpress detection timer.
8305      */
8306     private void removeLongPressCallback() {
8307         if (mPendingCheckForLongPress != null) {
8308           removeCallbacks(mPendingCheckForLongPress);
8309         }
8310     }
8311 
8312     /**
8313      * Remove the pending click action
8314      */
8315     private void removePerformClickCallback() {
8316         if (mPerformClick != null) {
8317             removeCallbacks(mPerformClick);
8318         }
8319     }
8320 
8321     /**
8322      * Remove the prepress detection timer.
8323      */
8324     private void removeUnsetPressCallback() {
8325         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
8326             setPressed(false);
8327             removeCallbacks(mUnsetPressedState);
8328         }
8329     }
8330 
8331     /**
8332      * Remove the tap detection timer.
8333      */
8334     private void removeTapCallback() {
8335         if (mPendingCheckForTap != null) {
8336             mPrivateFlags &= ~PFLAG_PREPRESSED;
8337             removeCallbacks(mPendingCheckForTap);
8338         }
8339     }
8340 
8341     /**
8342      * Cancels a pending long press.  Your subclass can use this if you
8343      * want the context menu to come up if the user presses and holds
8344      * at the same place, but you don't want it to come up if they press
8345      * and then move around enough to cause scrolling.
8346      */
8347     public void cancelLongPress() {
8348         removeLongPressCallback();
8349 
8350         /*
8351          * The prepressed state handled by the tap callback is a display
8352          * construct, but the tap callback will post a long press callback
8353          * less its own timeout. Remove it here.
8354          */
8355         removeTapCallback();
8356     }
8357 
8358     /**
8359      * Remove the pending callback for sending a
8360      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
8361      */
8362     private void removeSendViewScrolledAccessibilityEventCallback() {
8363         if (mSendViewScrolledAccessibilityEvent != null) {
8364             removeCallbacks(mSendViewScrolledAccessibilityEvent);
8365             mSendViewScrolledAccessibilityEvent.mIsPending = false;
8366         }
8367     }
8368 
8369     /**
8370      * Sets the TouchDelegate for this View.
8371      */
8372     public void setTouchDelegate(TouchDelegate delegate) {
8373         mTouchDelegate = delegate;
8374     }
8375 
8376     /**
8377      * Gets the TouchDelegate for this View.
8378      */
8379     public TouchDelegate getTouchDelegate() {
8380         return mTouchDelegate;
8381     }
8382 
8383     /**
8384      * Set flags controlling behavior of this view.
8385      *
8386      * @param flags Constant indicating the value which should be set
8387      * @param mask Constant indicating the bit range that should be changed
8388      */
8389     void setFlags(int flags, int mask) {
8390         int old = mViewFlags;
8391         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
8392 
8393         int changed = mViewFlags ^ old;
8394         if (changed == 0) {
8395             return;
8396         }
8397         int privateFlags = mPrivateFlags;
8398 
8399         /* Check if the FOCUSABLE bit has changed */
8400         if (((changed & FOCUSABLE_MASK) != 0) &&
8401                 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
8402             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
8403                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
8404                 /* Give up focus if we are no longer focusable */
8405                 clearFocus();
8406             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
8407                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
8408                 /*
8409                  * Tell the view system that we are now available to take focus
8410                  * if no one else already has it.
8411                  */
8412                 if (mParent != null) mParent.focusableViewAvailable(this);
8413             }
8414             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8415                 notifyAccessibilityStateChanged();
8416             }
8417         }
8418 
8419         if ((flags & VISIBILITY_MASK) == VISIBLE) {
8420             if ((changed & VISIBILITY_MASK) != 0) {
8421                 /*
8422                  * If this view is becoming visible, invalidate it in case it changed while
8423                  * it was not visible. Marking it drawn ensures that the invalidation will
8424                  * go through.
8425                  */
8426                 mPrivateFlags |= PFLAG_DRAWN;
8427                 invalidate(true);
8428 
8429                 needGlobalAttributesUpdate(true);
8430 
8431                 // a view becoming visible is worth notifying the parent
8432                 // about in case nothing has focus.  even if this specific view
8433                 // isn't focusable, it may contain something that is, so let
8434                 // the root view try to give this focus if nothing else does.
8435                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
8436                     mParent.focusableViewAvailable(this);
8437                 }
8438             }
8439         }
8440 
8441         /* Check if the GONE bit has changed */
8442         if ((changed & GONE) != 0) {
8443             needGlobalAttributesUpdate(false);
8444             requestLayout();
8445 
8446             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
8447                 if (hasFocus()) clearFocus();
8448                 clearAccessibilityFocus();
8449                 destroyDrawingCache();
8450                 if (mParent instanceof View) {
8451                     // GONE views noop invalidation, so invalidate the parent
8452                     ((View) mParent).invalidate(true);
8453                 }
8454                 // Mark the view drawn to ensure that it gets invalidated properly the next
8455                 // time it is visible and gets invalidated
8456                 mPrivateFlags |= PFLAG_DRAWN;
8457             }
8458             if (mAttachInfo != null) {
8459                 mAttachInfo.mViewVisibilityChanged = true;
8460             }
8461         }
8462 
8463         /* Check if the VISIBLE bit has changed */
8464         if ((changed & INVISIBLE) != 0) {
8465             needGlobalAttributesUpdate(false);
8466             /*
8467              * If this view is becoming invisible, set the DRAWN flag so that
8468              * the next invalidate() will not be skipped.
8469              */
8470             mPrivateFlags |= PFLAG_DRAWN;
8471 
8472             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
8473                 // root view becoming invisible shouldn't clear focus and accessibility focus
8474                 if (getRootView() != this) {
8475                     clearFocus();
8476                     clearAccessibilityFocus();
8477                 }
8478             }
8479             if (mAttachInfo != null) {
8480                 mAttachInfo.mViewVisibilityChanged = true;
8481             }
8482         }
8483 
8484         if ((changed & VISIBILITY_MASK) != 0) {
8485             if (mParent instanceof ViewGroup) {
8486                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
8487                         (changed & VISIBILITY_MASK), (flags & VISIBILITY_MASK));
8488                 ((View) mParent).invalidate(true);
8489             } else if (mParent != null) {
8490                 mParent.invalidateChild(this, null);
8491             }
8492             dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
8493         }
8494 
8495         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
8496             destroyDrawingCache();
8497         }
8498 
8499         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
8500             destroyDrawingCache();
8501             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
8502             invalidateParentCaches();
8503         }
8504 
8505         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
8506             destroyDrawingCache();
8507             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
8508         }
8509 
8510         if ((changed & DRAW_MASK) != 0) {
8511             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
8512                 if (mBackground != null) {
8513                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
8514                     mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
8515                 } else {
8516                     mPrivateFlags |= PFLAG_SKIP_DRAW;
8517                 }
8518             } else {
8519                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
8520             }
8521             requestLayout();
8522             invalidate(true);
8523         }
8524 
8525         if ((changed & KEEP_SCREEN_ON) != 0) {
8526             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
8527                 mParent.recomputeViewAttributes(this);
8528             }
8529         }
8530 
8531         if (AccessibilityManager.getInstance(mContext).isEnabled()
8532                 && ((changed & FOCUSABLE) != 0 || (changed & CLICKABLE) != 0
8533                         || (changed & LONG_CLICKABLE) != 0 || (changed & ENABLED) != 0)) {
8534             notifyAccessibilityStateChanged();
8535         }
8536     }
8537 
8538     /**
8539      * Change the view's z order in the tree, so it's on top of other sibling
8540      * views
8541      */
8542     public void bringToFront() {
8543         if (mParent != null) {
8544             mParent.bringChildToFront(this);
8545         }
8546     }
8547 
8548     /**
8549      * This is called in response to an internal scroll in this view (i.e., the
8550      * view scrolled its own contents). This is typically as a result of
8551      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
8552      * called.
8553      *
8554      * @param l Current horizontal scroll origin.
8555      * @param t Current vertical scroll origin.
8556      * @param oldl Previous horizontal scroll origin.
8557      * @param oldt Previous vertical scroll origin.
8558      */
8559     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
8560         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8561             postSendViewScrolledAccessibilityEventCallback();
8562         }
8563 
8564         mBackgroundSizeChanged = true;
8565 
8566         final AttachInfo ai = mAttachInfo;
8567         if (ai != null) {
8568             ai.mViewScrollChanged = true;
8569         }
8570     }
8571 
8572     /**
8573      * Interface definition for a callback to be invoked when the layout bounds of a view
8574      * changes due to layout processing.
8575      */
8576     public interface OnLayoutChangeListener {
8577         /**
8578          * Called when the focus state of a view has changed.
8579          *
8580          * @param v The view whose state has changed.
8581          * @param left The new value of the view's left property.
8582          * @param top The new value of the view's top property.
8583          * @param right The new value of the view's right property.
8584          * @param bottom The new value of the view's bottom property.
8585          * @param oldLeft The previous value of the view's left property.
8586          * @param oldTop The previous value of the view's top property.
8587          * @param oldRight The previous value of the view's right property.
8588          * @param oldBottom The previous value of the view's bottom property.
8589          */
8590         void onLayoutChange(View v, int left, int top, int right, int bottom,
8591             int oldLeft, int oldTop, int oldRight, int oldBottom);
8592     }
8593 
8594     /**
8595      * This is called during layout when the size of this view has changed. If
8596      * you were just added to the view hierarchy, you're called with the old
8597      * values of 0.
8598      *
8599      * @param w Current width of this view.
8600      * @param h Current height of this view.
8601      * @param oldw Old width of this view.
8602      * @param oldh Old height of this view.
8603      */
8604     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
8605     }
8606 
8607     /**
8608      * Called by draw to draw the child views. This may be overridden
8609      * by derived classes to gain control just before its children are drawn
8610      * (but after its own view has been drawn).
8611      * @param canvas the canvas on which to draw the view
8612      */
8613     protected void dispatchDraw(Canvas canvas) {
8614 
8615     }
8616 
8617     /**
8618      * Gets the parent of this view. Note that the parent is a
8619      * ViewParent and not necessarily a View.
8620      *
8621      * @return Parent of this view.
8622      */
8623     public final ViewParent getParent() {
8624         return mParent;
8625     }
8626 
8627     /**
8628      * Set the horizontal scrolled position of your view. This will cause a call to
8629      * {@link #onScrollChanged(int, int, int, int)} and the view will be
8630      * invalidated.
8631      * @param value the x position to scroll to
8632      */
8633     public void setScrollX(int value) {
8634         scrollTo(value, mScrollY);
8635     }
8636 
8637     /**
8638      * Set the vertical scrolled position of your view. This will cause a call to
8639      * {@link #onScrollChanged(int, int, int, int)} and the view will be
8640      * invalidated.
8641      * @param value the y position to scroll to
8642      */
8643     public void setScrollY(int value) {
8644         scrollTo(mScrollX, value);
8645     }
8646 
8647     /**
8648      * Return the scrolled left position of this view. This is the left edge of
8649      * the displayed part of your view. You do not need to draw any pixels
8650      * farther left, since those are outside of the frame of your view on
8651      * screen.
8652      *
8653      * @return The left edge of the displayed part of your view, in pixels.
8654      */
8655     public final int getScrollX() {
8656         return mScrollX;
8657     }
8658 
8659     /**
8660      * Return the scrolled top position of this view. This is the top edge of
8661      * the displayed part of your view. You do not need to draw any pixels above
8662      * it, since those are outside of the frame of your view on screen.
8663      *
8664      * @return The top edge of the displayed part of your view, in pixels.
8665      */
8666     public final int getScrollY() {
8667         return mScrollY;
8668     }
8669 
8670     /**
8671      * Return the width of the your view.
8672      *
8673      * @return The width of your view, in pixels.
8674      */
8675     @ViewDebug.ExportedProperty(category = "layout")
8676     public final int getWidth() {
8677         return mRight - mLeft;
8678     }
8679 
8680     /**
8681      * Return the height of your view.
8682      *
8683      * @return The height of your view, in pixels.
8684      */
8685     @ViewDebug.ExportedProperty(category = "layout")
8686     public final int getHeight() {
8687         return mBottom - mTop;
8688     }
8689 
8690     /**
8691      * Return the visible drawing bounds of your view. Fills in the output
8692      * rectangle with the values from getScrollX(), getScrollY(),
8693      * getWidth(), and getHeight(). These bounds do not account for any
8694      * transformation properties currently set on the view, such as
8695      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
8696      *
8697      * @param outRect The (scrolled) drawing bounds of the view.
8698      */
8699     public void getDrawingRect(Rect outRect) {
8700         outRect.left = mScrollX;
8701         outRect.top = mScrollY;
8702         outRect.right = mScrollX + (mRight - mLeft);
8703         outRect.bottom = mScrollY + (mBottom - mTop);
8704     }
8705 
8706     /**
8707      * Like {@link #getMeasuredWidthAndState()}, but only returns the
8708      * raw width component (that is the result is masked by
8709      * {@link #MEASURED_SIZE_MASK}).
8710      *
8711      * @return The raw measured width of this view.
8712      */
8713     public final int getMeasuredWidth() {
8714         return mMeasuredWidth & MEASURED_SIZE_MASK;
8715     }
8716 
8717     /**
8718      * Return the full width measurement information for this view as computed
8719      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
8720      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
8721      * This should be used during measurement and layout calculations only. Use
8722      * {@link #getWidth()} to see how wide a view is after layout.
8723      *
8724      * @return The measured width of this view as a bit mask.
8725      */
8726     public final int getMeasuredWidthAndState() {
8727         return mMeasuredWidth;
8728     }
8729 
8730     /**
8731      * Like {@link #getMeasuredHeightAndState()}, but only returns the
8732      * raw width component (that is the result is masked by
8733      * {@link #MEASURED_SIZE_MASK}).
8734      *
8735      * @return The raw measured height of this view.
8736      */
8737     public final int getMeasuredHeight() {
8738         return mMeasuredHeight & MEASURED_SIZE_MASK;
8739     }
8740 
8741     /**
8742      * Return the full height measurement information for this view as computed
8743      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
8744      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
8745      * This should be used during measurement and layout calculations only. Use
8746      * {@link #getHeight()} to see how wide a view is after layout.
8747      *
8748      * @return The measured width of this view as a bit mask.
8749      */
8750     public final int getMeasuredHeightAndState() {
8751         return mMeasuredHeight;
8752     }
8753 
8754     /**
8755      * Return only the state bits of {@link #getMeasuredWidthAndState()}
8756      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
8757      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
8758      * and the height component is at the shifted bits
8759      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
8760      */
8761     public final int getMeasuredState() {
8762         return (mMeasuredWidth&MEASURED_STATE_MASK)
8763                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
8764                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
8765     }
8766 
8767     /**
8768      * The transform matrix of this view, which is calculated based on the current
8769      * roation, scale, and pivot properties.
8770      *
8771      * @see #getRotation()
8772      * @see #getScaleX()
8773      * @see #getScaleY()
8774      * @see #getPivotX()
8775      * @see #getPivotY()
8776      * @return The current transform matrix for the view
8777      */
8778     public Matrix getMatrix() {
8779         if (mTransformationInfo != null) {
8780             updateMatrix();
8781             return mTransformationInfo.mMatrix;
8782         }
8783         return Matrix.IDENTITY_MATRIX;
8784     }
8785 
8786     /**
8787      * Utility function to determine if the value is far enough away from zero to be
8788      * considered non-zero.
8789      * @param value A floating point value to check for zero-ness
8790      * @return whether the passed-in value is far enough away from zero to be considered non-zero
8791      */
8792     private static boolean nonzero(float value) {
8793         return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
8794     }
8795 
8796     /**
8797      * Returns true if the transform matrix is the identity matrix.
8798      * Recomputes the matrix if necessary.
8799      *
8800      * @return True if the transform matrix is the identity matrix, false otherwise.
8801      */
8802     final boolean hasIdentityMatrix() {
8803         if (mTransformationInfo != null) {
8804             updateMatrix();
8805             return mTransformationInfo.mMatrixIsIdentity;
8806         }
8807         return true;
8808     }
8809 
8810     void ensureTransformationInfo() {
8811         if (mTransformationInfo == null) {
8812             mTransformationInfo = new TransformationInfo();
8813         }
8814     }
8815 
8816     /**
8817      * Recomputes the transform matrix if necessary.
8818      */
8819     private void updateMatrix() {
8820         final TransformationInfo info = mTransformationInfo;
8821         if (info == null) {
8822             return;
8823         }
8824         if (info.mMatrixDirty) {
8825             // transform-related properties have changed since the last time someone
8826             // asked for the matrix; recalculate it with the current values
8827 
8828             // Figure out if we need to update the pivot point
8829             if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
8830                 if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
8831                     info.mPrevWidth = mRight - mLeft;
8832                     info.mPrevHeight = mBottom - mTop;
8833                     info.mPivotX = info.mPrevWidth / 2f;
8834                     info.mPivotY = info.mPrevHeight / 2f;
8835                 }
8836             }
8837             info.mMatrix.reset();
8838             if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
8839                 info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
8840                 info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
8841                 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
8842             } else {
8843                 if (info.mCamera == null) {
8844                     info.mCamera = new Camera();
8845                     info.matrix3D = new Matrix();
8846                 }
8847                 info.mCamera.save();
8848                 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
8849                 info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
8850                 info.mCamera.getMatrix(info.matrix3D);
8851                 info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
8852                 info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
8853                         info.mPivotY + info.mTranslationY);
8854                 info.mMatrix.postConcat(info.matrix3D);
8855                 info.mCamera.restore();
8856             }
8857             info.mMatrixDirty = false;
8858             info.mMatrixIsIdentity = info.mMatrix.isIdentity();
8859             info.mInverseMatrixDirty = true;
8860         }
8861     }
8862 
8863    /**
8864      * Utility method to retrieve the inverse of the current mMatrix property.
8865      * We cache the matrix to avoid recalculating it when transform properties
8866      * have not changed.
8867      *
8868      * @return The inverse of the current matrix of this view.
8869      */
8870     final Matrix getInverseMatrix() {
8871         final TransformationInfo info = mTransformationInfo;
8872         if (info != null) {
8873             updateMatrix();
8874             if (info.mInverseMatrixDirty) {
8875                 if (info.mInverseMatrix == null) {
8876                     info.mInverseMatrix = new Matrix();
8877                 }
8878                 info.mMatrix.invert(info.mInverseMatrix);
8879                 info.mInverseMatrixDirty = false;
8880             }
8881             return info.mInverseMatrix;
8882         }
8883         return Matrix.IDENTITY_MATRIX;
8884     }
8885 
8886     /**
8887      * Gets the distance along the Z axis from the camera to this view.
8888      *
8889      * @see #setCameraDistance(float)
8890      *
8891      * @return The distance along the Z axis.
8892      */
8893     public float getCameraDistance() {
8894         ensureTransformationInfo();
8895         final float dpi = mResources.getDisplayMetrics().densityDpi;
8896         final TransformationInfo info = mTransformationInfo;
8897         if (info.mCamera == null) {
8898             info.mCamera = new Camera();
8899             info.matrix3D = new Matrix();
8900         }
8901         return -(info.mCamera.getLocationZ() * dpi);
8902     }
8903 
8904     /**
8905      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
8906      * views are drawn) from the camera to this view. The camera's distance
8907      * affects 3D transformations, for instance rotations around the X and Y
8908      * axis. If the rotationX or rotationY properties are changed and this view is
8909      * large (more than half the size of the screen), it is recommended to always
8910      * use a camera distance that's greater than the height (X axis rotation) or
8911      * the width (Y axis rotation) of this view.</p>
8912      *
8913      * <p>The distance of the camera from the view plane can have an affect on the
8914      * perspective distortion of the view when it is rotated around the x or y axis.
8915      * For example, a large distance will result in a large viewing angle, and there
8916      * will not be much perspective distortion of the view as it rotates. A short
8917      * distance may cause much more perspective distortion upon rotation, and can
8918      * also result in some drawing artifacts if the rotated view ends up partially
8919      * behind the camera (which is why the recommendation is to use a distance at
8920      * least as far as the size of the view, if the view is to be rotated.)</p>
8921      *
8922      * <p>The distance is expressed in "depth pixels." The default distance depends
8923      * on the screen density. For instance, on a medium density display, the
8924      * default distance is 1280. On a high density display, the default distance
8925      * is 1920.</p>
8926      *
8927      * <p>If you want to specify a distance that leads to visually consistent
8928      * results across various densities, use the following formula:</p>
8929      * <pre>
8930      * float scale = context.getResources().getDisplayMetrics().density;
8931      * view.setCameraDistance(distance * scale);
8932      * </pre>
8933      *
8934      * <p>The density scale factor of a high density display is 1.5,
8935      * and 1920 = 1280 * 1.5.</p>
8936      *
8937      * @param distance The distance in "depth pixels", if negative the opposite
8938      *        value is used
8939      *
8940      * @see #setRotationX(float)
8941      * @see #setRotationY(float)
8942      */
8943     public void setCameraDistance(float distance) {
8944         invalidateViewProperty(true, false);
8945 
8946         ensureTransformationInfo();
8947         final float dpi = mResources.getDisplayMetrics().densityDpi;
8948         final TransformationInfo info = mTransformationInfo;
8949         if (info.mCamera == null) {
8950             info.mCamera = new Camera();
8951             info.matrix3D = new Matrix();
8952         }
8953 
8954         info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
8955         info.mMatrixDirty = true;
8956 
8957         invalidateViewProperty(false, false);
8958         if (mDisplayList != null) {
8959             mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
8960         }
8961         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
8962             // View was rejected last time it was drawn by its parent; this may have changed
8963             invalidateParentIfNeeded();
8964         }
8965     }
8966 
8967     /**
8968      * The degrees that the view is rotated around the pivot point.
8969      *
8970      * @see #setRotation(float)
8971      * @see #getPivotX()
8972      * @see #getPivotY()
8973      *
8974      * @return The degrees of rotation.
8975      */
8976     @ViewDebug.ExportedProperty(category = "drawing")
8977     public float getRotation() {
8978         return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
8979     }
8980 
8981     /**
8982      * Sets the degrees that the view is rotated around the pivot point. Increasing values
8983      * result in clockwise rotation.
8984      *
8985      * @param rotation The degrees of rotation.
8986      *
8987      * @see #getRotation()
8988      * @see #getPivotX()
8989      * @see #getPivotY()
8990      * @see #setRotationX(float)
8991      * @see #setRotationY(float)
8992      *
8993      * @attr ref android.R.styleable#View_rotation
8994      */
8995     public void setRotation(float rotation) {
8996         ensureTransformationInfo();
8997         final TransformationInfo info = mTransformationInfo;
8998         if (info.mRotation != rotation) {
8999             // Double-invalidation is necessary to capture view's old and new areas
9000             invalidateViewProperty(true, false);
9001             info.mRotation = rotation;
9002             info.mMatrixDirty = true;
9003             invalidateViewProperty(false, true);
9004             if (mDisplayList != null) {
9005                 mDisplayList.setRotation(rotation);
9006             }
9007             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9008                 // View was rejected last time it was drawn by its parent; this may have changed
9009                 invalidateParentIfNeeded();
9010             }
9011         }
9012     }
9013 
9014     /**
9015      * The degrees that the view is rotated around the vertical axis through the pivot point.
9016      *
9017      * @see #getPivotX()
9018      * @see #getPivotY()
9019      * @see #setRotationY(float)
9020      *
9021      * @return The degrees of Y rotation.
9022      */
9023     @ViewDebug.ExportedProperty(category = "drawing")
9024     public float getRotationY() {
9025         return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
9026     }
9027 
9028     /**
9029      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
9030      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
9031      * down the y axis.
9032      *
9033      * When rotating large views, it is recommended to adjust the camera distance
9034      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
9035      *
9036      * @param rotationY The degrees of Y rotation.
9037      *
9038      * @see #getRotationY()
9039      * @see #getPivotX()
9040      * @see #getPivotY()
9041      * @see #setRotation(float)
9042      * @see #setRotationX(float)
9043      * @see #setCameraDistance(float)
9044      *
9045      * @attr ref android.R.styleable#View_rotationY
9046      */
9047     public void setRotationY(float rotationY) {
9048         ensureTransformationInfo();
9049         final TransformationInfo info = mTransformationInfo;
9050         if (info.mRotationY != rotationY) {
9051             invalidateViewProperty(true, false);
9052             info.mRotationY = rotationY;
9053             info.mMatrixDirty = true;
9054             invalidateViewProperty(false, true);
9055             if (mDisplayList != null) {
9056                 mDisplayList.setRotationY(rotationY);
9057             }
9058             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9059                 // View was rejected last time it was drawn by its parent; this may have changed
9060                 invalidateParentIfNeeded();
9061             }
9062         }
9063     }
9064 
9065     /**
9066      * The degrees that the view is rotated around the horizontal axis through the pivot point.
9067      *
9068      * @see #getPivotX()
9069      * @see #getPivotY()
9070      * @see #setRotationX(float)
9071      *
9072      * @return The degrees of X rotation.
9073      */
9074     @ViewDebug.ExportedProperty(category = "drawing")
9075     public float getRotationX() {
9076         return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
9077     }
9078 
9079     /**
9080      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
9081      * Increasing values result in clockwise rotation from the viewpoint of looking down the
9082      * x axis.
9083      *
9084      * When rotating large views, it is recommended to adjust the camera distance
9085      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
9086      *
9087      * @param rotationX The degrees of X rotation.
9088      *
9089      * @see #getRotationX()
9090      * @see #getPivotX()
9091      * @see #getPivotY()
9092      * @see #setRotation(float)
9093      * @see #setRotationY(float)
9094      * @see #setCameraDistance(float)
9095      *
9096      * @attr ref android.R.styleable#View_rotationX
9097      */
9098     public void setRotationX(float rotationX) {
9099         ensureTransformationInfo();
9100         final TransformationInfo info = mTransformationInfo;
9101         if (info.mRotationX != rotationX) {
9102             invalidateViewProperty(true, false);
9103             info.mRotationX = rotationX;
9104             info.mMatrixDirty = true;
9105             invalidateViewProperty(false, true);
9106             if (mDisplayList != null) {
9107                 mDisplayList.setRotationX(rotationX);
9108             }
9109             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9110                 // View was rejected last time it was drawn by its parent; this may have changed
9111                 invalidateParentIfNeeded();
9112             }
9113         }
9114     }
9115 
9116     /**
9117      * The amount that the view is scaled in x around the pivot point, as a proportion of
9118      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
9119      *
9120      * <p>By default, this is 1.0f.
9121      *
9122      * @see #getPivotX()
9123      * @see #getPivotY()
9124      * @return The scaling factor.
9125      */
9126     @ViewDebug.ExportedProperty(category = "drawing")
9127     public float getScaleX() {
9128         return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
9129     }
9130 
9131     /**
9132      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
9133      * the view's unscaled width. A value of 1 means that no scaling is applied.
9134      *
9135      * @param scaleX The scaling factor.
9136      * @see #getPivotX()
9137      * @see #getPivotY()
9138      *
9139      * @attr ref android.R.styleable#View_scaleX
9140      */
9141     public void setScaleX(float scaleX) {
9142         ensureTransformationInfo();
9143         final TransformationInfo info = mTransformationInfo;
9144         if (info.mScaleX != scaleX) {
9145             invalidateViewProperty(true, false);
9146             info.mScaleX = scaleX;
9147             info.mMatrixDirty = true;
9148             invalidateViewProperty(false, true);
9149             if (mDisplayList != null) {
9150                 mDisplayList.setScaleX(scaleX);
9151             }
9152             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9153                 // View was rejected last time it was drawn by its parent; this may have changed
9154                 invalidateParentIfNeeded();
9155             }
9156         }
9157     }
9158 
9159     /**
9160      * The amount that the view is scaled in y around the pivot point, as a proportion of
9161      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
9162      *
9163      * <p>By default, this is 1.0f.
9164      *
9165      * @see #getPivotX()
9166      * @see #getPivotY()
9167      * @return The scaling factor.
9168      */
9169     @ViewDebug.ExportedProperty(category = "drawing")
9170     public float getScaleY() {
9171         return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
9172     }
9173 
9174     /**
9175      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
9176      * the view's unscaled width. A value of 1 means that no scaling is applied.
9177      *
9178      * @param scaleY The scaling factor.
9179      * @see #getPivotX()
9180      * @see #getPivotY()
9181      *
9182      * @attr ref android.R.styleable#View_scaleY
9183      */
9184     public void setScaleY(float scaleY) {
9185         ensureTransformationInfo();
9186         final TransformationInfo info = mTransformationInfo;
9187         if (info.mScaleY != scaleY) {
9188             invalidateViewProperty(true, false);
9189             info.mScaleY = scaleY;
9190             info.mMatrixDirty = true;
9191             invalidateViewProperty(false, true);
9192             if (mDisplayList != null) {
9193                 mDisplayList.setScaleY(scaleY);
9194             }
9195             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9196                 // View was rejected last time it was drawn by its parent; this may have changed
9197                 invalidateParentIfNeeded();
9198             }
9199         }
9200     }
9201 
9202     /**
9203      * The x location of the point around which the view is {@link #setRotation(float) rotated}
9204      * and {@link #setScaleX(float) scaled}.
9205      *
9206      * @see #getRotation()
9207      * @see #getScaleX()
9208      * @see #getScaleY()
9209      * @see #getPivotY()
9210      * @return The x location of the pivot point.
9211      *
9212      * @attr ref android.R.styleable#View_transformPivotX
9213      */
9214     @ViewDebug.ExportedProperty(category = "drawing")
9215     public float getPivotX() {
9216         return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
9217     }
9218 
9219     /**
9220      * Sets the x location of the point around which the view is
9221      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
9222      * By default, the pivot point is centered on the object.
9223      * Setting this property disables this behavior and causes the view to use only the
9224      * explicitly set pivotX and pivotY values.
9225      *
9226      * @param pivotX The x location of the pivot point.
9227      * @see #getRotation()
9228      * @see #getScaleX()
9229      * @see #getScaleY()
9230      * @see #getPivotY()
9231      *
9232      * @attr ref android.R.styleable#View_transformPivotX
9233      */
9234     public void setPivotX(float pivotX) {
9235         ensureTransformationInfo();
9236         mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
9237         final TransformationInfo info = mTransformationInfo;
9238         if (info.mPivotX != pivotX) {
9239             invalidateViewProperty(true, false);
9240             info.mPivotX = pivotX;
9241             info.mMatrixDirty = true;
9242             invalidateViewProperty(false, true);
9243             if (mDisplayList != null) {
9244                 mDisplayList.setPivotX(pivotX);
9245             }
9246             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9247                 // View was rejected last time it was drawn by its parent; this may have changed
9248                 invalidateParentIfNeeded();
9249             }
9250         }
9251     }
9252 
9253     /**
9254      * The y location of the point around which the view is {@link #setRotation(float) rotated}
9255      * and {@link #setScaleY(float) scaled}.
9256      *
9257      * @see #getRotation()
9258      * @see #getScaleX()
9259      * @see #getScaleY()
9260      * @see #getPivotY()
9261      * @return The y location of the pivot point.
9262      *
9263      * @attr ref android.R.styleable#View_transformPivotY
9264      */
9265     @ViewDebug.ExportedProperty(category = "drawing")
9266     public float getPivotY() {
9267         return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
9268     }
9269 
9270     /**
9271      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
9272      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
9273      * Setting this property disables this behavior and causes the view to use only the
9274      * explicitly set pivotX and pivotY values.
9275      *
9276      * @param pivotY The y location of the pivot point.
9277      * @see #getRotation()
9278      * @see #getScaleX()
9279      * @see #getScaleY()
9280      * @see #getPivotY()
9281      *
9282      * @attr ref android.R.styleable#View_transformPivotY
9283      */
9284     public void setPivotY(float pivotY) {
9285         ensureTransformationInfo();
9286         mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
9287         final TransformationInfo info = mTransformationInfo;
9288         if (info.mPivotY != pivotY) {
9289             invalidateViewProperty(true, false);
9290             info.mPivotY = pivotY;
9291             info.mMatrixDirty = true;
9292             invalidateViewProperty(false, true);
9293             if (mDisplayList != null) {
9294                 mDisplayList.setPivotY(pivotY);
9295             }
9296             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9297                 // View was rejected last time it was drawn by its parent; this may have changed
9298                 invalidateParentIfNeeded();
9299             }
9300         }
9301     }
9302 
9303     /**
9304      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
9305      * completely transparent and 1 means the view is completely opaque.
9306      *
9307      * <p>By default this is 1.0f.
9308      * @return The opacity of the view.
9309      */
9310     @ViewDebug.ExportedProperty(category = "drawing")
9311     public float getAlpha() {
9312         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
9313     }
9314 
9315     /**
9316      * Returns whether this View has content which overlaps. This function, intended to be
9317      * overridden by specific View types, is an optimization when alpha is set on a view. If
9318      * rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer
9319      * and then composited it into place, which can be expensive. If the view has no overlapping
9320      * rendering, the view can draw each primitive with the appropriate alpha value directly.
9321      * An example of overlapping rendering is a TextView with a background image, such as a
9322      * Button. An example of non-overlapping rendering is a TextView with no background, or
9323      * an ImageView with only the foreground image. The default implementation returns true;
9324      * subclasses should override if they have cases which can be optimized.
9325      *
9326      * @return true if the content in this view might overlap, false otherwise.
9327      */
9328     public boolean hasOverlappingRendering() {
9329         return true;
9330     }
9331 
9332     /**
9333      * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
9334      * completely transparent and 1 means the view is completely opaque.</p>
9335      *
9336      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
9337      * responsible for applying the opacity itself. Otherwise, calling this method is
9338      * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
9339      * setting a hardware layer.</p>
9340      *
9341      * <p>Note that setting alpha to a translucent value (0 < alpha < 1) may have
9342      * performance implications. It is generally best to use the alpha property sparingly and
9343      * transiently, as in the case of fading animations.</p>
9344      *
9345      * @param alpha The opacity of the view.
9346      *
9347      * @see #setLayerType(int, android.graphics.Paint)
9348      *
9349      * @attr ref android.R.styleable#View_alpha
9350      */
9351     public void setAlpha(float alpha) {
9352         ensureTransformationInfo();
9353         if (mTransformationInfo.mAlpha != alpha) {
9354             mTransformationInfo.mAlpha = alpha;
9355             if (onSetAlpha((int) (alpha * 255))) {
9356                 mPrivateFlags |= PFLAG_ALPHA_SET;
9357                 // subclass is handling alpha - don't optimize rendering cache invalidation
9358                 invalidateParentCaches();
9359                 invalidate(true);
9360             } else {
9361                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
9362                 invalidateViewProperty(true, false);
9363                 if (mDisplayList != null) {
9364                     mDisplayList.setAlpha(alpha);
9365                 }
9366             }
9367         }
9368     }
9369 
9370     /**
9371      * Faster version of setAlpha() which performs the same steps except there are
9372      * no calls to invalidate(). The caller of this function should perform proper invalidation
9373      * on the parent and this object. The return value indicates whether the subclass handles
9374      * alpha (the return value for onSetAlpha()).
9375      *
9376      * @param alpha The new value for the alpha property
9377      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
9378      *         the new value for the alpha property is different from the old value
9379      */
9380     boolean setAlphaNoInvalidation(float alpha) {
9381         ensureTransformationInfo();
9382         if (mTransformationInfo.mAlpha != alpha) {
9383             mTransformationInfo.mAlpha = alpha;
9384             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
9385             if (subclassHandlesAlpha) {
9386                 mPrivateFlags |= PFLAG_ALPHA_SET;
9387                 return true;
9388             } else {
9389                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
9390                 if (mDisplayList != null) {
9391                     mDisplayList.setAlpha(alpha);
9392                 }
9393             }
9394         }
9395         return false;
9396     }
9397 
9398     /**
9399      * Top position of this view relative to its parent.
9400      *
9401      * @return The top of this view, in pixels.
9402      */
9403     @ViewDebug.CapturedViewProperty
9404     public final int getTop() {
9405         return mTop;
9406     }
9407 
9408     /**
9409      * Sets the top position of this view relative to its parent. This method is meant to be called
9410      * by the layout system and should not generally be called otherwise, because the property
9411      * may be changed at any time by the layout.
9412      *
9413      * @param top The top of this view, in pixels.
9414      */
9415     public final void setTop(int top) {
9416         if (top != mTop) {
9417             updateMatrix();
9418             final boolean matrixIsIdentity = mTransformationInfo == null
9419                     || mTransformationInfo.mMatrixIsIdentity;
9420             if (matrixIsIdentity) {
9421                 if (mAttachInfo != null) {
9422                     int minTop;
9423                     int yLoc;
9424                     if (top < mTop) {
9425                         minTop = top;
9426                         yLoc = top - mTop;
9427                     } else {
9428                         minTop = mTop;
9429                         yLoc = 0;
9430                     }
9431                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
9432                 }
9433             } else {
9434                 // Double-invalidation is necessary to capture view's old and new areas
9435                 invalidate(true);
9436             }
9437 
9438             int width = mRight - mLeft;
9439             int oldHeight = mBottom - mTop;
9440 
9441             mTop = top;
9442             if (mDisplayList != null) {
9443                 mDisplayList.setTop(mTop);
9444             }
9445 
9446             onSizeChanged(width, mBottom - mTop, width, oldHeight);
9447 
9448             if (!matrixIsIdentity) {
9449                 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9450                     // A change in dimension means an auto-centered pivot point changes, too
9451                     mTransformationInfo.mMatrixDirty = true;
9452                 }
9453                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9454                 invalidate(true);
9455             }
9456             mBackgroundSizeChanged = true;
9457             invalidateParentIfNeeded();
9458             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9459                 // View was rejected last time it was drawn by its parent; this may have changed
9460                 invalidateParentIfNeeded();
9461             }
9462         }
9463     }
9464 
9465     /**
9466      * Bottom position of this view relative to its parent.
9467      *
9468      * @return The bottom of this view, in pixels.
9469      */
9470     @ViewDebug.CapturedViewProperty
9471     public final int getBottom() {
9472         return mBottom;
9473     }
9474 
9475     /**
9476      * True if this view has changed since the last time being drawn.
9477      *
9478      * @return The dirty state of this view.
9479      */
9480     public boolean isDirty() {
9481         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
9482     }
9483 
9484     /**
9485      * Sets the bottom position of this view relative to its parent. This method is meant to be
9486      * called by the layout system and should not generally be called otherwise, because the
9487      * property may be changed at any time by the layout.
9488      *
9489      * @param bottom The bottom of this view, in pixels.
9490      */
9491     public final void setBottom(int bottom) {
9492         if (bottom != mBottom) {
9493             updateMatrix();
9494             final boolean matrixIsIdentity = mTransformationInfo == null
9495                     || mTransformationInfo.mMatrixIsIdentity;
9496             if (matrixIsIdentity) {
9497                 if (mAttachInfo != null) {
9498                     int maxBottom;
9499                     if (bottom < mBottom) {
9500                         maxBottom = mBottom;
9501                     } else {
9502                         maxBottom = bottom;
9503                     }
9504                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
9505                 }
9506             } else {
9507                 // Double-invalidation is necessary to capture view's old and new areas
9508                 invalidate(true);
9509             }
9510 
9511             int width = mRight - mLeft;
9512             int oldHeight = mBottom - mTop;
9513 
9514             mBottom = bottom;
9515             if (mDisplayList != null) {
9516                 mDisplayList.setBottom(mBottom);
9517             }
9518 
9519             onSizeChanged(width, mBottom - mTop, width, oldHeight);
9520 
9521             if (!matrixIsIdentity) {
9522                 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9523                     // A change in dimension means an auto-centered pivot point changes, too
9524                     mTransformationInfo.mMatrixDirty = true;
9525                 }
9526                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9527                 invalidate(true);
9528             }
9529             mBackgroundSizeChanged = true;
9530             invalidateParentIfNeeded();
9531             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9532                 // View was rejected last time it was drawn by its parent; this may have changed
9533                 invalidateParentIfNeeded();
9534             }
9535         }
9536     }
9537 
9538     /**
9539      * Left position of this view relative to its parent.
9540      *
9541      * @return The left edge of this view, in pixels.
9542      */
9543     @ViewDebug.CapturedViewProperty
9544     public final int getLeft() {
9545         return mLeft;
9546     }
9547 
9548     /**
9549      * Sets the left position of this view relative to its parent. This method is meant to be called
9550      * by the layout system and should not generally be called otherwise, because the property
9551      * may be changed at any time by the layout.
9552      *
9553      * @param left The bottom of this view, in pixels.
9554      */
9555     public final void setLeft(int left) {
9556         if (left != mLeft) {
9557             updateMatrix();
9558             final boolean matrixIsIdentity = mTransformationInfo == null
9559                     || mTransformationInfo.mMatrixIsIdentity;
9560             if (matrixIsIdentity) {
9561                 if (mAttachInfo != null) {
9562                     int minLeft;
9563                     int xLoc;
9564                     if (left < mLeft) {
9565                         minLeft = left;
9566                         xLoc = left - mLeft;
9567                     } else {
9568                         minLeft = mLeft;
9569                         xLoc = 0;
9570                     }
9571                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
9572                 }
9573             } else {
9574                 // Double-invalidation is necessary to capture view's old and new areas
9575                 invalidate(true);
9576             }
9577 
9578             int oldWidth = mRight - mLeft;
9579             int height = mBottom - mTop;
9580 
9581             mLeft = left;
9582             if (mDisplayList != null) {
9583                 mDisplayList.setLeft(left);
9584             }
9585 
9586             onSizeChanged(mRight - mLeft, height, oldWidth, height);
9587 
9588             if (!matrixIsIdentity) {
9589                 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9590                     // A change in dimension means an auto-centered pivot point changes, too
9591                     mTransformationInfo.mMatrixDirty = true;
9592                 }
9593                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9594                 invalidate(true);
9595             }
9596             mBackgroundSizeChanged = true;
9597             invalidateParentIfNeeded();
9598             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9599                 // View was rejected last time it was drawn by its parent; this may have changed
9600                 invalidateParentIfNeeded();
9601             }
9602         }
9603     }
9604 
9605     /**
9606      * Right position of this view relative to its parent.
9607      *
9608      * @return The right edge of this view, in pixels.
9609      */
9610     @ViewDebug.CapturedViewProperty
9611     public final int getRight() {
9612         return mRight;
9613     }
9614 
9615     /**
9616      * Sets the right position of this view relative to its parent. This method is meant to be called
9617      * by the layout system and should not generally be called otherwise, because the property
9618      * may be changed at any time by the layout.
9619      *
9620      * @param right The bottom of this view, in pixels.
9621      */
9622     public final void setRight(int right) {
9623         if (right != mRight) {
9624             updateMatrix();
9625             final boolean matrixIsIdentity = mTransformationInfo == null
9626                     || mTransformationInfo.mMatrixIsIdentity;
9627             if (matrixIsIdentity) {
9628                 if (mAttachInfo != null) {
9629                     int maxRight;
9630                     if (right < mRight) {
9631                         maxRight = mRight;
9632                     } else {
9633                         maxRight = right;
9634                     }
9635                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
9636                 }
9637             } else {
9638                 // Double-invalidation is necessary to capture view's old and new areas
9639                 invalidate(true);
9640             }
9641 
9642             int oldWidth = mRight - mLeft;
9643             int height = mBottom - mTop;
9644 
9645             mRight = right;
9646             if (mDisplayList != null) {
9647                 mDisplayList.setRight(mRight);
9648             }
9649 
9650             onSizeChanged(mRight - mLeft, height, oldWidth, height);
9651 
9652             if (!matrixIsIdentity) {
9653                 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9654                     // A change in dimension means an auto-centered pivot point changes, too
9655                     mTransformationInfo.mMatrixDirty = true;
9656                 }
9657                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9658                 invalidate(true);
9659             }
9660             mBackgroundSizeChanged = true;
9661             invalidateParentIfNeeded();
9662             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9663                 // View was rejected last time it was drawn by its parent; this may have changed
9664                 invalidateParentIfNeeded();
9665             }
9666         }
9667     }
9668 
9669     /**
9670      * The visual x position of this view, in pixels. This is equivalent to the
9671      * {@link #setTranslationX(float) translationX} property plus the current
9672      * {@link #getLeft() left} property.
9673      *
9674      * @return The visual x position of this view, in pixels.
9675      */
9676     @ViewDebug.ExportedProperty(category = "drawing")
9677     public float getX() {
9678         return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
9679     }
9680 
9681     /**
9682      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
9683      * {@link #setTranslationX(float) translationX} property to be the difference between
9684      * the x value passed in and the current {@link #getLeft() left} property.
9685      *
9686      * @param x The visual x position of this view, in pixels.
9687      */
9688     public void setX(float x) {
9689         setTranslationX(x - mLeft);
9690     }
9691 
9692     /**
9693      * The visual y position of this view, in pixels. This is equivalent to the
9694      * {@link #setTranslationY(float) translationY} property plus the current
9695      * {@link #getTop() top} property.
9696      *
9697      * @return The visual y position of this view, in pixels.
9698      */
9699     @ViewDebug.ExportedProperty(category = "drawing")
9700     public float getY() {
9701         return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
9702     }
9703 
9704     /**
9705      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
9706      * {@link #setTranslationY(float) translationY} property to be the difference between
9707      * the y value passed in and the current {@link #getTop() top} property.
9708      *
9709      * @param y The visual y position of this view, in pixels.
9710      */
9711     public void setY(float y) {
9712         setTranslationY(y - mTop);
9713     }
9714 
9715 
9716     /**
9717      * The horizontal location of this view relative to its {@link #getLeft() left} position.
9718      * This position is post-layout, in addition to wherever the object's
9719      * layout placed it.
9720      *
9721      * @return The horizontal position of this view relative to its left position, in pixels.
9722      */
9723     @ViewDebug.ExportedProperty(category = "drawing")
9724     public float getTranslationX() {
9725         return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
9726     }
9727 
9728     /**
9729      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
9730      * This effectively positions the object post-layout, in addition to wherever the object's
9731      * layout placed it.
9732      *
9733      * @param translationX The horizontal position of this view relative to its left position,
9734      * in pixels.
9735      *
9736      * @attr ref android.R.styleable#View_translationX
9737      */
9738     public void setTranslationX(float translationX) {
9739         ensureTransformationInfo();
9740         final TransformationInfo info = mTransformationInfo;
9741         if (info.mTranslationX != translationX) {
9742             // Double-invalidation is necessary to capture view's old and new areas
9743             invalidateViewProperty(true, false);
9744             info.mTranslationX = translationX;
9745             info.mMatrixDirty = true;
9746             invalidateViewProperty(false, true);
9747             if (mDisplayList != null) {
9748                 mDisplayList.setTranslationX(translationX);
9749             }
9750             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9751                 // View was rejected last time it was drawn by its parent; this may have changed
9752                 invalidateParentIfNeeded();
9753             }
9754         }
9755     }
9756 
9757     /**
9758      * The horizontal location of this view relative to its {@link #getTop() top} position.
9759      * This position is post-layout, in addition to wherever the object's
9760      * layout placed it.
9761      *
9762      * @return The vertical position of this view relative to its top position,
9763      * in pixels.
9764      */
9765     @ViewDebug.ExportedProperty(category = "drawing")
9766     public float getTranslationY() {
9767         return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
9768     }
9769 
9770     /**
9771      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
9772      * This effectively positions the object post-layout, in addition to wherever the object's
9773      * layout placed it.
9774      *
9775      * @param translationY The vertical position of this view relative to its top position,
9776      * in pixels.
9777      *
9778      * @attr ref android.R.styleable#View_translationY
9779      */
9780     public void setTranslationY(float translationY) {
9781         ensureTransformationInfo();
9782         final TransformationInfo info = mTransformationInfo;
9783         if (info.mTranslationY != translationY) {
9784             invalidateViewProperty(true, false);
9785             info.mTranslationY = translationY;
9786             info.mMatrixDirty = true;
9787             invalidateViewProperty(false, true);
9788             if (mDisplayList != null) {
9789                 mDisplayList.setTranslationY(translationY);
9790             }
9791             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9792                 // View was rejected last time it was drawn by its parent; this may have changed
9793                 invalidateParentIfNeeded();
9794             }
9795         }
9796     }
9797 
9798     /**
9799      * Hit rectangle in parent's coordinates
9800      *
9801      * @param outRect The hit rectangle of the view.
9802      */
9803     public void getHitRect(Rect outRect) {
9804         updateMatrix();
9805         final TransformationInfo info = mTransformationInfo;
9806         if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
9807             outRect.set(mLeft, mTop, mRight, mBottom);
9808         } else {
9809             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
9810             tmpRect.set(-info.mPivotX, -info.mPivotY,
9811                     getWidth() - info.mPivotX, getHeight() - info.mPivotY);
9812             info.mMatrix.mapRect(tmpRect);
9813             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
9814                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
9815         }
9816     }
9817 
9818     /**
9819      * Determines whether the given point, in local coordinates is inside the view.
9820      */
9821     /*package*/ final boolean pointInView(float localX, float localY) {
9822         return localX >= 0 && localX < (mRight - mLeft)
9823                 && localY >= 0 && localY < (mBottom - mTop);
9824     }
9825 
9826     /**
9827      * Utility method to determine whether the given point, in local coordinates,
9828      * is inside the view, where the area of the view is expanded by the slop factor.
9829      * This method is called while processing touch-move events to determine if the event
9830      * is still within the view.
9831      */
9832     private boolean pointInView(float localX, float localY, float slop) {
9833         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
9834                 localY < ((mBottom - mTop) + slop);
9835     }
9836 
9837     /**
9838      * When a view has focus and the user navigates away from it, the next view is searched for
9839      * starting from the rectangle filled in by this method.
9840      *
9841      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
9842      * of the view.  However, if your view maintains some idea of internal selection,
9843      * such as a cursor, or a selected row or column, you should override this method and
9844      * fill in a more specific rectangle.
9845      *
9846      * @param r The rectangle to fill in, in this view's coordinates.
9847      */
9848     public void getFocusedRect(Rect r) {
9849         getDrawingRect(r);
9850     }
9851 
9852     /**
9853      * If some part of this view is not clipped by any of its parents, then
9854      * return that area in r in global (root) coordinates. To convert r to local
9855      * coordinates (without taking possible View rotations into account), offset
9856      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
9857      * If the view is completely clipped or translated out, return false.
9858      *
9859      * @param r If true is returned, r holds the global coordinates of the
9860      *        visible portion of this view.
9861      * @param globalOffset If true is returned, globalOffset holds the dx,dy
9862      *        between this view and its root. globalOffet may be null.
9863      * @return true if r is non-empty (i.e. part of the view is visible at the
9864      *         root level.
9865      */
9866     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
9867         int width = mRight - mLeft;
9868         int height = mBottom - mTop;
9869         if (width > 0 && height > 0) {
9870             r.set(0, 0, width, height);
9871             if (globalOffset != null) {
9872                 globalOffset.set(-mScrollX, -mScrollY);
9873             }
9874             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
9875         }
9876         return false;
9877     }
9878 
9879     public final boolean getGlobalVisibleRect(Rect r) {
9880         return getGlobalVisibleRect(r, null);
9881     }
9882 
9883     public final boolean getLocalVisibleRect(Rect r) {
9884         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
9885         if (getGlobalVisibleRect(r, offset)) {
9886             r.offset(-offset.x, -offset.y); // make r local
9887             return true;
9888         }
9889         return false;
9890     }
9891 
9892     /**
9893      * Offset this view's vertical location by the specified number of pixels.
9894      *
9895      * @param offset the number of pixels to offset the view by
9896      */
9897     public void offsetTopAndBottom(int offset) {
9898         if (offset != 0) {
9899             updateMatrix();
9900             final boolean matrixIsIdentity = mTransformationInfo == null
9901                     || mTransformationInfo.mMatrixIsIdentity;
9902             if (matrixIsIdentity) {
9903                 if (mDisplayList != null) {
9904                     invalidateViewProperty(false, false);
9905                 } else {
9906                     final ViewParent p = mParent;
9907                     if (p != null && mAttachInfo != null) {
9908                         final Rect r = mAttachInfo.mTmpInvalRect;
9909                         int minTop;
9910                         int maxBottom;
9911                         int yLoc;
9912                         if (offset < 0) {
9913                             minTop = mTop + offset;
9914                             maxBottom = mBottom;
9915                             yLoc = offset;
9916                         } else {
9917                             minTop = mTop;
9918                             maxBottom = mBottom + offset;
9919                             yLoc = 0;
9920                         }
9921                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
9922                         p.invalidateChild(this, r);
9923                     }
9924                 }
9925             } else {
9926                 invalidateViewProperty(false, false);
9927             }
9928 
9929             mTop += offset;
9930             mBottom += offset;
9931             if (mDisplayList != null) {
9932                 mDisplayList.offsetTopBottom(offset);
9933                 invalidateViewProperty(false, false);
9934             } else {
9935                 if (!matrixIsIdentity) {
9936                     invalidateViewProperty(false, true);
9937                 }
9938                 invalidateParentIfNeeded();
9939             }
9940         }
9941     }
9942 
9943     /**
9944      * Offset this view's horizontal location by the specified amount of pixels.
9945      *
9946      * @param offset the numer of pixels to offset the view by
9947      */
9948     public void offsetLeftAndRight(int offset) {
9949         if (offset != 0) {
9950             updateMatrix();
9951             final boolean matrixIsIdentity = mTransformationInfo == null
9952                     || mTransformationInfo.mMatrixIsIdentity;
9953             if (matrixIsIdentity) {
9954                 if (mDisplayList != null) {
9955                     invalidateViewProperty(false, false);
9956                 } else {
9957                     final ViewParent p = mParent;
9958                     if (p != null && mAttachInfo != null) {
9959                         final Rect r = mAttachInfo.mTmpInvalRect;
9960                         int minLeft;
9961                         int maxRight;
9962                         if (offset < 0) {
9963                             minLeft = mLeft + offset;
9964                             maxRight = mRight;
9965                         } else {
9966                             minLeft = mLeft;
9967                             maxRight = mRight + offset;
9968                         }
9969                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
9970                         p.invalidateChild(this, r);
9971                     }
9972                 }
9973             } else {
9974                 invalidateViewProperty(false, false);
9975             }
9976 
9977             mLeft += offset;
9978             mRight += offset;
9979             if (mDisplayList != null) {
9980                 mDisplayList.offsetLeftRight(offset);
9981                 invalidateViewProperty(false, false);
9982             } else {
9983                 if (!matrixIsIdentity) {
9984                     invalidateViewProperty(false, true);
9985                 }
9986                 invalidateParentIfNeeded();
9987             }
9988         }
9989     }
9990 
9991     /**
9992      * Get the LayoutParams associated with this view. All views should have
9993      * layout parameters. These supply parameters to the <i>parent</i> of this
9994      * view specifying how it should be arranged. There are many subclasses of
9995      * ViewGroup.LayoutParams, and these correspond to the different subclasses
9996      * of ViewGroup that are responsible for arranging their children.
9997      *
9998      * This method may return null if this View is not attached to a parent
9999      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
10000      * was not invoked successfully. When a View is attached to a parent
10001      * ViewGroup, this method must not return null.
10002      *
10003      * @return The LayoutParams associated with this view, or null if no
10004      *         parameters have been set yet
10005      */
10006     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
10007     public ViewGroup.LayoutParams getLayoutParams() {
10008         return mLayoutParams;
10009     }
10010 
10011     /**
10012      * Set the layout parameters associated with this view. These supply
10013      * parameters to the <i>parent</i> of this view specifying how it should be
10014      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
10015      * correspond to the different subclasses of ViewGroup that are responsible
10016      * for arranging their children.
10017      *
10018      * @param params The layout parameters for this view, cannot be null
10019      */
10020     public void setLayoutParams(ViewGroup.LayoutParams params) {
10021         if (params == null) {
10022             throw new NullPointerException("Layout parameters cannot be null");
10023         }
10024         mLayoutParams = params;
10025         resolveLayoutParams();
10026         if (mParent instanceof ViewGroup) {
10027             ((ViewGroup) mParent).onSetLayoutParams(this, params);
10028         }
10029         requestLayout();
10030     }
10031 
10032     /**
10033      * Resolve the layout parameters depending on the resolved layout direction
10034      *
10035      * @hide
10036      */
10037     public void resolveLayoutParams() {
10038         if (mLayoutParams != null) {
10039             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
10040         }
10041     }
10042 
10043     /**
10044      * Set the scrolled position of your view. This will cause a call to
10045      * {@link #onScrollChanged(int, int, int, int)} and the view will be
10046      * invalidated.
10047      * @param x the x position to scroll to
10048      * @param y the y position to scroll to
10049      */
10050     public void scrollTo(int x, int y) {
10051         if (mScrollX != x || mScrollY != y) {
10052             int oldX = mScrollX;
10053             int oldY = mScrollY;
10054             mScrollX = x;
10055             mScrollY = y;
10056             invalidateParentCaches();
10057             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
10058             if (!awakenScrollBars()) {
10059                 postInvalidateOnAnimation();
10060             }
10061         }
10062     }
10063 
10064     /**
10065      * Move the scrolled position of your view. This will cause a call to
10066      * {@link #onScrollChanged(int, int, int, int)} and the view will be
10067      * invalidated.
10068      * @param x the amount of pixels to scroll by horizontally
10069      * @param y the amount of pixels to scroll by vertically
10070      */
10071     public void scrollBy(int x, int y) {
10072         scrollTo(mScrollX + x, mScrollY + y);
10073     }
10074 
10075     /**
10076      * <p>Trigger the scrollbars to draw. When invoked this method starts an
10077      * animation to fade the scrollbars out after a default delay. If a subclass
10078      * provides animated scrolling, the start delay should equal the duration
10079      * of the scrolling animation.</p>
10080      *
10081      * <p>The animation starts only if at least one of the scrollbars is
10082      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
10083      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
10084      * this method returns true, and false otherwise. If the animation is
10085      * started, this method calls {@link #invalidate()}; in that case the
10086      * caller should not call {@link #invalidate()}.</p>
10087      *
10088      * <p>This method should be invoked every time a subclass directly updates
10089      * the scroll parameters.</p>
10090      *
10091      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
10092      * and {@link #scrollTo(int, int)}.</p>
10093      *
10094      * @return true if the animation is played, false otherwise
10095      *
10096      * @see #awakenScrollBars(int)
10097      * @see #scrollBy(int, int)
10098      * @see #scrollTo(int, int)
10099      * @see #isHorizontalScrollBarEnabled()
10100      * @see #isVerticalScrollBarEnabled()
10101      * @see #setHorizontalScrollBarEnabled(boolean)
10102      * @see #setVerticalScrollBarEnabled(boolean)
10103      */
10104     protected boolean awakenScrollBars() {
10105         return mScrollCache != null &&
10106                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
10107     }
10108 
10109     /**
10110      * Trigger the scrollbars to draw.
10111      * This method differs from awakenScrollBars() only in its default duration.
10112      * initialAwakenScrollBars() will show the scroll bars for longer than
10113      * usual to give the user more of a chance to notice them.
10114      *
10115      * @return true if the animation is played, false otherwise.
10116      */
10117     private boolean initialAwakenScrollBars() {
10118         return mScrollCache != null &&
10119                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
10120     }
10121 
10122     /**
10123      * <p>
10124      * Trigger the scrollbars to draw. When invoked this method starts an
10125      * animation to fade the scrollbars out after a fixed delay. If a subclass
10126      * provides animated scrolling, the start delay should equal the duration of
10127      * the scrolling animation.
10128      * </p>
10129      *
10130      * <p>
10131      * The animation starts only if at least one of the scrollbars is enabled,
10132      * as specified by {@link #isHorizontalScrollBarEnabled()} and
10133      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
10134      * this method returns true, and false otherwise. If the animation is
10135      * started, this method calls {@link #invalidate()}; in that case the caller
10136      * should not call {@link #invalidate()}.
10137      * </p>
10138      *
10139      * <p>
10140      * This method should be invoked everytime a subclass directly updates the
10141      * scroll parameters.
10142      * </p>
10143      *
10144      * @param startDelay the delay, in milliseconds, after which the animation
10145      *        should start; when the delay is 0, the animation starts
10146      *        immediately
10147      * @return true if the animation is played, false otherwise
10148      *
10149      * @see #scrollBy(int, int)
10150      * @see #scrollTo(int, int)
10151      * @see #isHorizontalScrollBarEnabled()
10152      * @see #isVerticalScrollBarEnabled()
10153      * @see #setHorizontalScrollBarEnabled(boolean)
10154      * @see #setVerticalScrollBarEnabled(boolean)
10155      */
10156     protected boolean awakenScrollBars(int startDelay) {
10157         return awakenScrollBars(startDelay, true);
10158     }
10159 
10160     /**
10161      * <p>
10162      * Trigger the scrollbars to draw. When invoked this method starts an
10163      * animation to fade the scrollbars out after a fixed delay. If a subclass
10164      * provides animated scrolling, the start delay should equal the duration of
10165      * the scrolling animation.
10166      * </p>
10167      *
10168      * <p>
10169      * The animation starts only if at least one of the scrollbars is enabled,
10170      * as specified by {@link #isHorizontalScrollBarEnabled()} and
10171      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
10172      * this method returns true, and false otherwise. If the animation is
10173      * started, this method calls {@link #invalidate()} if the invalidate parameter
10174      * is set to true; in that case the caller
10175      * should not call {@link #invalidate()}.
10176      * </p>
10177      *
10178      * <p>
10179      * This method should be invoked everytime a subclass directly updates the
10180      * scroll parameters.
10181      * </p>
10182      *
10183      * @param startDelay the delay, in milliseconds, after which the animation
10184      *        should start; when the delay is 0, the animation starts
10185      *        immediately
10186      *
10187      * @param invalidate Wheter this method should call invalidate
10188      *
10189      * @return true if the animation is played, false otherwise
10190      *
10191      * @see #scrollBy(int, int)
10192      * @see #scrollTo(int, int)
10193      * @see #isHorizontalScrollBarEnabled()
10194      * @see #isVerticalScrollBarEnabled()
10195      * @see #setHorizontalScrollBarEnabled(boolean)
10196      * @see #setVerticalScrollBarEnabled(boolean)
10197      */
10198     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
10199         final ScrollabilityCache scrollCache = mScrollCache;
10200 
10201         if (scrollCache == null || !scrollCache.fadeScrollBars) {
10202             return false;
10203         }
10204 
10205         if (scrollCache.scrollBar == null) {
10206             scrollCache.scrollBar = new ScrollBarDrawable();
10207         }
10208 
10209         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
10210 
10211             if (invalidate) {
10212                 // Invalidate to show the scrollbars
10213                 postInvalidateOnAnimation();
10214             }
10215 
10216             if (scrollCache.state == ScrollabilityCache.OFF) {
10217                 // FIXME: this is copied from WindowManagerService.
10218                 // We should get this value from the system when it
10219                 // is possible to do so.
10220                 final int KEY_REPEAT_FIRST_DELAY = 750;
10221                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
10222             }
10223 
10224             // Tell mScrollCache when we should start fading. This may
10225             // extend the fade start time if one was already scheduled
10226             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
10227             scrollCache.fadeStartTime = fadeStartTime;
10228             scrollCache.state = ScrollabilityCache.ON;
10229 
10230             // Schedule our fader to run, unscheduling any old ones first
10231             if (mAttachInfo != null) {
10232                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
10233                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
10234             }
10235 
10236             return true;
10237         }
10238 
10239         return false;
10240     }
10241 
10242     /**
10243      * Do not invalidate views which are not visible and which are not running an animation. They
10244      * will not get drawn and they should not set dirty flags as if they will be drawn
10245      */
10246     private boolean skipInvalidate() {
10247         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
10248                 (!(mParent instanceof ViewGroup) ||
10249                         !((ViewGroup) mParent).isViewTransitioning(this));
10250     }
10251     /**
10252      * Mark the area defined by dirty as needing to be drawn. If the view is
10253      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
10254      * in the future. This must be called from a UI thread. To call from a non-UI
10255      * thread, call {@link #postInvalidate()}.
10256      *
10257      * WARNING: This method is destructive to dirty.
10258      * @param dirty the rectangle representing the bounds of the dirty region
10259      */
10260     public void invalidate(Rect dirty) {
10261         if (skipInvalidate()) {
10262             return;
10263         }
10264         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10265                 (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
10266                 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
10267             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10268             mPrivateFlags |= PFLAG_INVALIDATED;
10269             mPrivateFlags |= PFLAG_DIRTY;
10270             final ViewParent p = mParent;
10271             final AttachInfo ai = mAttachInfo;
10272             //noinspection PointlessBooleanExpression,ConstantConditions
10273             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10274                 if (p != null && ai != null && ai.mHardwareAccelerated) {
10275                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10276                     // with a null dirty rect, which tells the ViewAncestor to redraw everything
10277                     p.invalidateChild(this, null);
10278                     return;
10279                 }
10280             }
10281             if (p != null && ai != null) {
10282                 final int scrollX = mScrollX;
10283                 final int scrollY = mScrollY;
10284                 final Rect r = ai.mTmpInvalRect;
10285                 r.set(dirty.left - scrollX, dirty.top - scrollY,
10286                         dirty.right - scrollX, dirty.bottom - scrollY);
10287                 mParent.invalidateChild(this, r);
10288             }
10289         }
10290     }
10291 
10292     /**
10293      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn.
10294      * The coordinates of the dirty rect are relative to the view.
10295      * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
10296      * will be called at some point in the future. This must be called from
10297      * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
10298      * @param l the left position of the dirty region
10299      * @param t the top position of the dirty region
10300      * @param r the right position of the dirty region
10301      * @param b the bottom position of the dirty region
10302      */
10303     public void invalidate(int l, int t, int r, int b) {
10304         if (skipInvalidate()) {
10305             return;
10306         }
10307         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10308                 (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
10309                 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
10310             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10311             mPrivateFlags |= PFLAG_INVALIDATED;
10312             mPrivateFlags |= PFLAG_DIRTY;
10313             final ViewParent p = mParent;
10314             final AttachInfo ai = mAttachInfo;
10315             //noinspection PointlessBooleanExpression,ConstantConditions
10316             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10317                 if (p != null && ai != null && ai.mHardwareAccelerated) {
10318                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10319                     // with a null dirty rect, which tells the ViewAncestor to redraw everything
10320                     p.invalidateChild(this, null);
10321                     return;
10322                 }
10323             }
10324             if (p != null && ai != null && l < r && t < b) {
10325                 final int scrollX = mScrollX;
10326                 final int scrollY = mScrollY;
10327                 final Rect tmpr = ai.mTmpInvalRect;
10328                 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
10329                 p.invalidateChild(this, tmpr);
10330             }
10331         }
10332     }
10333 
10334     /**
10335      * Invalidate the whole view. If the view is visible,
10336      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
10337      * the future. This must be called from a UI thread. To call from a non-UI thread,
10338      * call {@link #postInvalidate()}.
10339      */
10340     public void invalidate() {
10341         invalidate(true);
10342     }
10343 
10344     /**
10345      * This is where the invalidate() work actually happens. A full invalidate()
10346      * causes the drawing cache to be invalidated, but this function can be called with
10347      * invalidateCache set to false to skip that invalidation step for cases that do not
10348      * need it (for example, a component that remains at the same dimensions with the same
10349      * content).
10350      *
10351      * @param invalidateCache Whether the drawing cache for this view should be invalidated as
10352      * well. This is usually true for a full invalidate, but may be set to false if the
10353      * View's contents or dimensions have not changed.
10354      */
10355     void invalidate(boolean invalidateCache) {
10356         if (skipInvalidate()) {
10357             return;
10358         }
10359         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10360                 (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
10361                 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
10362             mLastIsOpaque = isOpaque();
10363             mPrivateFlags &= ~PFLAG_DRAWN;
10364             mPrivateFlags |= PFLAG_DIRTY;
10365             if (invalidateCache) {
10366                 mPrivateFlags |= PFLAG_INVALIDATED;
10367                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10368             }
10369             final AttachInfo ai = mAttachInfo;
10370             final ViewParent p = mParent;
10371             //noinspection PointlessBooleanExpression,ConstantConditions
10372             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10373                 if (p != null && ai != null && ai.mHardwareAccelerated) {
10374                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10375                     // with a null dirty rect, which tells the ViewAncestor to redraw everything
10376                     p.invalidateChild(this, null);
10377                     return;
10378                 }
10379             }
10380 
10381             if (p != null && ai != null) {
10382                 final Rect r = ai.mTmpInvalRect;
10383                 r.set(0, 0, mRight - mLeft, mBottom - mTop);
10384                 // Don't call invalidate -- we don't want to internally scroll
10385                 // our own bounds
10386                 p.invalidateChild(this, r);
10387             }
10388         }
10389     }
10390 
10391     /**
10392      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
10393      * set any flags or handle all of the cases handled by the default invalidation methods.
10394      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
10395      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
10396      * walk up the hierarchy, transforming the dirty rect as necessary.
10397      *
10398      * The method also handles normal invalidation logic if display list properties are not
10399      * being used in this view. The invalidateParent and forceRedraw flags are used by that
10400      * backup approach, to handle these cases used in the various property-setting methods.
10401      *
10402      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
10403      * are not being used in this view
10404      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
10405      * list properties are not being used in this view
10406      */
10407     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
10408         if (mDisplayList == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) {
10409             if (invalidateParent) {
10410                 invalidateParentCaches();
10411             }
10412             if (forceRedraw) {
10413                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10414             }
10415             invalidate(false);
10416         } else {
10417             final AttachInfo ai = mAttachInfo;
10418             final ViewParent p = mParent;
10419             if (p != null && ai != null) {
10420                 final Rect r = ai.mTmpInvalRect;
10421                 r.set(0, 0, mRight - mLeft, mBottom - mTop);
10422                 if (mParent instanceof ViewGroup) {
10423                     ((ViewGroup) mParent).invalidateChildFast(this, r);
10424                 } else {
10425                     mParent.invalidateChild(this, r);
10426                 }
10427             }
10428         }
10429     }
10430 
10431     /**
10432      * Utility method to transform a given Rect by the current matrix of this view.
10433      */
10434     void transformRect(final Rect rect) {
10435         if (!getMatrix().isIdentity()) {
10436             RectF boundingRect = mAttachInfo.mTmpTransformRect;
10437             boundingRect.set(rect);
10438             getMatrix().mapRect(boundingRect);
10439             rect.set((int) (boundingRect.left - 0.5f),
10440                     (int) (boundingRect.top - 0.5f),
10441                     (int) (boundingRect.right + 0.5f),
10442                     (int) (boundingRect.bottom + 0.5f));
10443         }
10444     }
10445 
10446     /**
10447      * Used to indicate that the parent of this view should clear its caches. This functionality
10448      * is used to force the parent to rebuild its display list (when hardware-accelerated),
10449      * which is necessary when various parent-managed properties of the view change, such as
10450      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
10451      * clears the parent caches and does not causes an invalidate event.
10452      *
10453      * @hide
10454      */
10455     protected void invalidateParentCaches() {
10456         if (mParent instanceof View) {
10457             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
10458         }
10459     }
10460 
10461     /**
10462      * Used to indicate that the parent of this view should be invalidated. This functionality
10463      * is used to force the parent to rebuild its display list (when hardware-accelerated),
10464      * which is necessary when various parent-managed properties of the view change, such as
10465      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
10466      * an invalidation event to the parent.
10467      *
10468      * @hide
10469      */
10470     protected void invalidateParentIfNeeded() {
10471         if (isHardwareAccelerated() && mParent instanceof View) {
10472             ((View) mParent).invalidate(true);
10473         }
10474     }
10475 
10476     /**
10477      * Indicates whether this View is opaque. An opaque View guarantees that it will
10478      * draw all the pixels overlapping its bounds using a fully opaque color.
10479      *
10480      * Subclasses of View should override this method whenever possible to indicate
10481      * whether an instance is opaque. Opaque Views are treated in a special way by
10482      * the View hierarchy, possibly allowing it to perform optimizations during
10483      * invalidate/draw passes.
10484      *
10485      * @return True if this View is guaranteed to be fully opaque, false otherwise.
10486      */
10487     @ViewDebug.ExportedProperty(category = "drawing")
10488     public boolean isOpaque() {
10489         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
10490                 ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f);
10491     }
10492 
10493     /**
10494      * @hide
10495      */
10496     protected void computeOpaqueFlags() {
10497         // Opaque if:
10498         //   - Has a background
10499         //   - Background is opaque
10500         //   - Doesn't have scrollbars or scrollbars are inside overlay
10501 
10502         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
10503             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
10504         } else {
10505             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
10506         }
10507 
10508         final int flags = mViewFlags;
10509         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
10510                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
10511             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
10512         } else {
10513             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
10514         }
10515     }
10516 
10517     /**
10518      * @hide
10519      */
10520     protected boolean hasOpaqueScrollbars() {
10521         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
10522     }
10523 
10524     /**
10525      * @return A handler associated with the thread running the View. This
10526      * handler can be used to pump events in the UI events queue.
10527      */
10528     public Handler getHandler() {
10529         if (mAttachInfo != null) {
10530             return mAttachInfo.mHandler;
10531         }
10532         return null;
10533     }
10534 
10535     /**
10536      * Gets the view root associated with the View.
10537      * @return The view root, or null if none.
10538      * @hide
10539      */
10540     public ViewRootImpl getViewRootImpl() {
10541         if (mAttachInfo != null) {
10542             return mAttachInfo.mViewRootImpl;
10543         }
10544         return null;
10545     }
10546 
10547     /**
10548      * <p>Causes the Runnable to be added to the message queue.
10549      * The runnable will be run on the user interface thread.</p>
10550      *
10551      * @param action The Runnable that will be executed.
10552      *
10553      * @return Returns true if the Runnable was successfully placed in to the
10554      *         message queue.  Returns false on failure, usually because the
10555      *         looper processing the message queue is exiting.
10556      *
10557      * @see #postDelayed
10558      * @see #removeCallbacks
10559      */
10560     public boolean post(Runnable action) {
10561         final AttachInfo attachInfo = mAttachInfo;
10562         if (attachInfo != null) {
10563             return attachInfo.mHandler.post(action);
10564         }
10565         // Assume that post will succeed later
10566         ViewRootImpl.getRunQueue().post(action);
10567         return true;
10568     }
10569 
10570     /**
10571      * <p>Causes the Runnable to be added to the message queue, to be run
10572      * after the specified amount of time elapses.
10573      * The runnable will be run on the user interface thread.</p>
10574      *
10575      * @param action The Runnable that will be executed.
10576      * @param delayMillis The delay (in milliseconds) until the Runnable
10577      *        will be executed.
10578      *
10579      * @return true if the Runnable was successfully placed in to the
10580      *         message queue.  Returns false on failure, usually because the
10581      *         looper processing the message queue is exiting.  Note that a
10582      *         result of true does not mean the Runnable will be processed --
10583      *         if the looper is quit before the delivery time of the message
10584      *         occurs then the message will be dropped.
10585      *
10586      * @see #post
10587      * @see #removeCallbacks
10588      */
10589     public boolean postDelayed(Runnable action, long delayMillis) {
10590         final AttachInfo attachInfo = mAttachInfo;
10591         if (attachInfo != null) {
10592             return attachInfo.mHandler.postDelayed(action, delayMillis);
10593         }
10594         // Assume that post will succeed later
10595         ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10596         return true;
10597     }
10598 
10599     /**
10600      * <p>Causes the Runnable to execute on the next animation time step.
10601      * The runnable will be run on the user interface thread.</p>
10602      *
10603      * @param action The Runnable that will be executed.
10604      *
10605      * @see #postOnAnimationDelayed
10606      * @see #removeCallbacks
10607      */
10608     public void postOnAnimation(Runnable action) {
10609         final AttachInfo attachInfo = mAttachInfo;
10610         if (attachInfo != null) {
10611             attachInfo.mViewRootImpl.mChoreographer.postCallback(
10612                     Choreographer.CALLBACK_ANIMATION, action, null);
10613         } else {
10614             // Assume that post will succeed later
10615             ViewRootImpl.getRunQueue().post(action);
10616         }
10617     }
10618 
10619     /**
10620      * <p>Causes the Runnable to execute on the next animation time step,
10621      * after the specified amount of time elapses.
10622      * The runnable will be run on the user interface thread.</p>
10623      *
10624      * @param action The Runnable that will be executed.
10625      * @param delayMillis The delay (in milliseconds) until the Runnable
10626      *        will be executed.
10627      *
10628      * @see #postOnAnimation
10629      * @see #removeCallbacks
10630      */
10631     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
10632         final AttachInfo attachInfo = mAttachInfo;
10633         if (attachInfo != null) {
10634             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
10635                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
10636         } else {
10637             // Assume that post will succeed later
10638             ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10639         }
10640     }
10641 
10642     /**
10643      * <p>Removes the specified Runnable from the message queue.</p>
10644      *
10645      * @param action The Runnable to remove from the message handling queue
10646      *
10647      * @return true if this view could ask the Handler to remove the Runnable,
10648      *         false otherwise. When the returned value is true, the Runnable
10649      *         may or may not have been actually removed from the message queue
10650      *         (for instance, if the Runnable was not in the queue already.)
10651      *
10652      * @see #post
10653      * @see #postDelayed
10654      * @see #postOnAnimation
10655      * @see #postOnAnimationDelayed
10656      */
10657     public boolean removeCallbacks(Runnable action) {
10658         if (action != null) {
10659             final AttachInfo attachInfo = mAttachInfo;
10660             if (attachInfo != null) {
10661                 attachInfo.mHandler.removeCallbacks(action);
10662                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
10663                         Choreographer.CALLBACK_ANIMATION, action, null);
10664             } else {
10665                 // Assume that post will succeed later
10666                 ViewRootImpl.getRunQueue().removeCallbacks(action);
10667             }
10668         }
10669         return true;
10670     }
10671 
10672     /**
10673      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
10674      * Use this to invalidate the View from a non-UI thread.</p>
10675      *
10676      * <p>This method can be invoked from outside of the UI thread
10677      * only when this View is attached to a window.</p>
10678      *
10679      * @see #invalidate()
10680      * @see #postInvalidateDelayed(long)
10681      */
10682     public void postInvalidate() {
10683         postInvalidateDelayed(0);
10684     }
10685 
10686     /**
10687      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10688      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
10689      *
10690      * <p>This method can be invoked from outside of the UI thread
10691      * only when this View is attached to a window.</p>
10692      *
10693      * @param left The left coordinate of the rectangle to invalidate.
10694      * @param top The top coordinate of the rectangle to invalidate.
10695      * @param right The right coordinate of the rectangle to invalidate.
10696      * @param bottom The bottom coordinate of the rectangle to invalidate.
10697      *
10698      * @see #invalidate(int, int, int, int)
10699      * @see #invalidate(Rect)
10700      * @see #postInvalidateDelayed(long, int, int, int, int)
10701      */
10702     public void postInvalidate(int left, int top, int right, int bottom) {
10703         postInvalidateDelayed(0, left, top, right, bottom);
10704     }
10705 
10706     /**
10707      * <p>Cause an invalidate to happen on a subsequent cycle through the event
10708      * loop. Waits for the specified amount of time.</p>
10709      *
10710      * <p>This method can be invoked from outside of the UI thread
10711      * only when this View is attached to a window.</p>
10712      *
10713      * @param delayMilliseconds the duration in milliseconds to delay the
10714      *         invalidation by
10715      *
10716      * @see #invalidate()
10717      * @see #postInvalidate()
10718      */
10719     public void postInvalidateDelayed(long delayMilliseconds) {
10720         // We try only with the AttachInfo because there's no point in invalidating
10721         // if we are not attached to our window
10722         final AttachInfo attachInfo = mAttachInfo;
10723         if (attachInfo != null) {
10724             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
10725         }
10726     }
10727 
10728     /**
10729      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10730      * through the event loop. Waits for the specified amount of time.</p>
10731      *
10732      * <p>This method can be invoked from outside of the UI thread
10733      * only when this View is attached to a window.</p>
10734      *
10735      * @param delayMilliseconds the duration in milliseconds to delay the
10736      *         invalidation by
10737      * @param left The left coordinate of the rectangle to invalidate.
10738      * @param top The top coordinate of the rectangle to invalidate.
10739      * @param right The right coordinate of the rectangle to invalidate.
10740      * @param bottom The bottom coordinate of the rectangle to invalidate.
10741      *
10742      * @see #invalidate(int, int, int, int)
10743      * @see #invalidate(Rect)
10744      * @see #postInvalidate(int, int, int, int)
10745      */
10746     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
10747             int right, int bottom) {
10748 
10749         // We try only with the AttachInfo because there's no point in invalidating
10750         // if we are not attached to our window
10751         final AttachInfo attachInfo = mAttachInfo;
10752         if (attachInfo != null) {
10753             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
10754             info.target = this;
10755             info.left = left;
10756             info.top = top;
10757             info.right = right;
10758             info.bottom = bottom;
10759 
10760             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
10761         }
10762     }
10763 
10764     /**
10765      * <p>Cause an invalidate to happen on the next animation time step, typically the
10766      * next display frame.</p>
10767      *
10768      * <p>This method can be invoked from outside of the UI thread
10769      * only when this View is attached to a window.</p>
10770      *
10771      * @see #invalidate()
10772      */
10773     public void postInvalidateOnAnimation() {
10774         // We try only with the AttachInfo because there's no point in invalidating
10775         // if we are not attached to our window
10776         final AttachInfo attachInfo = mAttachInfo;
10777         if (attachInfo != null) {
10778             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
10779         }
10780     }
10781 
10782     /**
10783      * <p>Cause an invalidate of the specified area to happen on the next animation
10784      * time step, typically the next display frame.</p>
10785      *
10786      * <p>This method can be invoked from outside of the UI thread
10787      * only when this View is attached to a window.</p>
10788      *
10789      * @param left The left coordinate of the rectangle to invalidate.
10790      * @param top The top coordinate of the rectangle to invalidate.
10791      * @param right The right coordinate of the rectangle to invalidate.
10792      * @param bottom The bottom coordinate of the rectangle to invalidate.
10793      *
10794      * @see #invalidate(int, int, int, int)
10795      * @see #invalidate(Rect)
10796      */
10797     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
10798         // We try only with the AttachInfo because there's no point in invalidating
10799         // if we are not attached to our window
10800         final AttachInfo attachInfo = mAttachInfo;
10801         if (attachInfo != null) {
10802             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
10803             info.target = this;
10804             info.left = left;
10805             info.top = top;
10806             info.right = right;
10807             info.bottom = bottom;
10808 
10809             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
10810         }
10811     }
10812 
10813     /**
10814      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
10815      * This event is sent at most once every
10816      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
10817      */
10818     private void postSendViewScrolledAccessibilityEventCallback() {
10819         if (mSendViewScrolledAccessibilityEvent == null) {
10820             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
10821         }
10822         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
10823             mSendViewScrolledAccessibilityEvent.mIsPending = true;
10824             postDelayed(mSendViewScrolledAccessibilityEvent,
10825                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
10826         }
10827     }
10828 
10829     /**
10830      * Called by a parent to request that a child update its values for mScrollX
10831      * and mScrollY if necessary. This will typically be done if the child is
10832      * animating a scroll using a {@link android.widget.Scroller Scroller}
10833      * object.
10834      */
10835     public void computeScroll() {
10836     }
10837 
10838     /**
10839      * <p>Indicate whether the horizontal edges are faded when the view is
10840      * scrolled horizontally.</p>
10841      *
10842      * @return true if the horizontal edges should are faded on scroll, false
10843      *         otherwise
10844      *
10845      * @see #setHorizontalFadingEdgeEnabled(boolean)
10846      *
10847      * @attr ref android.R.styleable#View_requiresFadingEdge
10848      */
10849     public boolean isHorizontalFadingEdgeEnabled() {
10850         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
10851     }
10852 
10853     /**
10854      * <p>Define whether the horizontal edges should be faded when this view
10855      * is scrolled horizontally.</p>
10856      *
10857      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
10858      *                                    be faded when the view is scrolled
10859      *                                    horizontally
10860      *
10861      * @see #isHorizontalFadingEdgeEnabled()
10862      *
10863      * @attr ref android.R.styleable#View_requiresFadingEdge
10864      */
10865     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
10866         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
10867             if (horizontalFadingEdgeEnabled) {
10868                 initScrollCache();
10869             }
10870 
10871             mViewFlags ^= FADING_EDGE_HORIZONTAL;
10872         }
10873     }
10874 
10875     /**
10876      * <p>Indicate whether the vertical edges are faded when the view is
10877      * scrolled horizontally.</p>
10878      *
10879      * @return true if the vertical edges should are faded on scroll, false
10880      *         otherwise
10881      *
10882      * @see #setVerticalFadingEdgeEnabled(boolean)
10883      *
10884      * @attr ref android.R.styleable#View_requiresFadingEdge
10885      */
10886     public boolean isVerticalFadingEdgeEnabled() {
10887         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
10888     }
10889 
10890     /**
10891      * <p>Define whether the vertical edges should be faded when this view
10892      * is scrolled vertically.</p>
10893      *
10894      * @param verticalFadingEdgeEnabled true if the vertical edges should
10895      *                                  be faded when the view is scrolled
10896      *                                  vertically
10897      *
10898      * @see #isVerticalFadingEdgeEnabled()
10899      *
10900      * @attr ref android.R.styleable#View_requiresFadingEdge
10901      */
10902     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
10903         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
10904             if (verticalFadingEdgeEnabled) {
10905                 initScrollCache();
10906             }
10907 
10908             mViewFlags ^= FADING_EDGE_VERTICAL;
10909         }
10910     }
10911 
10912     /**
10913      * Returns the strength, or intensity, of the top faded edge. The strength is
10914      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10915      * returns 0.0 or 1.0 but no value in between.
10916      *
10917      * Subclasses should override this method to provide a smoother fade transition
10918      * when scrolling occurs.
10919      *
10920      * @return the intensity of the top fade as a float between 0.0f and 1.0f
10921      */
10922     protected float getTopFadingEdgeStrength() {
10923         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
10924     }
10925 
10926     /**
10927      * Returns the strength, or intensity, of the bottom faded edge. The strength is
10928      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10929      * returns 0.0 or 1.0 but no value in between.
10930      *
10931      * Subclasses should override this method to provide a smoother fade transition
10932      * when scrolling occurs.
10933      *
10934      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
10935      */
10936     protected float getBottomFadingEdgeStrength() {
10937         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
10938                 computeVerticalScrollRange() ? 1.0f : 0.0f;
10939     }
10940 
10941     /**
10942      * Returns the strength, or intensity, of the left faded edge. The strength is
10943      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10944      * returns 0.0 or 1.0 but no value in between.
10945      *
10946      * Subclasses should override this method to provide a smoother fade transition
10947      * when scrolling occurs.
10948      *
10949      * @return the intensity of the left fade as a float between 0.0f and 1.0f
10950      */
10951     protected float getLeftFadingEdgeStrength() {
10952         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
10953     }
10954 
10955     /**
10956      * Returns the strength, or intensity, of the right faded edge. The strength is
10957      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10958      * returns 0.0 or 1.0 but no value in between.
10959      *
10960      * Subclasses should override this method to provide a smoother fade transition
10961      * when scrolling occurs.
10962      *
10963      * @return the intensity of the right fade as a float between 0.0f and 1.0f
10964      */
10965     protected float getRightFadingEdgeStrength() {
10966         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
10967                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
10968     }
10969 
10970     /**
10971      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
10972      * scrollbar is not drawn by default.</p>
10973      *
10974      * @return true if the horizontal scrollbar should be painted, false
10975      *         otherwise
10976      *
10977      * @see #setHorizontalScrollBarEnabled(boolean)
10978      */
10979     public boolean isHorizontalScrollBarEnabled() {
10980         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
10981     }
10982 
10983     /**
10984      * <p>Define whether the horizontal scrollbar should be drawn or not. The
10985      * scrollbar is not drawn by default.</p>
10986      *
10987      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
10988      *                                   be painted
10989      *
10990      * @see #isHorizontalScrollBarEnabled()
10991      */
10992     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
10993         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
10994             mViewFlags ^= SCROLLBARS_HORIZONTAL;
10995             computeOpaqueFlags();
10996             resolvePadding();
10997         }
10998     }
10999 
11000     /**
11001      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
11002      * scrollbar is not drawn by default.</p>
11003      *
11004      * @return true if the vertical scrollbar should be painted, false
11005      *         otherwise
11006      *
11007      * @see #setVerticalScrollBarEnabled(boolean)
11008      */
11009     public boolean isVerticalScrollBarEnabled() {
11010         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
11011     }
11012 
11013     /**
11014      * <p>Define whether the vertical scrollbar should be drawn or not. The
11015      * scrollbar is not drawn by default.</p>
11016      *
11017      * @param verticalScrollBarEnabled true if the vertical scrollbar should
11018      *                                 be painted
11019      *
11020      * @see #isVerticalScrollBarEnabled()
11021      */
11022     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
11023         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
11024             mViewFlags ^= SCROLLBARS_VERTICAL;
11025             computeOpaqueFlags();
11026             resolvePadding();
11027         }
11028     }
11029 
11030     /**
11031      * @hide
11032      */
11033     protected void recomputePadding() {
11034         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
11035     }
11036 
11037     /**
11038      * Define whether scrollbars will fade when the view is not scrolling.
11039      *
11040      * @param fadeScrollbars wheter to enable fading
11041      *
11042      * @attr ref android.R.styleable#View_fadeScrollbars
11043      */
11044     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
11045         initScrollCache();
11046         final ScrollabilityCache scrollabilityCache = mScrollCache;
11047         scrollabilityCache.fadeScrollBars = fadeScrollbars;
11048         if (fadeScrollbars) {
11049             scrollabilityCache.state = ScrollabilityCache.OFF;
11050         } else {
11051             scrollabilityCache.state = ScrollabilityCache.ON;
11052         }
11053     }
11054 
11055     /**
11056      *
11057      * Returns true if scrollbars will fade when this view is not scrolling
11058      *
11059      * @return true if scrollbar fading is enabled
11060      *
11061      * @attr ref android.R.styleable#View_fadeScrollbars
11062      */
11063     public boolean isScrollbarFadingEnabled() {
11064         return mScrollCache != null && mScrollCache.fadeScrollBars;
11065     }
11066 
11067     /**
11068      *
11069      * Returns the delay before scrollbars fade.
11070      *
11071      * @return the delay before scrollbars fade
11072      *
11073      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
11074      */
11075     public int getScrollBarDefaultDelayBeforeFade() {
11076         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
11077                 mScrollCache.scrollBarDefaultDelayBeforeFade;
11078     }
11079 
11080     /**
11081      * Define the delay before scrollbars fade.
11082      *
11083      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
11084      *
11085      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
11086      */
11087     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
11088         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
11089     }
11090 
11091     /**
11092      *
11093      * Returns the scrollbar fade duration.
11094      *
11095      * @return the scrollbar fade duration
11096      *
11097      * @attr ref android.R.styleable#View_scrollbarFadeDuration
11098      */
11099     public int getScrollBarFadeDuration() {
11100         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
11101                 mScrollCache.scrollBarFadeDuration;
11102     }
11103 
11104     /**
11105      * Define the scrollbar fade duration.
11106      *
11107      * @param scrollBarFadeDuration - the scrollbar fade duration
11108      *
11109      * @attr ref android.R.styleable#View_scrollbarFadeDuration
11110      */
11111     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
11112         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
11113     }
11114 
11115     /**
11116      *
11117      * Returns the scrollbar size.
11118      *
11119      * @return the scrollbar size
11120      *
11121      * @attr ref android.R.styleable#View_scrollbarSize
11122      */
11123     public int getScrollBarSize() {
11124         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
11125                 mScrollCache.scrollBarSize;
11126     }
11127 
11128     /**
11129      * Define the scrollbar size.
11130      *
11131      * @param scrollBarSize - the scrollbar size
11132      *
11133      * @attr ref android.R.styleable#View_scrollbarSize
11134      */
11135     public void setScrollBarSize(int scrollBarSize) {
11136         getScrollCache().scrollBarSize = scrollBarSize;
11137     }
11138 
11139     /**
11140      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
11141      * inset. When inset, they add to the padding of the view. And the scrollbars
11142      * can be drawn inside the padding area or on the edge of the view. For example,
11143      * if a view has a background drawable and you want to draw the scrollbars
11144      * inside the padding specified by the drawable, you can use
11145      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
11146      * appear at the edge of the view, ignoring the padding, then you can use
11147      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
11148      * @param style the style of the scrollbars. Should be one of
11149      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
11150      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
11151      * @see #SCROLLBARS_INSIDE_OVERLAY
11152      * @see #SCROLLBARS_INSIDE_INSET
11153      * @see #SCROLLBARS_OUTSIDE_OVERLAY
11154      * @see #SCROLLBARS_OUTSIDE_INSET
11155      *
11156      * @attr ref android.R.styleable#View_scrollbarStyle
11157      */
11158     public void setScrollBarStyle(int style) {
11159         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
11160             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
11161             computeOpaqueFlags();
11162             resolvePadding();
11163         }
11164     }
11165 
11166     /**
11167      * <p>Returns the current scrollbar style.</p>
11168      * @return the current scrollbar style
11169      * @see #SCROLLBARS_INSIDE_OVERLAY
11170      * @see #SCROLLBARS_INSIDE_INSET
11171      * @see #SCROLLBARS_OUTSIDE_OVERLAY
11172      * @see #SCROLLBARS_OUTSIDE_INSET
11173      *
11174      * @attr ref android.R.styleable#View_scrollbarStyle
11175      */
11176     @ViewDebug.ExportedProperty(mapping = {
11177             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
11178             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
11179             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
11180             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
11181     })
11182     public int getScrollBarStyle() {
11183         return mViewFlags & SCROLLBARS_STYLE_MASK;
11184     }
11185 
11186     /**
11187      * <p>Compute the horizontal range that the horizontal scrollbar
11188      * represents.</p>
11189      *
11190      * <p>The range is expressed in arbitrary units that must be the same as the
11191      * units used by {@link #computeHorizontalScrollExtent()} and
11192      * {@link #computeHorizontalScrollOffset()}.</p>
11193      *
11194      * <p>The default range is the drawing width of this view.</p>
11195      *
11196      * @return the total horizontal range represented by the horizontal
11197      *         scrollbar
11198      *
11199      * @see #computeHorizontalScrollExtent()
11200      * @see #computeHorizontalScrollOffset()
11201      * @see android.widget.ScrollBarDrawable
11202      */
11203     protected int computeHorizontalScrollRange() {
11204         return getWidth();
11205     }
11206 
11207     /**
11208      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
11209      * within the horizontal range. This value is used to compute the position
11210      * of the thumb within the scrollbar's track.</p>
11211      *
11212      * <p>The range is expressed in arbitrary units that must be the same as the
11213      * units used by {@link #computeHorizontalScrollRange()} and
11214      * {@link #computeHorizontalScrollExtent()}.</p>
11215      *
11216      * <p>The default offset is the scroll offset of this view.</p>
11217      *
11218      * @return the horizontal offset of the scrollbar's thumb
11219      *
11220      * @see #computeHorizontalScrollRange()
11221      * @see #computeHorizontalScrollExtent()
11222      * @see android.widget.ScrollBarDrawable
11223      */
11224     protected int computeHorizontalScrollOffset() {
11225         return mScrollX;
11226     }
11227 
11228     /**
11229      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
11230      * within the horizontal range. This value is used to compute the length
11231      * of the thumb within the scrollbar's track.</p>
11232      *
11233      * <p>The range is expressed in arbitrary units that must be the same as the
11234      * units used by {@link #computeHorizontalScrollRange()} and
11235      * {@link #computeHorizontalScrollOffset()}.</p>
11236      *
11237      * <p>The default extent is the drawing width of this view.</p>
11238      *
11239      * @return the horizontal extent of the scrollbar's thumb
11240      *
11241      * @see #computeHorizontalScrollRange()
11242      * @see #computeHorizontalScrollOffset()
11243      * @see android.widget.ScrollBarDrawable
11244      */
11245     protected int computeHorizontalScrollExtent() {
11246         return getWidth();
11247     }
11248 
11249     /**
11250      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
11251      *
11252      * <p>The range is expressed in arbitrary units that must be the same as the
11253      * units used by {@link #computeVerticalScrollExtent()} and
11254      * {@link #computeVerticalScrollOffset()}.</p>
11255      *
11256      * @return the total vertical range represented by the vertical scrollbar
11257      *
11258      * <p>The default range is the drawing height of this view.</p>
11259      *
11260      * @see #computeVerticalScrollExtent()
11261      * @see #computeVerticalScrollOffset()
11262      * @see android.widget.ScrollBarDrawable
11263      */
11264     protected int computeVerticalScrollRange() {
11265         return getHeight();
11266     }
11267 
11268     /**
11269      * <p>Compute the vertical offset of the vertical scrollbar's thumb
11270      * within the horizontal range. This value is used to compute the position
11271      * of the thumb within the scrollbar's track.</p>
11272      *
11273      * <p>The range is expressed in arbitrary units that must be the same as the
11274      * units used by {@link #computeVerticalScrollRange()} and
11275      * {@link #computeVerticalScrollExtent()}.</p>
11276      *
11277      * <p>The default offset is the scroll offset of this view.</p>
11278      *
11279      * @return the vertical offset of the scrollbar's thumb
11280      *
11281      * @see #computeVerticalScrollRange()
11282      * @see #computeVerticalScrollExtent()
11283      * @see android.widget.ScrollBarDrawable
11284      */
11285     protected int computeVerticalScrollOffset() {
11286         return mScrollY;
11287     }
11288 
11289     /**
11290      * <p>Compute the vertical extent of the horizontal scrollbar's thumb
11291      * within the vertical range. This value is used to compute the length
11292      * of the thumb within the scrollbar's track.</p>
11293      *
11294      * <p>The range is expressed in arbitrary units that must be the same as the
11295      * units used by {@link #computeVerticalScrollRange()} and
11296      * {@link #computeVerticalScrollOffset()}.</p>
11297      *
11298      * <p>The default extent is the drawing height of this view.</p>
11299      *
11300      * @return the vertical extent of the scrollbar's thumb
11301      *
11302      * @see #computeVerticalScrollRange()
11303      * @see #computeVerticalScrollOffset()
11304      * @see android.widget.ScrollBarDrawable
11305      */
11306     protected int computeVerticalScrollExtent() {
11307         return getHeight();
11308     }
11309 
11310     /**
11311      * Check if this view can be scrolled horizontally in a certain direction.
11312      *
11313      * @param direction Negative to check scrolling left, positive to check scrolling right.
11314      * @return true if this view can be scrolled in the specified direction, false otherwise.
11315      */
11316     public boolean canScrollHorizontally(int direction) {
11317         final int offset = computeHorizontalScrollOffset();
11318         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
11319         if (range == 0) return false;
11320         if (direction < 0) {
11321             return offset > 0;
11322         } else {
11323             return offset < range - 1;
11324         }
11325     }
11326 
11327     /**
11328      * Check if this view can be scrolled vertically in a certain direction.
11329      *
11330      * @param direction Negative to check scrolling up, positive to check scrolling down.
11331      * @return true if this view can be scrolled in the specified direction, false otherwise.
11332      */
11333     public boolean canScrollVertically(int direction) {
11334         final int offset = computeVerticalScrollOffset();
11335         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
11336         if (range == 0) return false;
11337         if (direction < 0) {
11338             return offset > 0;
11339         } else {
11340             return offset < range - 1;
11341         }
11342     }
11343 
11344     /**
11345      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
11346      * scrollbars are painted only if they have been awakened first.</p>
11347      *
11348      * @param canvas the canvas on which to draw the scrollbars
11349      *
11350      * @see #awakenScrollBars(int)
11351      */
11352     protected final void onDrawScrollBars(Canvas canvas) {
11353         // scrollbars are drawn only when the animation is running
11354         final ScrollabilityCache cache = mScrollCache;
11355         if (cache != null) {
11356 
11357             int state = cache.state;
11358 
11359             if (state == ScrollabilityCache.OFF) {
11360                 return;
11361             }
11362 
11363             boolean invalidate = false;
11364 
11365             if (state == ScrollabilityCache.FADING) {
11366                 // We're fading -- get our fade interpolation
11367                 if (cache.interpolatorValues == null) {
11368                     cache.interpolatorValues = new float[1];
11369                 }
11370 
11371                 float[] values = cache.interpolatorValues;
11372 
11373                 // Stops the animation if we're done
11374                 if (cache.scrollBarInterpolator.timeToValues(values) ==
11375                         Interpolator.Result.FREEZE_END) {
11376                     cache.state = ScrollabilityCache.OFF;
11377                 } else {
11378                     cache.scrollBar.setAlpha(Math.round(values[0]));
11379                 }
11380 
11381                 // This will make the scroll bars inval themselves after
11382                 // drawing. We only want this when we're fading so that
11383                 // we prevent excessive redraws
11384                 invalidate = true;
11385             } else {
11386                 // We're just on -- but we may have been fading before so
11387                 // reset alpha
11388                 cache.scrollBar.setAlpha(255);
11389             }
11390 
11391 
11392             final int viewFlags = mViewFlags;
11393 
11394             final boolean drawHorizontalScrollBar =
11395                 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
11396             final boolean drawVerticalScrollBar =
11397                 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
11398                 && !isVerticalScrollBarHidden();
11399 
11400             if (drawVerticalScrollBar || drawHorizontalScrollBar) {
11401                 final int width = mRight - mLeft;
11402                 final int height = mBottom - mTop;
11403 
11404                 final ScrollBarDrawable scrollBar = cache.scrollBar;
11405 
11406                 final int scrollX = mScrollX;
11407                 final int scrollY = mScrollY;
11408                 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
11409 
11410                 int left, top, right, bottom;
11411 
11412                 if (drawHorizontalScrollBar) {
11413                     int size = scrollBar.getSize(false);
11414                     if (size <= 0) {
11415                         size = cache.scrollBarSize;
11416                     }
11417 
11418                     scrollBar.setParameters(computeHorizontalScrollRange(),
11419                                             computeHorizontalScrollOffset(),
11420                                             computeHorizontalScrollExtent(), false);
11421                     final int verticalScrollBarGap = drawVerticalScrollBar ?
11422                             getVerticalScrollbarWidth() : 0;
11423                     top = scrollY + height - size - (mUserPaddingBottom & inside);
11424                     left = scrollX + (mPaddingLeft & inside);
11425                     right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
11426                     bottom = top + size;
11427                     onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
11428                     if (invalidate) {
11429                         invalidate(left, top, right, bottom);
11430                     }
11431                 }
11432 
11433                 if (drawVerticalScrollBar) {
11434                     int size = scrollBar.getSize(true);
11435                     if (size <= 0) {
11436                         size = cache.scrollBarSize;
11437                     }
11438 
11439                     scrollBar.setParameters(computeVerticalScrollRange(),
11440                                             computeVerticalScrollOffset(),
11441                                             computeVerticalScrollExtent(), true);
11442                     int verticalScrollbarPosition = mVerticalScrollbarPosition;
11443                     if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
11444                         verticalScrollbarPosition = isLayoutRtl() ?
11445                                 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
11446                     }
11447                     switch (verticalScrollbarPosition) {
11448                         default:
11449                         case SCROLLBAR_POSITION_RIGHT:
11450                             left = scrollX + width - size - (mUserPaddingRight & inside);
11451                             break;
11452                         case SCROLLBAR_POSITION_LEFT:
11453                             left = scrollX + (mUserPaddingLeft & inside);
11454                             break;
11455                     }
11456                     top = scrollY + (mPaddingTop & inside);
11457                     right = left + size;
11458                     bottom = scrollY + height - (mUserPaddingBottom & inside);
11459                     onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
11460                     if (invalidate) {
11461                         invalidate(left, top, right, bottom);
11462                     }
11463                 }
11464             }
11465         }
11466     }
11467 
11468     /**
11469      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
11470      * FastScroller is visible.
11471      * @return whether to temporarily hide the vertical scrollbar
11472      * @hide
11473      */
11474     protected boolean isVerticalScrollBarHidden() {
11475         return false;
11476     }
11477 
11478     /**
11479      * <p>Draw the horizontal scrollbar if
11480      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
11481      *
11482      * @param canvas the canvas on which to draw the scrollbar
11483      * @param scrollBar the scrollbar's drawable
11484      *
11485      * @see #isHorizontalScrollBarEnabled()
11486      * @see #computeHorizontalScrollRange()
11487      * @see #computeHorizontalScrollExtent()
11488      * @see #computeHorizontalScrollOffset()
11489      * @see android.widget.ScrollBarDrawable
11490      * @hide
11491      */
11492     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
11493             int l, int t, int r, int b) {
11494         scrollBar.setBounds(l, t, r, b);
11495         scrollBar.draw(canvas);
11496     }
11497 
11498     /**
11499      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
11500      * returns true.</p>
11501      *
11502      * @param canvas the canvas on which to draw the scrollbar
11503      * @param scrollBar the scrollbar's drawable
11504      *
11505      * @see #isVerticalScrollBarEnabled()
11506      * @see #computeVerticalScrollRange()
11507      * @see #computeVerticalScrollExtent()
11508      * @see #computeVerticalScrollOffset()
11509      * @see android.widget.ScrollBarDrawable
11510      * @hide
11511      */
11512     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
11513             int l, int t, int r, int b) {
11514         scrollBar.setBounds(l, t, r, b);
11515         scrollBar.draw(canvas);
11516     }
11517 
11518     /**
11519      * Implement this to do your drawing.
11520      *
11521      * @param canvas the canvas on which the background will be drawn
11522      */
11523     protected void onDraw(Canvas canvas) {
11524     }
11525 
11526     /*
11527      * Caller is responsible for calling requestLayout if necessary.
11528      * (This allows addViewInLayout to not request a new layout.)
11529      */
11530     void assignParent(ViewParent parent) {
11531         if (mParent == null) {
11532             mParent = parent;
11533         } else if (parent == null) {
11534             mParent = null;
11535         } else {
11536             throw new RuntimeException("view " + this + " being added, but"
11537                     + " it already has a parent");
11538         }
11539     }
11540 
11541     /**
11542      * This is called when the view is attached to a window.  At this point it
11543      * has a Surface and will start drawing.  Note that this function is
11544      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
11545      * however it may be called any time before the first onDraw -- including
11546      * before or after {@link #onMeasure(int, int)}.
11547      *
11548      * @see #onDetachedFromWindow()
11549      */
11550     protected void onAttachedToWindow() {
11551         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
11552             mParent.requestTransparentRegion(this);
11553         }
11554 
11555         if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
11556             initialAwakenScrollBars();
11557             mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
11558         }
11559 
11560         jumpDrawablesToCurrentState();
11561 
11562         clearAccessibilityFocus();
11563         if (isFocused()) {
11564             InputMethodManager imm = InputMethodManager.peekInstance();
11565             imm.focusIn(this);
11566         }
11567 
11568         if (mAttachInfo != null && mDisplayList != null) {
11569             mAttachInfo.mViewRootImpl.dequeueDisplayList(mDisplayList);
11570         }
11571     }
11572 
11573     /**
11574      * Resolve all RTL related properties.
11575      *
11576      * @hide
11577      */
11578     public void resolveRtlPropertiesIfNeeded() {
11579         if (!needRtlPropertiesResolution()) return;
11580 
11581         // Order is important here: LayoutDirection MUST be resolved first
11582         if (!isLayoutDirectionResolved()) {
11583             resolveLayoutDirection();
11584             resolveLayoutParams();
11585         }
11586         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
11587         if (!isTextDirectionResolved()) {
11588             resolveTextDirection();
11589         }
11590         if (!isTextAlignmentResolved()) {
11591             resolveTextAlignment();
11592         }
11593         if (!isPaddingResolved()) {
11594             resolvePadding();
11595         }
11596         if (!isDrawablesResolved()) {
11597             resolveDrawables();
11598         }
11599         onRtlPropertiesChanged(getLayoutDirection());
11600     }
11601 
11602     /**
11603      * Reset resolution of all RTL related properties.
11604      *
11605      * @hide
11606      */
11607     public void resetRtlProperties() {
11608         resetResolvedLayoutDirection();
11609         resetResolvedTextDirection();
11610         resetResolvedTextAlignment();
11611         resetResolvedPadding();
11612         resetResolvedDrawables();
11613     }
11614 
11615     /**
11616      * @see #onScreenStateChanged(int)
11617      */
11618     void dispatchScreenStateChanged(int screenState) {
11619         onScreenStateChanged(screenState);
11620     }
11621 
11622     /**
11623      * This method is called whenever the state of the screen this view is
11624      * attached to changes. A state change will usually occurs when the screen
11625      * turns on or off (whether it happens automatically or the user does it
11626      * manually.)
11627      *
11628      * @param screenState The new state of the screen. Can be either
11629      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
11630      */
11631     public void onScreenStateChanged(int screenState) {
11632     }
11633 
11634     /**
11635      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
11636      */
11637     private boolean hasRtlSupport() {
11638         return mContext.getApplicationInfo().hasRtlSupport();
11639     }
11640 
11641     /**
11642      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
11643      * RTL not supported)
11644      */
11645     private boolean isRtlCompatibilityMode() {
11646         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
11647         return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
11648     }
11649 
11650     /**
11651      * @return true if RTL properties need resolution.
11652      */
11653     private boolean needRtlPropertiesResolution() {
11654         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
11655     }
11656 
11657     /**
11658      * Called when any RTL property (layout direction or text direction or text alignment) has
11659      * been changed.
11660      *
11661      * Subclasses need to override this method to take care of cached information that depends on the
11662      * resolved layout direction, or to inform child views that inherit their layout direction.
11663      *
11664      * The default implementation does nothing.
11665      *
11666      * @param layoutDirection the direction of the layout
11667      *
11668      * @see #LAYOUT_DIRECTION_LTR
11669      * @see #LAYOUT_DIRECTION_RTL
11670      */
11671     public void onRtlPropertiesChanged(int layoutDirection) {
11672     }
11673 
11674     /**
11675      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
11676      * that the parent directionality can and will be resolved before its children.
11677      *
11678      * @return true if resolution has been done, false otherwise.
11679      *
11680      * @hide
11681      */
11682     public boolean resolveLayoutDirection() {
11683         // Clear any previous layout direction resolution
11684         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
11685 
11686         if (hasRtlSupport()) {
11687             // Set resolved depending on layout direction
11688             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
11689                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
11690                 case LAYOUT_DIRECTION_INHERIT:
11691                     // We cannot resolve yet. LTR is by default and let the resolution happen again
11692                     // later to get the correct resolved value
11693                     if (!canResolveLayoutDirection()) return false;
11694 
11695                     View parent = ((View) mParent);
11696                     // Parent has not yet resolved, LTR is still the default
11697                     if (!parent.isLayoutDirectionResolved()) return false;
11698 
11699                     if (parent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
11700                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
11701                     }
11702                     break;
11703                 case LAYOUT_DIRECTION_RTL:
11704                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
11705                     break;
11706                 case LAYOUT_DIRECTION_LOCALE:
11707                     if((LAYOUT_DIRECTION_RTL ==
11708                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
11709                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
11710                     }
11711                     break;
11712                 default:
11713                     // Nothing to do, LTR by default
11714             }
11715         }
11716 
11717         // Set to resolved
11718         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
11719         return true;
11720     }
11721 
11722     /**
11723      * Check if layout direction resolution can be done.
11724      *
11725      * @return true if layout direction resolution can be done otherwise return false.
11726      *
11727      * @hide
11728      */
11729     public boolean canResolveLayoutDirection() {
11730         switch (getRawLayoutDirection()) {
11731             case LAYOUT_DIRECTION_INHERIT:
11732                 return (mParent != null) && (mParent instanceof ViewGroup) &&
11733                        ((ViewGroup) mParent).canResolveLayoutDirection();
11734             default:
11735                 return true;
11736         }
11737     }
11738 
11739     /**
11740      * Reset the resolved layout direction. Layout direction will be resolved during a call to
11741      * {@link #onMeasure(int, int)}.
11742      *
11743      * @hide
11744      */
11745     public void resetResolvedLayoutDirection() {
11746         // Reset the current resolved bits
11747         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
11748     }
11749 
11750     /**
11751      * @return true if the layout direction is inherited.
11752      *
11753      * @hide
11754      */
11755     public boolean isLayoutDirectionInherited() {
11756         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
11757     }
11758 
11759     /**
11760      * @return true if layout direction has been resolved.
11761      */
11762     private boolean isLayoutDirectionResolved() {
11763         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
11764     }
11765 
11766     /**
11767      * Return if padding has been resolved
11768      *
11769      * @hide
11770      */
11771     boolean isPaddingResolved() {
11772         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
11773     }
11774 
11775     /**
11776      * Resolve padding depending on layout direction.
11777      *
11778      * @hide
11779      */
11780     public void resolvePadding() {
11781         if (!isRtlCompatibilityMode()) {
11782             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
11783             // If start / end padding are defined, they will be resolved (hence overriding) to
11784             // left / right or right / left depending on the resolved layout direction.
11785             // If start / end padding are not defined, use the left / right ones.
11786             int resolvedLayoutDirection = getLayoutDirection();
11787             // Set user padding to initial values ...
11788             mUserPaddingLeft = mUserPaddingLeftInitial;
11789             mUserPaddingRight = mUserPaddingRightInitial;
11790             // ... then resolve it.
11791             switch (resolvedLayoutDirection) {
11792                 case LAYOUT_DIRECTION_RTL:
11793                     if (mUserPaddingStart != UNDEFINED_PADDING) {
11794                         mUserPaddingRight = mUserPaddingStart;
11795                     }
11796                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
11797                         mUserPaddingLeft = mUserPaddingEnd;
11798                     }
11799                     break;
11800                 case LAYOUT_DIRECTION_LTR:
11801                 default:
11802                     if (mUserPaddingStart != UNDEFINED_PADDING) {
11803                         mUserPaddingLeft = mUserPaddingStart;
11804                     }
11805                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
11806                         mUserPaddingRight = mUserPaddingEnd;
11807                     }
11808             }
11809 
11810             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11811 
11812             internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11813                     mUserPaddingBottom);
11814             onRtlPropertiesChanged(resolvedLayoutDirection);
11815         }
11816 
11817         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
11818     }
11819 
11820     /**
11821      * Reset the resolved layout direction.
11822      *
11823      * @hide
11824      */
11825     public void resetResolvedPadding() {
11826         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
11827     }
11828 
11829     /**
11830      * This is called when the view is detached from a window.  At this point it
11831      * no longer has a surface for drawing.
11832      *
11833      * @see #onAttachedToWindow()
11834      */
11835     protected void onDetachedFromWindow() {
11836         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
11837 
11838         removeUnsetPressCallback();
11839         removeLongPressCallback();
11840         removePerformClickCallback();
11841         removeSendViewScrolledAccessibilityEventCallback();
11842 
11843         destroyDrawingCache();
11844 
11845         destroyLayer(false);
11846 
11847         if (mAttachInfo != null) {
11848             if (mDisplayList != null) {
11849                 mAttachInfo.mViewRootImpl.enqueueDisplayList(mDisplayList);
11850             }
11851             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
11852         } else {
11853             // Should never happen
11854             clearDisplayList();
11855         }
11856 
11857         mCurrentAnimation = null;
11858 
11859         resetAccessibilityStateChanged();
11860     }
11861 
11862     /**
11863      * @return The number of times this view has been attached to a window
11864      */
11865     protected int getWindowAttachCount() {
11866         return mWindowAttachCount;
11867     }
11868 
11869     /**
11870      * Retrieve a unique token identifying the window this view is attached to.
11871      * @return Return the window's token for use in
11872      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
11873      */
11874     public IBinder getWindowToken() {
11875         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
11876     }
11877 
11878     /**
11879      * Retrieve a unique token identifying the top-level "real" window of
11880      * the window that this view is attached to.  That is, this is like
11881      * {@link #getWindowToken}, except if the window this view in is a panel
11882      * window (attached to another containing window), then the token of
11883      * the containing window is returned instead.
11884      *
11885      * @return Returns the associated window token, either
11886      * {@link #getWindowToken()} or the containing window's token.
11887      */
11888     public IBinder getApplicationWindowToken() {
11889         AttachInfo ai = mAttachInfo;
11890         if (ai != null) {
11891             IBinder appWindowToken = ai.mPanelParentWindowToken;
11892             if (appWindowToken == null) {
11893                 appWindowToken = ai.mWindowToken;
11894             }
11895             return appWindowToken;
11896         }
11897         return null;
11898     }
11899 
11900     /**
11901      * Gets the logical display to which the view's window has been attached.
11902      *
11903      * @return The logical display, or null if the view is not currently attached to a window.
11904      */
11905     public Display getDisplay() {
11906         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
11907     }
11908 
11909     /**
11910      * Retrieve private session object this view hierarchy is using to
11911      * communicate with the window manager.
11912      * @return the session object to communicate with the window manager
11913      */
11914     /*package*/ IWindowSession getWindowSession() {
11915         return mAttachInfo != null ? mAttachInfo.mSession : null;
11916     }
11917 
11918     /**
11919      * @param info the {@link android.view.View.AttachInfo} to associated with
11920      *        this view
11921      */
11922     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
11923         //System.out.println("Attached! " + this);
11924         mAttachInfo = info;
11925         mWindowAttachCount++;
11926         // We will need to evaluate the drawable state at least once.
11927         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
11928         if (mFloatingTreeObserver != null) {
11929             info.mTreeObserver.merge(mFloatingTreeObserver);
11930             mFloatingTreeObserver = null;
11931         }
11932         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
11933             mAttachInfo.mScrollContainers.add(this);
11934             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
11935         }
11936         performCollectViewAttributes(mAttachInfo, visibility);
11937         onAttachedToWindow();
11938 
11939         ListenerInfo li = mListenerInfo;
11940         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
11941                 li != null ? li.mOnAttachStateChangeListeners : null;
11942         if (listeners != null && listeners.size() > 0) {
11943             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
11944             // perform the dispatching. The iterator is a safe guard against listeners that
11945             // could mutate the list by calling the various add/remove methods. This prevents
11946             // the array from being modified while we iterate it.
11947             for (OnAttachStateChangeListener listener : listeners) {
11948                 listener.onViewAttachedToWindow(this);
11949             }
11950         }
11951 
11952         int vis = info.mWindowVisibility;
11953         if (vis != GONE) {
11954             onWindowVisibilityChanged(vis);
11955         }
11956         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
11957             // If nobody has evaluated the drawable state yet, then do it now.
11958             refreshDrawableState();
11959         }
11960         needGlobalAttributesUpdate(false);
11961     }
11962 
11963     void dispatchDetachedFromWindow() {
11964         AttachInfo info = mAttachInfo;
11965         if (info != null) {
11966             int vis = info.mWindowVisibility;
11967             if (vis != GONE) {
11968                 onWindowVisibilityChanged(GONE);
11969             }
11970         }
11971 
11972         onDetachedFromWindow();
11973 
11974         ListenerInfo li = mListenerInfo;
11975         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
11976                 li != null ? li.mOnAttachStateChangeListeners : null;
11977         if (listeners != null && listeners.size() > 0) {
11978             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
11979             // perform the dispatching. The iterator is a safe guard against listeners that
11980             // could mutate the list by calling the various add/remove methods. This prevents
11981             // the array from being modified while we iterate it.
11982             for (OnAttachStateChangeListener listener : listeners) {
11983                 listener.onViewDetachedFromWindow(this);
11984             }
11985         }
11986 
11987         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
11988             mAttachInfo.mScrollContainers.remove(this);
11989             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
11990         }
11991 
11992         mAttachInfo = null;
11993     }
11994 
11995     /**
11996      * Store this view hierarchy's frozen state into the given container.
11997      *
11998      * @param container The SparseArray in which to save the view's state.
11999      *
12000      * @see #restoreHierarchyState(android.util.SparseArray)
12001      * @see #dispatchSaveInstanceState(android.util.SparseArray)
12002      * @see #onSaveInstanceState()
12003      */
12004     public void saveHierarchyState(SparseArray<Parcelable> container) {
12005         dispatchSaveInstanceState(container);
12006     }
12007 
12008     /**
12009      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
12010      * this view and its children. May be overridden to modify how freezing happens to a
12011      * view's children; for example, some views may want to not store state for their children.
12012      *
12013      * @param container The SparseArray in which to save the view's state.
12014      *
12015      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
12016      * @see #saveHierarchyState(android.util.SparseArray)
12017      * @see #onSaveInstanceState()
12018      */
12019     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
12020         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
12021             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
12022             Parcelable state = onSaveInstanceState();
12023             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
12024                 throw new IllegalStateException(
12025                         "Derived class did not call super.onSaveInstanceState()");
12026             }
12027             if (state != null) {
12028                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
12029                 // + ": " + state);
12030                 container.put(mID, state);
12031             }
12032         }
12033     }
12034 
12035     /**
12036      * Hook allowing a view to generate a representation of its internal state
12037      * that can later be used to create a new instance with that same state.
12038      * This state should only contain information that is not persistent or can
12039      * not be reconstructed later. For example, you will never store your
12040      * current position on screen because that will be computed again when a
12041      * new instance of the view is placed in its view hierarchy.
12042      * <p>
12043      * Some examples of things you may store here: the current cursor position
12044      * in a text view (but usually not the text itself since that is stored in a
12045      * content provider or other persistent storage), the currently selected
12046      * item in a list view.
12047      *
12048      * @return Returns a Parcelable object containing the view's current dynamic
12049      *         state, or null if there is nothing interesting to save. The
12050      *         default implementation returns null.
12051      * @see #onRestoreInstanceState(android.os.Parcelable)
12052      * @see #saveHierarchyState(android.util.SparseArray)
12053      * @see #dispatchSaveInstanceState(android.util.SparseArray)
12054      * @see #setSaveEnabled(boolean)
12055      */
12056     protected Parcelable onSaveInstanceState() {
12057         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
12058         return BaseSavedState.EMPTY_STATE;
12059     }
12060 
12061     /**
12062      * Restore this view hierarchy's frozen state from the given container.
12063      *
12064      * @param container The SparseArray which holds previously frozen states.
12065      *
12066      * @see #saveHierarchyState(android.util.SparseArray)
12067      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
12068      * @see #onRestoreInstanceState(android.os.Parcelable)
12069      */
12070     public void restoreHierarchyState(SparseArray<Parcelable> container) {
12071         dispatchRestoreInstanceState(container);
12072     }
12073 
12074     /**
12075      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
12076      * state for this view and its children. May be overridden to modify how restoring
12077      * happens to a view's children; for example, some views may want to not store state
12078      * for their children.
12079      *
12080      * @param container The SparseArray which holds previously saved state.
12081      *
12082      * @see #dispatchSaveInstanceState(android.util.SparseArray)
12083      * @see #restoreHierarchyState(android.util.SparseArray)
12084      * @see #onRestoreInstanceState(android.os.Parcelable)
12085      */
12086     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
12087         if (mID != NO_ID) {
12088             Parcelable state = container.get(mID);
12089             if (state != null) {
12090                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
12091                 // + ": " + state);
12092                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
12093                 onRestoreInstanceState(state);
12094                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
12095                     throw new IllegalStateException(
12096                             "Derived class did not call super.onRestoreInstanceState()");
12097                 }
12098             }
12099         }
12100     }
12101 
12102     /**
12103      * Hook allowing a view to re-apply a representation of its internal state that had previously
12104      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
12105      * null state.
12106      *
12107      * @param state The frozen state that had previously been returned by
12108      *        {@link #onSaveInstanceState}.
12109      *
12110      * @see #onSaveInstanceState()
12111      * @see #restoreHierarchyState(android.util.SparseArray)
12112      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
12113      */
12114     protected void onRestoreInstanceState(Parcelable state) {
12115         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
12116         if (state != BaseSavedState.EMPTY_STATE && state != null) {
12117             throw new IllegalArgumentException("Wrong state class, expecting View State but "
12118                     + "received " + state.getClass().toString() + " instead. This usually happens "
12119                     + "when two views of different type have the same id in the same hierarchy. "
12120                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
12121                     + "other views do not use the same id.");
12122         }
12123     }
12124 
12125     /**
12126      * <p>Return the time at which the drawing of the view hierarchy started.</p>
12127      *
12128      * @return the drawing start time in milliseconds
12129      */
12130     public long getDrawingTime() {
12131         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
12132     }
12133 
12134     /**
12135      * <p>Enables or disables the duplication of the parent's state into this view. When
12136      * duplication is enabled, this view gets its drawable state from its parent rather
12137      * than from its own internal properties.</p>
12138      *
12139      * <p>Note: in the current implementation, setting this property to true after the
12140      * view was added to a ViewGroup might have no effect at all. This property should
12141      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
12142      *
12143      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
12144      * property is enabled, an exception will be thrown.</p>
12145      *
12146      * <p>Note: if the child view uses and updates additionnal states which are unknown to the
12147      * parent, these states should not be affected by this method.</p>
12148      *
12149      * @param enabled True to enable duplication of the parent's drawable state, false
12150      *                to disable it.
12151      *
12152      * @see #getDrawableState()
12153      * @see #isDuplicateParentStateEnabled()
12154      */
12155     public void setDuplicateParentStateEnabled(boolean enabled) {
12156         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
12157     }
12158 
12159     /**
12160      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
12161      *
12162      * @return True if this view's drawable state is duplicated from the parent,
12163      *         false otherwise
12164      *
12165      * @see #getDrawableState()
12166      * @see #setDuplicateParentStateEnabled(boolean)
12167      */
12168     public boolean isDuplicateParentStateEnabled() {
12169         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
12170     }
12171 
12172     /**
12173      * <p>Specifies the type of layer backing this view. The layer can be
12174      * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
12175      * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
12176      *
12177      * <p>A layer is associated with an optional {@link android.graphics.Paint}
12178      * instance that controls how the layer is composed on screen. The following
12179      * properties of the paint are taken into account when composing the layer:</p>
12180      * <ul>
12181      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
12182      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
12183      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
12184      * </ul>
12185      *
12186      * <p>If this view has an alpha value set to < 1.0 by calling
12187      * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
12188      * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
12189      * equivalent to setting a hardware layer on this view and providing a paint with
12190      * the desired alpha value.</p>
12191      *
12192      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
12193      * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
12194      * for more information on when and how to use layers.</p>
12195      *
12196      * @param layerType The type of layer to use with this view, must be one of
12197      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
12198      *        {@link #LAYER_TYPE_HARDWARE}
12199      * @param paint The paint used to compose the layer. This argument is optional
12200      *        and can be null. It is ignored when the layer type is
12201      *        {@link #LAYER_TYPE_NONE}
12202      *
12203      * @see #getLayerType()
12204      * @see #LAYER_TYPE_NONE
12205      * @see #LAYER_TYPE_SOFTWARE
12206      * @see #LAYER_TYPE_HARDWARE
12207      * @see #setAlpha(float)
12208      *
12209      * @attr ref android.R.styleable#View_layerType
12210      */
12211     public void setLayerType(int layerType, Paint paint) {
12212         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
12213             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
12214                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
12215         }
12216 
12217         if (layerType == mLayerType) {
12218             if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
12219                 mLayerPaint = paint == null ? new Paint() : paint;
12220                 invalidateParentCaches();
12221                 invalidate(true);
12222             }
12223             return;
12224         }
12225 
12226         // Destroy any previous software drawing cache if needed
12227         switch (mLayerType) {
12228             case LAYER_TYPE_HARDWARE:
12229                 destroyLayer(false);
12230                 // fall through - non-accelerated views may use software layer mechanism instead
12231             case LAYER_TYPE_SOFTWARE:
12232                 destroyDrawingCache();
12233                 break;
12234             default:
12235                 break;
12236         }
12237 
12238         mLayerType = layerType;
12239         final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
12240         mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
12241         mLocalDirtyRect = layerDisabled ? null : new Rect();
12242 
12243         invalidateParentCaches();
12244         invalidate(true);
12245     }
12246 
12247     /**
12248      * Updates the {@link Paint} object used with the current layer (used only if the current
12249      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
12250      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
12251      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
12252      * ensure that the view gets redrawn immediately.
12253      *
12254      * <p>A layer is associated with an optional {@link android.graphics.Paint}
12255      * instance that controls how the layer is composed on screen. The following
12256      * properties of the paint are taken into account when composing the layer:</p>
12257      * <ul>
12258      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
12259      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
12260      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
12261      * </ul>
12262      *
12263      * <p>If this view has an alpha value set to < 1.0 by calling
12264      * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
12265      * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
12266      * equivalent to setting a hardware layer on this view and providing a paint with
12267      * the desired alpha value.</p>
12268      *
12269      * @param paint The paint used to compose the layer. This argument is optional
12270      *        and can be null. It is ignored when the layer type is
12271      *        {@link #LAYER_TYPE_NONE}
12272      *
12273      * @see #setLayerType(int, android.graphics.Paint)
12274      */
12275     public void setLayerPaint(Paint paint) {
12276         int layerType = getLayerType();
12277         if (layerType != LAYER_TYPE_NONE) {
12278             mLayerPaint = paint == null ? new Paint() : paint;
12279             if (layerType == LAYER_TYPE_HARDWARE) {
12280                 HardwareLayer layer = getHardwareLayer();
12281                 if (layer != null) {
12282                     layer.setLayerPaint(paint);
12283                 }
12284                 invalidateViewProperty(false, false);
12285             } else {
12286                 invalidate();
12287             }
12288         }
12289     }
12290 
12291     /**
12292      * Indicates whether this view has a static layer. A view with layer type
12293      * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
12294      * dynamic.
12295      */
12296     boolean hasStaticLayer() {
12297         return true;
12298     }
12299 
12300     /**
12301      * Indicates what type of layer is currently associated with this view. By default
12302      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
12303      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
12304      * for more information on the different types of layers.
12305      *
12306      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
12307      *         {@link #LAYER_TYPE_HARDWARE}
12308      *
12309      * @see #setLayerType(int, android.graphics.Paint)
12310      * @see #buildLayer()
12311      * @see #LAYER_TYPE_NONE
12312      * @see #LAYER_TYPE_SOFTWARE
12313      * @see #LAYER_TYPE_HARDWARE
12314      */
12315     public int getLayerType() {
12316         return mLayerType;
12317     }
12318 
12319     /**
12320      * Forces this view's layer to be created and this view to be rendered
12321      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
12322      * invoking this method will have no effect.
12323      *
12324      * This method can for instance be used to render a view into its layer before
12325      * starting an animation. If this view is complex, rendering into the layer
12326      * before starting the animation will avoid skipping frames.
12327      *
12328      * @throws IllegalStateException If this view is not attached to a window
12329      *
12330      * @see #setLayerType(int, android.graphics.Paint)
12331      */
12332     public void buildLayer() {
12333         if (mLayerType == LAYER_TYPE_NONE) return;
12334 
12335         if (mAttachInfo == null) {
12336             throw new IllegalStateException("This view must be attached to a window first");
12337         }
12338 
12339         switch (mLayerType) {
12340             case LAYER_TYPE_HARDWARE:
12341                 if (mAttachInfo.mHardwareRenderer != null &&
12342                         mAttachInfo.mHardwareRenderer.isEnabled() &&
12343                         mAttachInfo.mHardwareRenderer.validate()) {
12344                     getHardwareLayer();
12345                 }
12346                 break;
12347             case LAYER_TYPE_SOFTWARE:
12348                 buildDrawingCache(true);
12349                 break;
12350         }
12351     }
12352 
12353     /**
12354      * <p>Returns a hardware layer that can be used to draw this view again
12355      * without executing its draw method.</p>
12356      *
12357      * @return A HardwareLayer ready to render, or null if an error occurred.
12358      */
12359     HardwareLayer getHardwareLayer() {
12360         if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
12361                 !mAttachInfo.mHardwareRenderer.isEnabled()) {
12362             return null;
12363         }
12364 
12365         if (!mAttachInfo.mHardwareRenderer.validate()) return null;
12366 
12367         final int width = mRight - mLeft;
12368         final int height = mBottom - mTop;
12369 
12370         if (width == 0 || height == 0) {
12371             return null;
12372         }
12373 
12374         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
12375             if (mHardwareLayer == null) {
12376                 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
12377                         width, height, isOpaque());
12378                 mLocalDirtyRect.set(0, 0, width, height);
12379             } else {
12380                 if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
12381                     if (mHardwareLayer.resize(width, height)) {
12382                         mLocalDirtyRect.set(0, 0, width, height);
12383                     }
12384                 }
12385 
12386                 // This should not be necessary but applications that change
12387                 // the parameters of their background drawable without calling
12388                 // this.setBackground(Drawable) can leave the view in a bad state
12389                 // (for instance isOpaque() returns true, but the background is
12390                 // not opaque.)
12391                 computeOpaqueFlags();
12392 
12393                 final boolean opaque = isOpaque();
12394                 if (mHardwareLayer.isValid() && mHardwareLayer.isOpaque() != opaque) {
12395                     mHardwareLayer.setOpaque(opaque);
12396                     mLocalDirtyRect.set(0, 0, width, height);
12397                 }
12398             }
12399 
12400             // The layer is not valid if the underlying GPU resources cannot be allocated
12401             if (!mHardwareLayer.isValid()) {
12402                 return null;
12403             }
12404 
12405             mHardwareLayer.setLayerPaint(mLayerPaint);
12406             mHardwareLayer.redrawLater(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
12407             ViewRootImpl viewRoot = getViewRootImpl();
12408             if (viewRoot != null) viewRoot.pushHardwareLayerUpdate(mHardwareLayer);
12409 
12410             mLocalDirtyRect.setEmpty();
12411         }
12412 
12413         return mHardwareLayer;
12414     }
12415 
12416     /**
12417      * Destroys this View's hardware layer if possible.
12418      *
12419      * @return True if the layer was destroyed, false otherwise.
12420      *
12421      * @see #setLayerType(int, android.graphics.Paint)
12422      * @see #LAYER_TYPE_HARDWARE
12423      */
12424     boolean destroyLayer(boolean valid) {
12425         if (mHardwareLayer != null) {
12426             AttachInfo info = mAttachInfo;
12427             if (info != null && info.mHardwareRenderer != null &&
12428                     info.mHardwareRenderer.isEnabled() &&
12429                     (valid || info.mHardwareRenderer.validate())) {
12430                 mHardwareLayer.destroy();
12431                 mHardwareLayer = null;
12432 
12433                 if (mDisplayList != null) {
12434                     mDisplayList.reset();
12435                 }
12436                 invalidate(true);
12437                 invalidateParentCaches();
12438             }
12439             return true;
12440         }
12441         return false;
12442     }
12443 
12444     /**
12445      * Destroys all hardware rendering resources. This method is invoked
12446      * when the system needs to reclaim resources. Upon execution of this
12447      * method, you should free any OpenGL resources created by the view.
12448      *
12449      * Note: you <strong>must</strong> call
12450      * <code>super.destroyHardwareResources()</code> when overriding
12451      * this method.
12452      *
12453      * @hide
12454      */
12455     protected void destroyHardwareResources() {
12456         destroyLayer(true);
12457     }
12458 
12459     /**
12460      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
12461      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
12462      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
12463      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
12464      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
12465      * null.</p>
12466      *
12467      * <p>Enabling the drawing cache is similar to
12468      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
12469      * acceleration is turned off. When hardware acceleration is turned on, enabling the
12470      * drawing cache has no effect on rendering because the system uses a different mechanism
12471      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
12472      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
12473      * for information on how to enable software and hardware layers.</p>
12474      *
12475      * <p>This API can be used to manually generate
12476      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
12477      * {@link #getDrawingCache()}.</p>
12478      *
12479      * @param enabled true to enable the drawing cache, false otherwise
12480      *
12481      * @see #isDrawingCacheEnabled()
12482      * @see #getDrawingCache()
12483      * @see #buildDrawingCache()
12484      * @see #setLayerType(int, android.graphics.Paint)
12485      */
12486     public void setDrawingCacheEnabled(boolean enabled) {
12487         mCachingFailed = false;
12488         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
12489     }
12490 
12491     /**
12492      * <p>Indicates whether the drawing cache is enabled for this view.</p>
12493      *
12494      * @return true if the drawing cache is enabled
12495      *
12496      * @see #setDrawingCacheEnabled(boolean)
12497      * @see #getDrawingCache()
12498      */
12499     @ViewDebug.ExportedProperty(category = "drawing")
12500     public boolean isDrawingCacheEnabled() {
12501         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
12502     }
12503 
12504     /**
12505      * Debugging utility which recursively outputs the dirty state of a view and its
12506      * descendants.
12507      *
12508      * @hide
12509      */
12510     @SuppressWarnings({"UnusedDeclaration"})
12511     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
12512         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
12513                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
12514                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
12515                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
12516         if (clear) {
12517             mPrivateFlags &= clearMask;
12518         }
12519         if (this instanceof ViewGroup) {
12520             ViewGroup parent = (ViewGroup) this;
12521             final int count = parent.getChildCount();
12522             for (int i = 0; i < count; i++) {
12523                 final View child = parent.getChildAt(i);
12524                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
12525             }
12526         }
12527     }
12528 
12529     /**
12530      * This method is used by ViewGroup to cause its children to restore or recreate their
12531      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
12532      * to recreate its own display list, which would happen if it went through the normal
12533      * draw/dispatchDraw mechanisms.
12534      *
12535      * @hide
12536      */
12537     protected void dispatchGetDisplayList() {}
12538 
12539     /**
12540      * A view that is not attached or hardware accelerated cannot create a display list.
12541      * This method checks these conditions and returns the appropriate result.
12542      *
12543      * @return true if view has the ability to create a display list, false otherwise.
12544      *
12545      * @hide
12546      */
12547     public boolean canHaveDisplayList() {
12548         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
12549     }
12550 
12551     /**
12552      * @return The HardwareRenderer associated with that view or null if hardware rendering
12553      * is not supported or this this has not been attached to a window.
12554      *
12555      * @hide
12556      */
12557     public HardwareRenderer getHardwareRenderer() {
12558         if (mAttachInfo != null) {
12559             return mAttachInfo.mHardwareRenderer;
12560         }
12561         return null;
12562     }
12563 
12564     /**
12565      * Returns a DisplayList. If the incoming displayList is null, one will be created.
12566      * Otherwise, the same display list will be returned (after having been rendered into
12567      * along the way, depending on the invalidation state of the view).
12568      *
12569      * @param displayList The previous version of this displayList, could be null.
12570      * @param isLayer Whether the requester of the display list is a layer. If so,
12571      * the view will avoid creating a layer inside the resulting display list.
12572      * @return A new or reused DisplayList object.
12573      */
12574     private DisplayList getDisplayList(DisplayList displayList, boolean isLayer) {
12575         if (!canHaveDisplayList()) {
12576             return null;
12577         }
12578 
12579         if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 ||
12580                 displayList == null || !displayList.isValid() ||
12581                 (!isLayer && mRecreateDisplayList))) {
12582             // Don't need to recreate the display list, just need to tell our
12583             // children to restore/recreate theirs
12584             if (displayList != null && displayList.isValid() &&
12585                     !isLayer && !mRecreateDisplayList) {
12586                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12587                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12588                 dispatchGetDisplayList();
12589 
12590                 return displayList;
12591             }
12592 
12593             if (!isLayer) {
12594                 // If we got here, we're recreating it. Mark it as such to ensure that
12595                 // we copy in child display lists into ours in drawChild()
12596                 mRecreateDisplayList = true;
12597             }
12598             if (displayList == null) {
12599                 final String name = getClass().getSimpleName();
12600                 displayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
12601                 // If we're creating a new display list, make sure our parent gets invalidated
12602                 // since they will need to recreate their display list to account for this
12603                 // new child display list.
12604                 invalidateParentCaches();
12605             }
12606 
12607             boolean caching = false;
12608             final HardwareCanvas canvas = displayList.start();
12609             int width = mRight - mLeft;
12610             int height = mBottom - mTop;
12611 
12612             try {
12613                 canvas.setViewport(width, height);
12614                 // The dirty rect should always be null for a display list
12615                 canvas.onPreDraw(null);
12616                 int layerType = getLayerType();
12617                 if (!isLayer && layerType != LAYER_TYPE_NONE) {
12618                     if (layerType == LAYER_TYPE_HARDWARE) {
12619                         final HardwareLayer layer = getHardwareLayer();
12620                         if (layer != null && layer.isValid()) {
12621                             canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
12622                         } else {
12623                             canvas.saveLayer(0, 0, mRight - mLeft, mBottom - mTop, mLayerPaint,
12624                                     Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
12625                                             Canvas.CLIP_TO_LAYER_SAVE_FLAG);
12626                         }
12627                         caching = true;
12628                     } else {
12629                         buildDrawingCache(true);
12630                         Bitmap cache = getDrawingCache(true);
12631                         if (cache != null) {
12632                             canvas.drawBitmap(cache, 0, 0, mLayerPaint);
12633                             caching = true;
12634                         }
12635                     }
12636                 } else {
12637 
12638                     computeScroll();
12639 
12640                     canvas.translate(-mScrollX, -mScrollY);
12641                     if (!isLayer) {
12642                         mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12643                         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12644                     }
12645 
12646                     // Fast path for layouts with no backgrounds
12647                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
12648                         dispatchDraw(canvas);
12649                     } else {
12650                         draw(canvas);
12651                     }
12652                 }
12653             } finally {
12654                 canvas.onPostDraw();
12655 
12656                 displayList.end();
12657                 displayList.setCaching(caching);
12658                 if (isLayer) {
12659                     displayList.setLeftTopRightBottom(0, 0, width, height);
12660                 } else {
12661                     setDisplayListProperties(displayList);
12662                 }
12663             }
12664         } else if (!isLayer) {
12665             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12666             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12667         }
12668 
12669         return displayList;
12670     }
12671 
12672     /**
12673      * Get the DisplayList for the HardwareLayer
12674      *
12675      * @param layer The HardwareLayer whose DisplayList we want
12676      * @return A DisplayList fopr the specified HardwareLayer
12677      */
12678     private DisplayList getHardwareLayerDisplayList(HardwareLayer layer) {
12679         DisplayList displayList = getDisplayList(layer.getDisplayList(), true);
12680         layer.setDisplayList(displayList);
12681         return displayList;
12682     }
12683 
12684 
12685     /**
12686      * <p>Returns a display list that can be used to draw this view again
12687      * without executing its draw method.</p>
12688      *
12689      * @return A DisplayList ready to replay, or null if caching is not enabled.
12690      *
12691      * @hide
12692      */
12693     public DisplayList getDisplayList() {
12694         mDisplayList = getDisplayList(mDisplayList, false);
12695         return mDisplayList;
12696     }
12697 
12698     private void clearDisplayList() {
12699         if (mDisplayList != null) {
12700             mDisplayList.invalidate();
12701             mDisplayList.clear();
12702         }
12703     }
12704 
12705     /**
12706      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
12707      *
12708      * @return A non-scaled bitmap representing this view or null if cache is disabled.
12709      *
12710      * @see #getDrawingCache(boolean)
12711      */
12712     public Bitmap getDrawingCache() {
12713         return getDrawingCache(false);
12714     }
12715 
12716     /**
12717      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
12718      * is null when caching is disabled. If caching is enabled and the cache is not ready,
12719      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
12720      * draw from the cache when the cache is enabled. To benefit from the cache, you must
12721      * request the drawing cache by calling this method and draw it on screen if the
12722      * returned bitmap is not null.</p>
12723      *
12724      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12725      * this method will create a bitmap of the same size as this view. Because this bitmap
12726      * will be drawn scaled by the parent ViewGroup, the result on screen might show
12727      * scaling artifacts. To avoid such artifacts, you should call this method by setting
12728      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12729      * size than the view. This implies that your application must be able to handle this
12730      * size.</p>
12731      *
12732      * @param autoScale Indicates whether the generated bitmap should be scaled based on
12733      *        the current density of the screen when the application is in compatibility
12734      *        mode.
12735      *
12736      * @return A bitmap representing this view or null if cache is disabled.
12737      *
12738      * @see #setDrawingCacheEnabled(boolean)
12739      * @see #isDrawingCacheEnabled()
12740      * @see #buildDrawingCache(boolean)
12741      * @see #destroyDrawingCache()
12742      */
12743     public Bitmap getDrawingCache(boolean autoScale) {
12744         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
12745             return null;
12746         }
12747         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
12748             buildDrawingCache(autoScale);
12749         }
12750         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
12751     }
12752 
12753     /**
12754      * <p>Frees the resources used by the drawing cache. If you call
12755      * {@link #buildDrawingCache()} manually without calling
12756      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12757      * should cleanup the cache with this method afterwards.</p>
12758      *
12759      * @see #setDrawingCacheEnabled(boolean)
12760      * @see #buildDrawingCache()
12761      * @see #getDrawingCache()
12762      */
12763     public void destroyDrawingCache() {
12764         if (mDrawingCache != null) {
12765             mDrawingCache.recycle();
12766             mDrawingCache = null;
12767         }
12768         if (mUnscaledDrawingCache != null) {
12769             mUnscaledDrawingCache.recycle();
12770             mUnscaledDrawingCache = null;
12771         }
12772     }
12773 
12774     /**
12775      * Setting a solid background color for the drawing cache's bitmaps will improve
12776      * performance and memory usage. Note, though that this should only be used if this
12777      * view will always be drawn on top of a solid color.
12778      *
12779      * @param color The background color to use for the drawing cache's bitmap
12780      *
12781      * @see #setDrawingCacheEnabled(boolean)
12782      * @see #buildDrawingCache()
12783      * @see #getDrawingCache()
12784      */
12785     public void setDrawingCacheBackgroundColor(int color) {
12786         if (color != mDrawingCacheBackgroundColor) {
12787             mDrawingCacheBackgroundColor = color;
12788             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12789         }
12790     }
12791 
12792     /**
12793      * @see #setDrawingCacheBackgroundColor(int)
12794      *
12795      * @return The background color to used for the drawing cache's bitmap
12796      */
12797     public int getDrawingCacheBackgroundColor() {
12798         return mDrawingCacheBackgroundColor;
12799     }
12800 
12801     /**
12802      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
12803      *
12804      * @see #buildDrawingCache(boolean)
12805      */
12806     public void buildDrawingCache() {
12807         buildDrawingCache(false);
12808     }
12809 
12810     /**
12811      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
12812      *
12813      * <p>If you call {@link #buildDrawingCache()} manually without calling
12814      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12815      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
12816      *
12817      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12818      * this method will create a bitmap of the same size as this view. Because this bitmap
12819      * will be drawn scaled by the parent ViewGroup, the result on screen might show
12820      * scaling artifacts. To avoid such artifacts, you should call this method by setting
12821      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12822      * size than the view. This implies that your application must be able to handle this
12823      * size.</p>
12824      *
12825      * <p>You should avoid calling this method when hardware acceleration is enabled. If
12826      * you do not need the drawing cache bitmap, calling this method will increase memory
12827      * usage and cause the view to be rendered in software once, thus negatively impacting
12828      * performance.</p>
12829      *
12830      * @see #getDrawingCache()
12831      * @see #destroyDrawingCache()
12832      */
12833     public void buildDrawingCache(boolean autoScale) {
12834         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
12835                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
12836             mCachingFailed = false;
12837 
12838             int width = mRight - mLeft;
12839             int height = mBottom - mTop;
12840 
12841             final AttachInfo attachInfo = mAttachInfo;
12842             final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
12843 
12844             if (autoScale && scalingRequired) {
12845                 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
12846                 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
12847             }
12848 
12849             final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
12850             final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
12851             final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
12852 
12853             final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
12854             final long drawingCacheSize =
12855                     ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
12856             if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
12857                 if (width > 0 && height > 0) {
12858                     Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
12859                             + projectedBitmapSize + " bytes, only "
12860                             + drawingCacheSize + " available");
12861                 }
12862                 destroyDrawingCache();
12863                 mCachingFailed = true;
12864                 return;
12865             }
12866 
12867             boolean clear = true;
12868             Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
12869 
12870             if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
12871                 Bitmap.Config quality;
12872                 if (!opaque) {
12873                     // Never pick ARGB_4444 because it looks awful
12874                     // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
12875                     switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
12876                         case DRAWING_CACHE_QUALITY_AUTO:
12877                             quality = Bitmap.Config.ARGB_8888;
12878                             break;
12879                         case DRAWING_CACHE_QUALITY_LOW:
12880                             quality = Bitmap.Config.ARGB_8888;
12881                             break;
12882                         case DRAWING_CACHE_QUALITY_HIGH:
12883                             quality = Bitmap.Config.ARGB_8888;
12884                             break;
12885                         default:
12886                             quality = Bitmap.Config.ARGB_8888;
12887                             break;
12888                     }
12889                 } else {
12890                     // Optimization for translucent windows
12891                     // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
12892                     quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
12893                 }
12894 
12895                 // Try to cleanup memory
12896                 if (bitmap != null) bitmap.recycle();
12897 
12898                 try {
12899                     bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
12900                             width, height, quality);
12901                     bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
12902                     if (autoScale) {
12903                         mDrawingCache = bitmap;
12904                     } else {
12905                         mUnscaledDrawingCache = bitmap;
12906                     }
12907                     if (opaque && use32BitCache) bitmap.setHasAlpha(false);
12908                 } catch (OutOfMemoryError e) {
12909                     // If there is not enough memory to create the bitmap cache, just
12910                     // ignore the issue as bitmap caches are not required to draw the
12911                     // view hierarchy
12912                     if (autoScale) {
12913                         mDrawingCache = null;
12914                     } else {
12915                         mUnscaledDrawingCache = null;
12916                     }
12917                     mCachingFailed = true;
12918                     return;
12919                 }
12920 
12921                 clear = drawingCacheBackgroundColor != 0;
12922             }
12923 
12924             Canvas canvas;
12925             if (attachInfo != null) {
12926                 canvas = attachInfo.mCanvas;
12927                 if (canvas == null) {
12928                     canvas = new Canvas();
12929                 }
12930                 canvas.setBitmap(bitmap);
12931                 // Temporarily clobber the cached Canvas in case one of our children
12932                 // is also using a drawing cache. Without this, the children would
12933                 // steal the canvas by attaching their own bitmap to it and bad, bad
12934                 // thing would happen (invisible views, corrupted drawings, etc.)
12935                 attachInfo.mCanvas = null;
12936             } else {
12937                 // This case should hopefully never or seldom happen
12938                 canvas = new Canvas(bitmap);
12939             }
12940 
12941             if (clear) {
12942                 bitmap.eraseColor(drawingCacheBackgroundColor);
12943             }
12944 
12945             computeScroll();
12946             final int restoreCount = canvas.save();
12947 
12948             if (autoScale && scalingRequired) {
12949                 final float scale = attachInfo.mApplicationScale;
12950                 canvas.scale(scale, scale);
12951             }
12952 
12953             canvas.translate(-mScrollX, -mScrollY);
12954 
12955             mPrivateFlags |= PFLAG_DRAWN;
12956             if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
12957                     mLayerType != LAYER_TYPE_NONE) {
12958                 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
12959             }
12960 
12961             // Fast path for layouts with no backgrounds
12962             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
12963                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12964                 dispatchDraw(canvas);
12965             } else {
12966                 draw(canvas);
12967             }
12968 
12969             canvas.restoreToCount(restoreCount);
12970             canvas.setBitmap(null);
12971 
12972             if (attachInfo != null) {
12973                 // Restore the cached Canvas for our siblings
12974                 attachInfo.mCanvas = canvas;
12975             }
12976         }
12977     }
12978 
12979     /**
12980      * Create a snapshot of the view into a bitmap.  We should probably make
12981      * some form of this public, but should think about the API.
12982      */
12983     Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
12984         int width = mRight - mLeft;
12985         int height = mBottom - mTop;
12986 
12987         final AttachInfo attachInfo = mAttachInfo;
12988         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
12989         width = (int) ((width * scale) + 0.5f);
12990         height = (int) ((height * scale) + 0.5f);
12991 
12992         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
12993                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
12994         if (bitmap == null) {
12995             throw new OutOfMemoryError();
12996         }
12997 
12998         Resources resources = getResources();
12999         if (resources != null) {
13000             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
13001         }
13002 
13003         Canvas canvas;
13004         if (attachInfo != null) {
13005             canvas = attachInfo.mCanvas;
13006             if (canvas == null) {
13007                 canvas = new Canvas();
13008             }
13009             canvas.setBitmap(bitmap);
13010             // Temporarily clobber the cached Canvas in case one of our children
13011             // is also using a drawing cache. Without this, the children would
13012             // steal the canvas by attaching their own bitmap to it and bad, bad
13013             // things would happen (invisible views, corrupted drawings, etc.)
13014             attachInfo.mCanvas = null;
13015         } else {
13016             // This case should hopefully never or seldom happen
13017             canvas = new Canvas(bitmap);
13018         }
13019 
13020         if ((backgroundColor & 0xff000000) != 0) {
13021             bitmap.eraseColor(backgroundColor);
13022         }
13023 
13024         computeScroll();
13025         final int restoreCount = canvas.save();
13026         canvas.scale(scale, scale);
13027         canvas.translate(-mScrollX, -mScrollY);
13028 
13029         // Temporarily remove the dirty mask
13030         int flags = mPrivateFlags;
13031         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13032 
13033         // Fast path for layouts with no backgrounds
13034         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13035             dispatchDraw(canvas);
13036         } else {
13037             draw(canvas);
13038         }
13039 
13040         mPrivateFlags = flags;
13041 
13042         canvas.restoreToCount(restoreCount);
13043         canvas.setBitmap(null);
13044 
13045         if (attachInfo != null) {
13046             // Restore the cached Canvas for our siblings
13047             attachInfo.mCanvas = canvas;
13048         }
13049 
13050         return bitmap;
13051     }
13052 
13053     /**
13054      * Indicates whether this View is currently in edit mode. A View is usually
13055      * in edit mode when displayed within a developer tool. For instance, if
13056      * this View is being drawn by a visual user interface builder, this method
13057      * should return true.
13058      *
13059      * Subclasses should check the return value of this method to provide
13060      * different behaviors if their normal behavior might interfere with the
13061      * host environment. For instance: the class spawns a thread in its
13062      * constructor, the drawing code relies on device-specific features, etc.
13063      *
13064      * This method is usually checked in the drawing code of custom widgets.
13065      *
13066      * @return True if this View is in edit mode, false otherwise.
13067      */
13068     public boolean isInEditMode() {
13069         return false;
13070     }
13071 
13072     /**
13073      * If the View draws content inside its padding and enables fading edges,
13074      * it needs to support padding offsets. Padding offsets are added to the
13075      * fading edges to extend the length of the fade so that it covers pixels
13076      * drawn inside the padding.
13077      *
13078      * Subclasses of this class should override this method if they need
13079      * to draw content inside the padding.
13080      *
13081      * @return True if padding offset must be applied, false otherwise.
13082      *
13083      * @see #getLeftPaddingOffset()
13084      * @see #getRightPaddingOffset()
13085      * @see #getTopPaddingOffset()
13086      * @see #getBottomPaddingOffset()
13087      *
13088      * @since CURRENT
13089      */
13090     protected boolean isPaddingOffsetRequired() {
13091         return false;
13092     }
13093 
13094     /**
13095      * Amount by which to extend the left fading region. Called only when
13096      * {@link #isPaddingOffsetRequired()} returns true.
13097      *
13098      * @return The left padding offset in pixels.
13099      *
13100      * @see #isPaddingOffsetRequired()
13101      *
13102      * @since CURRENT
13103      */
13104     protected int getLeftPaddingOffset() {
13105         return 0;
13106     }
13107 
13108     /**
13109      * Amount by which to extend the right fading region. Called only when
13110      * {@link #isPaddingOffsetRequired()} returns true.
13111      *
13112      * @return The right padding offset in pixels.
13113      *
13114      * @see #isPaddingOffsetRequired()
13115      *
13116      * @since CURRENT
13117      */
13118     protected int getRightPaddingOffset() {
13119         return 0;
13120     }
13121 
13122     /**
13123      * Amount by which to extend the top fading region. Called only when
13124      * {@link #isPaddingOffsetRequired()} returns true.
13125      *
13126      * @return The top padding offset in pixels.
13127      *
13128      * @see #isPaddingOffsetRequired()
13129      *
13130      * @since CURRENT
13131      */
13132     protected int getTopPaddingOffset() {
13133         return 0;
13134     }
13135 
13136     /**
13137      * Amount by which to extend the bottom fading region. Called only when
13138      * {@link #isPaddingOffsetRequired()} returns true.
13139      *
13140      * @return The bottom padding offset in pixels.
13141      *
13142      * @see #isPaddingOffsetRequired()
13143      *
13144      * @since CURRENT
13145      */
13146     protected int getBottomPaddingOffset() {
13147         return 0;
13148     }
13149 
13150     /**
13151      * @hide
13152      * @param offsetRequired
13153      */
13154     protected int getFadeTop(boolean offsetRequired) {
13155         int top = mPaddingTop;
13156         if (offsetRequired) top += getTopPaddingOffset();
13157         return top;
13158     }
13159 
13160     /**
13161      * @hide
13162      * @param offsetRequired
13163      */
13164     protected int getFadeHeight(boolean offsetRequired) {
13165         int padding = mPaddingTop;
13166         if (offsetRequired) padding += getTopPaddingOffset();
13167         return mBottom - mTop - mPaddingBottom - padding;
13168     }
13169 
13170     /**
13171      * <p>Indicates whether this view is attached to a hardware accelerated
13172      * window or not.</p>
13173      *
13174      * <p>Even if this method returns true, it does not mean that every call
13175      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
13176      * accelerated {@link android.graphics.Canvas}. For instance, if this view
13177      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
13178      * window is hardware accelerated,
13179      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
13180      * return false, and this method will return true.</p>
13181      *
13182      * @return True if the view is attached to a window and the window is
13183      *         hardware accelerated; false in any other case.
13184      */
13185     public boolean isHardwareAccelerated() {
13186         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
13187     }
13188 
13189     /**
13190      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
13191      * case of an active Animation being run on the view.
13192      */
13193     private boolean drawAnimation(ViewGroup parent, long drawingTime,
13194             Animation a, boolean scalingRequired) {
13195         Transformation invalidationTransform;
13196         final int flags = parent.mGroupFlags;
13197         final boolean initialized = a.isInitialized();
13198         if (!initialized) {
13199             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
13200             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
13201             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
13202             onAnimationStart();
13203         }
13204 
13205         boolean more = a.getTransformation(drawingTime, parent.mChildTransformation, 1f);
13206         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
13207             if (parent.mInvalidationTransformation == null) {
13208                 parent.mInvalidationTransformation = new Transformation();
13209             }
13210             invalidationTransform = parent.mInvalidationTransformation;
13211             a.getTransformation(drawingTime, invalidationTransform, 1f);
13212         } else {
13213             invalidationTransform = parent.mChildTransformation;
13214         }
13215 
13216         if (more) {
13217             if (!a.willChangeBounds()) {
13218                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
13219                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
13220                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
13221                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
13222                     // The child need to draw an animation, potentially offscreen, so
13223                     // make sure we do not cancel invalidate requests
13224                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
13225                     parent.invalidate(mLeft, mTop, mRight, mBottom);
13226                 }
13227             } else {
13228                 if (parent.mInvalidateRegion == null) {
13229                     parent.mInvalidateRegion = new RectF();
13230                 }
13231                 final RectF region = parent.mInvalidateRegion;
13232                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
13233                         invalidationTransform);
13234 
13235                 // The child need to draw an animation, potentially offscreen, so
13236                 // make sure we do not cancel invalidate requests
13237                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
13238 
13239                 final int left = mLeft + (int) region.left;
13240                 final int top = mTop + (int) region.top;
13241                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
13242                         top + (int) (region.height() + .5f));
13243             }
13244         }
13245         return more;
13246     }
13247 
13248     /**
13249      * This method is called by getDisplayList() when a display list is created or re-rendered.
13250      * It sets or resets the current value of all properties on that display list (resetting is
13251      * necessary when a display list is being re-created, because we need to make sure that
13252      * previously-set transform values
13253      */
13254     void setDisplayListProperties(DisplayList displayList) {
13255         if (displayList != null) {
13256             displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
13257             displayList.setHasOverlappingRendering(hasOverlappingRendering());
13258             if (mParent instanceof ViewGroup) {
13259                 displayList.setClipChildren(
13260                         (((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
13261             }
13262             float alpha = 1;
13263             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
13264                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
13265                 ViewGroup parentVG = (ViewGroup) mParent;
13266                 final boolean hasTransform =
13267                         parentVG.getChildStaticTransformation(this, parentVG.mChildTransformation);
13268                 if (hasTransform) {
13269                     Transformation transform = parentVG.mChildTransformation;
13270                     final int transformType = parentVG.mChildTransformation.getTransformationType();
13271                     if (transformType != Transformation.TYPE_IDENTITY) {
13272                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
13273                             alpha = transform.getAlpha();
13274                         }
13275                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
13276                             displayList.setStaticMatrix(transform.getMatrix());
13277                         }
13278                     }
13279                 }
13280             }
13281             if (mTransformationInfo != null) {
13282                 alpha *= mTransformationInfo.mAlpha;
13283                 if (alpha < 1) {
13284                     final int multipliedAlpha = (int) (255 * alpha);
13285                     if (onSetAlpha(multipliedAlpha)) {
13286                         alpha = 1;
13287                     }
13288                 }
13289                 displayList.setTransformationInfo(alpha,
13290                         mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY,
13291                         mTransformationInfo.mRotation, mTransformationInfo.mRotationX,
13292                         mTransformationInfo.mRotationY, mTransformationInfo.mScaleX,
13293                         mTransformationInfo.mScaleY);
13294                 if (mTransformationInfo.mCamera == null) {
13295                     mTransformationInfo.mCamera = new Camera();
13296                     mTransformationInfo.matrix3D = new Matrix();
13297                 }
13298                 displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ());
13299                 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) {
13300                     displayList.setPivotX(getPivotX());
13301                     displayList.setPivotY(getPivotY());
13302                 }
13303             } else if (alpha < 1) {
13304                 displayList.setAlpha(alpha);
13305             }
13306         }
13307     }
13308 
13309     /**
13310      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
13311      * This draw() method is an implementation detail and is not intended to be overridden or
13312      * to be called from anywhere else other than ViewGroup.drawChild().
13313      */
13314     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
13315         boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
13316         boolean more = false;
13317         final boolean childHasIdentityMatrix = hasIdentityMatrix();
13318         final int flags = parent.mGroupFlags;
13319 
13320         if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
13321             parent.mChildTransformation.clear();
13322             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13323         }
13324 
13325         Transformation transformToApply = null;
13326         boolean concatMatrix = false;
13327 
13328         boolean scalingRequired = false;
13329         boolean caching;
13330         int layerType = getLayerType();
13331 
13332         final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
13333         if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
13334                 (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
13335             caching = true;
13336             // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
13337             if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
13338         } else {
13339             caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
13340         }
13341 
13342         final Animation a = getAnimation();
13343         if (a != null) {
13344             more = drawAnimation(parent, drawingTime, a, scalingRequired);
13345             concatMatrix = a.willChangeTransformationMatrix();
13346             if (concatMatrix) {
13347                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
13348             }
13349             transformToApply = parent.mChildTransformation;
13350         } else {
13351             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) == PFLAG3_VIEW_IS_ANIMATING_TRANSFORM &&
13352                     mDisplayList != null) {
13353                 // No longer animating: clear out old animation matrix
13354                 mDisplayList.setAnimationMatrix(null);
13355                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
13356             }
13357             if (!useDisplayListProperties &&
13358                     (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
13359                 final boolean hasTransform =
13360                         parent.getChildStaticTransformation(this, parent.mChildTransformation);
13361                 if (hasTransform) {
13362                     final int transformType = parent.mChildTransformation.getTransformationType();
13363                     transformToApply = transformType != Transformation.TYPE_IDENTITY ?
13364                             parent.mChildTransformation : null;
13365                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
13366                 }
13367             }
13368         }
13369 
13370         concatMatrix |= !childHasIdentityMatrix;
13371 
13372         // Sets the flag as early as possible to allow draw() implementations
13373         // to call invalidate() successfully when doing animations
13374         mPrivateFlags |= PFLAG_DRAWN;
13375 
13376         if (!concatMatrix &&
13377                 (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
13378                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
13379                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
13380                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
13381             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
13382             return more;
13383         }
13384         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
13385 
13386         if (hardwareAccelerated) {
13387             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
13388             // retain the flag's value temporarily in the mRecreateDisplayList flag
13389             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
13390             mPrivateFlags &= ~PFLAG_INVALIDATED;
13391         }
13392 
13393         DisplayList displayList = null;
13394         Bitmap cache = null;
13395         boolean hasDisplayList = false;
13396         if (caching) {
13397             if (!hardwareAccelerated) {
13398                 if (layerType != LAYER_TYPE_NONE) {
13399                     layerType = LAYER_TYPE_SOFTWARE;
13400                     buildDrawingCache(true);
13401                 }
13402                 cache = getDrawingCache(true);
13403             } else {
13404                 switch (layerType) {
13405                     case LAYER_TYPE_SOFTWARE:
13406                         if (useDisplayListProperties) {
13407                             hasDisplayList = canHaveDisplayList();
13408                         } else {
13409                             buildDrawingCache(true);
13410                             cache = getDrawingCache(true);
13411                         }
13412                         break;
13413                     case LAYER_TYPE_HARDWARE:
13414                         if (useDisplayListProperties) {
13415                             hasDisplayList = canHaveDisplayList();
13416                         }
13417                         break;
13418                     case LAYER_TYPE_NONE:
13419                         // Delay getting the display list until animation-driven alpha values are
13420                         // set up and possibly passed on to the view
13421                         hasDisplayList = canHaveDisplayList();
13422                         break;
13423                 }
13424             }
13425         }
13426         useDisplayListProperties &= hasDisplayList;
13427         if (useDisplayListProperties) {
13428             displayList = getDisplayList();
13429             if (!displayList.isValid()) {
13430                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
13431                 // to getDisplayList(), the display list will be marked invalid and we should not
13432                 // try to use it again.
13433                 displayList = null;
13434                 hasDisplayList = false;
13435                 useDisplayListProperties = false;
13436             }
13437         }
13438 
13439         int sx = 0;
13440         int sy = 0;
13441         if (!hasDisplayList) {
13442             computeScroll();
13443             sx = mScrollX;
13444             sy = mScrollY;
13445         }
13446 
13447         final boolean hasNoCache = cache == null || hasDisplayList;
13448         final boolean offsetForScroll = cache == null && !hasDisplayList &&
13449                 layerType != LAYER_TYPE_HARDWARE;
13450 
13451         int restoreTo = -1;
13452         if (!useDisplayListProperties || transformToApply != null) {
13453             restoreTo = canvas.save();
13454         }
13455         if (offsetForScroll) {
13456             canvas.translate(mLeft - sx, mTop - sy);
13457         } else {
13458             if (!useDisplayListProperties) {
13459                 canvas.translate(mLeft, mTop);
13460             }
13461             if (scalingRequired) {
13462                 if (useDisplayListProperties) {
13463                     // TODO: Might not need this if we put everything inside the DL
13464                     restoreTo = canvas.save();
13465                 }
13466                 // mAttachInfo cannot be null, otherwise scalingRequired == false
13467                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
13468                 canvas.scale(scale, scale);
13469             }
13470         }
13471 
13472         float alpha = useDisplayListProperties ? 1 : getAlpha();
13473         if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
13474                 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
13475             if (transformToApply != null || !childHasIdentityMatrix) {
13476                 int transX = 0;
13477                 int transY = 0;
13478 
13479                 if (offsetForScroll) {
13480                     transX = -sx;
13481                     transY = -sy;
13482                 }
13483 
13484                 if (transformToApply != null) {
13485                     if (concatMatrix) {
13486                         if (useDisplayListProperties) {
13487                             displayList.setAnimationMatrix(transformToApply.getMatrix());
13488                         } else {
13489                             // Undo the scroll translation, apply the transformation matrix,
13490                             // then redo the scroll translate to get the correct result.
13491                             canvas.translate(-transX, -transY);
13492                             canvas.concat(transformToApply.getMatrix());
13493                             canvas.translate(transX, transY);
13494                         }
13495                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13496                     }
13497 
13498                     float transformAlpha = transformToApply.getAlpha();
13499                     if (transformAlpha < 1) {
13500                         alpha *= transformAlpha;
13501                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13502                     }
13503                 }
13504 
13505                 if (!childHasIdentityMatrix && !useDisplayListProperties) {
13506                     canvas.translate(-transX, -transY);
13507                     canvas.concat(getMatrix());
13508                     canvas.translate(transX, transY);
13509                 }
13510             }
13511 
13512             // Deal with alpha if it is or used to be <1
13513             if (alpha < 1 ||
13514                     (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
13515                 if (alpha < 1) {
13516                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
13517                 } else {
13518                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
13519                 }
13520                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13521                 if (hasNoCache) {
13522                     final int multipliedAlpha = (int) (255 * alpha);
13523                     if (!onSetAlpha(multipliedAlpha)) {
13524                         int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
13525                         if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
13526                                 layerType != LAYER_TYPE_NONE) {
13527                             layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
13528                         }
13529                         if (useDisplayListProperties) {
13530                             displayList.setAlpha(alpha * getAlpha());
13531                         } else  if (layerType == LAYER_TYPE_NONE) {
13532                             final int scrollX = hasDisplayList ? 0 : sx;
13533                             final int scrollY = hasDisplayList ? 0 : sy;
13534                             canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
13535                                     scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
13536                         }
13537                     } else {
13538                         // Alpha is handled by the child directly, clobber the layer's alpha
13539                         mPrivateFlags |= PFLAG_ALPHA_SET;
13540                     }
13541                 }
13542             }
13543         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
13544             onSetAlpha(255);
13545             mPrivateFlags &= ~PFLAG_ALPHA_SET;
13546         }
13547 
13548         if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
13549                 !useDisplayListProperties) {
13550             if (offsetForScroll) {
13551                 canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
13552             } else {
13553                 if (!scalingRequired || cache == null) {
13554                     canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
13555                 } else {
13556                     canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
13557                 }
13558             }
13559         }
13560 
13561         if (!useDisplayListProperties && hasDisplayList) {
13562             displayList = getDisplayList();
13563             if (!displayList.isValid()) {
13564                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
13565                 // to getDisplayList(), the display list will be marked invalid and we should not
13566                 // try to use it again.
13567                 displayList = null;
13568                 hasDisplayList = false;
13569             }
13570         }
13571 
13572         if (hasNoCache) {
13573             boolean layerRendered = false;
13574             if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) {
13575                 final HardwareLayer layer = getHardwareLayer();
13576                 if (layer != null && layer.isValid()) {
13577                     mLayerPaint.setAlpha((int) (alpha * 255));
13578                     ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
13579                     layerRendered = true;
13580                 } else {
13581                     final int scrollX = hasDisplayList ? 0 : sx;
13582                     final int scrollY = hasDisplayList ? 0 : sy;
13583                     canvas.saveLayer(scrollX, scrollY,
13584                             scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
13585                             Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
13586                 }
13587             }
13588 
13589             if (!layerRendered) {
13590                 if (!hasDisplayList) {
13591                     // Fast path for layouts with no backgrounds
13592                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13593                         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13594                         dispatchDraw(canvas);
13595                     } else {
13596                         draw(canvas);
13597                     }
13598                 } else {
13599                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13600                     ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
13601                 }
13602             }
13603         } else if (cache != null) {
13604             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13605             Paint cachePaint;
13606 
13607             if (layerType == LAYER_TYPE_NONE) {
13608                 cachePaint = parent.mCachePaint;
13609                 if (cachePaint == null) {
13610                     cachePaint = new Paint();
13611                     cachePaint.setDither(false);
13612                     parent.mCachePaint = cachePaint;
13613                 }
13614                 if (alpha < 1) {
13615                     cachePaint.setAlpha((int) (alpha * 255));
13616                     parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
13617                 } else if  ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) {
13618                     cachePaint.setAlpha(255);
13619                     parent.mGroupFlags &= ~ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
13620                 }
13621             } else {
13622                 cachePaint = mLayerPaint;
13623                 cachePaint.setAlpha((int) (alpha * 255));
13624             }
13625             canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
13626         }
13627 
13628         if (restoreTo >= 0) {
13629             canvas.restoreToCount(restoreTo);
13630         }
13631 
13632         if (a != null && !more) {
13633             if (!hardwareAccelerated && !a.getFillAfter()) {
13634                 onSetAlpha(255);
13635             }
13636             parent.finishAnimatingView(this, a);
13637         }
13638 
13639         if (more && hardwareAccelerated) {
13640             // invalidation is the trigger to recreate display lists, so if we're using
13641             // display lists to render, force an invalidate to allow the animation to
13642             // continue drawing another frame
13643             parent.invalidate(true);
13644             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
13645                 // alpha animations should cause the child to recreate its display list
13646                 invalidate(true);
13647             }
13648         }
13649 
13650         mRecreateDisplayList = false;
13651 
13652         return more;
13653     }
13654 
13655     /**
13656      * Manually render this view (and all of its children) to the given Canvas.
13657      * The view must have already done a full layout before this function is
13658      * called.  When implementing a view, implement
13659      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
13660      * If you do need to override this method, call the superclass version.
13661      *
13662      * @param canvas The Canvas to which the View is rendered.
13663      */
13664     public void draw(Canvas canvas) {
13665         final int privateFlags = mPrivateFlags;
13666         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
13667                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
13668         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
13669 
13670         /*
13671          * Draw traversal performs several drawing steps which must be executed
13672          * in the appropriate order:
13673          *
13674          *      1. Draw the background
13675          *      2. If necessary, save the canvas' layers to prepare for fading
13676          *      3. Draw view's content
13677          *      4. Draw children
13678          *      5. If necessary, draw the fading edges and restore layers
13679          *      6. Draw decorations (scrollbars for instance)
13680          */
13681 
13682         // Step 1, draw the background, if needed
13683         int saveCount;
13684 
13685         if (!dirtyOpaque) {
13686             final Drawable background = mBackground;
13687             if (background != null) {
13688                 final int scrollX = mScrollX;
13689                 final int scrollY = mScrollY;
13690 
13691                 if (mBackgroundSizeChanged) {
13692                     background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
13693                     mBackgroundSizeChanged = false;
13694                 }
13695 
13696                 if ((scrollX | scrollY) == 0) {
13697                     background.draw(canvas);
13698                 } else {
13699                     canvas.translate(scrollX, scrollY);
13700                     background.draw(canvas);
13701                     canvas.translate(-scrollX, -scrollY);
13702                 }
13703             }
13704         }
13705 
13706         // skip step 2 & 5 if possible (common case)
13707         final int viewFlags = mViewFlags;
13708         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
13709         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
13710         if (!verticalEdges && !horizontalEdges) {
13711             // Step 3, draw the content
13712             if (!dirtyOpaque) onDraw(canvas);
13713 
13714             // Step 4, draw the children
13715             dispatchDraw(canvas);
13716 
13717             // Step 6, draw decorations (scrollbars)
13718             onDrawScrollBars(canvas);
13719 
13720             // we're done...
13721             return;
13722         }
13723 
13724         /*
13725          * Here we do the full fledged routine...
13726          * (this is an uncommon case where speed matters less,
13727          * this is why we repeat some of the tests that have been
13728          * done above)
13729          */
13730 
13731         boolean drawTop = false;
13732         boolean drawBottom = false;
13733         boolean drawLeft = false;
13734         boolean drawRight = false;
13735 
13736         float topFadeStrength = 0.0f;
13737         float bottomFadeStrength = 0.0f;
13738         float leftFadeStrength = 0.0f;
13739         float rightFadeStrength = 0.0f;
13740 
13741         // Step 2, save the canvas' layers
13742         int paddingLeft = mPaddingLeft;
13743 
13744         final boolean offsetRequired = isPaddingOffsetRequired();
13745         if (offsetRequired) {
13746             paddingLeft += getLeftPaddingOffset();
13747         }
13748 
13749         int left = mScrollX + paddingLeft;
13750         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
13751         int top = mScrollY + getFadeTop(offsetRequired);
13752         int bottom = top + getFadeHeight(offsetRequired);
13753 
13754         if (offsetRequired) {
13755             right += getRightPaddingOffset();
13756             bottom += getBottomPaddingOffset();
13757         }
13758 
13759         final ScrollabilityCache scrollabilityCache = mScrollCache;
13760         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
13761         int length = (int) fadeHeight;
13762 
13763         // clip the fade length if top and bottom fades overlap
13764         // overlapping fades produce odd-looking artifacts
13765         if (verticalEdges && (top + length > bottom - length)) {
13766             length = (bottom - top) / 2;
13767         }
13768 
13769         // also clip horizontal fades if necessary
13770         if (horizontalEdges && (left + length > right - length)) {
13771             length = (right - left) / 2;
13772         }
13773 
13774         if (verticalEdges) {
13775             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
13776             drawTop = topFadeStrength * fadeHeight > 1.0f;
13777             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
13778             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
13779         }
13780 
13781         if (horizontalEdges) {
13782             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
13783             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
13784             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
13785             drawRight = rightFadeStrength * fadeHeight > 1.0f;
13786         }
13787 
13788         saveCount = canvas.getSaveCount();
13789 
13790         int solidColor = getSolidColor();
13791         if (solidColor == 0) {
13792             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
13793 
13794             if (drawTop) {
13795                 canvas.saveLayer(left, top, right, top + length, null, flags);
13796             }
13797 
13798             if (drawBottom) {
13799                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
13800             }
13801 
13802             if (drawLeft) {
13803                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
13804             }
13805 
13806             if (drawRight) {
13807                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
13808             }
13809         } else {
13810             scrollabilityCache.setFadeColor(solidColor);
13811         }
13812 
13813         // Step 3, draw the content
13814         if (!dirtyOpaque) onDraw(canvas);
13815 
13816         // Step 4, draw the children
13817         dispatchDraw(canvas);
13818 
13819         // Step 5, draw the fade effect and restore layers
13820         final Paint p = scrollabilityCache.paint;
13821         final Matrix matrix = scrollabilityCache.matrix;
13822         final Shader fade = scrollabilityCache.shader;
13823 
13824         if (drawTop) {
13825             matrix.setScale(1, fadeHeight * topFadeStrength);
13826             matrix.postTranslate(left, top);
13827             fade.setLocalMatrix(matrix);
13828             canvas.drawRect(left, top, right, top + length, p);
13829         }
13830 
13831         if (drawBottom) {
13832             matrix.setScale(1, fadeHeight * bottomFadeStrength);
13833             matrix.postRotate(180);
13834             matrix.postTranslate(left, bottom);
13835             fade.setLocalMatrix(matrix);
13836             canvas.drawRect(left, bottom - length, right, bottom, p);
13837         }
13838 
13839         if (drawLeft) {
13840             matrix.setScale(1, fadeHeight * leftFadeStrength);
13841             matrix.postRotate(-90);
13842             matrix.postTranslate(left, top);
13843             fade.setLocalMatrix(matrix);
13844             canvas.drawRect(left, top, left + length, bottom, p);
13845         }
13846 
13847         if (drawRight) {
13848             matrix.setScale(1, fadeHeight * rightFadeStrength);
13849             matrix.postRotate(90);
13850             matrix.postTranslate(right, top);
13851             fade.setLocalMatrix(matrix);
13852             canvas.drawRect(right - length, top, right, bottom, p);
13853         }
13854 
13855         canvas.restoreToCount(saveCount);
13856 
13857         // Step 6, draw decorations (scrollbars)
13858         onDrawScrollBars(canvas);
13859     }
13860 
13861     /**
13862      * Override this if your view is known to always be drawn on top of a solid color background,
13863      * and needs to draw fading edges. Returning a non-zero color enables the view system to
13864      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
13865      * should be set to 0xFF.
13866      *
13867      * @see #setVerticalFadingEdgeEnabled(boolean)
13868      * @see #setHorizontalFadingEdgeEnabled(boolean)
13869      *
13870      * @return The known solid color background for this view, or 0 if the color may vary
13871      */
13872     @ViewDebug.ExportedProperty(category = "drawing")
13873     public int getSolidColor() {
13874         return 0;
13875     }
13876 
13877     /**
13878      * Build a human readable string representation of the specified view flags.
13879      *
13880      * @param flags the view flags to convert to a string
13881      * @return a String representing the supplied flags
13882      */
13883     private static String printFlags(int flags) {
13884         String output = "";
13885         int numFlags = 0;
13886         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
13887             output += "TAKES_FOCUS";
13888             numFlags++;
13889         }
13890 
13891         switch (flags & VISIBILITY_MASK) {
13892         case INVISIBLE:
13893             if (numFlags > 0) {
13894                 output += " ";
13895             }
13896             output += "INVISIBLE";
13897             // USELESS HERE numFlags++;
13898             break;
13899         case GONE:
13900             if (numFlags > 0) {
13901                 output += " ";
13902             }
13903             output += "GONE";
13904             // USELESS HERE numFlags++;
13905             break;
13906         default:
13907             break;
13908         }
13909         return output;
13910     }
13911 
13912     /**
13913      * Build a human readable string representation of the specified private
13914      * view flags.
13915      *
13916      * @param privateFlags the private view flags to convert to a string
13917      * @return a String representing the supplied flags
13918      */
13919     private static String printPrivateFlags(int privateFlags) {
13920         String output = "";
13921         int numFlags = 0;
13922 
13923         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
13924             output += "WANTS_FOCUS";
13925             numFlags++;
13926         }
13927 
13928         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
13929             if (numFlags > 0) {
13930                 output += " ";
13931             }
13932             output += "FOCUSED";
13933             numFlags++;
13934         }
13935 
13936         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
13937             if (numFlags > 0) {
13938                 output += " ";
13939             }
13940             output += "SELECTED";
13941             numFlags++;
13942         }
13943 
13944         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
13945             if (numFlags > 0) {
13946                 output += " ";
13947             }
13948             output += "IS_ROOT_NAMESPACE";
13949             numFlags++;
13950         }
13951 
13952         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
13953             if (numFlags > 0) {
13954                 output += " ";
13955             }
13956             output += "HAS_BOUNDS";
13957             numFlags++;
13958         }
13959 
13960         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
13961             if (numFlags > 0) {
13962                 output += " ";
13963             }
13964             output += "DRAWN";
13965             // USELESS HERE numFlags++;
13966         }
13967         return output;
13968     }
13969 
13970     /**
13971      * <p>Indicates whether or not this view's layout will be requested during
13972      * the next hierarchy layout pass.</p>
13973      *
13974      * @return true if the layout will be forced during next layout pass
13975      */
13976     public boolean isLayoutRequested() {
13977         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
13978     }
13979 
13980     /**
13981      * Assign a size and position to a view and all of its
13982      * descendants
13983      *
13984      * <p>This is the second phase of the layout mechanism.
13985      * (The first is measuring). In this phase, each parent calls
13986      * layout on all of its children to position them.
13987      * This is typically done using the child measurements
13988      * that were stored in the measure pass().</p>
13989      *
13990      * <p>Derived classes should not override this method.
13991      * Derived classes with children should override
13992      * onLayout. In that method, they should
13993      * call layout on each of their children.</p>
13994      *
13995      * @param l Left position, relative to parent
13996      * @param t Top position, relative to parent
13997      * @param r Right position, relative to parent
13998      * @param b Bottom position, relative to parent
13999      */
14000     @SuppressWarnings({"unchecked"})
14001     public void layout(int l, int t, int r, int b) {
14002         int oldL = mLeft;
14003         int oldT = mTop;
14004         int oldB = mBottom;
14005         int oldR = mRight;
14006         boolean changed = setFrame(l, t, r, b);
14007         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
14008             onLayout(changed, l, t, r, b);
14009             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
14010 
14011             ListenerInfo li = mListenerInfo;
14012             if (li != null && li.mOnLayoutChangeListeners != null) {
14013                 ArrayList<OnLayoutChangeListener> listenersCopy =
14014                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
14015                 int numListeners = listenersCopy.size();
14016                 for (int i = 0; i < numListeners; ++i) {
14017                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
14018                 }
14019             }
14020         }
14021         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
14022     }
14023 
14024     /**
14025      * Called from layout when this view should
14026      * assign a size and position to each of its children.
14027      *
14028      * Derived classes with children should override
14029      * this method and call layout on each of
14030      * their children.
14031      * @param changed This is a new size or position for this view
14032      * @param left Left position, relative to parent
14033      * @param top Top position, relative to parent
14034      * @param right Right position, relative to parent
14035      * @param bottom Bottom position, relative to parent
14036      */
14037     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
14038     }
14039 
14040     /**
14041      * Assign a size and position to this view.
14042      *
14043      * This is called from layout.
14044      *
14045      * @param left Left position, relative to parent
14046      * @param top Top position, relative to parent
14047      * @param right Right position, relative to parent
14048      * @param bottom Bottom position, relative to parent
14049      * @return true if the new size and position are different than the
14050      *         previous ones
14051      * {@hide}
14052      */
14053     protected boolean setFrame(int left, int top, int right, int bottom) {
14054         boolean changed = false;
14055 
14056         if (DBG) {
14057             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
14058                     + right + "," + bottom + ")");
14059         }
14060 
14061         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
14062             changed = true;
14063 
14064             // Remember our drawn bit
14065             int drawn = mPrivateFlags & PFLAG_DRAWN;
14066 
14067             int oldWidth = mRight - mLeft;
14068             int oldHeight = mBottom - mTop;
14069             int newWidth = right - left;
14070             int newHeight = bottom - top;
14071             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
14072 
14073             // Invalidate our old position
14074             invalidate(sizeChanged);
14075 
14076             mLeft = left;
14077             mTop = top;
14078             mRight = right;
14079             mBottom = bottom;
14080             if (mDisplayList != null) {
14081                 mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
14082             }
14083 
14084             mPrivateFlags |= PFLAG_HAS_BOUNDS;
14085 
14086 
14087             if (sizeChanged) {
14088                 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
14089                     // A change in dimension means an auto-centered pivot point changes, too
14090                     if (mTransformationInfo != null) {
14091                         mTransformationInfo.mMatrixDirty = true;
14092                     }
14093                 }
14094                 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
14095             }
14096 
14097             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
14098                 // If we are visible, force the DRAWN bit to on so that
14099                 // this invalidate will go through (at least to our parent).
14100                 // This is because someone may have invalidated this view
14101                 // before this call to setFrame came in, thereby clearing
14102                 // the DRAWN bit.
14103                 mPrivateFlags |= PFLAG_DRAWN;
14104                 invalidate(sizeChanged);
14105                 // parent display list may need to be recreated based on a change in the bounds
14106                 // of any child
14107                 invalidateParentCaches();
14108             }
14109 
14110             // Reset drawn bit to original value (invalidate turns it off)
14111             mPrivateFlags |= drawn;
14112 
14113             mBackgroundSizeChanged = true;
14114         }
14115         return changed;
14116     }
14117 
14118     /**
14119      * Finalize inflating a view from XML.  This is called as the last phase
14120      * of inflation, after all child views have been added.
14121      *
14122      * <p>Even if the subclass overrides onFinishInflate, they should always be
14123      * sure to call the super method, so that we get called.
14124      */
14125     protected void onFinishInflate() {
14126     }
14127 
14128     /**
14129      * Returns the resources associated with this view.
14130      *
14131      * @return Resources object.
14132      */
14133     public Resources getResources() {
14134         return mResources;
14135     }
14136 
14137     /**
14138      * Invalidates the specified Drawable.
14139      *
14140      * @param drawable the drawable to invalidate
14141      */
14142     public void invalidateDrawable(Drawable drawable) {
14143         if (verifyDrawable(drawable)) {
14144             final Rect dirty = drawable.getBounds();
14145             final int scrollX = mScrollX;
14146             final int scrollY = mScrollY;
14147 
14148             invalidate(dirty.left + scrollX, dirty.top + scrollY,
14149                     dirty.right + scrollX, dirty.bottom + scrollY);
14150         }
14151     }
14152 
14153     /**
14154      * Schedules an action on a drawable to occur at a specified time.
14155      *
14156      * @param who the recipient of the action
14157      * @param what the action to run on the drawable
14158      * @param when the time at which the action must occur. Uses the
14159      *        {@link SystemClock#uptimeMillis} timebase.
14160      */
14161     public void scheduleDrawable(Drawable who, Runnable what, long when) {
14162         if (verifyDrawable(who) && what != null) {
14163             final long delay = when - SystemClock.uptimeMillis();
14164             if (mAttachInfo != null) {
14165                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
14166                         Choreographer.CALLBACK_ANIMATION, what, who,
14167                         Choreographer.subtractFrameDelay(delay));
14168             } else {
14169                 ViewRootImpl.getRunQueue().postDelayed(what, delay);
14170             }
14171         }
14172     }
14173 
14174     /**
14175      * Cancels a scheduled action on a drawable.
14176      *
14177      * @param who the recipient of the action
14178      * @param what the action to cancel
14179      */
14180     public void unscheduleDrawable(Drawable who, Runnable what) {
14181         if (verifyDrawable(who) && what != null) {
14182             if (mAttachInfo != null) {
14183                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14184                         Choreographer.CALLBACK_ANIMATION, what, who);
14185             } else {
14186                 ViewRootImpl.getRunQueue().removeCallbacks(what);
14187             }
14188         }
14189     }
14190 
14191     /**
14192      * Unschedule any events associated with the given Drawable.  This can be
14193      * used when selecting a new Drawable into a view, so that the previous
14194      * one is completely unscheduled.
14195      *
14196      * @param who The Drawable to unschedule.
14197      *
14198      * @see #drawableStateChanged
14199      */
14200     public void unscheduleDrawable(Drawable who) {
14201         if (mAttachInfo != null && who != null) {
14202             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14203                     Choreographer.CALLBACK_ANIMATION, null, who);
14204         }
14205     }
14206 
14207     /**
14208      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
14209      * that the View directionality can and will be resolved before its Drawables.
14210      *
14211      * Will call {@link View#onResolveDrawables} when resolution is done.
14212      *
14213      * @hide
14214      */
14215     protected void resolveDrawables() {
14216         if (canResolveLayoutDirection()) {
14217             if (mBackground != null) {
14218                 mBackground.setLayoutDirection(getLayoutDirection());
14219             }
14220             mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
14221             onResolveDrawables(getLayoutDirection());
14222         }
14223     }
14224 
14225     /**
14226      * Called when layout direction has been resolved.
14227      *
14228      * The default implementation does nothing.
14229      *
14230      * @param layoutDirection The resolved layout direction.
14231      *
14232      * @see #LAYOUT_DIRECTION_LTR
14233      * @see #LAYOUT_DIRECTION_RTL
14234      *
14235      * @hide
14236      */
14237     public void onResolveDrawables(int layoutDirection) {
14238     }
14239 
14240     /**
14241      * @hide
14242      */
14243     protected void resetResolvedDrawables() {
14244         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
14245     }
14246 
14247     private boolean isDrawablesResolved() {
14248         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
14249     }
14250 
14251     /**
14252      * If your view subclass is displaying its own Drawable objects, it should
14253      * override this function and return true for any Drawable it is
14254      * displaying.  This allows animations for those drawables to be
14255      * scheduled.
14256      *
14257      * <p>Be sure to call through to the super class when overriding this
14258      * function.
14259      *
14260      * @param who The Drawable to verify.  Return true if it is one you are
14261      *            displaying, else return the result of calling through to the
14262      *            super class.
14263      *
14264      * @return boolean If true than the Drawable is being displayed in the
14265      *         view; else false and it is not allowed to animate.
14266      *
14267      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
14268      * @see #drawableStateChanged()
14269      */
14270     protected boolean verifyDrawable(Drawable who) {
14271         return who == mBackground;
14272     }
14273 
14274     /**
14275      * This function is called whenever the state of the view changes in such
14276      * a way that it impacts the state of drawables being shown.
14277      *
14278      * <p>Be sure to call through to the superclass when overriding this
14279      * function.
14280      *
14281      * @see Drawable#setState(int[])
14282      */
14283     protected void drawableStateChanged() {
14284         Drawable d = mBackground;
14285         if (d != null && d.isStateful()) {
14286             d.setState(getDrawableState());
14287         }
14288     }
14289 
14290     /**
14291      * Call this to force a view to update its drawable state. This will cause
14292      * drawableStateChanged to be called on this view. Views that are interested
14293      * in the new state should call getDrawableState.
14294      *
14295      * @see #drawableStateChanged
14296      * @see #getDrawableState
14297      */
14298     public void refreshDrawableState() {
14299         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14300         drawableStateChanged();
14301 
14302         ViewParent parent = mParent;
14303         if (parent != null) {
14304             parent.childDrawableStateChanged(this);
14305         }
14306     }
14307 
14308     /**
14309      * Return an array of resource IDs of the drawable states representing the
14310      * current state of the view.
14311      *
14312      * @return The current drawable state
14313      *
14314      * @see Drawable#setState(int[])
14315      * @see #drawableStateChanged()
14316      * @see #onCreateDrawableState(int)
14317      */
14318     public final int[] getDrawableState() {
14319         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
14320             return mDrawableState;
14321         } else {
14322             mDrawableState = onCreateDrawableState(0);
14323             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
14324             return mDrawableState;
14325         }
14326     }
14327 
14328     /**
14329      * Generate the new {@link android.graphics.drawable.Drawable} state for
14330      * this view. This is called by the view
14331      * system when the cached Drawable state is determined to be invalid.  To
14332      * retrieve the current state, you should use {@link #getDrawableState}.
14333      *
14334      * @param extraSpace if non-zero, this is the number of extra entries you
14335      * would like in the returned array in which you can place your own
14336      * states.
14337      *
14338      * @return Returns an array holding the current {@link Drawable} state of
14339      * the view.
14340      *
14341      * @see #mergeDrawableStates(int[], int[])
14342      */
14343     protected int[] onCreateDrawableState(int extraSpace) {
14344         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
14345                 mParent instanceof View) {
14346             return ((View) mParent).onCreateDrawableState(extraSpace);
14347         }
14348 
14349         int[] drawableState;
14350 
14351         int privateFlags = mPrivateFlags;
14352 
14353         int viewStateIndex = 0;
14354         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
14355         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
14356         if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
14357         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
14358         if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
14359         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
14360         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
14361                 HardwareRenderer.isAvailable()) {
14362             // This is set if HW acceleration is requested, even if the current
14363             // process doesn't allow it.  This is just to allow app preview
14364             // windows to better match their app.
14365             viewStateIndex |= VIEW_STATE_ACCELERATED;
14366         }
14367         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
14368 
14369         final int privateFlags2 = mPrivateFlags2;
14370         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
14371         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
14372 
14373         drawableState = VIEW_STATE_SETS[viewStateIndex];
14374 
14375         //noinspection ConstantIfStatement
14376         if (false) {
14377             Log.i("View", "drawableStateIndex=" + viewStateIndex);
14378             Log.i("View", toString()
14379                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
14380                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
14381                     + " fo=" + hasFocus()
14382                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
14383                     + " wf=" + hasWindowFocus()
14384                     + ": " + Arrays.toString(drawableState));
14385         }
14386 
14387         if (extraSpace == 0) {
14388             return drawableState;
14389         }
14390 
14391         final int[] fullState;
14392         if (drawableState != null) {
14393             fullState = new int[drawableState.length + extraSpace];
14394             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
14395         } else {
14396             fullState = new int[extraSpace];
14397         }
14398 
14399         return fullState;
14400     }
14401 
14402     /**
14403      * Merge your own state values in <var>additionalState</var> into the base
14404      * state values <var>baseState</var> that were returned by
14405      * {@link #onCreateDrawableState(int)}.
14406      *
14407      * @param baseState The base state values returned by
14408      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
14409      * own additional state values.
14410      *
14411      * @param additionalState The additional state values you would like
14412      * added to <var>baseState</var>; this array is not modified.
14413      *
14414      * @return As a convenience, the <var>baseState</var> array you originally
14415      * passed into the function is returned.
14416      *
14417      * @see #onCreateDrawableState(int)
14418      */
14419     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
14420         final int N = baseState.length;
14421         int i = N - 1;
14422         while (i >= 0 && baseState[i] == 0) {
14423             i--;
14424         }
14425         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
14426         return baseState;
14427     }
14428 
14429     /**
14430      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
14431      * on all Drawable objects associated with this view.
14432      */
14433     public void jumpDrawablesToCurrentState() {
14434         if (mBackground != null) {
14435             mBackground.jumpToCurrentState();
14436         }
14437     }
14438 
14439     /**
14440      * Sets the background color for this view.
14441      * @param color the color of the background
14442      */
14443     @RemotableViewMethod
14444     public void setBackgroundColor(int color) {
14445         if (mBackground instanceof ColorDrawable) {
14446             ((ColorDrawable) mBackground.mutate()).setColor(color);
14447             computeOpaqueFlags();
14448         } else {
14449             setBackground(new ColorDrawable(color));
14450         }
14451     }
14452 
14453     /**
14454      * Set the background to a given resource. The resource should refer to
14455      * a Drawable object or 0 to remove the background.
14456      * @param resid The identifier of the resource.
14457      *
14458      * @attr ref android.R.styleable#View_background
14459      */
14460     @RemotableViewMethod
14461     public void setBackgroundResource(int resid) {
14462         if (resid != 0 && resid == mBackgroundResource) {
14463             return;
14464         }
14465 
14466         Drawable d= null;
14467         if (resid != 0) {
14468             d = mResources.getDrawable(resid);
14469         }
14470         setBackground(d);
14471 
14472         mBackgroundResource = resid;
14473     }
14474 
14475     /**
14476      * Set the background to a given Drawable, or remove the background. If the
14477      * background has padding, this View's padding is set to the background's
14478      * padding. However, when a background is removed, this View's padding isn't
14479      * touched. If setting the padding is desired, please use
14480      * {@link #setPadding(int, int, int, int)}.
14481      *
14482      * @param background The Drawable to use as the background, or null to remove the
14483      *        background
14484      */
14485     public void setBackground(Drawable background) {
14486         //noinspection deprecation
14487         setBackgroundDrawable(background);
14488     }
14489 
14490     /**
14491      * @deprecated use {@link #setBackground(Drawable)} instead
14492      */
14493     @Deprecated
14494     public void setBackgroundDrawable(Drawable background) {
14495         computeOpaqueFlags();
14496 
14497         if (background == mBackground) {
14498             return;
14499         }
14500 
14501         boolean requestLayout = false;
14502 
14503         mBackgroundResource = 0;
14504 
14505         /*
14506          * Regardless of whether we're setting a new background or not, we want
14507          * to clear the previous drawable.
14508          */
14509         if (mBackground != null) {
14510             mBackground.setCallback(null);
14511             unscheduleDrawable(mBackground);
14512         }
14513 
14514         if (background != null) {
14515             Rect padding = sThreadLocal.get();
14516             if (padding == null) {
14517                 padding = new Rect();
14518                 sThreadLocal.set(padding);
14519             }
14520             resetResolvedDrawables();
14521             background.setLayoutDirection(getLayoutDirection());
14522             if (background.getPadding(padding)) {
14523                 resetResolvedPadding();
14524                 switch (background.getLayoutDirection()) {
14525                     case LAYOUT_DIRECTION_RTL:
14526                         mUserPaddingLeftInitial = padding.right;
14527                         mUserPaddingRightInitial = padding.left;
14528                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
14529                         break;
14530                     case LAYOUT_DIRECTION_LTR:
14531                     default:
14532                         mUserPaddingLeftInitial = padding.left;
14533                         mUserPaddingRightInitial = padding.right;
14534                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
14535                 }
14536             }
14537 
14538             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
14539             // if it has a different minimum size, we should layout again
14540             if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() ||
14541                     mBackground.getMinimumWidth() != background.getMinimumWidth()) {
14542                 requestLayout = true;
14543             }
14544 
14545             background.setCallback(this);
14546             if (background.isStateful()) {
14547                 background.setState(getDrawableState());
14548             }
14549             background.setVisible(getVisibility() == VISIBLE, false);
14550             mBackground = background;
14551 
14552             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
14553                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
14554                 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
14555                 requestLayout = true;
14556             }
14557         } else {
14558             /* Remove the background */
14559             mBackground = null;
14560 
14561             if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
14562                 /*
14563                  * This view ONLY drew the background before and we're removing
14564                  * the background, so now it won't draw anything
14565                  * (hence we SKIP_DRAW)
14566                  */
14567                 mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
14568                 mPrivateFlags |= PFLAG_SKIP_DRAW;
14569             }
14570 
14571             /*
14572              * When the background is set, we try to apply its padding to this
14573              * View. When the background is removed, we don't touch this View's
14574              * padding. This is noted in the Javadocs. Hence, we don't need to
14575              * requestLayout(), the invalidate() below is sufficient.
14576              */
14577 
14578             // The old background's minimum size could have affected this
14579             // View's layout, so let's requestLayout
14580             requestLayout = true;
14581         }
14582 
14583         computeOpaqueFlags();
14584 
14585         if (requestLayout) {
14586             requestLayout();
14587         }
14588 
14589         mBackgroundSizeChanged = true;
14590         invalidate(true);
14591     }
14592 
14593     /**
14594      * Gets the background drawable
14595      *
14596      * @return The drawable used as the background for this view, if any.
14597      *
14598      * @see #setBackground(Drawable)
14599      *
14600      * @attr ref android.R.styleable#View_background
14601      */
14602     public Drawable getBackground() {
14603         return mBackground;
14604     }
14605 
14606     /**
14607      * Sets the padding. The view may add on the space required to display
14608      * the scrollbars, depending on the style and visibility of the scrollbars.
14609      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
14610      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
14611      * from the values set in this call.
14612      *
14613      * @attr ref android.R.styleable#View_padding
14614      * @attr ref android.R.styleable#View_paddingBottom
14615      * @attr ref android.R.styleable#View_paddingLeft
14616      * @attr ref android.R.styleable#View_paddingRight
14617      * @attr ref android.R.styleable#View_paddingTop
14618      * @param left the left padding in pixels
14619      * @param top the top padding in pixels
14620      * @param right the right padding in pixels
14621      * @param bottom the bottom padding in pixels
14622      */
14623     public void setPadding(int left, int top, int right, int bottom) {
14624         resetResolvedPadding();
14625 
14626         mUserPaddingStart = UNDEFINED_PADDING;
14627         mUserPaddingEnd = UNDEFINED_PADDING;
14628 
14629         mUserPaddingLeftInitial = left;
14630         mUserPaddingRightInitial = right;
14631 
14632         internalSetPadding(left, top, right, bottom);
14633     }
14634 
14635     /**
14636      * @hide
14637      */
14638     protected void internalSetPadding(int left, int top, int right, int bottom) {
14639         mUserPaddingLeft = left;
14640         mUserPaddingRight = right;
14641         mUserPaddingBottom = bottom;
14642 
14643         final int viewFlags = mViewFlags;
14644         boolean changed = false;
14645 
14646         // Common case is there are no scroll bars.
14647         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
14648             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
14649                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
14650                         ? 0 : getVerticalScrollbarWidth();
14651                 switch (mVerticalScrollbarPosition) {
14652                     case SCROLLBAR_POSITION_DEFAULT:
14653                         if (isLayoutRtl()) {
14654                             left += offset;
14655                         } else {
14656                             right += offset;
14657                         }
14658                         break;
14659                     case SCROLLBAR_POSITION_RIGHT:
14660                         right += offset;
14661                         break;
14662                     case SCROLLBAR_POSITION_LEFT:
14663                         left += offset;
14664                         break;
14665                 }
14666             }
14667             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
14668                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
14669                         ? 0 : getHorizontalScrollbarHeight();
14670             }
14671         }
14672 
14673         if (mPaddingLeft != left) {
14674             changed = true;
14675             mPaddingLeft = left;
14676         }
14677         if (mPaddingTop != top) {
14678             changed = true;
14679             mPaddingTop = top;
14680         }
14681         if (mPaddingRight != right) {
14682             changed = true;
14683             mPaddingRight = right;
14684         }
14685         if (mPaddingBottom != bottom) {
14686             changed = true;
14687             mPaddingBottom = bottom;
14688         }
14689 
14690         if (changed) {
14691             requestLayout();
14692         }
14693     }
14694 
14695     /**
14696      * Sets the relative padding. The view may add on the space required to display
14697      * the scrollbars, depending on the style and visibility of the scrollbars.
14698      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
14699      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
14700      * from the values set in this call.
14701      *
14702      * @attr ref android.R.styleable#View_padding
14703      * @attr ref android.R.styleable#View_paddingBottom
14704      * @attr ref android.R.styleable#View_paddingStart
14705      * @attr ref android.R.styleable#View_paddingEnd
14706      * @attr ref android.R.styleable#View_paddingTop
14707      * @param start the start padding in pixels
14708      * @param top the top padding in pixels
14709      * @param end the end padding in pixels
14710      * @param bottom the bottom padding in pixels
14711      */
14712     public void setPaddingRelative(int start, int top, int end, int bottom) {
14713         resetResolvedPadding();
14714 
14715         mUserPaddingStart = start;
14716         mUserPaddingEnd = end;
14717 
14718         switch(getLayoutDirection()) {
14719             case LAYOUT_DIRECTION_RTL:
14720                 mUserPaddingLeftInitial = end;
14721                 mUserPaddingRightInitial = start;
14722                 internalSetPadding(end, top, start, bottom);
14723                 break;
14724             case LAYOUT_DIRECTION_LTR:
14725             default:
14726                 mUserPaddingLeftInitial = start;
14727                 mUserPaddingRightInitial = end;
14728                 internalSetPadding(start, top, end, bottom);
14729         }
14730     }
14731 
14732     /**
14733      * Returns the top padding of this view.
14734      *
14735      * @return the top padding in pixels
14736      */
14737     public int getPaddingTop() {
14738         return mPaddingTop;
14739     }
14740 
14741     /**
14742      * Returns the bottom padding of this view. If there are inset and enabled
14743      * scrollbars, this value may include the space required to display the
14744      * scrollbars as well.
14745      *
14746      * @return the bottom padding in pixels
14747      */
14748     public int getPaddingBottom() {
14749         return mPaddingBottom;
14750     }
14751 
14752     /**
14753      * Returns the left padding of this view. If there are inset and enabled
14754      * scrollbars, this value may include the space required to display the
14755      * scrollbars as well.
14756      *
14757      * @return the left padding in pixels
14758      */
14759     public int getPaddingLeft() {
14760         if (!isPaddingResolved()) {
14761             resolvePadding();
14762         }
14763         return mPaddingLeft;
14764     }
14765 
14766     /**
14767      * Returns the start padding of this view depending on its resolved layout direction.
14768      * If there are inset and enabled scrollbars, this value may include the space
14769      * required to display the scrollbars as well.
14770      *
14771      * @return the start padding in pixels
14772      */
14773     public int getPaddingStart() {
14774         if (!isPaddingResolved()) {
14775             resolvePadding();
14776         }
14777         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
14778                 mPaddingRight : mPaddingLeft;
14779     }
14780 
14781     /**
14782      * Returns the right padding of this view. If there are inset and enabled
14783      * scrollbars, this value may include the space required to display the
14784      * scrollbars as well.
14785      *
14786      * @return the right padding in pixels
14787      */
14788     public int getPaddingRight() {
14789         if (!isPaddingResolved()) {
14790             resolvePadding();
14791         }
14792         return mPaddingRight;
14793     }
14794 
14795     /**
14796      * Returns the end padding of this view depending on its resolved layout direction.
14797      * If there are inset and enabled scrollbars, this value may include the space
14798      * required to display the scrollbars as well.
14799      *
14800      * @return the end padding in pixels
14801      */
14802     public int getPaddingEnd() {
14803         if (!isPaddingResolved()) {
14804             resolvePadding();
14805         }
14806         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
14807                 mPaddingLeft : mPaddingRight;
14808     }
14809 
14810     /**
14811      * Return if the padding as been set thru relative values
14812      * {@link #setPaddingRelative(int, int, int, int)} or thru
14813      * @attr ref android.R.styleable#View_paddingStart or
14814      * @attr ref android.R.styleable#View_paddingEnd
14815      *
14816      * @return true if the padding is relative or false if it is not.
14817      */
14818     public boolean isPaddingRelative() {
14819         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
14820     }
14821 
14822     /**
14823      * @hide
14824      */
14825     public void resetPaddingToInitialValues() {
14826         if (isRtlCompatibilityMode()) {
14827             mPaddingLeft = mUserPaddingLeftInitial;
14828             mPaddingRight = mUserPaddingRightInitial;
14829             return;
14830         }
14831         if (isLayoutRtl()) {
14832             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
14833             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
14834         } else {
14835             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
14836             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
14837         }
14838     }
14839 
14840     /**
14841      * @hide
14842      */
14843     public Insets getOpticalInsets() {
14844         if (mLayoutInsets == null) {
14845             mLayoutInsets = (mBackground == null) ? Insets.NONE : mBackground.getLayoutInsets();
14846         }
14847         return mLayoutInsets;
14848     }
14849 
14850     /**
14851      * @hide
14852      */
14853     public void setLayoutInsets(Insets layoutInsets) {
14854         mLayoutInsets = layoutInsets;
14855     }
14856 
14857     /**
14858      * Changes the selection state of this view. A view can be selected or not.
14859      * Note that selection is not the same as focus. Views are typically
14860      * selected in the context of an AdapterView like ListView or GridView;
14861      * the selected view is the view that is highlighted.
14862      *
14863      * @param selected true if the view must be selected, false otherwise
14864      */
14865     public void setSelected(boolean selected) {
14866         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
14867             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
14868             if (!selected) resetPressedState();
14869             invalidate(true);
14870             refreshDrawableState();
14871             dispatchSetSelected(selected);
14872             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
14873                 notifyAccessibilityStateChanged();
14874             }
14875         }
14876     }
14877 
14878     /**
14879      * Dispatch setSelected to all of this View's children.
14880      *
14881      * @see #setSelected(boolean)
14882      *
14883      * @param selected The new selected state
14884      */
14885     protected void dispatchSetSelected(boolean selected) {
14886     }
14887 
14888     /**
14889      * Indicates the selection state of this view.
14890      *
14891      * @return true if the view is selected, false otherwise
14892      */
14893     @ViewDebug.ExportedProperty
14894     public boolean isSelected() {
14895         return (mPrivateFlags & PFLAG_SELECTED) != 0;
14896     }
14897 
14898     /**
14899      * Changes the activated state of this view. A view can be activated or not.
14900      * Note that activation is not the same as selection.  Selection is
14901      * a transient property, representing the view (hierarchy) the user is
14902      * currently interacting with.  Activation is a longer-term state that the
14903      * user can move views in and out of.  For example, in a list view with
14904      * single or multiple selection enabled, the views in the current selection
14905      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
14906      * here.)  The activated state is propagated down to children of the view it
14907      * is set on.
14908      *
14909      * @param activated true if the view must be activated, false otherwise
14910      */
14911     public void setActivated(boolean activated) {
14912         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
14913             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
14914             invalidate(true);
14915             refreshDrawableState();
14916             dispatchSetActivated(activated);
14917         }
14918     }
14919 
14920     /**
14921      * Dispatch setActivated to all of this View's children.
14922      *
14923      * @see #setActivated(boolean)
14924      *
14925      * @param activated The new activated state
14926      */
14927     protected void dispatchSetActivated(boolean activated) {
14928     }
14929 
14930     /**
14931      * Indicates the activation state of this view.
14932      *
14933      * @return true if the view is activated, false otherwise
14934      */
14935     @ViewDebug.ExportedProperty
14936     public boolean isActivated() {
14937         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
14938     }
14939 
14940     /**
14941      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
14942      * observer can be used to get notifications when global events, like
14943      * layout, happen.
14944      *
14945      * The returned ViewTreeObserver observer is not guaranteed to remain
14946      * valid for the lifetime of this View. If the caller of this method keeps
14947      * a long-lived reference to ViewTreeObserver, it should always check for
14948      * the return value of {@link ViewTreeObserver#isAlive()}.
14949      *
14950      * @return The ViewTreeObserver for this view's hierarchy.
14951      */
14952     public ViewTreeObserver getViewTreeObserver() {
14953         if (mAttachInfo != null) {
14954             return mAttachInfo.mTreeObserver;
14955         }
14956         if (mFloatingTreeObserver == null) {
14957             mFloatingTreeObserver = new ViewTreeObserver();
14958         }
14959         return mFloatingTreeObserver;
14960     }
14961 
14962     /**
14963      * <p>Finds the topmost view in the current view hierarchy.</p>
14964      *
14965      * @return the topmost view containing this view
14966      */
14967     public View getRootView() {
14968         if (mAttachInfo != null) {
14969             final View v = mAttachInfo.mRootView;
14970             if (v != null) {
14971                 return v;
14972             }
14973         }
14974 
14975         View parent = this;
14976 
14977         while (parent.mParent != null && parent.mParent instanceof View) {
14978             parent = (View) parent.mParent;
14979         }
14980 
14981         return parent;
14982     }
14983 
14984     /**
14985      * <p>Computes the coordinates of this view on the screen. The argument
14986      * must be an array of two integers. After the method returns, the array
14987      * contains the x and y location in that order.</p>
14988      *
14989      * @param location an array of two integers in which to hold the coordinates
14990      */
14991     public void getLocationOnScreen(int[] location) {
14992         getLocationInWindow(location);
14993 
14994         final AttachInfo info = mAttachInfo;
14995         if (info != null) {
14996             location[0] += info.mWindowLeft;
14997             location[1] += info.mWindowTop;
14998         }
14999     }
15000 
15001     /**
15002      * <p>Computes the coordinates of this view in its window. The argument
15003      * must be an array of two integers. After the method returns, the array
15004      * contains the x and y location in that order.</p>
15005      *
15006      * @param location an array of two integers in which to hold the coordinates
15007      */
15008     public void getLocationInWindow(int[] location) {
15009         if (location == null || location.length < 2) {
15010             throw new IllegalArgumentException("location must be an array of two integers");
15011         }
15012 
15013         if (mAttachInfo == null) {
15014             // When the view is not attached to a window, this method does not make sense
15015             location[0] = location[1] = 0;
15016             return;
15017         }
15018 
15019         float[] position = mAttachInfo.mTmpTransformLocation;
15020         position[0] = position[1] = 0.0f;
15021 
15022         if (!hasIdentityMatrix()) {
15023             getMatrix().mapPoints(position);
15024         }
15025 
15026         position[0] += mLeft;
15027         position[1] += mTop;
15028 
15029         ViewParent viewParent = mParent;
15030         while (viewParent instanceof View) {
15031             final View view = (View) viewParent;
15032 
15033             position[0] -= view.mScrollX;
15034             position[1] -= view.mScrollY;
15035 
15036             if (!view.hasIdentityMatrix()) {
15037                 view.getMatrix().mapPoints(position);
15038             }
15039 
15040             position[0] += view.mLeft;
15041             position[1] += view.mTop;
15042 
15043             viewParent = view.mParent;
15044          }
15045 
15046         if (viewParent instanceof ViewRootImpl) {
15047             // *cough*
15048             final ViewRootImpl vr = (ViewRootImpl) viewParent;
15049             position[1] -= vr.mCurScrollY;
15050         }
15051 
15052         location[0] = (int) (position[0] + 0.5f);
15053         location[1] = (int) (position[1] + 0.5f);
15054     }
15055 
15056     /**
15057      * {@hide}
15058      * @param id the id of the view to be found
15059      * @return the view of the specified id, null if cannot be found
15060      */
15061     protected View findViewTraversal(int id) {
15062         if (id == mID) {
15063             return this;
15064         }
15065         return null;
15066     }
15067 
15068     /**
15069      * {@hide}
15070      * @param tag the tag of the view to be found
15071      * @return the view of specified tag, null if cannot be found
15072      */
15073     protected View findViewWithTagTraversal(Object tag) {
15074         if (tag != null && tag.equals(mTag)) {
15075             return this;
15076         }
15077         return null;
15078     }
15079 
15080     /**
15081      * {@hide}
15082      * @param predicate The predicate to evaluate.
15083      * @param childToSkip If not null, ignores this child during the recursive traversal.
15084      * @return The first view that matches the predicate or null.
15085      */
15086     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
15087         if (predicate.apply(this)) {
15088             return this;
15089         }
15090         return null;
15091     }
15092 
15093     /**
15094      * Look for a child view with the given id.  If this view has the given
15095      * id, return this view.
15096      *
15097      * @param id The id to search for.
15098      * @return The view that has the given id in the hierarchy or null
15099      */
15100     public final View findViewById(int id) {
15101         if (id < 0) {
15102             return null;
15103         }
15104         return findViewTraversal(id);
15105     }
15106 
15107     /**
15108      * Finds a view by its unuque and stable accessibility id.
15109      *
15110      * @param accessibilityId The searched accessibility id.
15111      * @return The found view.
15112      */
15113     final View findViewByAccessibilityId(int accessibilityId) {
15114         if (accessibilityId < 0) {
15115             return null;
15116         }
15117         return findViewByAccessibilityIdTraversal(accessibilityId);
15118     }
15119 
15120     /**
15121      * Performs the traversal to find a view by its unuque and stable accessibility id.
15122      *
15123      * <strong>Note:</strong>This method does not stop at the root namespace
15124      * boundary since the user can touch the screen at an arbitrary location
15125      * potentially crossing the root namespace bounday which will send an
15126      * accessibility event to accessibility services and they should be able
15127      * to obtain the event source. Also accessibility ids are guaranteed to be
15128      * unique in the window.
15129      *
15130      * @param accessibilityId The accessibility id.
15131      * @return The found view.
15132      */
15133     View findViewByAccessibilityIdTraversal(int accessibilityId) {
15134         if (getAccessibilityViewId() == accessibilityId) {
15135             return this;
15136         }
15137         return null;
15138     }
15139 
15140     /**
15141      * Look for a child view with the given tag.  If this view has the given
15142      * tag, return this view.
15143      *
15144      * @param tag The tag to search for, using "tag.equals(getTag())".
15145      * @return The View that has the given tag in the hierarchy or null
15146      */
15147     public final View findViewWithTag(Object tag) {
15148         if (tag == null) {
15149             return null;
15150         }
15151         return findViewWithTagTraversal(tag);
15152     }
15153 
15154     /**
15155      * {@hide}
15156      * Look for a child view that matches the specified predicate.
15157      * If this view matches the predicate, return this view.
15158      *
15159      * @param predicate The predicate to evaluate.
15160      * @return The first view that matches the predicate or null.
15161      */
15162     public final View findViewByPredicate(Predicate<View> predicate) {
15163         return findViewByPredicateTraversal(predicate, null);
15164     }
15165 
15166     /**
15167      * {@hide}
15168      * Look for a child view that matches the specified predicate,
15169      * starting with the specified view and its descendents and then
15170      * recusively searching the ancestors and siblings of that view
15171      * until this view is reached.
15172      *
15173      * This method is useful in cases where the predicate does not match
15174      * a single unique view (perhaps multiple views use the same id)
15175      * and we are trying to find the view that is "closest" in scope to the
15176      * starting view.
15177      *
15178      * @param start The view to start from.
15179      * @param predicate The predicate to evaluate.
15180      * @return The first view that matches the predicate or null.
15181      */
15182     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
15183         View childToSkip = null;
15184         for (;;) {
15185             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
15186             if (view != null || start == this) {
15187                 return view;
15188             }
15189 
15190             ViewParent parent = start.getParent();
15191             if (parent == null || !(parent instanceof View)) {
15192                 return null;
15193             }
15194 
15195             childToSkip = start;
15196             start = (View) parent;
15197         }
15198     }
15199 
15200     /**
15201      * Sets the identifier for this view. The identifier does not have to be
15202      * unique in this view's hierarchy. The identifier should be a positive
15203      * number.
15204      *
15205      * @see #NO_ID
15206      * @see #getId()
15207      * @see #findViewById(int)
15208      *
15209      * @param id a number used to identify the view
15210      *
15211      * @attr ref android.R.styleable#View_id
15212      */
15213     public void setId(int id) {
15214         mID = id;
15215         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
15216             mID = generateViewId();
15217         }
15218     }
15219 
15220     /**
15221      * {@hide}
15222      *
15223      * @param isRoot true if the view belongs to the root namespace, false
15224      *        otherwise
15225      */
15226     public void setIsRootNamespace(boolean isRoot) {
15227         if (isRoot) {
15228             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
15229         } else {
15230             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
15231         }
15232     }
15233 
15234     /**
15235      * {@hide}
15236      *
15237      * @return true if the view belongs to the root namespace, false otherwise
15238      */
15239     public boolean isRootNamespace() {
15240         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
15241     }
15242 
15243     /**
15244      * Returns this view's identifier.
15245      *
15246      * @return a positive integer used to identify the view or {@link #NO_ID}
15247      *         if the view has no ID
15248      *
15249      * @see #setId(int)
15250      * @see #findViewById(int)
15251      * @attr ref android.R.styleable#View_id
15252      */
15253     @ViewDebug.CapturedViewProperty
15254     public int getId() {
15255         return mID;
15256     }
15257 
15258     /**
15259      * Returns this view's tag.
15260      *
15261      * @return the Object stored in this view as a tag
15262      *
15263      * @see #setTag(Object)
15264      * @see #getTag(int)
15265      */
15266     @ViewDebug.ExportedProperty
15267     public Object getTag() {
15268         return mTag;
15269     }
15270 
15271     /**
15272      * Sets the tag associated with this view. A tag can be used to mark
15273      * a view in its hierarchy and does not have to be unique within the
15274      * hierarchy. Tags can also be used to store data within a view without
15275      * resorting to another data structure.
15276      *
15277      * @param tag an Object to tag the view with
15278      *
15279      * @see #getTag()
15280      * @see #setTag(int, Object)
15281      */
15282     public void setTag(final Object tag) {
15283         mTag = tag;
15284     }
15285 
15286     /**
15287      * Returns the tag associated with this view and the specified key.
15288      *
15289      * @param key The key identifying the tag
15290      *
15291      * @return the Object stored in this view as a tag
15292      *
15293      * @see #setTag(int, Object)
15294      * @see #getTag()
15295      */
15296     public Object getTag(int key) {
15297         if (mKeyedTags != null) return mKeyedTags.get(key);
15298         return null;
15299     }
15300 
15301     /**
15302      * Sets a tag associated with this view and a key. A tag can be used
15303      * to mark a view in its hierarchy and does not have to be unique within
15304      * the hierarchy. Tags can also be used to store data within a view
15305      * without resorting to another data structure.
15306      *
15307      * The specified key should be an id declared in the resources of the
15308      * application to ensure it is unique (see the <a
15309      * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
15310      * Keys identified as belonging to
15311      * the Android framework or not associated with any package will cause
15312      * an {@link IllegalArgumentException} to be thrown.
15313      *
15314      * @param key The key identifying the tag
15315      * @param tag An Object to tag the view with
15316      *
15317      * @throws IllegalArgumentException If they specified key is not valid
15318      *
15319      * @see #setTag(Object)
15320      * @see #getTag(int)
15321      */
15322     public void setTag(int key, final Object tag) {
15323         // If the package id is 0x00 or 0x01, it's either an undefined package
15324         // or a framework id
15325         if ((key >>> 24) < 2) {
15326             throw new IllegalArgumentException("The key must be an application-specific "
15327                     + "resource id.");
15328         }
15329 
15330         setKeyedTag(key, tag);
15331     }
15332 
15333     /**
15334      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
15335      * framework id.
15336      *
15337      * @hide
15338      */
15339     public void setTagInternal(int key, Object tag) {
15340         if ((key >>> 24) != 0x1) {
15341             throw new IllegalArgumentException("The key must be a framework-specific "
15342                     + "resource id.");
15343         }
15344 
15345         setKeyedTag(key, tag);
15346     }
15347 
15348     private void setKeyedTag(int key, Object tag) {
15349         if (mKeyedTags == null) {
15350             mKeyedTags = new SparseArray<Object>();
15351         }
15352 
15353         mKeyedTags.put(key, tag);
15354     }
15355 
15356     /**
15357      * Prints information about this view in the log output, with the tag
15358      * {@link #VIEW_LOG_TAG}.
15359      *
15360      * @hide
15361      */
15362     public void debug() {
15363         debug(0);
15364     }
15365 
15366     /**
15367      * Prints information about this view in the log output, with the tag
15368      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
15369      * indentation defined by the <code>depth</code>.
15370      *
15371      * @param depth the indentation level
15372      *
15373      * @hide
15374      */
15375     protected void debug(int depth) {
15376         String output = debugIndent(depth - 1);
15377 
15378         output += "+ " + this;
15379         int id = getId();
15380         if (id != -1) {
15381             output += " (id=" + id + ")";
15382         }
15383         Object tag = getTag();
15384         if (tag != null) {
15385             output += " (tag=" + tag + ")";
15386         }
15387         Log.d(VIEW_LOG_TAG, output);
15388 
15389         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
15390             output = debugIndent(depth) + " FOCUSED";
15391             Log.d(VIEW_LOG_TAG, output);
15392         }
15393 
15394         output = debugIndent(depth);
15395         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
15396                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
15397                 + "} ";
15398         Log.d(VIEW_LOG_TAG, output);
15399 
15400         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
15401                 || mPaddingBottom != 0) {
15402             output = debugIndent(depth);
15403             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
15404                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
15405             Log.d(VIEW_LOG_TAG, output);
15406         }
15407 
15408         output = debugIndent(depth);
15409         output += "mMeasureWidth=" + mMeasuredWidth +
15410                 " mMeasureHeight=" + mMeasuredHeight;
15411         Log.d(VIEW_LOG_TAG, output);
15412 
15413         output = debugIndent(depth);
15414         if (mLayoutParams == null) {
15415             output += "BAD! no layout params";
15416         } else {
15417             output = mLayoutParams.debug(output);
15418         }
15419         Log.d(VIEW_LOG_TAG, output);
15420 
15421         output = debugIndent(depth);
15422         output += "flags={";
15423         output += View.printFlags(mViewFlags);
15424         output += "}";
15425         Log.d(VIEW_LOG_TAG, output);
15426 
15427         output = debugIndent(depth);
15428         output += "privateFlags={";
15429         output += View.printPrivateFlags(mPrivateFlags);
15430         output += "}";
15431         Log.d(VIEW_LOG_TAG, output);
15432     }
15433 
15434     /**
15435      * Creates a string of whitespaces used for indentation.
15436      *
15437      * @param depth the indentation level
15438      * @return a String containing (depth * 2 + 3) * 2 white spaces
15439      *
15440      * @hide
15441      */
15442     protected static String debugIndent(int depth) {
15443         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
15444         for (int i = 0; i < (depth * 2) + 3; i++) {
15445             spaces.append(' ').append(' ');
15446         }
15447         return spaces.toString();
15448     }
15449 
15450     /**
15451      * <p>Return the offset of the widget's text baseline from the widget's top
15452      * boundary. If this widget does not support baseline alignment, this
15453      * method returns -1. </p>
15454      *
15455      * @return the offset of the baseline within the widget's bounds or -1
15456      *         if baseline alignment is not supported
15457      */
15458     @ViewDebug.ExportedProperty(category = "layout")
15459     public int getBaseline() {
15460         return -1;
15461     }
15462 
15463     /**
15464      * Call this when something has changed which has invalidated the
15465      * layout of this view. This will schedule a layout pass of the view
15466      * tree.
15467      */
15468     public void requestLayout() {
15469         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
15470         mPrivateFlags |= PFLAG_INVALIDATED;
15471 
15472         if (mParent != null && !mParent.isLayoutRequested()) {
15473             mParent.requestLayout();
15474         }
15475     }
15476 
15477     /**
15478      * Forces this view to be laid out during the next layout pass.
15479      * This method does not call requestLayout() or forceLayout()
15480      * on the parent.
15481      */
15482     public void forceLayout() {
15483         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
15484         mPrivateFlags |= PFLAG_INVALIDATED;
15485     }
15486 
15487     /**
15488      * <p>
15489      * This is called to find out how big a view should be. The parent
15490      * supplies constraint information in the width and height parameters.
15491      * </p>
15492      *
15493      * <p>
15494      * The actual measurement work of a view is performed in
15495      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
15496      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
15497      * </p>
15498      *
15499      *
15500      * @param widthMeasureSpec Horizontal space requirements as imposed by the
15501      *        parent
15502      * @param heightMeasureSpec Vertical space requirements as imposed by the
15503      *        parent
15504      *
15505      * @see #onMeasure(int, int)
15506      */
15507     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
15508         if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
15509                 widthMeasureSpec != mOldWidthMeasureSpec ||
15510                 heightMeasureSpec != mOldHeightMeasureSpec) {
15511 
15512             // first clears the measured dimension flag
15513             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
15514 
15515             resolveRtlPropertiesIfNeeded();
15516 
15517             // measure ourselves, this should set the measured dimension flag back
15518             onMeasure(widthMeasureSpec, heightMeasureSpec);
15519 
15520             // flag not set, setMeasuredDimension() was not invoked, we raise
15521             // an exception to warn the developer
15522             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
15523                 throw new IllegalStateException("onMeasure() did not set the"
15524                         + " measured dimension by calling"
15525                         + " setMeasuredDimension()");
15526             }
15527 
15528             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
15529         }
15530 
15531         mOldWidthMeasureSpec = widthMeasureSpec;
15532         mOldHeightMeasureSpec = heightMeasureSpec;
15533     }
15534 
15535     /**
15536      * <p>
15537      * Measure the view and its content to determine the measured width and the
15538      * measured height. This method is invoked by {@link #measure(int, int)} and
15539      * should be overriden by subclasses to provide accurate and efficient
15540      * measurement of their contents.
15541      * </p>
15542      *
15543      * <p>
15544      * <strong>CONTRACT:</strong> When overriding this method, you
15545      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
15546      * measured width and height of this view. Failure to do so will trigger an
15547      * <code>IllegalStateException</code>, thrown by
15548      * {@link #measure(int, int)}. Calling the superclass'
15549      * {@link #onMeasure(int, int)} is a valid use.
15550      * </p>
15551      *
15552      * <p>
15553      * The base class implementation of measure defaults to the background size,
15554      * unless a larger size is allowed by the MeasureSpec. Subclasses should
15555      * override {@link #onMeasure(int, int)} to provide better measurements of
15556      * their content.
15557      * </p>
15558      *
15559      * <p>
15560      * If this method is overridden, it is the subclass's responsibility to make
15561      * sure the measured height and width are at least the view's minimum height
15562      * and width ({@link #getSuggestedMinimumHeight()} and
15563      * {@link #getSuggestedMinimumWidth()}).
15564      * </p>
15565      *
15566      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
15567      *                         The requirements are encoded with
15568      *                         {@link android.view.View.MeasureSpec}.
15569      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
15570      *                         The requirements are encoded with
15571      *                         {@link android.view.View.MeasureSpec}.
15572      *
15573      * @see #getMeasuredWidth()
15574      * @see #getMeasuredHeight()
15575      * @see #setMeasuredDimension(int, int)
15576      * @see #getSuggestedMinimumHeight()
15577      * @see #getSuggestedMinimumWidth()
15578      * @see android.view.View.MeasureSpec#getMode(int)
15579      * @see android.view.View.MeasureSpec#getSize(int)
15580      */
15581     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
15582         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
15583                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
15584     }
15585 
15586     /**
15587      * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
15588      * measured width and measured height. Failing to do so will trigger an
15589      * exception at measurement time.</p>
15590      *
15591      * @param measuredWidth The measured width of this view.  May be a complex
15592      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15593      * {@link #MEASURED_STATE_TOO_SMALL}.
15594      * @param measuredHeight The measured height of this view.  May be a complex
15595      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15596      * {@link #MEASURED_STATE_TOO_SMALL}.
15597      */
15598     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
15599         mMeasuredWidth = measuredWidth;
15600         mMeasuredHeight = measuredHeight;
15601 
15602         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
15603     }
15604 
15605     /**
15606      * Merge two states as returned by {@link #getMeasuredState()}.
15607      * @param curState The current state as returned from a view or the result
15608      * of combining multiple views.
15609      * @param newState The new view state to combine.
15610      * @return Returns a new integer reflecting the combination of the two
15611      * states.
15612      */
15613     public static int combineMeasuredStates(int curState, int newState) {
15614         return curState | newState;
15615     }
15616 
15617     /**
15618      * Version of {@link #resolveSizeAndState(int, int, int)}
15619      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
15620      */
15621     public static int resolveSize(int size, int measureSpec) {
15622         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
15623     }
15624 
15625     /**
15626      * Utility to reconcile a desired size and state, with constraints imposed
15627      * by a MeasureSpec.  Will take the desired size, unless a different size
15628      * is imposed by the constraints.  The returned value is a compound integer,
15629      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
15630      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
15631      * size is smaller than the size the view wants to be.
15632      *
15633      * @param size How big the view wants to be
15634      * @param measureSpec Constraints imposed by the parent
15635      * @return Size information bit mask as defined by
15636      * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
15637      */
15638     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
15639         int result = size;
15640         int specMode = MeasureSpec.getMode(measureSpec);
15641         int specSize =  MeasureSpec.getSize(measureSpec);
15642         switch (specMode) {
15643         case MeasureSpec.UNSPECIFIED:
15644             result = size;
15645             break;
15646         case MeasureSpec.AT_MOST:
15647             if (specSize < size) {
15648                 result = specSize | MEASURED_STATE_TOO_SMALL;
15649             } else {
15650                 result = size;
15651             }
15652             break;
15653         case MeasureSpec.EXACTLY:
15654             result = specSize;
15655             break;
15656         }
15657         return result | (childMeasuredState&MEASURED_STATE_MASK);
15658     }
15659 
15660     /**
15661      * Utility to return a default size. Uses the supplied size if the
15662      * MeasureSpec imposed no constraints. Will get larger if allowed
15663      * by the MeasureSpec.
15664      *
15665      * @param size Default size for this view
15666      * @param measureSpec Constraints imposed by the parent
15667      * @return The size this view should be.
15668      */
15669     public static int getDefaultSize(int size, int measureSpec) {
15670         int result = size;
15671         int specMode = MeasureSpec.getMode(measureSpec);
15672         int specSize = MeasureSpec.getSize(measureSpec);
15673 
15674         switch (specMode) {
15675         case MeasureSpec.UNSPECIFIED:
15676             result = size;
15677             break;
15678         case MeasureSpec.AT_MOST:
15679         case MeasureSpec.EXACTLY:
15680             result = specSize;
15681             break;
15682         }
15683         return result;
15684     }
15685 
15686     /**
15687      * Returns the suggested minimum height that the view should use. This
15688      * returns the maximum of the view's minimum height
15689      * and the background's minimum height
15690      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
15691      * <p>
15692      * When being used in {@link #onMeasure(int, int)}, the caller should still
15693      * ensure the returned height is within the requirements of the parent.
15694      *
15695      * @return The suggested minimum height of the view.
15696      */
15697     protected int getSuggestedMinimumHeight() {
15698         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
15699 
15700     }
15701 
15702     /**
15703      * Returns the suggested minimum width that the view should use. This
15704      * returns the maximum of the view's minimum width)
15705      * and the background's minimum width
15706      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
15707      * <p>
15708      * When being used in {@link #onMeasure(int, int)}, the caller should still
15709      * ensure the returned width is within the requirements of the parent.
15710      *
15711      * @return The suggested minimum width of the view.
15712      */
15713     protected int getSuggestedMinimumWidth() {
15714         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
15715     }
15716 
15717     /**
15718      * Returns the minimum height of the view.
15719      *
15720      * @return the minimum height the view will try to be.
15721      *
15722      * @see #setMinimumHeight(int)
15723      *
15724      * @attr ref android.R.styleable#View_minHeight
15725      */
15726     public int getMinimumHeight() {
15727         return mMinHeight;
15728     }
15729 
15730     /**
15731      * Sets the minimum height of the view. It is not guaranteed the view will
15732      * be able to achieve this minimum height (for example, if its parent layout
15733      * constrains it with less available height).
15734      *
15735      * @param minHeight The minimum height the view will try to be.
15736      *
15737      * @see #getMinimumHeight()
15738      *
15739      * @attr ref android.R.styleable#View_minHeight
15740      */
15741     public void setMinimumHeight(int minHeight) {
15742         mMinHeight = minHeight;
15743         requestLayout();
15744     }
15745 
15746     /**
15747      * Returns the minimum width of the view.
15748      *
15749      * @return the minimum width the view will try to be.
15750      *
15751      * @see #setMinimumWidth(int)
15752      *
15753      * @attr ref android.R.styleable#View_minWidth
15754      */
15755     public int getMinimumWidth() {
15756         return mMinWidth;
15757     }
15758 
15759     /**
15760      * Sets the minimum width of the view. It is not guaranteed the view will
15761      * be able to achieve this minimum width (for example, if its parent layout
15762      * constrains it with less available width).
15763      *
15764      * @param minWidth The minimum width the view will try to be.
15765      *
15766      * @see #getMinimumWidth()
15767      *
15768      * @attr ref android.R.styleable#View_minWidth
15769      */
15770     public void setMinimumWidth(int minWidth) {
15771         mMinWidth = minWidth;
15772         requestLayout();
15773 
15774     }
15775 
15776     /**
15777      * Get the animation currently associated with this view.
15778      *
15779      * @return The animation that is currently playing or
15780      *         scheduled to play for this view.
15781      */
15782     public Animation getAnimation() {
15783         return mCurrentAnimation;
15784     }
15785 
15786     /**
15787      * Start the specified animation now.
15788      *
15789      * @param animation the animation to start now
15790      */
15791     public void startAnimation(Animation animation) {
15792         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
15793         setAnimation(animation);
15794         invalidateParentCaches();
15795         invalidate(true);
15796     }
15797 
15798     /**
15799      * Cancels any animations for this view.
15800      */
15801     public void clearAnimation() {
15802         if (mCurrentAnimation != null) {
15803             mCurrentAnimation.detach();
15804         }
15805         mCurrentAnimation = null;
15806         invalidateParentIfNeeded();
15807     }
15808 
15809     /**
15810      * Sets the next animation to play for this view.
15811      * If you want the animation to play immediately, use
15812      * {@link #startAnimation(android.view.animation.Animation)} instead.
15813      * This method provides allows fine-grained
15814      * control over the start time and invalidation, but you
15815      * must make sure that 1) the animation has a start time set, and
15816      * 2) the view's parent (which controls animations on its children)
15817      * will be invalidated when the animation is supposed to
15818      * start.
15819      *
15820      * @param animation The next animation, or null.
15821      */
15822     public void setAnimation(Animation animation) {
15823         mCurrentAnimation = animation;
15824 
15825         if (animation != null) {
15826             // If the screen is off assume the animation start time is now instead of
15827             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
15828             // would cause the animation to start when the screen turns back on
15829             if (mAttachInfo != null && !mAttachInfo.mScreenOn &&
15830                     animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
15831                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
15832             }
15833             animation.reset();
15834         }
15835     }
15836 
15837     /**
15838      * Invoked by a parent ViewGroup to notify the start of the animation
15839      * currently associated with this view. If you override this method,
15840      * always call super.onAnimationStart();
15841      *
15842      * @see #setAnimation(android.view.animation.Animation)
15843      * @see #getAnimation()
15844      */
15845     protected void onAnimationStart() {
15846         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
15847     }
15848 
15849     /**
15850      * Invoked by a parent ViewGroup to notify the end of the animation
15851      * currently associated with this view. If you override this method,
15852      * always call super.onAnimationEnd();
15853      *
15854      * @see #setAnimation(android.view.animation.Animation)
15855      * @see #getAnimation()
15856      */
15857     protected void onAnimationEnd() {
15858         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
15859     }
15860 
15861     /**
15862      * Invoked if there is a Transform that involves alpha. Subclass that can
15863      * draw themselves with the specified alpha should return true, and then
15864      * respect that alpha when their onDraw() is called. If this returns false
15865      * then the view may be redirected to draw into an offscreen buffer to
15866      * fulfill the request, which will look fine, but may be slower than if the
15867      * subclass handles it internally. The default implementation returns false.
15868      *
15869      * @param alpha The alpha (0..255) to apply to the view's drawing
15870      * @return true if the view can draw with the specified alpha.
15871      */
15872     protected boolean onSetAlpha(int alpha) {
15873         return false;
15874     }
15875 
15876     /**
15877      * This is used by the RootView to perform an optimization when
15878      * the view hierarchy contains one or several SurfaceView.
15879      * SurfaceView is always considered transparent, but its children are not,
15880      * therefore all View objects remove themselves from the global transparent
15881      * region (passed as a parameter to this function).
15882      *
15883      * @param region The transparent region for this ViewAncestor (window).
15884      *
15885      * @return Returns true if the effective visibility of the view at this
15886      * point is opaque, regardless of the transparent region; returns false
15887      * if it is possible for underlying windows to be seen behind the view.
15888      *
15889      * {@hide}
15890      */
15891     public boolean gatherTransparentRegion(Region region) {
15892         final AttachInfo attachInfo = mAttachInfo;
15893         if (region != null && attachInfo != null) {
15894             final int pflags = mPrivateFlags;
15895             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
15896                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
15897                 // remove it from the transparent region.
15898                 final int[] location = attachInfo.mTransparentLocation;
15899                 getLocationInWindow(location);
15900                 region.op(location[0], location[1], location[0] + mRight - mLeft,
15901                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
15902             } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
15903                 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
15904                 // exists, so we remove the background drawable's non-transparent
15905                 // parts from this transparent region.
15906                 applyDrawableToTransparentRegion(mBackground, region);
15907             }
15908         }
15909         return true;
15910     }
15911 
15912     /**
15913      * Play a sound effect for this view.
15914      *
15915      * <p>The framework will play sound effects for some built in actions, such as
15916      * clicking, but you may wish to play these effects in your widget,
15917      * for instance, for internal navigation.
15918      *
15919      * <p>The sound effect will only be played if sound effects are enabled by the user, and
15920      * {@link #isSoundEffectsEnabled()} is true.
15921      *
15922      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
15923      */
15924     public void playSoundEffect(int soundConstant) {
15925         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
15926             return;
15927         }
15928         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
15929     }
15930 
15931     /**
15932      * BZZZTT!!1!
15933      *
15934      * <p>Provide haptic feedback to the user for this view.
15935      *
15936      * <p>The framework will provide haptic feedback for some built in actions,
15937      * such as long presses, but you may wish to provide feedback for your
15938      * own widget.
15939      *
15940      * <p>The feedback will only be performed if
15941      * {@link #isHapticFeedbackEnabled()} is true.
15942      *
15943      * @param feedbackConstant One of the constants defined in
15944      * {@link HapticFeedbackConstants}
15945      */
15946     public boolean performHapticFeedback(int feedbackConstant) {
15947         return performHapticFeedback(feedbackConstant, 0);
15948     }
15949 
15950     /**
15951      * BZZZTT!!1!
15952      *
15953      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
15954      *
15955      * @param feedbackConstant One of the constants defined in
15956      * {@link HapticFeedbackConstants}
15957      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
15958      */
15959     public boolean performHapticFeedback(int feedbackConstant, int flags) {
15960         if (mAttachInfo == null) {
15961             return false;
15962         }
15963         //noinspection SimplifiableIfStatement
15964         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
15965                 && !isHapticFeedbackEnabled()) {
15966             return false;
15967         }
15968         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
15969                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
15970     }
15971 
15972     /**
15973      * Request that the visibility of the status bar or other screen/window
15974      * decorations be changed.
15975      *
15976      * <p>This method is used to put the over device UI into temporary modes
15977      * where the user's attention is focused more on the application content,
15978      * by dimming or hiding surrounding system affordances.  This is typically
15979      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
15980      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
15981      * to be placed behind the action bar (and with these flags other system
15982      * affordances) so that smooth transitions between hiding and showing them
15983      * can be done.
15984      *
15985      * <p>Two representative examples of the use of system UI visibility is
15986      * implementing a content browsing application (like a magazine reader)
15987      * and a video playing application.
15988      *
15989      * <p>The first code shows a typical implementation of a View in a content
15990      * browsing application.  In this implementation, the application goes
15991      * into a content-oriented mode by hiding the status bar and action bar,
15992      * and putting the navigation elements into lights out mode.  The user can
15993      * then interact with content while in this mode.  Such an application should
15994      * provide an easy way for the user to toggle out of the mode (such as to
15995      * check information in the status bar or access notifications).  In the
15996      * implementation here, this is done simply by tapping on the content.
15997      *
15998      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
15999      *      content}
16000      *
16001      * <p>This second code sample shows a typical implementation of a View
16002      * in a video playing application.  In this situation, while the video is
16003      * playing the application would like to go into a complete full-screen mode,
16004      * to use as much of the display as possible for the video.  When in this state
16005      * the user can not interact with the application; the system intercepts
16006      * touching on the screen to pop the UI out of full screen mode.  See
16007      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
16008      *
16009      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
16010      *      content}
16011      *
16012      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
16013      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
16014      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
16015      * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
16016      */
16017     public void setSystemUiVisibility(int visibility) {
16018         if (visibility != mSystemUiVisibility) {
16019             mSystemUiVisibility = visibility;
16020             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
16021                 mParent.recomputeViewAttributes(this);
16022             }
16023         }
16024     }
16025 
16026     /**
16027      * Returns the last {@link #setSystemUiVisibility(int) that this view has requested.
16028      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
16029      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
16030      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
16031      * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
16032      */
16033     public int getSystemUiVisibility() {
16034         return mSystemUiVisibility;
16035     }
16036 
16037     /**
16038      * Returns the current system UI visibility that is currently set for
16039      * the entire window.  This is the combination of the
16040      * {@link #setSystemUiVisibility(int)} values supplied by all of the
16041      * views in the window.
16042      */
16043     public int getWindowSystemUiVisibility() {
16044         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
16045     }
16046 
16047     /**
16048      * Override to find out when the window's requested system UI visibility
16049      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
16050      * This is different from the callbacks recieved through
16051      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
16052      * in that this is only telling you about the local request of the window,
16053      * not the actual values applied by the system.
16054      */
16055     public void onWindowSystemUiVisibilityChanged(int visible) {
16056     }
16057 
16058     /**
16059      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
16060      * the view hierarchy.
16061      */
16062     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
16063         onWindowSystemUiVisibilityChanged(visible);
16064     }
16065 
16066     /**
16067      * Set a listener to receive callbacks when the visibility of the system bar changes.
16068      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
16069      */
16070     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
16071         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
16072         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
16073             mParent.recomputeViewAttributes(this);
16074         }
16075     }
16076 
16077     /**
16078      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
16079      * the view hierarchy.
16080      */
16081     public void dispatchSystemUiVisibilityChanged(int visibility) {
16082         ListenerInfo li = mListenerInfo;
16083         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
16084             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
16085                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
16086         }
16087     }
16088 
16089     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
16090         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
16091         if (val != mSystemUiVisibility) {
16092             setSystemUiVisibility(val);
16093             return true;
16094         }
16095         return false;
16096     }
16097 
16098     /** @hide */
16099     public void setDisabledSystemUiVisibility(int flags) {
16100         if (mAttachInfo != null) {
16101             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
16102                 mAttachInfo.mDisabledSystemUiVisibility = flags;
16103                 if (mParent != null) {
16104                     mParent.recomputeViewAttributes(this);
16105                 }
16106             }
16107         }
16108     }
16109 
16110     /**
16111      * Creates an image that the system displays during the drag and drop
16112      * operation. This is called a &quot;drag shadow&quot;. The default implementation
16113      * for a DragShadowBuilder based on a View returns an image that has exactly the same
16114      * appearance as the given View. The default also positions the center of the drag shadow
16115      * directly under the touch point. If no View is provided (the constructor with no parameters
16116      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
16117      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
16118      * default is an invisible drag shadow.
16119      * <p>
16120      * You are not required to use the View you provide to the constructor as the basis of the
16121      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
16122      * anything you want as the drag shadow.
16123      * </p>
16124      * <p>
16125      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
16126      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
16127      *  size and position of the drag shadow. It uses this data to construct a
16128      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
16129      *  so that your application can draw the shadow image in the Canvas.
16130      * </p>
16131      *
16132      * <div class="special reference">
16133      * <h3>Developer Guides</h3>
16134      * <p>For a guide to implementing drag and drop features, read the
16135      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
16136      * </div>
16137      */
16138     public static class DragShadowBuilder {
16139         private final WeakReference<View> mView;
16140 
16141         /**
16142          * Constructs a shadow image builder based on a View. By default, the resulting drag
16143          * shadow will have the same appearance and dimensions as the View, with the touch point
16144          * over the center of the View.
16145          * @param view A View. Any View in scope can be used.
16146          */
16147         public DragShadowBuilder(View view) {
16148             mView = new WeakReference<View>(view);
16149         }
16150 
16151         /**
16152          * Construct a shadow builder object with no associated View.  This
16153          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
16154          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
16155          * to supply the drag shadow's dimensions and appearance without
16156          * reference to any View object. If they are not overridden, then the result is an
16157          * invisible drag shadow.
16158          */
16159         public DragShadowBuilder() {
16160             mView = new WeakReference<View>(null);
16161         }
16162 
16163         /**
16164          * Returns the View object that had been passed to the
16165          * {@link #View.DragShadowBuilder(View)}
16166          * constructor.  If that View parameter was {@code null} or if the
16167          * {@link #View.DragShadowBuilder()}
16168          * constructor was used to instantiate the builder object, this method will return
16169          * null.
16170          *
16171          * @return The View object associate with this builder object.
16172          */
16173         @SuppressWarnings({"JavadocReference"})
16174         final public View getView() {
16175             return mView.get();
16176         }
16177 
16178         /**
16179          * Provides the metrics for the shadow image. These include the dimensions of
16180          * the shadow image, and the point within that shadow that should
16181          * be centered under the touch location while dragging.
16182          * <p>
16183          * The default implementation sets the dimensions of the shadow to be the
16184          * same as the dimensions of the View itself and centers the shadow under
16185          * the touch point.
16186          * </p>
16187          *
16188          * @param shadowSize A {@link android.graphics.Point} containing the width and height
16189          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
16190          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
16191          * image.
16192          *
16193          * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
16194          * shadow image that should be underneath the touch point during the drag and drop
16195          * operation. Your application must set {@link android.graphics.Point#x} to the
16196          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
16197          */
16198         public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
16199             final View view = mView.get();
16200             if (view != null) {
16201                 shadowSize.set(view.getWidth(), view.getHeight());
16202                 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
16203             } else {
16204                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
16205             }
16206         }
16207 
16208         /**
16209          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
16210          * based on the dimensions it received from the
16211          * {@link #onProvideShadowMetrics(Point, Point)} callback.
16212          *
16213          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
16214          */
16215         public void onDrawShadow(Canvas canvas) {
16216             final View view = mView.get();
16217             if (view != null) {
16218                 view.draw(canvas);
16219             } else {
16220                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
16221             }
16222         }
16223     }
16224 
16225     /**
16226      * Starts a drag and drop operation. When your application calls this method, it passes a
16227      * {@link android.view.View.DragShadowBuilder} object to the system. The
16228      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
16229      * to get metrics for the drag shadow, and then calls the object's
16230      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
16231      * <p>
16232      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
16233      *  drag events to all the View objects in your application that are currently visible. It does
16234      *  this either by calling the View object's drag listener (an implementation of
16235      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
16236      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
16237      *  Both are passed a {@link android.view.DragEvent} object that has a
16238      *  {@link android.view.DragEvent#getAction()} value of
16239      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
16240      * </p>
16241      * <p>
16242      * Your application can invoke startDrag() on any attached View object. The View object does not
16243      * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
16244      * be related to the View the user selected for dragging.
16245      * </p>
16246      * @param data A {@link android.content.ClipData} object pointing to the data to be
16247      * transferred by the drag and drop operation.
16248      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
16249      * drag shadow.
16250      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
16251      * drop operation. This Object is put into every DragEvent object sent by the system during the
16252      * current drag.
16253      * <p>
16254      * myLocalState is a lightweight mechanism for the sending information from the dragged View
16255      * to the target Views. For example, it can contain flags that differentiate between a
16256      * a copy operation and a move operation.
16257      * </p>
16258      * @param flags Flags that control the drag and drop operation. No flags are currently defined,
16259      * so the parameter should be set to 0.
16260      * @return {@code true} if the method completes successfully, or
16261      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
16262      * do a drag, and so no drag operation is in progress.
16263      */
16264     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
16265             Object myLocalState, int flags) {
16266         if (ViewDebug.DEBUG_DRAG) {
16267             Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
16268         }
16269         boolean okay = false;
16270 
16271         Point shadowSize = new Point();
16272         Point shadowTouchPoint = new Point();
16273         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
16274 
16275         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
16276                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
16277             throw new IllegalStateException("Drag shadow dimensions must not be negative");
16278         }
16279 
16280         if (ViewDebug.DEBUG_DRAG) {
16281             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
16282                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
16283         }
16284         Surface surface = new Surface();
16285         try {
16286             IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
16287                     flags, shadowSize.x, shadowSize.y, surface);
16288             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
16289                     + " surface=" + surface);
16290             if (token != null) {
16291                 Canvas canvas = surface.lockCanvas(null);
16292                 try {
16293                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
16294                     shadowBuilder.onDrawShadow(canvas);
16295                 } finally {
16296                     surface.unlockCanvasAndPost(canvas);
16297                 }
16298 
16299                 final ViewRootImpl root = getViewRootImpl();
16300 
16301                 // Cache the local state object for delivery with DragEvents
16302                 root.setLocalDragState(myLocalState);
16303 
16304                 // repurpose 'shadowSize' for the last touch point
16305                 root.getLastTouchPoint(shadowSize);
16306 
16307                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
16308                         shadowSize.x, shadowSize.y,
16309                         shadowTouchPoint.x, shadowTouchPoint.y, data);
16310                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
16311 
16312                 // Off and running!  Release our local surface instance; the drag
16313                 // shadow surface is now managed by the system process.
16314                 surface.release();
16315             }
16316         } catch (Exception e) {
16317             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
16318             surface.destroy();
16319         }
16320 
16321         return okay;
16322     }
16323 
16324     /**
16325      * Handles drag events sent by the system following a call to
16326      * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
16327      *<p>
16328      * When the system calls this method, it passes a
16329      * {@link android.view.DragEvent} object. A call to
16330      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
16331      * in DragEvent. The method uses these to determine what is happening in the drag and drop
16332      * operation.
16333      * @param event The {@link android.view.DragEvent} sent by the system.
16334      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
16335      * in DragEvent, indicating the type of drag event represented by this object.
16336      * @return {@code true} if the method was successful, otherwise {@code false}.
16337      * <p>
16338      *  The method should return {@code true} in response to an action type of
16339      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
16340      *  operation.
16341      * </p>
16342      * <p>
16343      *  The method should also return {@code true} in response to an action type of
16344      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
16345      *  {@code false} if it didn't.
16346      * </p>
16347      */
16348     public boolean onDragEvent(DragEvent event) {
16349         return false;
16350     }
16351 
16352     /**
16353      * Detects if this View is enabled and has a drag event listener.
16354      * If both are true, then it calls the drag event listener with the
16355      * {@link android.view.DragEvent} it received. If the drag event listener returns
16356      * {@code true}, then dispatchDragEvent() returns {@code true}.
16357      * <p>
16358      * For all other cases, the method calls the
16359      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
16360      * method and returns its result.
16361      * </p>
16362      * <p>
16363      * This ensures that a drag event is always consumed, even if the View does not have a drag
16364      * event listener. However, if the View has a listener and the listener returns true, then
16365      * onDragEvent() is not called.
16366      * </p>
16367      */
16368     public boolean dispatchDragEvent(DragEvent event) {
16369         //noinspection SimplifiableIfStatement
16370         ListenerInfo li = mListenerInfo;
16371         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
16372                 && li.mOnDragListener.onDrag(this, event)) {
16373             return true;
16374         }
16375         return onDragEvent(event);
16376     }
16377 
16378     boolean canAcceptDrag() {
16379         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
16380     }
16381 
16382     /**
16383      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
16384      * it is ever exposed at all.
16385      * @hide
16386      */
16387     public void onCloseSystemDialogs(String reason) {
16388     }
16389 
16390     /**
16391      * Given a Drawable whose bounds have been set to draw into this view,
16392      * update a Region being computed for
16393      * {@link #gatherTransparentRegion(android.graphics.Region)} so
16394      * that any non-transparent parts of the Drawable are removed from the
16395      * given transparent region.
16396      *
16397      * @param dr The Drawable whose transparency is to be applied to the region.
16398      * @param region A Region holding the current transparency information,
16399      * where any parts of the region that are set are considered to be
16400      * transparent.  On return, this region will be modified to have the
16401      * transparency information reduced by the corresponding parts of the
16402      * Drawable that are not transparent.
16403      * {@hide}
16404      */
16405     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
16406         if (DBG) {
16407             Log.i("View", "Getting transparent region for: " + this);
16408         }
16409         final Region r = dr.getTransparentRegion();
16410         final Rect db = dr.getBounds();
16411         final AttachInfo attachInfo = mAttachInfo;
16412         if (r != null && attachInfo != null) {
16413             final int w = getRight()-getLeft();
16414             final int h = getBottom()-getTop();
16415             if (db.left > 0) {
16416                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
16417                 r.op(0, 0, db.left, h, Region.Op.UNION);
16418             }
16419             if (db.right < w) {
16420                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
16421                 r.op(db.right, 0, w, h, Region.Op.UNION);
16422             }
16423             if (db.top > 0) {
16424                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
16425                 r.op(0, 0, w, db.top, Region.Op.UNION);
16426             }
16427             if (db.bottom < h) {
16428                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
16429                 r.op(0, db.bottom, w, h, Region.Op.UNION);
16430             }
16431             final int[] location = attachInfo.mTransparentLocation;
16432             getLocationInWindow(location);
16433             r.translate(location[0], location[1]);
16434             region.op(r, Region.Op.INTERSECT);
16435         } else {
16436             region.op(db, Region.Op.DIFFERENCE);
16437         }
16438     }
16439 
16440     private void checkForLongClick(int delayOffset) {
16441         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
16442             mHasPerformedLongPress = false;
16443 
16444             if (mPendingCheckForLongPress == null) {
16445                 mPendingCheckForLongPress = new CheckForLongPress();
16446             }
16447             mPendingCheckForLongPress.rememberWindowAttachCount();
16448             postDelayed(mPendingCheckForLongPress,
16449                     ViewConfiguration.getLongPressTimeout() - delayOffset);
16450         }
16451     }
16452 
16453     /**
16454      * Inflate a view from an XML resource.  This convenience method wraps the {@link
16455      * LayoutInflater} class, which provides a full range of options for view inflation.
16456      *
16457      * @param context The Context object for your activity or application.
16458      * @param resource The resource ID to inflate
16459      * @param root A view group that will be the parent.  Used to properly inflate the
16460      * layout_* parameters.
16461      * @see LayoutInflater
16462      */
16463     public static View inflate(Context context, int resource, ViewGroup root) {
16464         LayoutInflater factory = LayoutInflater.from(context);
16465         return factory.inflate(resource, root);
16466     }
16467 
16468     /**
16469      * Scroll the view with standard behavior for scrolling beyond the normal
16470      * content boundaries. Views that call this method should override
16471      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
16472      * results of an over-scroll operation.
16473      *
16474      * Views can use this method to handle any touch or fling-based scrolling.
16475      *
16476      * @param deltaX Change in X in pixels
16477      * @param deltaY Change in Y in pixels
16478      * @param scrollX Current X scroll value in pixels before applying deltaX
16479      * @param scrollY Current Y scroll value in pixels before applying deltaY
16480      * @param scrollRangeX Maximum content scroll range along the X axis
16481      * @param scrollRangeY Maximum content scroll range along the Y axis
16482      * @param maxOverScrollX Number of pixels to overscroll by in either direction
16483      *          along the X axis.
16484      * @param maxOverScrollY Number of pixels to overscroll by in either direction
16485      *          along the Y axis.
16486      * @param isTouchEvent true if this scroll operation is the result of a touch event.
16487      * @return true if scrolling was clamped to an over-scroll boundary along either
16488      *          axis, false otherwise.
16489      */
16490     @SuppressWarnings({"UnusedParameters"})
16491     protected boolean overScrollBy(int deltaX, int deltaY,
16492             int scrollX, int scrollY,
16493             int scrollRangeX, int scrollRangeY,
16494             int maxOverScrollX, int maxOverScrollY,
16495             boolean isTouchEvent) {
16496         final int overScrollMode = mOverScrollMode;
16497         final boolean canScrollHorizontal =
16498                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
16499         final boolean canScrollVertical =
16500                 computeVerticalScrollRange() > computeVerticalScrollExtent();
16501         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
16502                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
16503         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
16504                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
16505 
16506         int newScrollX = scrollX + deltaX;
16507         if (!overScrollHorizontal) {
16508             maxOverScrollX = 0;
16509         }
16510 
16511         int newScrollY = scrollY + deltaY;
16512         if (!overScrollVertical) {
16513             maxOverScrollY = 0;
16514         }
16515 
16516         // Clamp values if at the limits and record
16517         final int left = -maxOverScrollX;
16518         final int right = maxOverScrollX + scrollRangeX;
16519         final int top = -maxOverScrollY;
16520         final int bottom = maxOverScrollY + scrollRangeY;
16521 
16522         boolean clampedX = false;
16523         if (newScrollX > right) {
16524             newScrollX = right;
16525             clampedX = true;
16526         } else if (newScrollX < left) {
16527             newScrollX = left;
16528             clampedX = true;
16529         }
16530 
16531         boolean clampedY = false;
16532         if (newScrollY > bottom) {
16533             newScrollY = bottom;
16534             clampedY = true;
16535         } else if (newScrollY < top) {
16536             newScrollY = top;
16537             clampedY = true;
16538         }
16539 
16540         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
16541 
16542         return clampedX || clampedY;
16543     }
16544 
16545     /**
16546      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
16547      * respond to the results of an over-scroll operation.
16548      *
16549      * @param scrollX New X scroll value in pixels
16550      * @param scrollY New Y scroll value in pixels
16551      * @param clampedX True if scrollX was clamped to an over-scroll boundary
16552      * @param clampedY True if scrollY was clamped to an over-scroll boundary
16553      */
16554     protected void onOverScrolled(int scrollX, int scrollY,
16555             boolean clampedX, boolean clampedY) {
16556         // Intentionally empty.
16557     }
16558 
16559     /**
16560      * Returns the over-scroll mode for this view. The result will be
16561      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16562      * (allow over-scrolling only if the view content is larger than the container),
16563      * or {@link #OVER_SCROLL_NEVER}.
16564      *
16565      * @return This view's over-scroll mode.
16566      */
16567     public int getOverScrollMode() {
16568         return mOverScrollMode;
16569     }
16570 
16571     /**
16572      * Set the over-scroll mode for this view. Valid over-scroll modes are
16573      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16574      * (allow over-scrolling only if the view content is larger than the container),
16575      * or {@link #OVER_SCROLL_NEVER}.
16576      *
16577      * Setting the over-scroll mode of a view will have an effect only if the
16578      * view is capable of scrolling.
16579      *
16580      * @param overScrollMode The new over-scroll mode for this view.
16581      */
16582     public void setOverScrollMode(int overScrollMode) {
16583         if (overScrollMode != OVER_SCROLL_ALWAYS &&
16584                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
16585                 overScrollMode != OVER_SCROLL_NEVER) {
16586             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
16587         }
16588         mOverScrollMode = overScrollMode;
16589     }
16590 
16591     /**
16592      * Gets a scale factor that determines the distance the view should scroll
16593      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
16594      * @return The vertical scroll scale factor.
16595      * @hide
16596      */
16597     protected float getVerticalScrollFactor() {
16598         if (mVerticalScrollFactor == 0) {
16599             TypedValue outValue = new TypedValue();
16600             if (!mContext.getTheme().resolveAttribute(
16601                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
16602                 throw new IllegalStateException(
16603                         "Expected theme to define listPreferredItemHeight.");
16604             }
16605             mVerticalScrollFactor = outValue.getDimension(
16606                     mContext.getResources().getDisplayMetrics());
16607         }
16608         return mVerticalScrollFactor;
16609     }
16610 
16611     /**
16612      * Gets a scale factor that determines the distance the view should scroll
16613      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
16614      * @return The horizontal scroll scale factor.
16615      * @hide
16616      */
16617     protected float getHorizontalScrollFactor() {
16618         // TODO: Should use something else.
16619         return getVerticalScrollFactor();
16620     }
16621 
16622     /**
16623      * Return the value specifying the text direction or policy that was set with
16624      * {@link #setTextDirection(int)}.
16625      *
16626      * @return the defined text direction. It can be one of:
16627      *
16628      * {@link #TEXT_DIRECTION_INHERIT},
16629      * {@link #TEXT_DIRECTION_FIRST_STRONG}
16630      * {@link #TEXT_DIRECTION_ANY_RTL},
16631      * {@link #TEXT_DIRECTION_LTR},
16632      * {@link #TEXT_DIRECTION_RTL},
16633      * {@link #TEXT_DIRECTION_LOCALE}
16634      *
16635      * @attr ref android.R.styleable#View_textDirection
16636      *
16637      * @hide
16638      */
16639     @ViewDebug.ExportedProperty(category = "text", mapping = {
16640             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
16641             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
16642             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
16643             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
16644             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
16645             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
16646     })
16647     public int getRawTextDirection() {
16648         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
16649     }
16650 
16651     /**
16652      * Set the text direction.
16653      *
16654      * @param textDirection the direction to set. Should be one of:
16655      *
16656      * {@link #TEXT_DIRECTION_INHERIT},
16657      * {@link #TEXT_DIRECTION_FIRST_STRONG}
16658      * {@link #TEXT_DIRECTION_ANY_RTL},
16659      * {@link #TEXT_DIRECTION_LTR},
16660      * {@link #TEXT_DIRECTION_RTL},
16661      * {@link #TEXT_DIRECTION_LOCALE}
16662      *
16663      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
16664      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
16665      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
16666      *
16667      * @attr ref android.R.styleable#View_textDirection
16668      */
16669     public void setTextDirection(int textDirection) {
16670         if (getRawTextDirection() != textDirection) {
16671             // Reset the current text direction and the resolved one
16672             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
16673             resetResolvedTextDirection();
16674             // Set the new text direction
16675             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
16676             // Do resolution
16677             resolveTextDirection();
16678             // Notify change
16679             onRtlPropertiesChanged(getLayoutDirection());
16680             // Refresh
16681             requestLayout();
16682             invalidate(true);
16683         }
16684     }
16685 
16686     /**
16687      * Return the resolved text direction.
16688      *
16689      * @return the resolved text direction. Returns one of:
16690      *
16691      * {@link #TEXT_DIRECTION_FIRST_STRONG}
16692      * {@link #TEXT_DIRECTION_ANY_RTL},
16693      * {@link #TEXT_DIRECTION_LTR},
16694      * {@link #TEXT_DIRECTION_RTL},
16695      * {@link #TEXT_DIRECTION_LOCALE}
16696      *
16697      * @attr ref android.R.styleable#View_textDirection
16698      */
16699     public int getTextDirection() {
16700         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
16701     }
16702 
16703     /**
16704      * Resolve the text direction.
16705      *
16706      * @return true if resolution has been done, false otherwise.
16707      *
16708      * @hide
16709      */
16710     public boolean resolveTextDirection() {
16711         // Reset any previous text direction resolution
16712         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
16713 
16714         if (hasRtlSupport()) {
16715             // Set resolved text direction flag depending on text direction flag
16716             final int textDirection = getRawTextDirection();
16717             switch(textDirection) {
16718                 case TEXT_DIRECTION_INHERIT:
16719                     if (!canResolveTextDirection()) {
16720                         // We cannot do the resolution if there is no parent, so use the default one
16721                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16722                         // Resolution will need to happen again later
16723                         return false;
16724                     }
16725 
16726                     View parent = ((View) mParent);
16727                     // Parent has not yet resolved, so we still return the default
16728                     if (!parent.isTextDirectionResolved()) {
16729                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16730                         // Resolution will need to happen again later
16731                         return false;
16732                     }
16733 
16734                     // Set current resolved direction to the same value as the parent's one
16735                     final int parentResolvedDirection = parent.getTextDirection();
16736                     switch (parentResolvedDirection) {
16737                         case TEXT_DIRECTION_FIRST_STRONG:
16738                         case TEXT_DIRECTION_ANY_RTL:
16739                         case TEXT_DIRECTION_LTR:
16740                         case TEXT_DIRECTION_RTL:
16741                         case TEXT_DIRECTION_LOCALE:
16742                             mPrivateFlags2 |=
16743                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
16744                             break;
16745                         default:
16746                             // Default resolved direction is "first strong" heuristic
16747                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16748                     }
16749                     break;
16750                 case TEXT_DIRECTION_FIRST_STRONG:
16751                 case TEXT_DIRECTION_ANY_RTL:
16752                 case TEXT_DIRECTION_LTR:
16753                 case TEXT_DIRECTION_RTL:
16754                 case TEXT_DIRECTION_LOCALE:
16755                     // Resolved direction is the same as text direction
16756                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
16757                     break;
16758                 default:
16759                     // Default resolved direction is "first strong" heuristic
16760                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16761             }
16762         } else {
16763             // Default resolved direction is "first strong" heuristic
16764             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16765         }
16766 
16767         // Set to resolved
16768         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
16769         return true;
16770     }
16771 
16772     /**
16773      * Check if text direction resolution can be done.
16774      *
16775      * @return true if text direction resolution can be done otherwise return false.
16776      */
16777     private boolean canResolveTextDirection() {
16778         switch (getRawTextDirection()) {
16779             case TEXT_DIRECTION_INHERIT:
16780                 return (mParent != null) && (mParent instanceof View) &&
16781                        ((View) mParent).canResolveTextDirection();
16782             default:
16783                 return true;
16784         }
16785     }
16786 
16787     /**
16788      * Reset resolved text direction. Text direction will be resolved during a call to
16789      * {@link #onMeasure(int, int)}.
16790      *
16791      * @hide
16792      */
16793     public void resetResolvedTextDirection() {
16794         // Reset any previous text direction resolution
16795         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
16796         // Set to default value
16797         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16798     }
16799 
16800     /**
16801      * @return true if text direction is inherited.
16802      *
16803      * @hide
16804      */
16805     public boolean isTextDirectionInherited() {
16806         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
16807     }
16808 
16809     /**
16810      * @return true if text direction is resolved.
16811      */
16812     private boolean isTextDirectionResolved() {
16813         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
16814     }
16815 
16816     /**
16817      * Return the value specifying the text alignment or policy that was set with
16818      * {@link #setTextAlignment(int)}.
16819      *
16820      * @return the defined text alignment. It can be one of:
16821      *
16822      * {@link #TEXT_ALIGNMENT_INHERIT},
16823      * {@link #TEXT_ALIGNMENT_GRAVITY},
16824      * {@link #TEXT_ALIGNMENT_CENTER},
16825      * {@link #TEXT_ALIGNMENT_TEXT_START},
16826      * {@link #TEXT_ALIGNMENT_TEXT_END},
16827      * {@link #TEXT_ALIGNMENT_VIEW_START},
16828      * {@link #TEXT_ALIGNMENT_VIEW_END}
16829      *
16830      * @attr ref android.R.styleable#View_textAlignment
16831      *
16832      * @hide
16833      */
16834     @ViewDebug.ExportedProperty(category = "text", mapping = {
16835             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
16836             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
16837             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
16838             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
16839             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
16840             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
16841             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
16842     })
16843     public int getRawTextAlignment() {
16844         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
16845     }
16846 
16847     /**
16848      * Set the text alignment.
16849      *
16850      * @param textAlignment The text alignment to set. Should be one of
16851      *
16852      * {@link #TEXT_ALIGNMENT_INHERIT},
16853      * {@link #TEXT_ALIGNMENT_GRAVITY},
16854      * {@link #TEXT_ALIGNMENT_CENTER},
16855      * {@link #TEXT_ALIGNMENT_TEXT_START},
16856      * {@link #TEXT_ALIGNMENT_TEXT_END},
16857      * {@link #TEXT_ALIGNMENT_VIEW_START},
16858      * {@link #TEXT_ALIGNMENT_VIEW_END}
16859      *
16860      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
16861      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
16862      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
16863      *
16864      * @attr ref android.R.styleable#View_textAlignment
16865      */
16866     public void setTextAlignment(int textAlignment) {
16867         if (textAlignment != getRawTextAlignment()) {
16868             // Reset the current and resolved text alignment
16869             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
16870             resetResolvedTextAlignment();
16871             // Set the new text alignment
16872             mPrivateFlags2 |=
16873                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
16874             // Do resolution
16875             resolveTextAlignment();
16876             // Notify change
16877             onRtlPropertiesChanged(getLayoutDirection());
16878             // Refresh
16879             requestLayout();
16880             invalidate(true);
16881         }
16882     }
16883 
16884     /**
16885      * Return the resolved text alignment.
16886      *
16887      * @return the resolved text alignment. Returns one of:
16888      *
16889      * {@link #TEXT_ALIGNMENT_GRAVITY},
16890      * {@link #TEXT_ALIGNMENT_CENTER},
16891      * {@link #TEXT_ALIGNMENT_TEXT_START},
16892      * {@link #TEXT_ALIGNMENT_TEXT_END},
16893      * {@link #TEXT_ALIGNMENT_VIEW_START},
16894      * {@link #TEXT_ALIGNMENT_VIEW_END}
16895      *
16896      * @attr ref android.R.styleable#View_textAlignment
16897      */
16898     @ViewDebug.ExportedProperty(category = "text", mapping = {
16899             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
16900             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
16901             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
16902             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
16903             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
16904             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
16905             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
16906     })
16907     public int getTextAlignment() {
16908         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
16909                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
16910     }
16911 
16912     /**
16913      * Resolve the text alignment.
16914      *
16915      * @return true if resolution has been done, false otherwise.
16916      *
16917      * @hide
16918      */
16919     public boolean resolveTextAlignment() {
16920         // Reset any previous text alignment resolution
16921         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
16922 
16923         if (hasRtlSupport()) {
16924             // Set resolved text alignment flag depending on text alignment flag
16925             final int textAlignment = getRawTextAlignment();
16926             switch (textAlignment) {
16927                 case TEXT_ALIGNMENT_INHERIT:
16928                     // Check if we can resolve the text alignment
16929                     if (!canResolveTextAlignment()) {
16930                         // We cannot do the resolution if there is no parent so use the default
16931                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16932                         // Resolution will need to happen again later
16933                         return false;
16934                     }
16935                     View parent = (View) mParent;
16936 
16937                     // Parent has not yet resolved, so we still return the default
16938                     if (!parent.isTextAlignmentResolved()) {
16939                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16940                         // Resolution will need to happen again later
16941                         return false;
16942                     }
16943 
16944                     final int parentResolvedTextAlignment = parent.getTextAlignment();
16945                     switch (parentResolvedTextAlignment) {
16946                         case TEXT_ALIGNMENT_GRAVITY:
16947                         case TEXT_ALIGNMENT_TEXT_START:
16948                         case TEXT_ALIGNMENT_TEXT_END:
16949                         case TEXT_ALIGNMENT_CENTER:
16950                         case TEXT_ALIGNMENT_VIEW_START:
16951                         case TEXT_ALIGNMENT_VIEW_END:
16952                             // Resolved text alignment is the same as the parent resolved
16953                             // text alignment
16954                             mPrivateFlags2 |=
16955                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
16956                             break;
16957                         default:
16958                             // Use default resolved text alignment
16959                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16960                     }
16961                     break;
16962                 case TEXT_ALIGNMENT_GRAVITY:
16963                 case TEXT_ALIGNMENT_TEXT_START:
16964                 case TEXT_ALIGNMENT_TEXT_END:
16965                 case TEXT_ALIGNMENT_CENTER:
16966                 case TEXT_ALIGNMENT_VIEW_START:
16967                 case TEXT_ALIGNMENT_VIEW_END:
16968                     // Resolved text alignment is the same as text alignment
16969                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
16970                     break;
16971                 default:
16972                     // Use default resolved text alignment
16973                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16974             }
16975         } else {
16976             // Use default resolved text alignment
16977             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16978         }
16979 
16980         // Set the resolved
16981         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
16982         return true;
16983     }
16984 
16985     /**
16986      * Check if text alignment resolution can be done.
16987      *
16988      * @return true if text alignment resolution can be done otherwise return false.
16989      */
16990     private boolean canResolveTextAlignment() {
16991         switch (getRawTextAlignment()) {
16992             case TEXT_DIRECTION_INHERIT:
16993                 return (mParent != null) && (mParent instanceof View) &&
16994                        ((View) mParent).canResolveTextAlignment();
16995             default:
16996                 return true;
16997         }
16998     }
16999 
17000     /**
17001      * Reset resolved text alignment. Text alignment will be resolved during a call to
17002      * {@link #onMeasure(int, int)}.
17003      *
17004      * @hide
17005      */
17006     public void resetResolvedTextAlignment() {
17007         // Reset any previous text alignment resolution
17008         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
17009         // Set to default
17010         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17011     }
17012 
17013     /**
17014      * @return true if text alignment is inherited.
17015      *
17016      * @hide
17017      */
17018     public boolean isTextAlignmentInherited() {
17019         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
17020     }
17021 
17022     /**
17023      * @return true if text alignment is resolved.
17024      */
17025     private boolean isTextAlignmentResolved() {
17026         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
17027     }
17028 
17029     /**
17030      * Generate a value suitable for use in {@link #setId(int)}.
17031      * This value will not collide with ID values generated at build time by aapt for R.id.
17032      *
17033      * @return a generated ID value
17034      */
17035     public static int generateViewId() {
17036         for (;;) {
17037             final int result = sNextGeneratedId.get();
17038             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
17039             int newValue = result + 1;
17040             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
17041             if (sNextGeneratedId.compareAndSet(result, newValue)) {
17042                 return result;
17043             }
17044         }
17045     }
17046 
17047     //
17048     // Properties
17049     //
17050     /**
17051      * A Property wrapper around the <code>alpha</code> functionality handled by the
17052      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
17053      */
17054     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
17055         @Override
17056         public void setValue(View object, float value) {
17057             object.setAlpha(value);
17058         }
17059 
17060         @Override
17061         public Float get(View object) {
17062             return object.getAlpha();
17063         }
17064     };
17065 
17066     /**
17067      * A Property wrapper around the <code>translationX</code> functionality handled by the
17068      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
17069      */
17070     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
17071         @Override
17072         public void setValue(View object, float value) {
17073             object.setTranslationX(value);
17074         }
17075 
17076                 @Override
17077         public Float get(View object) {
17078             return object.getTranslationX();
17079         }
17080     };
17081 
17082     /**
17083      * A Property wrapper around the <code>translationY</code> functionality handled by the
17084      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
17085      */
17086     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
17087         @Override
17088         public void setValue(View object, float value) {
17089             object.setTranslationY(value);
17090         }
17091 
17092         @Override
17093         public Float get(View object) {
17094             return object.getTranslationY();
17095         }
17096     };
17097 
17098     /**
17099      * A Property wrapper around the <code>x</code> functionality handled by the
17100      * {@link View#setX(float)} and {@link View#getX()} methods.
17101      */
17102     public static final Property<View, Float> X = new FloatProperty<View>("x") {
17103         @Override
17104         public void setValue(View object, float value) {
17105             object.setX(value);
17106         }
17107 
17108         @Override
17109         public Float get(View object) {
17110             return object.getX();
17111         }
17112     };
17113 
17114     /**
17115      * A Property wrapper around the <code>y</code> functionality handled by the
17116      * {@link View#setY(float)} and {@link View#getY()} methods.
17117      */
17118     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
17119         @Override
17120         public void setValue(View object, float value) {
17121             object.setY(value);
17122         }
17123 
17124         @Override
17125         public Float get(View object) {
17126             return object.getY();
17127         }
17128     };
17129 
17130     /**
17131      * A Property wrapper around the <code>rotation</code> functionality handled by the
17132      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
17133      */
17134     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
17135         @Override
17136         public void setValue(View object, float value) {
17137             object.setRotation(value);
17138         }
17139 
17140         @Override
17141         public Float get(View object) {
17142             return object.getRotation();
17143         }
17144     };
17145 
17146     /**
17147      * A Property wrapper around the <code>rotationX</code> functionality handled by the
17148      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
17149      */
17150     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
17151         @Override
17152         public void setValue(View object, float value) {
17153             object.setRotationX(value);
17154         }
17155 
17156         @Override
17157         public Float get(View object) {
17158             return object.getRotationX();
17159         }
17160     };
17161 
17162     /**
17163      * A Property wrapper around the <code>rotationY</code> functionality handled by the
17164      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
17165      */
17166     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
17167         @Override
17168         public void setValue(View object, float value) {
17169             object.setRotationY(value);
17170         }
17171 
17172         @Override
17173         public Float get(View object) {
17174             return object.getRotationY();
17175         }
17176     };
17177 
17178     /**
17179      * A Property wrapper around the <code>scaleX</code> functionality handled by the
17180      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
17181      */
17182     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
17183         @Override
17184         public void setValue(View object, float value) {
17185             object.setScaleX(value);
17186         }
17187 
17188         @Override
17189         public Float get(View object) {
17190             return object.getScaleX();
17191         }
17192     };
17193 
17194     /**
17195      * A Property wrapper around the <code>scaleY</code> functionality handled by the
17196      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
17197      */
17198     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
17199         @Override
17200         public void setValue(View object, float value) {
17201             object.setScaleY(value);
17202         }
17203 
17204         @Override
17205         public Float get(View object) {
17206             return object.getScaleY();
17207         }
17208     };
17209 
17210     /**
17211      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
17212      * Each MeasureSpec represents a requirement for either the width or the height.
17213      * A MeasureSpec is comprised of a size and a mode. There are three possible
17214      * modes:
17215      * <dl>
17216      * <dt>UNSPECIFIED</dt>
17217      * <dd>
17218      * The parent has not imposed any constraint on the child. It can be whatever size
17219      * it wants.
17220      * </dd>
17221      *
17222      * <dt>EXACTLY</dt>
17223      * <dd>
17224      * The parent has determined an exact size for the child. The child is going to be
17225      * given those bounds regardless of how big it wants to be.
17226      * </dd>
17227      *
17228      * <dt>AT_MOST</dt>
17229      * <dd>
17230      * The child can be as large as it wants up to the specified size.
17231      * </dd>
17232      * </dl>
17233      *
17234      * MeasureSpecs are implemented as ints to reduce object allocation. This class
17235      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
17236      */
17237     public static class MeasureSpec {
17238         private static final int MODE_SHIFT = 30;
17239         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
17240 
17241         /**
17242          * Measure specification mode: The parent has not imposed any constraint
17243          * on the child. It can be whatever size it wants.
17244          */
17245         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
17246 
17247         /**
17248          * Measure specification mode: The parent has determined an exact size
17249          * for the child. The child is going to be given those bounds regardless
17250          * of how big it wants to be.
17251          */
17252         public static final int EXACTLY     = 1 << MODE_SHIFT;
17253 
17254         /**
17255          * Measure specification mode: The child can be as large as it wants up
17256          * to the specified size.
17257          */
17258         public static final int AT_MOST     = 2 << MODE_SHIFT;
17259 
17260         /**
17261          * Creates a measure specification based on the supplied size and mode.
17262          *
17263          * The mode must always be one of the following:
17264          * <ul>
17265          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
17266          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
17267          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
17268          * </ul>
17269          *
17270          * @param size the size of the measure specification
17271          * @param mode the mode of the measure specification
17272          * @return the measure specification based on size and mode
17273          */
17274         public static int makeMeasureSpec(int size, int mode) {
17275             return size + mode;
17276         }
17277 
17278         /**
17279          * Extracts the mode from the supplied measure specification.
17280          *
17281          * @param measureSpec the measure specification to extract the mode from
17282          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
17283          *         {@link android.view.View.MeasureSpec#AT_MOST} or
17284          *         {@link android.view.View.MeasureSpec#EXACTLY}
17285          */
17286         public static int getMode(int measureSpec) {
17287             return (measureSpec & MODE_MASK);
17288         }
17289 
17290         /**
17291          * Extracts the size from the supplied measure specification.
17292          *
17293          * @param measureSpec the measure specification to extract the size from
17294          * @return the size in pixels defined in the supplied measure specification
17295          */
17296         public static int getSize(int measureSpec) {
17297             return (measureSpec & ~MODE_MASK);
17298         }
17299 
17300         /**
17301          * Returns a String representation of the specified measure
17302          * specification.
17303          *
17304          * @param measureSpec the measure specification to convert to a String
17305          * @return a String with the following format: "MeasureSpec: MODE SIZE"
17306          */
17307         public static String toString(int measureSpec) {
17308             int mode = getMode(measureSpec);
17309             int size = getSize(measureSpec);
17310 
17311             StringBuilder sb = new StringBuilder("MeasureSpec: ");
17312 
17313             if (mode == UNSPECIFIED)
17314                 sb.append("UNSPECIFIED ");
17315             else if (mode == EXACTLY)
17316                 sb.append("EXACTLY ");
17317             else if (mode == AT_MOST)
17318                 sb.append("AT_MOST ");
17319             else
17320                 sb.append(mode).append(" ");
17321 
17322             sb.append(size);
17323             return sb.toString();
17324         }
17325     }
17326 
17327     class CheckForLongPress implements Runnable {
17328 
17329         private int mOriginalWindowAttachCount;
17330 
17331         public void run() {
17332             if (isPressed() && (mParent != null)
17333                     && mOriginalWindowAttachCount == mWindowAttachCount) {
17334                 if (performLongClick()) {
17335                     mHasPerformedLongPress = true;
17336                 }
17337             }
17338         }
17339 
17340         public void rememberWindowAttachCount() {
17341             mOriginalWindowAttachCount = mWindowAttachCount;
17342         }
17343     }
17344 
17345     private final class CheckForTap implements Runnable {
17346         public void run() {
17347             mPrivateFlags &= ~PFLAG_PREPRESSED;
17348             setPressed(true);
17349             checkForLongClick(ViewConfiguration.getTapTimeout());
17350         }
17351     }
17352 
17353     private final class PerformClick implements Runnable {
17354         public void run() {
17355             performClick();
17356         }
17357     }
17358 
17359     /** @hide */
17360     public void hackTurnOffWindowResizeAnim(boolean off) {
17361         mAttachInfo.mTurnOffWindowResizeAnim = off;
17362     }
17363 
17364     /**
17365      * This method returns a ViewPropertyAnimator object, which can be used to animate
17366      * specific properties on this View.
17367      *
17368      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
17369      */
17370     public ViewPropertyAnimator animate() {
17371         if (mAnimator == null) {
17372             mAnimator = new ViewPropertyAnimator(this);
17373         }
17374         return mAnimator;
17375     }
17376 
17377     /**
17378      * Interface definition for a callback to be invoked when a hardware key event is
17379      * dispatched to this view. The callback will be invoked before the key event is
17380      * given to the view. This is only useful for hardware keyboards; a software input
17381      * method has no obligation to trigger this listener.
17382      */
17383     public interface OnKeyListener {
17384         /**
17385          * Called when a hardware key is dispatched to a view. This allows listeners to
17386          * get a chance to respond before the target view.
17387          * <p>Key presses in software keyboards will generally NOT trigger this method,
17388          * although some may elect to do so in some situations. Do not assume a
17389          * software input method has to be key-based; even if it is, it may use key presses
17390          * in a different way than you expect, so there is no way to reliably catch soft
17391          * input key presses.
17392          *
17393          * @param v The view the key has been dispatched to.
17394          * @param keyCode The code for the physical key that was pressed
17395          * @param event The KeyEvent object containing full information about
17396          *        the event.
17397          * @return True if the listener has consumed the event, false otherwise.
17398          */
17399         boolean onKey(View v, int keyCode, KeyEvent event);
17400     }
17401 
17402     /**
17403      * Interface definition for a callback to be invoked when a touch event is
17404      * dispatched to this view. The callback will be invoked before the touch
17405      * event is given to the view.
17406      */
17407     public interface OnTouchListener {
17408         /**
17409          * Called when a touch event is dispatched to a view. This allows listeners to
17410          * get a chance to respond before the target view.
17411          *
17412          * @param v The view the touch event has been dispatched to.
17413          * @param event The MotionEvent object containing full information about
17414          *        the event.
17415          * @return True if the listener has consumed the event, false otherwise.
17416          */
17417         boolean onTouch(View v, MotionEvent event);
17418     }
17419 
17420     /**
17421      * Interface definition for a callback to be invoked when a hover event is
17422      * dispatched to this view. The callback will be invoked before the hover
17423      * event is given to the view.
17424      */
17425     public interface OnHoverListener {
17426         /**
17427          * Called when a hover event is dispatched to a view. This allows listeners to
17428          * get a chance to respond before the target view.
17429          *
17430          * @param v The view the hover event has been dispatched to.
17431          * @param event The MotionEvent object containing full information about
17432          *        the event.
17433          * @return True if the listener has consumed the event, false otherwise.
17434          */
17435         boolean onHover(View v, MotionEvent event);
17436     }
17437 
17438     /**
17439      * Interface definition for a callback to be invoked when a generic motion event is
17440      * dispatched to this view. The callback will be invoked before the generic motion
17441      * event is given to the view.
17442      */
17443     public interface OnGenericMotionListener {
17444         /**
17445          * Called when a generic motion event is dispatched to a view. This allows listeners to
17446          * get a chance to respond before the target view.
17447          *
17448          * @param v The view the generic motion event has been dispatched to.
17449          * @param event The MotionEvent object containing full information about
17450          *        the event.
17451          * @return True if the listener has consumed the event, false otherwise.
17452          */
17453         boolean onGenericMotion(View v, MotionEvent event);
17454     }
17455 
17456     /**
17457      * Interface definition for a callback to be invoked when a view has been clicked and held.
17458      */
17459     public interface OnLongClickListener {
17460         /**
17461          * Called when a view has been clicked and held.
17462          *
17463          * @param v The view that was clicked and held.
17464          *
17465          * @return true if the callback consumed the long click, false otherwise.
17466          */
17467         boolean onLongClick(View v);
17468     }
17469 
17470     /**
17471      * Interface definition for a callback to be invoked when a drag is being dispatched
17472      * to this view.  The callback will be invoked before the hosting view's own
17473      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
17474      * onDrag(event) behavior, it should return 'false' from this callback.
17475      *
17476      * <div class="special reference">
17477      * <h3>Developer Guides</h3>
17478      * <p>For a guide to implementing drag and drop features, read the
17479      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
17480      * </div>
17481      */
17482     public interface OnDragListener {
17483         /**
17484          * Called when a drag event is dispatched to a view. This allows listeners
17485          * to get a chance to override base View behavior.
17486          *
17487          * @param v The View that received the drag event.
17488          * @param event The {@link android.view.DragEvent} object for the drag event.
17489          * @return {@code true} if the drag event was handled successfully, or {@code false}
17490          * if the drag event was not handled. Note that {@code false} will trigger the View
17491          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
17492          */
17493         boolean onDrag(View v, DragEvent event);
17494     }
17495 
17496     /**
17497      * Interface definition for a callback to be invoked when the focus state of
17498      * a view changed.
17499      */
17500     public interface OnFocusChangeListener {
17501         /**
17502          * Called when the focus state of a view has changed.
17503          *
17504          * @param v The view whose state has changed.
17505          * @param hasFocus The new focus state of v.
17506          */
17507         void onFocusChange(View v, boolean hasFocus);
17508     }
17509 
17510     /**
17511      * Interface definition for a callback to be invoked when a view is clicked.
17512      */
17513     public interface OnClickListener {
17514         /**
17515          * Called when a view has been clicked.
17516          *
17517          * @param v The view that was clicked.
17518          */
17519         void onClick(View v);
17520     }
17521 
17522     /**
17523      * Interface definition for a callback to be invoked when the context menu
17524      * for this view is being built.
17525      */
17526     public interface OnCreateContextMenuListener {
17527         /**
17528          * Called when the context menu for this view is being built. It is not
17529          * safe to hold onto the menu after this method returns.
17530          *
17531          * @param menu The context menu that is being built
17532          * @param v The view for which the context menu is being built
17533          * @param menuInfo Extra information about the item for which the
17534          *            context menu should be shown. This information will vary
17535          *            depending on the class of v.
17536          */
17537         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
17538     }
17539 
17540     /**
17541      * Interface definition for a callback to be invoked when the status bar changes
17542      * visibility.  This reports <strong>global</strong> changes to the system UI
17543      * state, not what the application is requesting.
17544      *
17545      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
17546      */
17547     public interface OnSystemUiVisibilityChangeListener {
17548         /**
17549          * Called when the status bar changes visibility because of a call to
17550          * {@link View#setSystemUiVisibility(int)}.
17551          *
17552          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17553          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
17554          * This tells you the <strong>global</strong> state of these UI visibility
17555          * flags, not what your app is currently applying.
17556          */
17557         public void onSystemUiVisibilityChange(int visibility);
17558     }
17559 
17560     /**
17561      * Interface definition for a callback to be invoked when this view is attached
17562      * or detached from its window.
17563      */
17564     public interface OnAttachStateChangeListener {
17565         /**
17566          * Called when the view is attached to a window.
17567          * @param v The view that was attached
17568          */
17569         public void onViewAttachedToWindow(View v);
17570         /**
17571          * Called when the view is detached from a window.
17572          * @param v The view that was detached
17573          */
17574         public void onViewDetachedFromWindow(View v);
17575     }
17576 
17577     private final class UnsetPressedState implements Runnable {
17578         public void run() {
17579             setPressed(false);
17580         }
17581     }
17582 
17583     /**
17584      * Base class for derived classes that want to save and restore their own
17585      * state in {@link android.view.View#onSaveInstanceState()}.
17586      */
17587     public static class BaseSavedState extends AbsSavedState {
17588         /**
17589          * Constructor used when reading from a parcel. Reads the state of the superclass.
17590          *
17591          * @param source
17592          */
17593         public BaseSavedState(Parcel source) {
17594             super(source);
17595         }
17596 
17597         /**
17598          * Constructor called by derived classes when creating their SavedState objects
17599          *
17600          * @param superState The state of the superclass of this view
17601          */
17602         public BaseSavedState(Parcelable superState) {
17603             super(superState);
17604         }
17605 
17606         public static final Parcelable.Creator<BaseSavedState> CREATOR =
17607                 new Parcelable.Creator<BaseSavedState>() {
17608             public BaseSavedState createFromParcel(Parcel in) {
17609                 return new BaseSavedState(in);
17610             }
17611 
17612             public BaseSavedState[] newArray(int size) {
17613                 return new BaseSavedState[size];
17614             }
17615         };
17616     }
17617 
17618     /**
17619      * A set of information given to a view when it is attached to its parent
17620      * window.
17621      */
17622     static class AttachInfo {
17623         interface Callbacks {
17624             void playSoundEffect(int effectId);
17625             boolean performHapticFeedback(int effectId, boolean always);
17626         }
17627 
17628         /**
17629          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
17630          * to a Handler. This class contains the target (View) to invalidate and
17631          * the coordinates of the dirty rectangle.
17632          *
17633          * For performance purposes, this class also implements a pool of up to
17634          * POOL_LIMIT objects that get reused. This reduces memory allocations
17635          * whenever possible.
17636          */
17637         static class InvalidateInfo implements Poolable<InvalidateInfo> {
17638             private static final int POOL_LIMIT = 10;
17639             private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
17640                     Pools.finitePool(new PoolableManager<InvalidateInfo>() {
17641                         public InvalidateInfo newInstance() {
17642                             return new InvalidateInfo();
17643                         }
17644 
17645                         public void onAcquired(InvalidateInfo element) {
17646                         }
17647 
17648                         public void onReleased(InvalidateInfo element) {
17649                             element.target = null;
17650                         }
17651                     }, POOL_LIMIT)
17652             );
17653 
17654             private InvalidateInfo mNext;
17655             private boolean mIsPooled;
17656 
17657             View target;
17658 
17659             int left;
17660             int top;
17661             int right;
17662             int bottom;
17663 
17664             public void setNextPoolable(InvalidateInfo element) {
17665                 mNext = element;
17666             }
17667 
17668             public InvalidateInfo getNextPoolable() {
17669                 return mNext;
17670             }
17671 
17672             static InvalidateInfo acquire() {
17673                 return sPool.acquire();
17674             }
17675 
17676             void release() {
17677                 sPool.release(this);
17678             }
17679 
17680             public boolean isPooled() {
17681                 return mIsPooled;
17682             }
17683 
17684             public void setPooled(boolean isPooled) {
17685                 mIsPooled = isPooled;
17686             }
17687         }
17688 
17689         final IWindowSession mSession;
17690 
17691         final IWindow mWindow;
17692 
17693         final IBinder mWindowToken;
17694 
17695         final Display mDisplay;
17696 
17697         final Callbacks mRootCallbacks;
17698 
17699         HardwareCanvas mHardwareCanvas;
17700 
17701         /**
17702          * The top view of the hierarchy.
17703          */
17704         View mRootView;
17705 
17706         IBinder mPanelParentWindowToken;
17707         Surface mSurface;
17708 
17709         boolean mHardwareAccelerated;
17710         boolean mHardwareAccelerationRequested;
17711         HardwareRenderer mHardwareRenderer;
17712 
17713         boolean mScreenOn;
17714 
17715         /**
17716          * Scale factor used by the compatibility mode
17717          */
17718         float mApplicationScale;
17719 
17720         /**
17721          * Indicates whether the application is in compatibility mode
17722          */
17723         boolean mScalingRequired;
17724 
17725         /**
17726          * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
17727          */
17728         boolean mTurnOffWindowResizeAnim;
17729 
17730         /**
17731          * Left position of this view's window
17732          */
17733         int mWindowLeft;
17734 
17735         /**
17736          * Top position of this view's window
17737          */
17738         int mWindowTop;
17739 
17740         /**
17741          * Indicates whether views need to use 32-bit drawing caches
17742          */
17743         boolean mUse32BitDrawingCache;
17744 
17745         /**
17746          * For windows that are full-screen but using insets to layout inside
17747          * of the screen decorations, these are the current insets for the
17748          * content of the window.
17749          */
17750         final Rect mContentInsets = new Rect();
17751 
17752         /**
17753          * For windows that are full-screen but using insets to layout inside
17754          * of the screen decorations, these are the current insets for the
17755          * actual visible parts of the window.
17756          */
17757         final Rect mVisibleInsets = new Rect();
17758 
17759         /**
17760          * The internal insets given by this window.  This value is
17761          * supplied by the client (through
17762          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
17763          * be given to the window manager when changed to be used in laying
17764          * out windows behind it.
17765          */
17766         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
17767                 = new ViewTreeObserver.InternalInsetsInfo();
17768 
17769         /**
17770          * All views in the window's hierarchy that serve as scroll containers,
17771          * used to determine if the window can be resized or must be panned
17772          * to adjust for a soft input area.
17773          */
17774         final ArrayList<View> mScrollContainers = new ArrayList<View>();
17775 
17776         final KeyEvent.DispatcherState mKeyDispatchState
17777                 = new KeyEvent.DispatcherState();
17778 
17779         /**
17780          * Indicates whether the view's window currently has the focus.
17781          */
17782         boolean mHasWindowFocus;
17783 
17784         /**
17785          * The current visibility of the window.
17786          */
17787         int mWindowVisibility;
17788 
17789         /**
17790          * Indicates the time at which drawing started to occur.
17791          */
17792         long mDrawingTime;
17793 
17794         /**
17795          * Indicates whether or not ignoring the DIRTY_MASK flags.
17796          */
17797         boolean mIgnoreDirtyState;
17798 
17799         /**
17800          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
17801          * to avoid clearing that flag prematurely.
17802          */
17803         boolean mSetIgnoreDirtyState = false;
17804 
17805         /**
17806          * Indicates whether the view's window is currently in touch mode.
17807          */
17808         boolean mInTouchMode;
17809 
17810         /**
17811          * Indicates that ViewAncestor should trigger a global layout change
17812          * the next time it performs a traversal
17813          */
17814         boolean mRecomputeGlobalAttributes;
17815 
17816         /**
17817          * Always report new attributes at next traversal.
17818          */
17819         boolean mForceReportNewAttributes;
17820 
17821         /**
17822          * Set during a traveral if any views want to keep the screen on.
17823          */
17824         boolean mKeepScreenOn;
17825 
17826         /**
17827          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
17828          */
17829         int mSystemUiVisibility;
17830 
17831         /**
17832          * Hack to force certain system UI visibility flags to be cleared.
17833          */
17834         int mDisabledSystemUiVisibility;
17835 
17836         /**
17837          * Last global system UI visibility reported by the window manager.
17838          */
17839         int mGlobalSystemUiVisibility;
17840 
17841         /**
17842          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
17843          * attached.
17844          */
17845         boolean mHasSystemUiListeners;
17846 
17847         /**
17848          * Set if the visibility of any views has changed.
17849          */
17850         boolean mViewVisibilityChanged;
17851 
17852         /**
17853          * Set to true if a view has been scrolled.
17854          */
17855         boolean mViewScrollChanged;
17856 
17857         /**
17858          * Global to the view hierarchy used as a temporary for dealing with
17859          * x/y points in the transparent region computations.
17860          */
17861         final int[] mTransparentLocation = new int[2];
17862 
17863         /**
17864          * Global to the view hierarchy used as a temporary for dealing with
17865          * x/y points in the ViewGroup.invalidateChild implementation.
17866          */
17867         final int[] mInvalidateChildLocation = new int[2];
17868 
17869 
17870         /**
17871          * Global to the view hierarchy used as a temporary for dealing with
17872          * x/y location when view is transformed.
17873          */
17874         final float[] mTmpTransformLocation = new float[2];
17875 
17876         /**
17877          * The view tree observer used to dispatch global events like
17878          * layout, pre-draw, touch mode change, etc.
17879          */
17880         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
17881 
17882         /**
17883          * A Canvas used by the view hierarchy to perform bitmap caching.
17884          */
17885         Canvas mCanvas;
17886 
17887         /**
17888          * The view root impl.
17889          */
17890         final ViewRootImpl mViewRootImpl;
17891 
17892         /**
17893          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
17894          * handler can be used to pump events in the UI events queue.
17895          */
17896         final Handler mHandler;
17897 
17898         /**
17899          * Temporary for use in computing invalidate rectangles while
17900          * calling up the hierarchy.
17901          */
17902         final Rect mTmpInvalRect = new Rect();
17903 
17904         /**
17905          * Temporary for use in computing hit areas with transformed views
17906          */
17907         final RectF mTmpTransformRect = new RectF();
17908 
17909         /**
17910          * Temporary for use in transforming invalidation rect
17911          */
17912         final Matrix mTmpMatrix = new Matrix();
17913 
17914         /**
17915          * Temporary for use in transforming invalidation rect
17916          */
17917         final Transformation mTmpTransformation = new Transformation();
17918 
17919         /**
17920          * Temporary list for use in collecting focusable descendents of a view.
17921          */
17922         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
17923 
17924         /**
17925          * The id of the window for accessibility purposes.
17926          */
17927         int mAccessibilityWindowId = View.NO_ID;
17928 
17929         /**
17930          * Whether to ingore not exposed for accessibility Views when
17931          * reporting the view tree to accessibility services.
17932          */
17933         boolean mIncludeNotImportantViews;
17934 
17935         /**
17936          * The drawable for highlighting accessibility focus.
17937          */
17938         Drawable mAccessibilityFocusDrawable;
17939 
17940         /**
17941          * Show where the margins, bounds and layout bounds are for each view.
17942          */
17943         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
17944 
17945         /**
17946          * Point used to compute visible regions.
17947          */
17948         final Point mPoint = new Point();
17949 
17950         /**
17951          * Creates a new set of attachment information with the specified
17952          * events handler and thread.
17953          *
17954          * @param handler the events handler the view must use
17955          */
17956         AttachInfo(IWindowSession session, IWindow window, Display display,
17957                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
17958             mSession = session;
17959             mWindow = window;
17960             mWindowToken = window.asBinder();
17961             mDisplay = display;
17962             mViewRootImpl = viewRootImpl;
17963             mHandler = handler;
17964             mRootCallbacks = effectPlayer;
17965         }
17966     }
17967 
17968     /**
17969      * <p>ScrollabilityCache holds various fields used by a View when scrolling
17970      * is supported. This avoids keeping too many unused fields in most
17971      * instances of View.</p>
17972      */
17973     private static class ScrollabilityCache implements Runnable {
17974 
17975         /**
17976          * Scrollbars are not visible
17977          */
17978         public static final int OFF = 0;
17979 
17980         /**
17981          * Scrollbars are visible
17982          */
17983         public static final int ON = 1;
17984 
17985         /**
17986          * Scrollbars are fading away
17987          */
17988         public static final int FADING = 2;
17989 
17990         public boolean fadeScrollBars;
17991 
17992         public int fadingEdgeLength;
17993         public int scrollBarDefaultDelayBeforeFade;
17994         public int scrollBarFadeDuration;
17995 
17996         public int scrollBarSize;
17997         public ScrollBarDrawable scrollBar;
17998         public float[] interpolatorValues;
17999         public View host;
18000 
18001         public final Paint paint;
18002         public final Matrix matrix;
18003         public Shader shader;
18004 
18005         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
18006 
18007         private static final float[] OPAQUE = { 255 };
18008         private static final float[] TRANSPARENT = { 0.0f };
18009 
18010         /**
18011          * When fading should start. This time moves into the future every time
18012          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
18013          */
18014         public long fadeStartTime;
18015 
18016 
18017         /**
18018          * The current state of the scrollbars: ON, OFF, or FADING
18019          */
18020         public int state = OFF;
18021 
18022         private int mLastColor;
18023 
18024         public ScrollabilityCache(ViewConfiguration configuration, View host) {
18025             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
18026             scrollBarSize = configuration.getScaledScrollBarSize();
18027             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
18028             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
18029 
18030             paint = new Paint();
18031             matrix = new Matrix();
18032             // use use a height of 1, and then wack the matrix each time we
18033             // actually use it.
18034             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
18035             paint.setShader(shader);
18036             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
18037 
18038             this.host = host;
18039         }
18040 
18041         public void setFadeColor(int color) {
18042             if (color != mLastColor) {
18043                 mLastColor = color;
18044 
18045                 if (color != 0) {
18046                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
18047                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
18048                     paint.setShader(shader);
18049                     // Restore the default transfer mode (src_over)
18050                     paint.setXfermode(null);
18051                 } else {
18052                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
18053                     paint.setShader(shader);
18054                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
18055                 }
18056             }
18057         }
18058 
18059         public void run() {
18060             long now = AnimationUtils.currentAnimationTimeMillis();
18061             if (now >= fadeStartTime) {
18062 
18063                 // the animation fades the scrollbars out by changing
18064                 // the opacity (alpha) from fully opaque to fully
18065                 // transparent
18066                 int nextFrame = (int) now;
18067                 int framesCount = 0;
18068 
18069                 Interpolator interpolator = scrollBarInterpolator;
18070 
18071                 // Start opaque
18072                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
18073 
18074                 // End transparent
18075                 nextFrame += scrollBarFadeDuration;
18076                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
18077 
18078                 state = FADING;
18079 
18080                 // Kick off the fade animation
18081                 host.invalidate(true);
18082             }
18083         }
18084     }
18085 
18086     /**
18087      * Resuable callback for sending
18088      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
18089      */
18090     private class SendViewScrolledAccessibilityEvent implements Runnable {
18091         public volatile boolean mIsPending;
18092 
18093         public void run() {
18094             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
18095             mIsPending = false;
18096         }
18097     }
18098 
18099     /**
18100      * <p>
18101      * This class represents a delegate that can be registered in a {@link View}
18102      * to enhance accessibility support via composition rather via inheritance.
18103      * It is specifically targeted to widget developers that extend basic View
18104      * classes i.e. classes in package android.view, that would like their
18105      * applications to be backwards compatible.
18106      * </p>
18107      * <div class="special reference">
18108      * <h3>Developer Guides</h3>
18109      * <p>For more information about making applications accessible, read the
18110      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
18111      * developer guide.</p>
18112      * </div>
18113      * <p>
18114      * A scenario in which a developer would like to use an accessibility delegate
18115      * is overriding a method introduced in a later API version then the minimal API
18116      * version supported by the application. For example, the method
18117      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
18118      * in API version 4 when the accessibility APIs were first introduced. If a
18119      * developer would like his application to run on API version 4 devices (assuming
18120      * all other APIs used by the application are version 4 or lower) and take advantage
18121      * of this method, instead of overriding the method which would break the application's
18122      * backwards compatibility, he can override the corresponding method in this
18123      * delegate and register the delegate in the target View if the API version of
18124      * the system is high enough i.e. the API version is same or higher to the API
18125      * version that introduced
18126      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
18127      * </p>
18128      * <p>
18129      * Here is an example implementation:
18130      * </p>
18131      * <code><pre><p>
18132      * if (Build.VERSION.SDK_INT >= 14) {
18133      *     // If the API version is equal of higher than the version in
18134      *     // which onInitializeAccessibilityNodeInfo was introduced we
18135      *     // register a delegate with a customized implementation.
18136      *     View view = findViewById(R.id.view_id);
18137      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
18138      *         public void onInitializeAccessibilityNodeInfo(View host,
18139      *                 AccessibilityNodeInfo info) {
18140      *             // Let the default implementation populate the info.
18141      *             super.onInitializeAccessibilityNodeInfo(host, info);
18142      *             // Set some other information.
18143      *             info.setEnabled(host.isEnabled());
18144      *         }
18145      *     });
18146      * }
18147      * </code></pre></p>
18148      * <p>
18149      * This delegate contains methods that correspond to the accessibility methods
18150      * in View. If a delegate has been specified the implementation in View hands
18151      * off handling to the corresponding method in this delegate. The default
18152      * implementation the delegate methods behaves exactly as the corresponding
18153      * method in View for the case of no accessibility delegate been set. Hence,
18154      * to customize the behavior of a View method, clients can override only the
18155      * corresponding delegate method without altering the behavior of the rest
18156      * accessibility related methods of the host view.
18157      * </p>
18158      */
18159     public static class AccessibilityDelegate {
18160 
18161         /**
18162          * Sends an accessibility event of the given type. If accessibility is not
18163          * enabled this method has no effect.
18164          * <p>
18165          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
18166          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
18167          * been set.
18168          * </p>
18169          *
18170          * @param host The View hosting the delegate.
18171          * @param eventType The type of the event to send.
18172          *
18173          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
18174          */
18175         public void sendAccessibilityEvent(View host, int eventType) {
18176             host.sendAccessibilityEventInternal(eventType);
18177         }
18178 
18179         /**
18180          * Performs the specified accessibility action on the view. For
18181          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
18182          * <p>
18183          * The default implementation behaves as
18184          * {@link View#performAccessibilityAction(int, Bundle)
18185          *  View#performAccessibilityAction(int, Bundle)} for the case of
18186          *  no accessibility delegate been set.
18187          * </p>
18188          *
18189          * @param action The action to perform.
18190          * @return Whether the action was performed.
18191          *
18192          * @see View#performAccessibilityAction(int, Bundle)
18193          *      View#performAccessibilityAction(int, Bundle)
18194          */
18195         public boolean performAccessibilityAction(View host, int action, Bundle args) {
18196             return host.performAccessibilityActionInternal(action, args);
18197         }
18198 
18199         /**
18200          * Sends an accessibility event. This method behaves exactly as
18201          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
18202          * empty {@link AccessibilityEvent} and does not perform a check whether
18203          * accessibility is enabled.
18204          * <p>
18205          * The default implementation behaves as
18206          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
18207          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
18208          * the case of no accessibility delegate been set.
18209          * </p>
18210          *
18211          * @param host The View hosting the delegate.
18212          * @param event The event to send.
18213          *
18214          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
18215          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
18216          */
18217         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
18218             host.sendAccessibilityEventUncheckedInternal(event);
18219         }
18220 
18221         /**
18222          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
18223          * to its children for adding their text content to the event.
18224          * <p>
18225          * The default implementation behaves as
18226          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
18227          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
18228          * the case of no accessibility delegate been set.
18229          * </p>
18230          *
18231          * @param host The View hosting the delegate.
18232          * @param event The event.
18233          * @return True if the event population was completed.
18234          *
18235          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
18236          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
18237          */
18238         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
18239             return host.dispatchPopulateAccessibilityEventInternal(event);
18240         }
18241 
18242         /**
18243          * Gives a chance to the host View to populate the accessibility event with its
18244          * text content.
18245          * <p>
18246          * The default implementation behaves as
18247          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
18248          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
18249          * the case of no accessibility delegate been set.
18250          * </p>
18251          *
18252          * @param host The View hosting the delegate.
18253          * @param event The accessibility event which to populate.
18254          *
18255          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
18256          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
18257          */
18258         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
18259             host.onPopulateAccessibilityEventInternal(event);
18260         }
18261 
18262         /**
18263          * Initializes an {@link AccessibilityEvent} with information about the
18264          * the host View which is the event source.
18265          * <p>
18266          * The default implementation behaves as
18267          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
18268          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
18269          * the case of no accessibility delegate been set.
18270          * </p>
18271          *
18272          * @param host The View hosting the delegate.
18273          * @param event The event to initialize.
18274          *
18275          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
18276          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
18277          */
18278         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
18279             host.onInitializeAccessibilityEventInternal(event);
18280         }
18281 
18282         /**
18283          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
18284          * <p>
18285          * The default implementation behaves as
18286          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
18287          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
18288          * the case of no accessibility delegate been set.
18289          * </p>
18290          *
18291          * @param host The View hosting the delegate.
18292          * @param info The instance to initialize.
18293          *
18294          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
18295          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
18296          */
18297         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
18298             host.onInitializeAccessibilityNodeInfoInternal(info);
18299         }
18300 
18301         /**
18302          * Called when a child of the host View has requested sending an
18303          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
18304          * to augment the event.
18305          * <p>
18306          * The default implementation behaves as
18307          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
18308          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
18309          * the case of no accessibility delegate been set.
18310          * </p>
18311          *
18312          * @param host The View hosting the delegate.
18313          * @param child The child which requests sending the event.
18314          * @param event The event to be sent.
18315          * @return True if the event should be sent
18316          *
18317          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
18318          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
18319          */
18320         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
18321                 AccessibilityEvent event) {
18322             return host.onRequestSendAccessibilityEventInternal(child, event);
18323         }
18324 
18325         /**
18326          * Gets the provider for managing a virtual view hierarchy rooted at this View
18327          * and reported to {@link android.accessibilityservice.AccessibilityService}s
18328          * that explore the window content.
18329          * <p>
18330          * The default implementation behaves as
18331          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
18332          * the case of no accessibility delegate been set.
18333          * </p>
18334          *
18335          * @return The provider.
18336          *
18337          * @see AccessibilityNodeProvider
18338          */
18339         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
18340             return null;
18341         }
18342     }
18343 
18344     private class MatchIdPredicate implements Predicate<View> {
18345         public int mId;
18346 
18347         @Override
18348         public boolean apply(View view) {
18349             return (view.mID == mId);
18350         }
18351     }
18352 
18353     private class MatchLabelForPredicate implements Predicate<View> {
18354         private int mLabeledId;
18355 
18356         @Override
18357         public boolean apply(View view) {
18358             return (view.mLabelForId == mLabeledId);
18359         }
18360     }
18361 
18362     /**
18363      * Dump all private flags in readable format, useful for documentation and
18364      * sanity checking.
18365      */
18366     private static void dumpFlags() {
18367         final HashMap<String, String> found = Maps.newHashMap();
18368         try {
18369             for (Field field : View.class.getDeclaredFields()) {
18370                 final int modifiers = field.getModifiers();
18371                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
18372                     if (field.getType().equals(int.class)) {
18373                         final int value = field.getInt(null);
18374                         dumpFlag(found, field.getName(), value);
18375                     } else if (field.getType().equals(int[].class)) {
18376                         final int[] values = (int[]) field.get(null);
18377                         for (int i = 0; i < values.length; i++) {
18378                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
18379                         }
18380                     }
18381                 }
18382             }
18383         } catch (IllegalAccessException e) {
18384             throw new RuntimeException(e);
18385         }
18386 
18387         final ArrayList<String> keys = Lists.newArrayList();
18388         keys.addAll(found.keySet());
18389         Collections.sort(keys);
18390         for (String key : keys) {
18391             Log.d(VIEW_LOG_TAG, found.get(key));
18392         }
18393     }
18394 
18395     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
18396         // Sort flags by prefix, then by bits, always keeping unique keys
18397         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
18398         final int prefix = name.indexOf('_');
18399         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
18400         final String output = bits + " " + name;
18401         found.put(key, output);
18402     }
18403 }
18404