• 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.Build;
44 import android.os.Bundle;
45 import android.os.Handler;
46 import android.os.IBinder;
47 import android.os.Parcel;
48 import android.os.Parcelable;
49 import android.os.RemoteException;
50 import android.os.SystemClock;
51 import android.os.SystemProperties;
52 import android.text.TextUtils;
53 import android.util.AttributeSet;
54 import android.util.FloatProperty;
55 import android.util.Log;
56 import android.util.Pools.SynchronizedPool;
57 import android.util.Property;
58 import android.util.SparseArray;
59 import android.util.TypedValue;
60 import android.view.ContextMenu.ContextMenuInfo;
61 import android.view.AccessibilityIterators.TextSegmentIterator;
62 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
63 import android.view.AccessibilityIterators.WordTextSegmentIterator;
64 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
65 import android.view.accessibility.AccessibilityEvent;
66 import android.view.accessibility.AccessibilityEventSource;
67 import android.view.accessibility.AccessibilityManager;
68 import android.view.accessibility.AccessibilityNodeInfo;
69 import android.view.accessibility.AccessibilityNodeProvider;
70 import android.view.animation.Animation;
71 import android.view.animation.AnimationUtils;
72 import android.view.animation.Transformation;
73 import android.view.inputmethod.EditorInfo;
74 import android.view.inputmethod.InputConnection;
75 import android.view.inputmethod.InputMethodManager;
76 import android.widget.ScrollBarDrawable;
77 
78 import static android.os.Build.VERSION_CODES.*;
79 import static java.lang.Math.max;
80 
81 import com.android.internal.R;
82 import com.android.internal.util.Predicate;
83 import com.android.internal.view.menu.MenuBuilder;
84 import com.google.android.collect.Lists;
85 import com.google.android.collect.Maps;
86 
87 import java.lang.ref.WeakReference;
88 import java.lang.reflect.Field;
89 import java.lang.reflect.InvocationTargetException;
90 import java.lang.reflect.Method;
91 import java.lang.reflect.Modifier;
92 import java.util.ArrayList;
93 import java.util.Arrays;
94 import java.util.Collections;
95 import java.util.HashMap;
96 import java.util.Locale;
97 import java.util.concurrent.CopyOnWriteArrayList;
98 import java.util.concurrent.atomic.AtomicInteger;
99 
100 /**
101  * <p>
102  * This class represents the basic building block for user interface components. A View
103  * occupies a rectangular area on the screen and is responsible for drawing and
104  * event handling. View is the base class for <em>widgets</em>, which are
105  * used to create interactive UI components (buttons, text fields, etc.). The
106  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
107  * are invisible containers that hold other Views (or other ViewGroups) and define
108  * their layout properties.
109  * </p>
110  *
111  * <div class="special reference">
112  * <h3>Developer Guides</h3>
113  * <p>For information about using this class to develop your application's user interface,
114  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
115  * </div>
116  *
117  * <a name="Using"></a>
118  * <h3>Using Views</h3>
119  * <p>
120  * All of the views in a window are arranged in a single tree. You can add views
121  * either from code or by specifying a tree of views in one or more XML layout
122  * files. There are many specialized subclasses of views that act as controls or
123  * are capable of displaying text, images, or other content.
124  * </p>
125  * <p>
126  * Once you have created a tree of views, there are typically a few types of
127  * common operations you may wish to perform:
128  * <ul>
129  * <li><strong>Set properties:</strong> for example setting the text of a
130  * {@link android.widget.TextView}. The available properties and the methods
131  * that set them will vary among the different subclasses of views. Note that
132  * properties that are known at build time can be set in the XML layout
133  * files.</li>
134  * <li><strong>Set focus:</strong> The framework will handled moving focus in
135  * response to user input. To force focus to a specific view, call
136  * {@link #requestFocus}.</li>
137  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
138  * that will be notified when something interesting happens to the view. For
139  * example, all views will let you set a listener to be notified when the view
140  * gains or loses focus. You can register such a listener using
141  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
142  * Other view subclasses offer more specialized listeners. For example, a Button
143  * exposes a listener to notify clients when the button is clicked.</li>
144  * <li><strong>Set visibility:</strong> You can hide or show views using
145  * {@link #setVisibility(int)}.</li>
146  * </ul>
147  * </p>
148  * <p><em>
149  * Note: The Android framework is responsible for measuring, laying out and
150  * drawing views. You should not call methods that perform these actions on
151  * views yourself unless you are actually implementing a
152  * {@link android.view.ViewGroup}.
153  * </em></p>
154  *
155  * <a name="Lifecycle"></a>
156  * <h3>Implementing a Custom View</h3>
157  *
158  * <p>
159  * To implement a custom view, you will usually begin by providing overrides for
160  * some of the standard methods that the framework calls on all views. You do
161  * not need to override all of these methods. In fact, you can start by just
162  * overriding {@link #onDraw(android.graphics.Canvas)}.
163  * <table border="2" width="85%" align="center" cellpadding="5">
164  *     <thead>
165  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
166  *     </thead>
167  *
168  *     <tbody>
169  *     <tr>
170  *         <td rowspan="2">Creation</td>
171  *         <td>Constructors</td>
172  *         <td>There is a form of the constructor that are called when the view
173  *         is created from code and a form that is called when the view is
174  *         inflated from a layout file. The second form should parse and apply
175  *         any attributes defined in the layout file.
176  *         </td>
177  *     </tr>
178  *     <tr>
179  *         <td><code>{@link #onFinishInflate()}</code></td>
180  *         <td>Called after a view and all of its children has been inflated
181  *         from XML.</td>
182  *     </tr>
183  *
184  *     <tr>
185  *         <td rowspan="3">Layout</td>
186  *         <td><code>{@link #onMeasure(int, int)}</code></td>
187  *         <td>Called to determine the size requirements for this view and all
188  *         of its children.
189  *         </td>
190  *     </tr>
191  *     <tr>
192  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
193  *         <td>Called when this view should assign a size and position to all
194  *         of its children.
195  *         </td>
196  *     </tr>
197  *     <tr>
198  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
199  *         <td>Called when the size of this view has changed.
200  *         </td>
201  *     </tr>
202  *
203  *     <tr>
204  *         <td>Drawing</td>
205  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
206  *         <td>Called when the view should render its content.
207  *         </td>
208  *     </tr>
209  *
210  *     <tr>
211  *         <td rowspan="4">Event processing</td>
212  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
213  *         <td>Called when a new hardware key event occurs.
214  *         </td>
215  *     </tr>
216  *     <tr>
217  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
218  *         <td>Called when a hardware key up event occurs.
219  *         </td>
220  *     </tr>
221  *     <tr>
222  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
223  *         <td>Called when a trackball motion event occurs.
224  *         </td>
225  *     </tr>
226  *     <tr>
227  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
228  *         <td>Called when a touch screen motion event occurs.
229  *         </td>
230  *     </tr>
231  *
232  *     <tr>
233  *         <td rowspan="2">Focus</td>
234  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
235  *         <td>Called when the view gains or loses focus.
236  *         </td>
237  *     </tr>
238  *
239  *     <tr>
240  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
241  *         <td>Called when the window containing the view gains or loses focus.
242  *         </td>
243  *     </tr>
244  *
245  *     <tr>
246  *         <td rowspan="3">Attaching</td>
247  *         <td><code>{@link #onAttachedToWindow()}</code></td>
248  *         <td>Called when the view is attached to a window.
249  *         </td>
250  *     </tr>
251  *
252  *     <tr>
253  *         <td><code>{@link #onDetachedFromWindow}</code></td>
254  *         <td>Called when the view is detached from its window.
255  *         </td>
256  *     </tr>
257  *
258  *     <tr>
259  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
260  *         <td>Called when the visibility of the window containing the view
261  *         has changed.
262  *         </td>
263  *     </tr>
264  *     </tbody>
265  *
266  * </table>
267  * </p>
268  *
269  * <a name="IDs"></a>
270  * <h3>IDs</h3>
271  * Views may have an integer id associated with them. These ids are typically
272  * assigned in the layout XML files, and are used to find specific views within
273  * the view tree. A common pattern is to:
274  * <ul>
275  * <li>Define a Button in the layout file and assign it a unique ID.
276  * <pre>
277  * &lt;Button
278  *     android:id="@+id/my_button"
279  *     android:layout_width="wrap_content"
280  *     android:layout_height="wrap_content"
281  *     android:text="@string/my_button_text"/&gt;
282  * </pre></li>
283  * <li>From the onCreate method of an Activity, find the Button
284  * <pre class="prettyprint">
285  *      Button myButton = (Button) findViewById(R.id.my_button);
286  * </pre></li>
287  * </ul>
288  * <p>
289  * View IDs need not be unique throughout the tree, but it is good practice to
290  * ensure that they are at least unique within the part of the tree you are
291  * searching.
292  * </p>
293  *
294  * <a name="Position"></a>
295  * <h3>Position</h3>
296  * <p>
297  * The geometry of a view is that of a rectangle. A view has a location,
298  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
299  * two dimensions, expressed as a width and a height. The unit for location
300  * and dimensions is the pixel.
301  * </p>
302  *
303  * <p>
304  * It is possible to retrieve the location of a view by invoking the methods
305  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
306  * coordinate of the rectangle representing the view. The latter returns the
307  * top, or Y, coordinate of the rectangle representing the view. These methods
308  * both return the location of the view relative to its parent. For instance,
309  * when getLeft() returns 20, that means the view is located 20 pixels to the
310  * right of the left edge of its direct parent.
311  * </p>
312  *
313  * <p>
314  * In addition, several convenience methods are offered to avoid unnecessary
315  * computations, namely {@link #getRight()} and {@link #getBottom()}.
316  * These methods return the coordinates of the right and bottom edges of the
317  * rectangle representing the view. For instance, calling {@link #getRight()}
318  * is similar to the following computation: <code>getLeft() + getWidth()</code>
319  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
320  * </p>
321  *
322  * <a name="SizePaddingMargins"></a>
323  * <h3>Size, padding and margins</h3>
324  * <p>
325  * The size of a view is expressed with a width and a height. A view actually
326  * possess two pairs of width and height values.
327  * </p>
328  *
329  * <p>
330  * The first pair is known as <em>measured width</em> and
331  * <em>measured height</em>. These dimensions define how big a view wants to be
332  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
333  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
334  * and {@link #getMeasuredHeight()}.
335  * </p>
336  *
337  * <p>
338  * The second pair is simply known as <em>width</em> and <em>height</em>, or
339  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
340  * dimensions define the actual size of the view on screen, at drawing time and
341  * after layout. These values may, but do not have to, be different from the
342  * measured width and height. The width and height can be obtained by calling
343  * {@link #getWidth()} and {@link #getHeight()}.
344  * </p>
345  *
346  * <p>
347  * To measure its dimensions, a view takes into account its padding. The padding
348  * is expressed in pixels for the left, top, right and bottom parts of the view.
349  * Padding can be used to offset the content of the view by a specific amount of
350  * pixels. For instance, a left padding of 2 will push the view's content by
351  * 2 pixels to the right of the left edge. Padding can be set using the
352  * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
353  * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
354  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
355  * {@link #getPaddingEnd()}.
356  * </p>
357  *
358  * <p>
359  * Even though a view can define a padding, it does not provide any support for
360  * margins. However, view groups provide such a support. Refer to
361  * {@link android.view.ViewGroup} and
362  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
363  * </p>
364  *
365  * <a name="Layout"></a>
366  * <h3>Layout</h3>
367  * <p>
368  * Layout is a two pass process: a measure pass and a layout pass. The measuring
369  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
370  * of the view tree. Each view pushes dimension specifications down the tree
371  * during the recursion. At the end of the measure pass, every view has stored
372  * its measurements. The second pass happens in
373  * {@link #layout(int,int,int,int)} and is also top-down. During
374  * this pass each parent is responsible for positioning all of its children
375  * using the sizes computed in the measure pass.
376  * </p>
377  *
378  * <p>
379  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
380  * {@link #getMeasuredHeight()} values must be set, along with those for all of
381  * that view's descendants. A view's measured width and measured height values
382  * must respect the constraints imposed by the view's parents. This guarantees
383  * that at the end of the measure pass, all parents accept all of their
384  * children's measurements. A parent view may call measure() more than once on
385  * its children. For example, the parent may measure each child once with
386  * unspecified dimensions to find out how big they want to be, then call
387  * measure() on them again with actual numbers if the sum of all the children's
388  * unconstrained sizes is too big or too small.
389  * </p>
390  *
391  * <p>
392  * The measure pass uses two classes to communicate dimensions. The
393  * {@link MeasureSpec} class is used by views to tell their parents how they
394  * want to be measured and positioned. The base LayoutParams class just
395  * describes how big the view wants to be for both width and height. For each
396  * dimension, it can specify one of:
397  * <ul>
398  * <li> an exact number
399  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
400  * (minus padding)
401  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
402  * enclose its content (plus padding).
403  * </ul>
404  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
405  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
406  * an X and Y value.
407  * </p>
408  *
409  * <p>
410  * MeasureSpecs are used to push requirements down the tree from parent to
411  * child. A MeasureSpec can be in one of three modes:
412  * <ul>
413  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
414  * of a child view. For example, a LinearLayout may call measure() on its child
415  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
416  * tall the child view wants to be given a width of 240 pixels.
417  * <li>EXACTLY: This is used by the parent to impose an exact size on the
418  * child. The child must use this size, and guarantee that all of its
419  * descendants will fit within this size.
420  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
421  * child. The child must gurantee that it and all of its descendants will fit
422  * within this size.
423  * </ul>
424  * </p>
425  *
426  * <p>
427  * To intiate a layout, call {@link #requestLayout}. This method is typically
428  * called by a view on itself when it believes that is can no longer fit within
429  * its current bounds.
430  * </p>
431  *
432  * <a name="Drawing"></a>
433  * <h3>Drawing</h3>
434  * <p>
435  * Drawing is handled by walking the tree and rendering each view that
436  * intersects the invalid region. Because the tree is traversed in-order,
437  * this means that parents will draw before (i.e., behind) their children, with
438  * siblings drawn in the order they appear in the tree.
439  * If you set a background drawable for a View, then the View will draw it for you
440  * before calling back to its <code>onDraw()</code> method.
441  * </p>
442  *
443  * <p>
444  * Note that the framework will not draw views that are not in the invalid region.
445  * </p>
446  *
447  * <p>
448  * To force a view to draw, call {@link #invalidate()}.
449  * </p>
450  *
451  * <a name="EventHandlingThreading"></a>
452  * <h3>Event Handling and Threading</h3>
453  * <p>
454  * The basic cycle of a view is as follows:
455  * <ol>
456  * <li>An event comes in and is dispatched to the appropriate view. The view
457  * handles the event and notifies any listeners.</li>
458  * <li>If in the course of processing the event, the view's bounds may need
459  * to be changed, the view will call {@link #requestLayout()}.</li>
460  * <li>Similarly, if in the course of processing the event the view's appearance
461  * may need to be changed, the view will call {@link #invalidate()}.</li>
462  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
463  * the framework will take care of measuring, laying out, and drawing the tree
464  * as appropriate.</li>
465  * </ol>
466  * </p>
467  *
468  * <p><em>Note: The entire view tree is single threaded. You must always be on
469  * the UI thread when calling any method on any view.</em>
470  * If you are doing work on other threads and want to update the state of a view
471  * from that thread, you should use a {@link Handler}.
472  * </p>
473  *
474  * <a name="FocusHandling"></a>
475  * <h3>Focus Handling</h3>
476  * <p>
477  * The framework will handle routine focus movement in response to user input.
478  * This includes changing the focus as views are removed or hidden, or as new
479  * views become available. Views indicate their willingness to take focus
480  * through the {@link #isFocusable} method. To change whether a view can take
481  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
482  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
483  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
484  * </p>
485  * <p>
486  * Focus movement is based on an algorithm which finds the nearest neighbor in a
487  * given direction. In rare cases, the default algorithm may not match the
488  * intended behavior of the developer. In these situations, you can provide
489  * explicit overrides by using these XML attributes in the layout file:
490  * <pre>
491  * nextFocusDown
492  * nextFocusLeft
493  * nextFocusRight
494  * nextFocusUp
495  * </pre>
496  * </p>
497  *
498  *
499  * <p>
500  * To get a particular view to take focus, call {@link #requestFocus()}.
501  * </p>
502  *
503  * <a name="TouchMode"></a>
504  * <h3>Touch Mode</h3>
505  * <p>
506  * When a user is navigating a user interface via directional keys such as a D-pad, it is
507  * necessary to give focus to actionable items such as buttons so the user can see
508  * what will take input.  If the device has touch capabilities, however, and the user
509  * begins interacting with the interface by touching it, it is no longer necessary to
510  * always highlight, or give focus to, a particular view.  This motivates a mode
511  * for interaction named 'touch mode'.
512  * </p>
513  * <p>
514  * For a touch capable device, once the user touches the screen, the device
515  * will enter touch mode.  From this point onward, only views for which
516  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
517  * Other views that are touchable, like buttons, will not take focus when touched; they will
518  * only fire the on click listeners.
519  * </p>
520  * <p>
521  * Any time a user hits a directional key, such as a D-pad direction, the view device will
522  * exit touch mode, and find a view to take focus, so that the user may resume interacting
523  * with the user interface without touching the screen again.
524  * </p>
525  * <p>
526  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
527  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
528  * </p>
529  *
530  * <a name="Scrolling"></a>
531  * <h3>Scrolling</h3>
532  * <p>
533  * The framework provides basic support for views that wish to internally
534  * scroll their content. This includes keeping track of the X and Y scroll
535  * offset as well as mechanisms for drawing scrollbars. See
536  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
537  * {@link #awakenScrollBars()} for more details.
538  * </p>
539  *
540  * <a name="Tags"></a>
541  * <h3>Tags</h3>
542  * <p>
543  * Unlike IDs, tags are not used to identify views. Tags are essentially an
544  * extra piece of information that can be associated with a view. They are most
545  * often used as a convenience to store data related to views in the views
546  * themselves rather than by putting them in a separate structure.
547  * </p>
548  *
549  * <a name="Properties"></a>
550  * <h3>Properties</h3>
551  * <p>
552  * The View class exposes an {@link #ALPHA} property, as well as several transform-related
553  * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
554  * available both in the {@link Property} form as well as in similarly-named setter/getter
555  * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
556  * be used to set persistent state associated with these rendering-related properties on the view.
557  * The properties and methods can also be used in conjunction with
558  * {@link android.animation.Animator Animator}-based animations, described more in the
559  * <a href="#Animation">Animation</a> section.
560  * </p>
561  *
562  * <a name="Animation"></a>
563  * <h3>Animation</h3>
564  * <p>
565  * Starting with Android 3.0, the preferred way of animating views is to use the
566  * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
567  * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
568  * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
569  * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
570  * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
571  * makes animating these View properties particularly easy and efficient.
572  * </p>
573  * <p>
574  * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
575  * You can attach an {@link Animation} object to a view using
576  * {@link #setAnimation(Animation)} or
577  * {@link #startAnimation(Animation)}. The animation can alter the scale,
578  * rotation, translation and alpha of a view over time. If the animation is
579  * attached to a view that has children, the animation will affect the entire
580  * subtree rooted by that node. When an animation is started, the framework will
581  * take care of redrawing the appropriate views until the animation completes.
582  * </p>
583  *
584  * <a name="Security"></a>
585  * <h3>Security</h3>
586  * <p>
587  * Sometimes it is essential that an application be able to verify that an action
588  * is being performed with the full knowledge and consent of the user, such as
589  * granting a permission request, making a purchase or clicking on an advertisement.
590  * Unfortunately, a malicious application could try to spoof the user into
591  * performing these actions, unaware, by concealing the intended purpose of the view.
592  * As a remedy, the framework offers a touch filtering mechanism that can be used to
593  * improve the security of views that provide access to sensitive functionality.
594  * </p><p>
595  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
596  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
597  * will discard touches that are received whenever the view's window is obscured by
598  * another visible window.  As a result, the view will not receive touches whenever a
599  * toast, dialog or other window appears above the view's window.
600  * </p><p>
601  * For more fine-grained control over security, consider overriding the
602  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
603  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
604  * </p>
605  *
606  * @attr ref android.R.styleable#View_alpha
607  * @attr ref android.R.styleable#View_background
608  * @attr ref android.R.styleable#View_clickable
609  * @attr ref android.R.styleable#View_contentDescription
610  * @attr ref android.R.styleable#View_drawingCacheQuality
611  * @attr ref android.R.styleable#View_duplicateParentState
612  * @attr ref android.R.styleable#View_id
613  * @attr ref android.R.styleable#View_requiresFadingEdge
614  * @attr ref android.R.styleable#View_fadeScrollbars
615  * @attr ref android.R.styleable#View_fadingEdgeLength
616  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
617  * @attr ref android.R.styleable#View_fitsSystemWindows
618  * @attr ref android.R.styleable#View_isScrollContainer
619  * @attr ref android.R.styleable#View_focusable
620  * @attr ref android.R.styleable#View_focusableInTouchMode
621  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
622  * @attr ref android.R.styleable#View_keepScreenOn
623  * @attr ref android.R.styleable#View_layerType
624  * @attr ref android.R.styleable#View_layoutDirection
625  * @attr ref android.R.styleable#View_longClickable
626  * @attr ref android.R.styleable#View_minHeight
627  * @attr ref android.R.styleable#View_minWidth
628  * @attr ref android.R.styleable#View_nextFocusDown
629  * @attr ref android.R.styleable#View_nextFocusLeft
630  * @attr ref android.R.styleable#View_nextFocusRight
631  * @attr ref android.R.styleable#View_nextFocusUp
632  * @attr ref android.R.styleable#View_onClick
633  * @attr ref android.R.styleable#View_padding
634  * @attr ref android.R.styleable#View_paddingBottom
635  * @attr ref android.R.styleable#View_paddingLeft
636  * @attr ref android.R.styleable#View_paddingRight
637  * @attr ref android.R.styleable#View_paddingTop
638  * @attr ref android.R.styleable#View_paddingStart
639  * @attr ref android.R.styleable#View_paddingEnd
640  * @attr ref android.R.styleable#View_saveEnabled
641  * @attr ref android.R.styleable#View_rotation
642  * @attr ref android.R.styleable#View_rotationX
643  * @attr ref android.R.styleable#View_rotationY
644  * @attr ref android.R.styleable#View_scaleX
645  * @attr ref android.R.styleable#View_scaleY
646  * @attr ref android.R.styleable#View_scrollX
647  * @attr ref android.R.styleable#View_scrollY
648  * @attr ref android.R.styleable#View_scrollbarSize
649  * @attr ref android.R.styleable#View_scrollbarStyle
650  * @attr ref android.R.styleable#View_scrollbars
651  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
652  * @attr ref android.R.styleable#View_scrollbarFadeDuration
653  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
654  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
655  * @attr ref android.R.styleable#View_scrollbarThumbVertical
656  * @attr ref android.R.styleable#View_scrollbarTrackVertical
657  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
658  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
659  * @attr ref android.R.styleable#View_soundEffectsEnabled
660  * @attr ref android.R.styleable#View_tag
661  * @attr ref android.R.styleable#View_textAlignment
662  * @attr ref android.R.styleable#View_textDirection
663  * @attr ref android.R.styleable#View_transformPivotX
664  * @attr ref android.R.styleable#View_transformPivotY
665  * @attr ref android.R.styleable#View_translationX
666  * @attr ref android.R.styleable#View_translationY
667  * @attr ref android.R.styleable#View_visibility
668  *
669  * @see android.view.ViewGroup
670  */
671 public class View implements Drawable.Callback, KeyEvent.Callback,
672         AccessibilityEventSource {
673     private static final boolean DBG = false;
674 
675     /**
676      * The logging tag used by this class with android.util.Log.
677      */
678     protected static final String VIEW_LOG_TAG = "View";
679 
680     /**
681      * When set to true, apps will draw debugging information about their layouts.
682      *
683      * @hide
684      */
685     public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
686 
687     /**
688      * Used to mark a View that has no ID.
689      */
690     public static final int NO_ID = -1;
691 
692     private static boolean sUseBrokenMakeMeasureSpec = false;
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     private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1565 
1566     /**
1567      * The view's tag.
1568      * {@hide}
1569      *
1570      * @see #setTag(Object)
1571      * @see #getTag()
1572      */
1573     protected Object mTag;
1574 
1575     // for mPrivateFlags:
1576     /** {@hide} */
1577     static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1578     /** {@hide} */
1579     static final int PFLAG_FOCUSED                     = 0x00000002;
1580     /** {@hide} */
1581     static final int PFLAG_SELECTED                    = 0x00000004;
1582     /** {@hide} */
1583     static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1584     /** {@hide} */
1585     static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1586     /** {@hide} */
1587     static final int PFLAG_DRAWN                       = 0x00000020;
1588     /**
1589      * When this flag is set, this view is running an animation on behalf of its
1590      * children and should therefore not cancel invalidate requests, even if they
1591      * lie outside of this view's bounds.
1592      *
1593      * {@hide}
1594      */
1595     static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1596     /** {@hide} */
1597     static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1598     /** {@hide} */
1599     static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
1600     /** {@hide} */
1601     static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1602     /** {@hide} */
1603     static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1604     /** {@hide} */
1605     static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1606     /** {@hide} */
1607     static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1608     /** {@hide} */
1609     static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1610 
1611     private static final int PFLAG_PRESSED             = 0x00004000;
1612 
1613     /** {@hide} */
1614     static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1615     /**
1616      * Flag used to indicate that this view should be drawn once more (and only once
1617      * more) after its animation has completed.
1618      * {@hide}
1619      */
1620     static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1621 
1622     private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1623 
1624     /**
1625      * Indicates that the View returned true when onSetAlpha() was called and that
1626      * the alpha must be restored.
1627      * {@hide}
1628      */
1629     static final int PFLAG_ALPHA_SET                   = 0x00040000;
1630 
1631     /**
1632      * Set by {@link #setScrollContainer(boolean)}.
1633      */
1634     static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1635 
1636     /**
1637      * Set by {@link #setScrollContainer(boolean)}.
1638      */
1639     static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1640 
1641     /**
1642      * View flag indicating whether this view was invalidated (fully or partially.)
1643      *
1644      * @hide
1645      */
1646     static final int PFLAG_DIRTY                       = 0x00200000;
1647 
1648     /**
1649      * View flag indicating whether this view was invalidated by an opaque
1650      * invalidate request.
1651      *
1652      * @hide
1653      */
1654     static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1655 
1656     /**
1657      * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1658      *
1659      * @hide
1660      */
1661     static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1662 
1663     /**
1664      * Indicates whether the background is opaque.
1665      *
1666      * @hide
1667      */
1668     static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1669 
1670     /**
1671      * Indicates whether the scrollbars are opaque.
1672      *
1673      * @hide
1674      */
1675     static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1676 
1677     /**
1678      * Indicates whether the view is opaque.
1679      *
1680      * @hide
1681      */
1682     static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1683 
1684     /**
1685      * Indicates a prepressed state;
1686      * the short time between ACTION_DOWN and recognizing
1687      * a 'real' press. Prepressed is used to recognize quick taps
1688      * even when they are shorter than ViewConfiguration.getTapTimeout().
1689      *
1690      * @hide
1691      */
1692     private static final int PFLAG_PREPRESSED          = 0x02000000;
1693 
1694     /**
1695      * Indicates whether the view is temporarily detached.
1696      *
1697      * @hide
1698      */
1699     static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1700 
1701     /**
1702      * Indicates that we should awaken scroll bars once attached
1703      *
1704      * @hide
1705      */
1706     private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1707 
1708     /**
1709      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1710      * @hide
1711      */
1712     private static final int PFLAG_HOVERED             = 0x10000000;
1713 
1714     /**
1715      * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
1716      * for transform operations
1717      *
1718      * @hide
1719      */
1720     private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000;
1721 
1722     /** {@hide} */
1723     static final int PFLAG_ACTIVATED                   = 0x40000000;
1724 
1725     /**
1726      * Indicates that this view was specifically invalidated, not just dirtied because some
1727      * child view was invalidated. The flag is used to determine when we need to recreate
1728      * a view's display list (as opposed to just returning a reference to its existing
1729      * display list).
1730      *
1731      * @hide
1732      */
1733     static final int PFLAG_INVALIDATED                 = 0x80000000;
1734 
1735     /**
1736      * Masks for mPrivateFlags2, as generated by dumpFlags():
1737      *
1738      * -------|-------|-------|-------|
1739      *                                  PFLAG2_TEXT_ALIGNMENT_FLAGS[0]
1740      *                                  PFLAG2_TEXT_DIRECTION_FLAGS[0]
1741      *                                1 PFLAG2_DRAG_CAN_ACCEPT
1742      *                               1  PFLAG2_DRAG_HOVERED
1743      *                               1  PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT
1744      *                              11  PFLAG2_TEXT_DIRECTION_MASK_SHIFT
1745      *                             1 1  PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT
1746      *                             11   PFLAG2_LAYOUT_DIRECTION_MASK
1747      *                             11 1 PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
1748      *                            1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1749      *                            1   1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT
1750      *                            1 1   PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT
1751      *                           1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1752      *                           11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1753      *                          1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1754      *                         1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1755      *                         11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1756      *                        1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1757      *                        1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1758      *                        111       PFLAG2_TEXT_DIRECTION_MASK
1759      *                       1          PFLAG2_TEXT_DIRECTION_RESOLVED
1760      *                      1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1761      *                    111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1762      *                   1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1763      *                  1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1764      *                  11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1765      *                 1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1766      *                 1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1767      *                 11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1768      *                 111              PFLAG2_TEXT_ALIGNMENT_MASK
1769      *                1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1770      *               1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1771      *             111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1772      *           11                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1773      *          1                       PFLAG2_HAS_TRANSIENT_STATE
1774      *      1                           PFLAG2_ACCESSIBILITY_FOCUSED
1775      *     1                            PFLAG2_ACCESSIBILITY_STATE_CHANGED
1776      *    1                             PFLAG2_VIEW_QUICK_REJECTED
1777      *   1                              PFLAG2_PADDING_RESOLVED
1778      * -------|-------|-------|-------|
1779      */
1780 
1781     /**
1782      * Indicates that this view has reported that it can accept the current drag's content.
1783      * Cleared when the drag operation concludes.
1784      * @hide
1785      */
1786     static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1787 
1788     /**
1789      * Indicates that this view is currently directly under the drag location in a
1790      * drag-and-drop operation involving content that it can accept.  Cleared when
1791      * the drag exits the view, or when the drag operation concludes.
1792      * @hide
1793      */
1794     static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1795 
1796     /**
1797      * Horizontal layout direction of this view is from Left to Right.
1798      * Use with {@link #setLayoutDirection}.
1799      */
1800     public static final int LAYOUT_DIRECTION_LTR = 0;
1801 
1802     /**
1803      * Horizontal layout direction of this view is from Right to Left.
1804      * Use with {@link #setLayoutDirection}.
1805      */
1806     public static final int LAYOUT_DIRECTION_RTL = 1;
1807 
1808     /**
1809      * Horizontal layout direction of this view is inherited from its parent.
1810      * Use with {@link #setLayoutDirection}.
1811      */
1812     public static final int LAYOUT_DIRECTION_INHERIT = 2;
1813 
1814     /**
1815      * Horizontal layout direction of this view is from deduced from the default language
1816      * script for the locale. Use with {@link #setLayoutDirection}.
1817      */
1818     public static final int LAYOUT_DIRECTION_LOCALE = 3;
1819 
1820     /**
1821      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1822      * @hide
1823      */
1824     static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1825 
1826     /**
1827      * Mask for use with private flags indicating bits used for horizontal layout direction.
1828      * @hide
1829      */
1830     static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1831 
1832     /**
1833      * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1834      * right-to-left direction.
1835      * @hide
1836      */
1837     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1838 
1839     /**
1840      * Indicates whether the view horizontal layout direction has been resolved.
1841      * @hide
1842      */
1843     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1844 
1845     /**
1846      * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1847      * @hide
1848      */
1849     static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1850             << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1851 
1852     /*
1853      * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1854      * flag value.
1855      * @hide
1856      */
1857     private static final int[] LAYOUT_DIRECTION_FLAGS = {
1858             LAYOUT_DIRECTION_LTR,
1859             LAYOUT_DIRECTION_RTL,
1860             LAYOUT_DIRECTION_INHERIT,
1861             LAYOUT_DIRECTION_LOCALE
1862     };
1863 
1864     /**
1865      * Default horizontal layout direction.
1866      */
1867     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1868 
1869     /**
1870      * Default horizontal layout direction.
1871      * @hide
1872      */
1873     static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1874 
1875     /**
1876      * Indicates that the view is tracking some sort of transient state
1877      * that the app should not need to be aware of, but that the framework
1878      * should take special care to preserve.
1879      *
1880      * @hide
1881      */
1882     static final int PFLAG2_HAS_TRANSIENT_STATE = 0x1 << 22;
1883 
1884     /**
1885      * Text direction is inherited thru {@link ViewGroup}
1886      */
1887     public static final int TEXT_DIRECTION_INHERIT = 0;
1888 
1889     /**
1890      * Text direction is using "first strong algorithm". The first strong directional character
1891      * determines the paragraph direction. If there is no strong directional character, the
1892      * paragraph direction is the view's resolved layout direction.
1893      */
1894     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1895 
1896     /**
1897      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1898      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1899      * If there are neither, the paragraph direction is the view's resolved layout direction.
1900      */
1901     public static final int TEXT_DIRECTION_ANY_RTL = 2;
1902 
1903     /**
1904      * Text direction is forced to LTR.
1905      */
1906     public static final int TEXT_DIRECTION_LTR = 3;
1907 
1908     /**
1909      * Text direction is forced to RTL.
1910      */
1911     public static final int TEXT_DIRECTION_RTL = 4;
1912 
1913     /**
1914      * Text direction is coming from the system Locale.
1915      */
1916     public static final int TEXT_DIRECTION_LOCALE = 5;
1917 
1918     /**
1919      * Default text direction is inherited
1920      */
1921     private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
1922 
1923     /**
1924      * Default resolved text direction
1925      * @hide
1926      */
1927     static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
1928 
1929     /**
1930      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
1931      * @hide
1932      */
1933     static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
1934 
1935     /**
1936      * Mask for use with private flags indicating bits used for text direction.
1937      * @hide
1938      */
1939     static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
1940             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
1941 
1942     /**
1943      * Array of text direction flags for mapping attribute "textDirection" to correct
1944      * flag value.
1945      * @hide
1946      */
1947     private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
1948             TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1949             TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1950             TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1951             TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1952             TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1953             TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
1954     };
1955 
1956     /**
1957      * Indicates whether the view text direction has been resolved.
1958      * @hide
1959      */
1960     static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
1961             << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
1962 
1963     /**
1964      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1965      * @hide
1966      */
1967     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
1968 
1969     /**
1970      * Mask for use with private flags indicating bits used for resolved text direction.
1971      * @hide
1972      */
1973     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
1974             << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
1975 
1976     /**
1977      * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
1978      * @hide
1979      */
1980     static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
1981             TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
1982 
1983     /*
1984      * Default text alignment. The text alignment of this View is inherited from its parent.
1985      * Use with {@link #setTextAlignment(int)}
1986      */
1987     public static final int TEXT_ALIGNMENT_INHERIT = 0;
1988 
1989     /**
1990      * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
1991      * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
1992      *
1993      * Use with {@link #setTextAlignment(int)}
1994      */
1995     public static final int TEXT_ALIGNMENT_GRAVITY = 1;
1996 
1997     /**
1998      * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
1999      *
2000      * Use with {@link #setTextAlignment(int)}
2001      */
2002     public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2003 
2004     /**
2005      * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2006      *
2007      * Use with {@link #setTextAlignment(int)}
2008      */
2009     public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2010 
2011     /**
2012      * Center the paragraph, e.g. ALIGN_CENTER.
2013      *
2014      * Use with {@link #setTextAlignment(int)}
2015      */
2016     public static final int TEXT_ALIGNMENT_CENTER = 4;
2017 
2018     /**
2019      * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2020      * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2021      *
2022      * Use with {@link #setTextAlignment(int)}
2023      */
2024     public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2025 
2026     /**
2027      * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2028      * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2029      *
2030      * Use with {@link #setTextAlignment(int)}
2031      */
2032     public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2033 
2034     /**
2035      * Default text alignment is inherited
2036      */
2037     private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2038 
2039     /**
2040      * Default resolved text alignment
2041      * @hide
2042      */
2043     static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2044 
2045     /**
2046       * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2047       * @hide
2048       */
2049     static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2050 
2051     /**
2052       * Mask for use with private flags indicating bits used for text alignment.
2053       * @hide
2054       */
2055     static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2056 
2057     /**
2058      * Array of text direction flags for mapping attribute "textAlignment" to correct
2059      * flag value.
2060      * @hide
2061      */
2062     private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2063             TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2064             TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2065             TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2066             TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2067             TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2068             TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2069             TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2070     };
2071 
2072     /**
2073      * Indicates whether the view text alignment has been resolved.
2074      * @hide
2075      */
2076     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2077 
2078     /**
2079      * Bit shift to get the resolved text alignment.
2080      * @hide
2081      */
2082     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2083 
2084     /**
2085      * Mask for use with private flags indicating bits used for text alignment.
2086      * @hide
2087      */
2088     static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2089             << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2090 
2091     /**
2092      * Indicates whether if the view text alignment has been resolved to gravity
2093      */
2094     private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2095             TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2096 
2097     // Accessiblity constants for mPrivateFlags2
2098 
2099     /**
2100      * Shift for the bits in {@link #mPrivateFlags2} related to the
2101      * "importantForAccessibility" attribute.
2102      */
2103     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2104 
2105     /**
2106      * Automatically determine whether a view is important for accessibility.
2107      */
2108     public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2109 
2110     /**
2111      * The view is important for accessibility.
2112      */
2113     public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2114 
2115     /**
2116      * The view is not important for accessibility.
2117      */
2118     public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2119 
2120     /**
2121      * The default whether the view is important for accessibility.
2122      */
2123     static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2124 
2125     /**
2126      * Mask for obtainig the bits which specify how to determine
2127      * whether a view is important for accessibility.
2128      */
2129     static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2130         | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO)
2131         << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2132 
2133     /**
2134      * Flag indicating whether a view has accessibility focus.
2135      */
2136     static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x00000040 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2137 
2138     /**
2139      * Flag indicating whether a view state for accessibility has changed.
2140      */
2141     static final int PFLAG2_ACCESSIBILITY_STATE_CHANGED = 0x00000080
2142             << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2143 
2144     /**
2145      * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2146      * is used to check whether later changes to the view's transform should invalidate the
2147      * view to force the quickReject test to run again.
2148      */
2149     static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2150 
2151     /**
2152      * Flag indicating that start/end padding has been resolved into left/right padding
2153      * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2154      * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2155      * during measurement. In some special cases this is required such as when an adapter-based
2156      * view measures prospective children without attaching them to a window.
2157      */
2158     static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2159 
2160     /**
2161      * Flag indicating that the start/end drawables has been resolved into left/right ones.
2162      */
2163     static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2164 
2165     /**
2166      * Group of bits indicating that RTL properties resolution is done.
2167      */
2168     static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2169             PFLAG2_TEXT_DIRECTION_RESOLVED |
2170             PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2171             PFLAG2_PADDING_RESOLVED |
2172             PFLAG2_DRAWABLE_RESOLVED;
2173 
2174     // There are a couple of flags left in mPrivateFlags2
2175 
2176     /* End of masks for mPrivateFlags2 */
2177 
2178     /* Masks for mPrivateFlags3 */
2179 
2180     /**
2181      * Flag indicating that view has a transform animation set on it. This is used to track whether
2182      * an animation is cleared between successive frames, in order to tell the associated
2183      * DisplayList to clear its animation matrix.
2184      */
2185     static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2186 
2187     /**
2188      * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2189      * animation is cleared between successive frames, in order to tell the associated
2190      * DisplayList to restore its alpha value.
2191      */
2192     static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2193 
2194 
2195     /* End of masks for mPrivateFlags3 */
2196 
2197     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2198 
2199     /**
2200      * Always allow a user to over-scroll this view, provided it is a
2201      * view that can scroll.
2202      *
2203      * @see #getOverScrollMode()
2204      * @see #setOverScrollMode(int)
2205      */
2206     public static final int OVER_SCROLL_ALWAYS = 0;
2207 
2208     /**
2209      * Allow a user to over-scroll this view only if the content is large
2210      * enough to meaningfully scroll, provided it is a view that can scroll.
2211      *
2212      * @see #getOverScrollMode()
2213      * @see #setOverScrollMode(int)
2214      */
2215     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2216 
2217     /**
2218      * Never allow a user to over-scroll this view.
2219      *
2220      * @see #getOverScrollMode()
2221      * @see #setOverScrollMode(int)
2222      */
2223     public static final int OVER_SCROLL_NEVER = 2;
2224 
2225     /**
2226      * Special constant for {@link #setSystemUiVisibility(int)}: View has
2227      * requested the system UI (status bar) to be visible (the default).
2228      *
2229      * @see #setSystemUiVisibility(int)
2230      */
2231     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2232 
2233     /**
2234      * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2235      * system UI to enter an unobtrusive "low profile" mode.
2236      *
2237      * <p>This is for use in games, book readers, video players, or any other
2238      * "immersive" application where the usual system chrome is deemed too distracting.
2239      *
2240      * <p>In low profile mode, the status bar and/or navigation icons may dim.
2241      *
2242      * @see #setSystemUiVisibility(int)
2243      */
2244     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2245 
2246     /**
2247      * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2248      * system navigation be temporarily hidden.
2249      *
2250      * <p>This is an even less obtrusive state than that called for by
2251      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2252      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2253      * those to disappear. This is useful (in conjunction with the
2254      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2255      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2256      * window flags) for displaying content using every last pixel on the display.
2257      *
2258      * <p>There is a limitation: because navigation controls are so important, the least user
2259      * interaction will cause them to reappear immediately.  When this happens, both
2260      * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2261      * so that both elements reappear at the same time.
2262      *
2263      * @see #setSystemUiVisibility(int)
2264      */
2265     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2266 
2267     /**
2268      * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2269      * into the normal fullscreen mode so that its content can take over the screen
2270      * while still allowing the user to interact with the application.
2271      *
2272      * <p>This has the same visual effect as
2273      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2274      * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2275      * meaning that non-critical screen decorations (such as the status bar) will be
2276      * hidden while the user is in the View's window, focusing the experience on
2277      * that content.  Unlike the window flag, if you are using ActionBar in
2278      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2279      * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2280      * hide the action bar.
2281      *
2282      * <p>This approach to going fullscreen is best used over the window flag when
2283      * it is a transient state -- that is, the application does this at certain
2284      * points in its user interaction where it wants to allow the user to focus
2285      * on content, but not as a continuous state.  For situations where the application
2286      * would like to simply stay full screen the entire time (such as a game that
2287      * wants to take over the screen), the
2288      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2289      * is usually a better approach.  The state set here will be removed by the system
2290      * in various situations (such as the user moving to another application) like
2291      * the other system UI states.
2292      *
2293      * <p>When using this flag, the application should provide some easy facility
2294      * for the user to go out of it.  A common example would be in an e-book
2295      * reader, where tapping on the screen brings back whatever screen and UI
2296      * decorations that had been hidden while the user was immersed in reading
2297      * the book.
2298      *
2299      * @see #setSystemUiVisibility(int)
2300      */
2301     public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2302 
2303     /**
2304      * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2305      * flags, we would like a stable view of the content insets given to
2306      * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2307      * will always represent the worst case that the application can expect
2308      * as a continuous state.  In the stock Android UI this is the space for
2309      * the system bar, nav bar, and status bar, but not more transient elements
2310      * such as an input method.
2311      *
2312      * The stable layout your UI sees is based on the system UI modes you can
2313      * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2314      * then you will get a stable layout for changes of the
2315      * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2316      * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2317      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2318      * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2319      * with a stable layout.  (Note that you should avoid using
2320      * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2321      *
2322      * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2323      * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2324      * then a hidden status bar will be considered a "stable" state for purposes
2325      * here.  This allows your UI to continually hide the status bar, while still
2326      * using the system UI flags to hide the action bar while still retaining
2327      * a stable layout.  Note that changing the window fullscreen flag will never
2328      * provide a stable layout for a clean transition.
2329      *
2330      * <p>If you are using ActionBar in
2331      * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2332      * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2333      * insets it adds to those given to the application.
2334      */
2335     public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2336 
2337     /**
2338      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2339      * to be layed out as if it has requested
2340      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2341      * allows it to avoid artifacts when switching in and out of that mode, at
2342      * the expense that some of its user interface may be covered by screen
2343      * decorations when they are shown.  You can perform layout of your inner
2344      * UI elements to account for the navagation system UI through the
2345      * {@link #fitSystemWindows(Rect)} method.
2346      */
2347     public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2348 
2349     /**
2350      * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2351      * to be layed out as if it has requested
2352      * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2353      * allows it to avoid artifacts when switching in and out of that mode, at
2354      * the expense that some of its user interface may be covered by screen
2355      * decorations when they are shown.  You can perform layout of your inner
2356      * UI elements to account for non-fullscreen system UI through the
2357      * {@link #fitSystemWindows(Rect)} method.
2358      */
2359     public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2360 
2361     /**
2362      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2363      */
2364     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2365 
2366     /**
2367      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2368      */
2369     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2370 
2371     /**
2372      * @hide
2373      *
2374      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2375      * out of the public fields to keep the undefined bits out of the developer's way.
2376      *
2377      * Flag to make the status bar not expandable.  Unless you also
2378      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2379      */
2380     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2381 
2382     /**
2383      * @hide
2384      *
2385      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2386      * out of the public fields to keep the undefined bits out of the developer's way.
2387      *
2388      * Flag to hide notification icons and scrolling ticker text.
2389      */
2390     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2391 
2392     /**
2393      * @hide
2394      *
2395      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2396      * out of the public fields to keep the undefined bits out of the developer's way.
2397      *
2398      * Flag to disable incoming notification alerts.  This will not block
2399      * icons, but it will block sound, vibrating and other visual or aural notifications.
2400      */
2401     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2402 
2403     /**
2404      * @hide
2405      *
2406      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2407      * out of the public fields to keep the undefined bits out of the developer's way.
2408      *
2409      * Flag to hide only the scrolling ticker.  Note that
2410      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2411      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2412      */
2413     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2414 
2415     /**
2416      * @hide
2417      *
2418      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2419      * out of the public fields to keep the undefined bits out of the developer's way.
2420      *
2421      * Flag to hide the center system info area.
2422      */
2423     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2424 
2425     /**
2426      * @hide
2427      *
2428      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2429      * out of the public fields to keep the undefined bits out of the developer's way.
2430      *
2431      * Flag to hide only the home button.  Don't use this
2432      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2433      */
2434     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2435 
2436     /**
2437      * @hide
2438      *
2439      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2440      * out of the public fields to keep the undefined bits out of the developer's way.
2441      *
2442      * Flag to hide only the back button. Don't use this
2443      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2444      */
2445     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2446 
2447     /**
2448      * @hide
2449      *
2450      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2451      * out of the public fields to keep the undefined bits out of the developer's way.
2452      *
2453      * Flag to hide only the clock.  You might use this if your activity has
2454      * its own clock making the status bar's clock redundant.
2455      */
2456     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2457 
2458     /**
2459      * @hide
2460      *
2461      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2462      * out of the public fields to keep the undefined bits out of the developer's way.
2463      *
2464      * Flag to hide only the recent apps button. Don't use this
2465      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2466      */
2467     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2468 
2469     /**
2470      * @hide
2471      *
2472      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2473      * out of the public fields to keep the undefined bits out of the developer's way.
2474      *
2475      * Flag to disable the global search gesture. Don't use this
2476      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2477      */
2478     public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2479 
2480     /**
2481      * @hide
2482      */
2483     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
2484 
2485     /**
2486      * These are the system UI flags that can be cleared by events outside
2487      * of an application.  Currently this is just the ability to tap on the
2488      * screen while hiding the navigation bar to have it return.
2489      * @hide
2490      */
2491     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2492             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2493             | SYSTEM_UI_FLAG_FULLSCREEN;
2494 
2495     /**
2496      * Flags that can impact the layout in relation to system UI.
2497      */
2498     public static final int SYSTEM_UI_LAYOUT_FLAGS =
2499             SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2500             | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2501 
2502     /**
2503      * Find views that render the specified text.
2504      *
2505      * @see #findViewsWithText(ArrayList, CharSequence, int)
2506      */
2507     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2508 
2509     /**
2510      * Find find views that contain the specified content description.
2511      *
2512      * @see #findViewsWithText(ArrayList, CharSequence, int)
2513      */
2514     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2515 
2516     /**
2517      * Find views that contain {@link AccessibilityNodeProvider}. Such
2518      * a View is a root of virtual view hierarchy and may contain the searched
2519      * text. If this flag is set Views with providers are automatically
2520      * added and it is a responsibility of the client to call the APIs of
2521      * the provider to determine whether the virtual tree rooted at this View
2522      * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2523      * represeting the virtual views with this text.
2524      *
2525      * @see #findViewsWithText(ArrayList, CharSequence, int)
2526      *
2527      * @hide
2528      */
2529     public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2530 
2531     /**
2532      * The undefined cursor position.
2533      *
2534      * @hide
2535      */
2536     public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2537 
2538     /**
2539      * Indicates that the screen has changed state and is now off.
2540      *
2541      * @see #onScreenStateChanged(int)
2542      */
2543     public static final int SCREEN_STATE_OFF = 0x0;
2544 
2545     /**
2546      * Indicates that the screen has changed state and is now on.
2547      *
2548      * @see #onScreenStateChanged(int)
2549      */
2550     public static final int SCREEN_STATE_ON = 0x1;
2551 
2552     /**
2553      * Controls the over-scroll mode for this view.
2554      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2555      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2556      * and {@link #OVER_SCROLL_NEVER}.
2557      */
2558     private int mOverScrollMode;
2559 
2560     /**
2561      * The parent this view is attached to.
2562      * {@hide}
2563      *
2564      * @see #getParent()
2565      */
2566     protected ViewParent mParent;
2567 
2568     /**
2569      * {@hide}
2570      */
2571     AttachInfo mAttachInfo;
2572 
2573     /**
2574      * {@hide}
2575      */
2576     @ViewDebug.ExportedProperty(flagMapping = {
2577         @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2578                 name = "FORCE_LAYOUT"),
2579         @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2580                 name = "LAYOUT_REQUIRED"),
2581         @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2582             name = "DRAWING_CACHE_INVALID", outputIf = false),
2583         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2584         @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2585         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2586         @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2587     })
2588     int mPrivateFlags;
2589     int mPrivateFlags2;
2590     int mPrivateFlags3;
2591 
2592     /**
2593      * This view's request for the visibility of the status bar.
2594      * @hide
2595      */
2596     @ViewDebug.ExportedProperty(flagMapping = {
2597         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2598                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2599                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2600         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2601                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2602                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2603         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2604                                 equals = SYSTEM_UI_FLAG_VISIBLE,
2605                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2606     })
2607     int mSystemUiVisibility;
2608 
2609     /**
2610      * Reference count for transient state.
2611      * @see #setHasTransientState(boolean)
2612      */
2613     int mTransientStateCount = 0;
2614 
2615     /**
2616      * Count of how many windows this view has been attached to.
2617      */
2618     int mWindowAttachCount;
2619 
2620     /**
2621      * The layout parameters associated with this view and used by the parent
2622      * {@link android.view.ViewGroup} to determine how this view should be
2623      * laid out.
2624      * {@hide}
2625      */
2626     protected ViewGroup.LayoutParams mLayoutParams;
2627 
2628     /**
2629      * The view flags hold various views states.
2630      * {@hide}
2631      */
2632     @ViewDebug.ExportedProperty
2633     int mViewFlags;
2634 
2635     static class TransformationInfo {
2636         /**
2637          * The transform matrix for the View. This transform is calculated internally
2638          * based on the rotation, scaleX, and scaleY properties. The identity matrix
2639          * is used by default. Do *not* use this variable directly; instead call
2640          * getMatrix(), which will automatically recalculate the matrix if necessary
2641          * to get the correct matrix based on the latest rotation and scale properties.
2642          */
2643         private final Matrix mMatrix = new Matrix();
2644 
2645         /**
2646          * The transform matrix for the View. This transform is calculated internally
2647          * based on the rotation, scaleX, and scaleY properties. The identity matrix
2648          * is used by default. Do *not* use this variable directly; instead call
2649          * getInverseMatrix(), which will automatically recalculate the matrix if necessary
2650          * to get the correct matrix based on the latest rotation and scale properties.
2651          */
2652         private Matrix mInverseMatrix;
2653 
2654         /**
2655          * An internal variable that tracks whether we need to recalculate the
2656          * transform matrix, based on whether the rotation or scaleX/Y properties
2657          * have changed since the matrix was last calculated.
2658          */
2659         boolean mMatrixDirty = false;
2660 
2661         /**
2662          * An internal variable that tracks whether we need to recalculate the
2663          * transform matrix, based on whether the rotation or scaleX/Y properties
2664          * have changed since the matrix was last calculated.
2665          */
2666         private boolean mInverseMatrixDirty = true;
2667 
2668         /**
2669          * A variable that tracks whether we need to recalculate the
2670          * transform matrix, based on whether the rotation or scaleX/Y properties
2671          * have changed since the matrix was last calculated. This variable
2672          * is only valid after a call to updateMatrix() or to a function that
2673          * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
2674          */
2675         private boolean mMatrixIsIdentity = true;
2676 
2677         /**
2678          * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
2679          */
2680         private Camera mCamera = null;
2681 
2682         /**
2683          * This matrix is used when computing the matrix for 3D rotations.
2684          */
2685         private Matrix matrix3D = null;
2686 
2687         /**
2688          * These prev values are used to recalculate a centered pivot point when necessary. The
2689          * pivot point is only used in matrix operations (when rotation, scale, or translation are
2690          * set), so thes values are only used then as well.
2691          */
2692         private int mPrevWidth = -1;
2693         private int mPrevHeight = -1;
2694 
2695         /**
2696          * The degrees rotation around the vertical axis through the pivot point.
2697          */
2698         @ViewDebug.ExportedProperty
2699         float mRotationY = 0f;
2700 
2701         /**
2702          * The degrees rotation around the horizontal axis through the pivot point.
2703          */
2704         @ViewDebug.ExportedProperty
2705         float mRotationX = 0f;
2706 
2707         /**
2708          * The degrees rotation around the pivot point.
2709          */
2710         @ViewDebug.ExportedProperty
2711         float mRotation = 0f;
2712 
2713         /**
2714          * The amount of translation of the object away from its left property (post-layout).
2715          */
2716         @ViewDebug.ExportedProperty
2717         float mTranslationX = 0f;
2718 
2719         /**
2720          * The amount of translation of the object away from its top property (post-layout).
2721          */
2722         @ViewDebug.ExportedProperty
2723         float mTranslationY = 0f;
2724 
2725         /**
2726          * The amount of scale in the x direction around the pivot point. A
2727          * value of 1 means no scaling is applied.
2728          */
2729         @ViewDebug.ExportedProperty
2730         float mScaleX = 1f;
2731 
2732         /**
2733          * The amount of scale in the y direction around the pivot point. A
2734          * value of 1 means no scaling is applied.
2735          */
2736         @ViewDebug.ExportedProperty
2737         float mScaleY = 1f;
2738 
2739         /**
2740          * The x location of the point around which the view is rotated and scaled.
2741          */
2742         @ViewDebug.ExportedProperty
2743         float mPivotX = 0f;
2744 
2745         /**
2746          * The y location of the point around which the view is rotated and scaled.
2747          */
2748         @ViewDebug.ExportedProperty
2749         float mPivotY = 0f;
2750 
2751         /**
2752          * The opacity of the View. This is a value from 0 to 1, where 0 means
2753          * completely transparent and 1 means completely opaque.
2754          */
2755         @ViewDebug.ExportedProperty
2756         float mAlpha = 1f;
2757     }
2758 
2759     TransformationInfo mTransformationInfo;
2760 
2761     /**
2762      * Current clip bounds. to which all drawing of this view are constrained.
2763      */
2764     private Rect mClipBounds = null;
2765 
2766     private boolean mLastIsOpaque;
2767 
2768     /**
2769      * Convenience value to check for float values that are close enough to zero to be considered
2770      * zero.
2771      */
2772     private static final float NONZERO_EPSILON = .001f;
2773 
2774     /**
2775      * The distance in pixels from the left edge of this view's parent
2776      * to the left edge of this view.
2777      * {@hide}
2778      */
2779     @ViewDebug.ExportedProperty(category = "layout")
2780     protected int mLeft;
2781     /**
2782      * The distance in pixels from the left edge of this view's parent
2783      * to the right edge of this view.
2784      * {@hide}
2785      */
2786     @ViewDebug.ExportedProperty(category = "layout")
2787     protected int mRight;
2788     /**
2789      * The distance in pixels from the top edge of this view's parent
2790      * to the top edge of this view.
2791      * {@hide}
2792      */
2793     @ViewDebug.ExportedProperty(category = "layout")
2794     protected int mTop;
2795     /**
2796      * The distance in pixels from the top edge of this view's parent
2797      * to the bottom edge of this view.
2798      * {@hide}
2799      */
2800     @ViewDebug.ExportedProperty(category = "layout")
2801     protected int mBottom;
2802 
2803     /**
2804      * The offset, in pixels, by which the content of this view is scrolled
2805      * horizontally.
2806      * {@hide}
2807      */
2808     @ViewDebug.ExportedProperty(category = "scrolling")
2809     protected int mScrollX;
2810     /**
2811      * The offset, in pixels, by which the content of this view is scrolled
2812      * vertically.
2813      * {@hide}
2814      */
2815     @ViewDebug.ExportedProperty(category = "scrolling")
2816     protected int mScrollY;
2817 
2818     /**
2819      * The left padding in pixels, that is the distance in pixels between the
2820      * left edge of this view and the left edge of its content.
2821      * {@hide}
2822      */
2823     @ViewDebug.ExportedProperty(category = "padding")
2824     protected int mPaddingLeft = 0;
2825     /**
2826      * The right padding in pixels, that is the distance in pixels between the
2827      * right edge of this view and the right edge of its content.
2828      * {@hide}
2829      */
2830     @ViewDebug.ExportedProperty(category = "padding")
2831     protected int mPaddingRight = 0;
2832     /**
2833      * The top padding in pixels, that is the distance in pixels between the
2834      * top edge of this view and the top edge of its content.
2835      * {@hide}
2836      */
2837     @ViewDebug.ExportedProperty(category = "padding")
2838     protected int mPaddingTop;
2839     /**
2840      * The bottom padding in pixels, that is the distance in pixels between the
2841      * bottom edge of this view and the bottom edge of its content.
2842      * {@hide}
2843      */
2844     @ViewDebug.ExportedProperty(category = "padding")
2845     protected int mPaddingBottom;
2846 
2847     /**
2848      * The layout insets in pixels, that is the distance in pixels between the
2849      * visible edges of this view its bounds.
2850      */
2851     private Insets mLayoutInsets;
2852 
2853     /**
2854      * Briefly describes the view and is primarily used for accessibility support.
2855      */
2856     private CharSequence mContentDescription;
2857 
2858     /**
2859      * Specifies the id of a view for which this view serves as a label for
2860      * accessibility purposes.
2861      */
2862     private int mLabelForId = View.NO_ID;
2863 
2864     /**
2865      * Predicate for matching labeled view id with its label for
2866      * accessibility purposes.
2867      */
2868     private MatchLabelForPredicate mMatchLabelForPredicate;
2869 
2870     /**
2871      * Predicate for matching a view by its id.
2872      */
2873     private MatchIdPredicate mMatchIdPredicate;
2874 
2875     /**
2876      * Cache the paddingRight set by the user to append to the scrollbar's size.
2877      *
2878      * @hide
2879      */
2880     @ViewDebug.ExportedProperty(category = "padding")
2881     protected int mUserPaddingRight;
2882 
2883     /**
2884      * Cache the paddingBottom set by the user to append to the scrollbar's size.
2885      *
2886      * @hide
2887      */
2888     @ViewDebug.ExportedProperty(category = "padding")
2889     protected int mUserPaddingBottom;
2890 
2891     /**
2892      * Cache the paddingLeft set by the user to append to the scrollbar's size.
2893      *
2894      * @hide
2895      */
2896     @ViewDebug.ExportedProperty(category = "padding")
2897     protected int mUserPaddingLeft;
2898 
2899     /**
2900      * Cache the paddingStart set by the user to append to the scrollbar's size.
2901      *
2902      */
2903     @ViewDebug.ExportedProperty(category = "padding")
2904     int mUserPaddingStart;
2905 
2906     /**
2907      * Cache the paddingEnd set by the user to append to the scrollbar's size.
2908      *
2909      */
2910     @ViewDebug.ExportedProperty(category = "padding")
2911     int mUserPaddingEnd;
2912 
2913     /**
2914      * Cache initial left padding.
2915      *
2916      * @hide
2917      */
2918     int mUserPaddingLeftInitial;
2919 
2920     /**
2921      * Cache initial right padding.
2922      *
2923      * @hide
2924      */
2925     int mUserPaddingRightInitial;
2926 
2927     /**
2928      * Default undefined padding
2929      */
2930     private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
2931 
2932     /**
2933      * @hide
2934      */
2935     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
2936     /**
2937      * @hide
2938      */
2939     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
2940 
2941     @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
2942     private Drawable mBackground;
2943 
2944     private int mBackgroundResource;
2945     private boolean mBackgroundSizeChanged;
2946 
2947     static class ListenerInfo {
2948         /**
2949          * Listener used to dispatch focus change events.
2950          * This field should be made private, so it is hidden from the SDK.
2951          * {@hide}
2952          */
2953         protected OnFocusChangeListener mOnFocusChangeListener;
2954 
2955         /**
2956          * Listeners for layout change events.
2957          */
2958         private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
2959 
2960         /**
2961          * Listeners for attach events.
2962          */
2963         private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
2964 
2965         /**
2966          * Listener used to dispatch click events.
2967          * This field should be made private, so it is hidden from the SDK.
2968          * {@hide}
2969          */
2970         public OnClickListener mOnClickListener;
2971 
2972         /**
2973          * Listener used to dispatch long click events.
2974          * This field should be made private, so it is hidden from the SDK.
2975          * {@hide}
2976          */
2977         protected OnLongClickListener mOnLongClickListener;
2978 
2979         /**
2980          * Listener used to build the context menu.
2981          * This field should be made private, so it is hidden from the SDK.
2982          * {@hide}
2983          */
2984         protected OnCreateContextMenuListener mOnCreateContextMenuListener;
2985 
2986         private OnKeyListener mOnKeyListener;
2987 
2988         private OnTouchListener mOnTouchListener;
2989 
2990         private OnHoverListener mOnHoverListener;
2991 
2992         private OnGenericMotionListener mOnGenericMotionListener;
2993 
2994         private OnDragListener mOnDragListener;
2995 
2996         private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
2997     }
2998 
2999     ListenerInfo mListenerInfo;
3000 
3001     /**
3002      * The application environment this view lives in.
3003      * This field should be made private, so it is hidden from the SDK.
3004      * {@hide}
3005      */
3006     protected Context mContext;
3007 
3008     private final Resources mResources;
3009 
3010     private ScrollabilityCache mScrollCache;
3011 
3012     private int[] mDrawableState = null;
3013 
3014     /**
3015      * Set to true when drawing cache is enabled and cannot be created.
3016      *
3017      * @hide
3018      */
3019     public boolean mCachingFailed;
3020 
3021     private Bitmap mDrawingCache;
3022     private Bitmap mUnscaledDrawingCache;
3023     private HardwareLayer mHardwareLayer;
3024     DisplayList mDisplayList;
3025 
3026     /**
3027      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3028      * the user may specify which view to go to next.
3029      */
3030     private int mNextFocusLeftId = View.NO_ID;
3031 
3032     /**
3033      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3034      * the user may specify which view to go to next.
3035      */
3036     private int mNextFocusRightId = View.NO_ID;
3037 
3038     /**
3039      * When this view has focus and the next focus is {@link #FOCUS_UP},
3040      * the user may specify which view to go to next.
3041      */
3042     private int mNextFocusUpId = View.NO_ID;
3043 
3044     /**
3045      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3046      * the user may specify which view to go to next.
3047      */
3048     private int mNextFocusDownId = View.NO_ID;
3049 
3050     /**
3051      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3052      * the user may specify which view to go to next.
3053      */
3054     int mNextFocusForwardId = View.NO_ID;
3055 
3056     private CheckForLongPress mPendingCheckForLongPress;
3057     private CheckForTap mPendingCheckForTap = null;
3058     private PerformClick mPerformClick;
3059     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3060 
3061     private UnsetPressedState mUnsetPressedState;
3062 
3063     /**
3064      * Whether the long press's action has been invoked.  The tap's action is invoked on the
3065      * up event while a long press is invoked as soon as the long press duration is reached, so
3066      * a long press could be performed before the tap is checked, in which case the tap's action
3067      * should not be invoked.
3068      */
3069     private boolean mHasPerformedLongPress;
3070 
3071     /**
3072      * The minimum height of the view. We'll try our best to have the height
3073      * of this view to at least this amount.
3074      */
3075     @ViewDebug.ExportedProperty(category = "measurement")
3076     private int mMinHeight;
3077 
3078     /**
3079      * The minimum width of the view. We'll try our best to have the width
3080      * of this view to at least this amount.
3081      */
3082     @ViewDebug.ExportedProperty(category = "measurement")
3083     private int mMinWidth;
3084 
3085     /**
3086      * The delegate to handle touch events that are physically in this view
3087      * but should be handled by another view.
3088      */
3089     private TouchDelegate mTouchDelegate = null;
3090 
3091     /**
3092      * Solid color to use as a background when creating the drawing cache. Enables
3093      * the cache to use 16 bit bitmaps instead of 32 bit.
3094      */
3095     private int mDrawingCacheBackgroundColor = 0;
3096 
3097     /**
3098      * Special tree observer used when mAttachInfo is null.
3099      */
3100     private ViewTreeObserver mFloatingTreeObserver;
3101 
3102     /**
3103      * Cache the touch slop from the context that created the view.
3104      */
3105     private int mTouchSlop;
3106 
3107     /**
3108      * Object that handles automatic animation of view properties.
3109      */
3110     private ViewPropertyAnimator mAnimator = null;
3111 
3112     /**
3113      * Flag indicating that a drag can cross window boundaries.  When
3114      * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3115      * with this flag set, all visible applications will be able to participate
3116      * in the drag operation and receive the dragged content.
3117      *
3118      * @hide
3119      */
3120     public static final int DRAG_FLAG_GLOBAL = 1;
3121 
3122     /**
3123      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3124      */
3125     private float mVerticalScrollFactor;
3126 
3127     /**
3128      * Position of the vertical scroll bar.
3129      */
3130     private int mVerticalScrollbarPosition;
3131 
3132     /**
3133      * Position the scroll bar at the default position as determined by the system.
3134      */
3135     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3136 
3137     /**
3138      * Position the scroll bar along the left edge.
3139      */
3140     public static final int SCROLLBAR_POSITION_LEFT = 1;
3141 
3142     /**
3143      * Position the scroll bar along the right edge.
3144      */
3145     public static final int SCROLLBAR_POSITION_RIGHT = 2;
3146 
3147     /**
3148      * Indicates that the view does not have a layer.
3149      *
3150      * @see #getLayerType()
3151      * @see #setLayerType(int, android.graphics.Paint)
3152      * @see #LAYER_TYPE_SOFTWARE
3153      * @see #LAYER_TYPE_HARDWARE
3154      */
3155     public static final int LAYER_TYPE_NONE = 0;
3156 
3157     /**
3158      * <p>Indicates that the view has a software layer. A software layer is backed
3159      * by a bitmap and causes the view to be rendered using Android's software
3160      * rendering pipeline, even if hardware acceleration is enabled.</p>
3161      *
3162      * <p>Software layers have various usages:</p>
3163      * <p>When the application is not using hardware acceleration, a software layer
3164      * is useful to apply a specific color filter and/or blending mode and/or
3165      * translucency to a view and all its children.</p>
3166      * <p>When the application is using hardware acceleration, a software layer
3167      * is useful to render drawing primitives not supported by the hardware
3168      * accelerated pipeline. It can also be used to cache a complex view tree
3169      * into a texture and reduce the complexity of drawing operations. For instance,
3170      * when animating a complex view tree with a translation, a software layer can
3171      * be used to render the view tree only once.</p>
3172      * <p>Software layers should be avoided when the affected view tree updates
3173      * often. Every update will require to re-render the software layer, which can
3174      * potentially be slow (particularly when hardware acceleration is turned on
3175      * since the layer will have to be uploaded into a hardware texture after every
3176      * update.)</p>
3177      *
3178      * @see #getLayerType()
3179      * @see #setLayerType(int, android.graphics.Paint)
3180      * @see #LAYER_TYPE_NONE
3181      * @see #LAYER_TYPE_HARDWARE
3182      */
3183     public static final int LAYER_TYPE_SOFTWARE = 1;
3184 
3185     /**
3186      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3187      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3188      * OpenGL hardware) and causes the view to be rendered using Android's hardware
3189      * rendering pipeline, but only if hardware acceleration is turned on for the
3190      * view hierarchy. When hardware acceleration is turned off, hardware layers
3191      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3192      *
3193      * <p>A hardware layer is useful to apply a specific color filter and/or
3194      * blending mode and/or translucency to a view and all its children.</p>
3195      * <p>A hardware layer can be used to cache a complex view tree into a
3196      * texture and reduce the complexity of drawing operations. For instance,
3197      * when animating a complex view tree with a translation, a hardware layer can
3198      * be used to render the view tree only once.</p>
3199      * <p>A hardware layer can also be used to increase the rendering quality when
3200      * rotation transformations are applied on a view. It can also be used to
3201      * prevent potential clipping issues when applying 3D transforms on a view.</p>
3202      *
3203      * @see #getLayerType()
3204      * @see #setLayerType(int, android.graphics.Paint)
3205      * @see #LAYER_TYPE_NONE
3206      * @see #LAYER_TYPE_SOFTWARE
3207      */
3208     public static final int LAYER_TYPE_HARDWARE = 2;
3209 
3210     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3211             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3212             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3213             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3214     })
3215     int mLayerType = LAYER_TYPE_NONE;
3216     Paint mLayerPaint;
3217     Rect mLocalDirtyRect;
3218 
3219     /**
3220      * Set to true when the view is sending hover accessibility events because it
3221      * is the innermost hovered view.
3222      */
3223     private boolean mSendingHoverAccessibilityEvents;
3224 
3225     /**
3226      * Delegate for injecting accessibility functionality.
3227      */
3228     AccessibilityDelegate mAccessibilityDelegate;
3229 
3230     /**
3231      * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3232      * and add/remove objects to/from the overlay directly through the Overlay methods.
3233      */
3234     ViewOverlay mOverlay;
3235 
3236     /**
3237      * Consistency verifier for debugging purposes.
3238      * @hide
3239      */
3240     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3241             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3242                     new InputEventConsistencyVerifier(this, 0) : null;
3243 
3244     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3245 
3246     /**
3247      * Simple constructor to use when creating a view from code.
3248      *
3249      * @param context The Context the view is running in, through which it can
3250      *        access the current theme, resources, etc.
3251      */
View(Context context)3252     public View(Context context) {
3253         mContext = context;
3254         mResources = context != null ? context.getResources() : null;
3255         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3256         // Set some flags defaults
3257         mPrivateFlags2 =
3258                 (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3259                 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3260                 (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3261                 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3262                 (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3263                 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3264         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3265         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3266         mUserPaddingStart = UNDEFINED_PADDING;
3267         mUserPaddingEnd = UNDEFINED_PADDING;
3268 
3269         if (!sUseBrokenMakeMeasureSpec && context.getApplicationInfo().targetSdkVersion <=
3270                 Build.VERSION_CODES.JELLY_BEAN_MR1 ) {
3271             // Older apps may need this compatibility hack for measurement.
3272             sUseBrokenMakeMeasureSpec = true;
3273         }
3274     }
3275 
3276     /**
3277      * Constructor that is called when inflating a view from XML. This is called
3278      * when a view is being constructed from an XML file, supplying attributes
3279      * that were specified in the XML file. This version uses a default style of
3280      * 0, so the only attribute values applied are those in the Context's Theme
3281      * and the given AttributeSet.
3282      *
3283      * <p>
3284      * The method onFinishInflate() will be called after all children have been
3285      * added.
3286      *
3287      * @param context The Context the view is running in, through which it can
3288      *        access the current theme, resources, etc.
3289      * @param attrs The attributes of the XML tag that is inflating the view.
3290      * @see #View(Context, AttributeSet, int)
3291      */
View(Context context, AttributeSet attrs)3292     public View(Context context, AttributeSet attrs) {
3293         this(context, attrs, 0);
3294     }
3295 
3296     /**
3297      * Perform inflation from XML and apply a class-specific base style. This
3298      * constructor of View allows subclasses to use their own base style when
3299      * they are inflating. For example, a Button class's constructor would call
3300      * this version of the super class constructor and supply
3301      * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
3302      * the theme's button style to modify all of the base view attributes (in
3303      * particular its background) as well as the Button class's attributes.
3304      *
3305      * @param context The Context the view is running in, through which it can
3306      *        access the current theme, resources, etc.
3307      * @param attrs The attributes of the XML tag that is inflating the view.
3308      * @param defStyle The default style to apply to this view. If 0, no style
3309      *        will be applied (beyond what is included in the theme). This may
3310      *        either be an attribute resource, whose value will be retrieved
3311      *        from the current theme, or an explicit style resource.
3312      * @see #View(Context, AttributeSet)
3313      */
View(Context context, AttributeSet attrs, int defStyle)3314     public View(Context context, AttributeSet attrs, int defStyle) {
3315         this(context);
3316 
3317         TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
3318                 defStyle, 0);
3319 
3320         Drawable background = null;
3321 
3322         int leftPadding = -1;
3323         int topPadding = -1;
3324         int rightPadding = -1;
3325         int bottomPadding = -1;
3326         int startPadding = UNDEFINED_PADDING;
3327         int endPadding = UNDEFINED_PADDING;
3328 
3329         int padding = -1;
3330 
3331         int viewFlagValues = 0;
3332         int viewFlagMasks = 0;
3333 
3334         boolean setScrollContainer = false;
3335 
3336         int x = 0;
3337         int y = 0;
3338 
3339         float tx = 0;
3340         float ty = 0;
3341         float rotation = 0;
3342         float rotationX = 0;
3343         float rotationY = 0;
3344         float sx = 1f;
3345         float sy = 1f;
3346         boolean transformSet = false;
3347 
3348         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3349         int overScrollMode = mOverScrollMode;
3350         boolean initializeScrollbars = false;
3351 
3352         boolean leftPaddingDefined = false;
3353         boolean rightPaddingDefined = false;
3354         boolean startPaddingDefined = false;
3355         boolean endPaddingDefined = false;
3356 
3357         final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3358 
3359         final int N = a.getIndexCount();
3360         for (int i = 0; i < N; i++) {
3361             int attr = a.getIndex(i);
3362             switch (attr) {
3363                 case com.android.internal.R.styleable.View_background:
3364                     background = a.getDrawable(attr);
3365                     break;
3366                 case com.android.internal.R.styleable.View_padding:
3367                     padding = a.getDimensionPixelSize(attr, -1);
3368                     mUserPaddingLeftInitial = padding;
3369                     mUserPaddingRightInitial = padding;
3370                     leftPaddingDefined = true;
3371                     rightPaddingDefined = true;
3372                     break;
3373                  case com.android.internal.R.styleable.View_paddingLeft:
3374                     leftPadding = a.getDimensionPixelSize(attr, -1);
3375                     mUserPaddingLeftInitial = leftPadding;
3376                     leftPaddingDefined = true;
3377                     break;
3378                 case com.android.internal.R.styleable.View_paddingTop:
3379                     topPadding = a.getDimensionPixelSize(attr, -1);
3380                     break;
3381                 case com.android.internal.R.styleable.View_paddingRight:
3382                     rightPadding = a.getDimensionPixelSize(attr, -1);
3383                     mUserPaddingRightInitial = rightPadding;
3384                     rightPaddingDefined = true;
3385                     break;
3386                 case com.android.internal.R.styleable.View_paddingBottom:
3387                     bottomPadding = a.getDimensionPixelSize(attr, -1);
3388                     break;
3389                 case com.android.internal.R.styleable.View_paddingStart:
3390                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3391                     startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3392                     break;
3393                 case com.android.internal.R.styleable.View_paddingEnd:
3394                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3395                     endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3396                     break;
3397                 case com.android.internal.R.styleable.View_scrollX:
3398                     x = a.getDimensionPixelOffset(attr, 0);
3399                     break;
3400                 case com.android.internal.R.styleable.View_scrollY:
3401                     y = a.getDimensionPixelOffset(attr, 0);
3402                     break;
3403                 case com.android.internal.R.styleable.View_alpha:
3404                     setAlpha(a.getFloat(attr, 1f));
3405                     break;
3406                 case com.android.internal.R.styleable.View_transformPivotX:
3407                     setPivotX(a.getDimensionPixelOffset(attr, 0));
3408                     break;
3409                 case com.android.internal.R.styleable.View_transformPivotY:
3410                     setPivotY(a.getDimensionPixelOffset(attr, 0));
3411                     break;
3412                 case com.android.internal.R.styleable.View_translationX:
3413                     tx = a.getDimensionPixelOffset(attr, 0);
3414                     transformSet = true;
3415                     break;
3416                 case com.android.internal.R.styleable.View_translationY:
3417                     ty = a.getDimensionPixelOffset(attr, 0);
3418                     transformSet = true;
3419                     break;
3420                 case com.android.internal.R.styleable.View_rotation:
3421                     rotation = a.getFloat(attr, 0);
3422                     transformSet = true;
3423                     break;
3424                 case com.android.internal.R.styleable.View_rotationX:
3425                     rotationX = a.getFloat(attr, 0);
3426                     transformSet = true;
3427                     break;
3428                 case com.android.internal.R.styleable.View_rotationY:
3429                     rotationY = a.getFloat(attr, 0);
3430                     transformSet = true;
3431                     break;
3432                 case com.android.internal.R.styleable.View_scaleX:
3433                     sx = a.getFloat(attr, 1f);
3434                     transformSet = true;
3435                     break;
3436                 case com.android.internal.R.styleable.View_scaleY:
3437                     sy = a.getFloat(attr, 1f);
3438                     transformSet = true;
3439                     break;
3440                 case com.android.internal.R.styleable.View_id:
3441                     mID = a.getResourceId(attr, NO_ID);
3442                     break;
3443                 case com.android.internal.R.styleable.View_tag:
3444                     mTag = a.getText(attr);
3445                     break;
3446                 case com.android.internal.R.styleable.View_fitsSystemWindows:
3447                     if (a.getBoolean(attr, false)) {
3448                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
3449                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3450                     }
3451                     break;
3452                 case com.android.internal.R.styleable.View_focusable:
3453                     if (a.getBoolean(attr, false)) {
3454                         viewFlagValues |= FOCUSABLE;
3455                         viewFlagMasks |= FOCUSABLE_MASK;
3456                     }
3457                     break;
3458                 case com.android.internal.R.styleable.View_focusableInTouchMode:
3459                     if (a.getBoolean(attr, false)) {
3460                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3461                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3462                     }
3463                     break;
3464                 case com.android.internal.R.styleable.View_clickable:
3465                     if (a.getBoolean(attr, false)) {
3466                         viewFlagValues |= CLICKABLE;
3467                         viewFlagMasks |= CLICKABLE;
3468                     }
3469                     break;
3470                 case com.android.internal.R.styleable.View_longClickable:
3471                     if (a.getBoolean(attr, false)) {
3472                         viewFlagValues |= LONG_CLICKABLE;
3473                         viewFlagMasks |= LONG_CLICKABLE;
3474                     }
3475                     break;
3476                 case com.android.internal.R.styleable.View_saveEnabled:
3477                     if (!a.getBoolean(attr, true)) {
3478                         viewFlagValues |= SAVE_DISABLED;
3479                         viewFlagMasks |= SAVE_DISABLED_MASK;
3480                     }
3481                     break;
3482                 case com.android.internal.R.styleable.View_duplicateParentState:
3483                     if (a.getBoolean(attr, false)) {
3484                         viewFlagValues |= DUPLICATE_PARENT_STATE;
3485                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
3486                     }
3487                     break;
3488                 case com.android.internal.R.styleable.View_visibility:
3489                     final int visibility = a.getInt(attr, 0);
3490                     if (visibility != 0) {
3491                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
3492                         viewFlagMasks |= VISIBILITY_MASK;
3493                     }
3494                     break;
3495                 case com.android.internal.R.styleable.View_layoutDirection:
3496                     // Clear any layout direction flags (included resolved bits) already set
3497                     mPrivateFlags2 &=
3498                             ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3499                     // Set the layout direction flags depending on the value of the attribute
3500                     final int layoutDirection = a.getInt(attr, -1);
3501                     final int value = (layoutDirection != -1) ?
3502                             LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3503                     mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3504                     break;
3505                 case com.android.internal.R.styleable.View_drawingCacheQuality:
3506                     final int cacheQuality = a.getInt(attr, 0);
3507                     if (cacheQuality != 0) {
3508                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3509                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3510                     }
3511                     break;
3512                 case com.android.internal.R.styleable.View_contentDescription:
3513                     setContentDescription(a.getString(attr));
3514                     break;
3515                 case com.android.internal.R.styleable.View_labelFor:
3516                     setLabelFor(a.getResourceId(attr, NO_ID));
3517                     break;
3518                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
3519                     if (!a.getBoolean(attr, true)) {
3520                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3521                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3522                     }
3523                     break;
3524                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3525                     if (!a.getBoolean(attr, true)) {
3526                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3527                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3528                     }
3529                     break;
3530                 case R.styleable.View_scrollbars:
3531                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3532                     if (scrollbars != SCROLLBARS_NONE) {
3533                         viewFlagValues |= scrollbars;
3534                         viewFlagMasks |= SCROLLBARS_MASK;
3535                         initializeScrollbars = true;
3536                     }
3537                     break;
3538                 //noinspection deprecation
3539                 case R.styleable.View_fadingEdge:
3540                     if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3541                         // Ignore the attribute starting with ICS
3542                         break;
3543                     }
3544                     // With builds < ICS, fall through and apply fading edges
3545                 case R.styleable.View_requiresFadingEdge:
3546                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3547                     if (fadingEdge != FADING_EDGE_NONE) {
3548                         viewFlagValues |= fadingEdge;
3549                         viewFlagMasks |= FADING_EDGE_MASK;
3550                         initializeFadingEdge(a);
3551                     }
3552                     break;
3553                 case R.styleable.View_scrollbarStyle:
3554                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3555                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3556                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3557                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3558                     }
3559                     break;
3560                 case R.styleable.View_isScrollContainer:
3561                     setScrollContainer = true;
3562                     if (a.getBoolean(attr, false)) {
3563                         setScrollContainer(true);
3564                     }
3565                     break;
3566                 case com.android.internal.R.styleable.View_keepScreenOn:
3567                     if (a.getBoolean(attr, false)) {
3568                         viewFlagValues |= KEEP_SCREEN_ON;
3569                         viewFlagMasks |= KEEP_SCREEN_ON;
3570                     }
3571                     break;
3572                 case R.styleable.View_filterTouchesWhenObscured:
3573                     if (a.getBoolean(attr, false)) {
3574                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3575                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3576                     }
3577                     break;
3578                 case R.styleable.View_nextFocusLeft:
3579                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3580                     break;
3581                 case R.styleable.View_nextFocusRight:
3582                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3583                     break;
3584                 case R.styleable.View_nextFocusUp:
3585                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3586                     break;
3587                 case R.styleable.View_nextFocusDown:
3588                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3589                     break;
3590                 case R.styleable.View_nextFocusForward:
3591                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3592                     break;
3593                 case R.styleable.View_minWidth:
3594                     mMinWidth = a.getDimensionPixelSize(attr, 0);
3595                     break;
3596                 case R.styleable.View_minHeight:
3597                     mMinHeight = a.getDimensionPixelSize(attr, 0);
3598                     break;
3599                 case R.styleable.View_onClick:
3600                     if (context.isRestricted()) {
3601                         throw new IllegalStateException("The android:onClick attribute cannot "
3602                                 + "be used within a restricted context");
3603                     }
3604 
3605                     final String handlerName = a.getString(attr);
3606                     if (handlerName != null) {
3607                         setOnClickListener(new OnClickListener() {
3608                             private Method mHandler;
3609 
3610                             public void onClick(View v) {
3611                                 if (mHandler == null) {
3612                                     try {
3613                                         mHandler = getContext().getClass().getMethod(handlerName,
3614                                                 View.class);
3615                                     } catch (NoSuchMethodException e) {
3616                                         int id = getId();
3617                                         String idText = id == NO_ID ? "" : " with id '"
3618                                                 + getContext().getResources().getResourceEntryName(
3619                                                     id) + "'";
3620                                         throw new IllegalStateException("Could not find a method " +
3621                                                 handlerName + "(View) in the activity "
3622                                                 + getContext().getClass() + " for onClick handler"
3623                                                 + " on view " + View.this.getClass() + idText, e);
3624                                     }
3625                                 }
3626 
3627                                 try {
3628                                     mHandler.invoke(getContext(), View.this);
3629                                 } catch (IllegalAccessException e) {
3630                                     throw new IllegalStateException("Could not execute non "
3631                                             + "public method of the activity", e);
3632                                 } catch (InvocationTargetException e) {
3633                                     throw new IllegalStateException("Could not execute "
3634                                             + "method of the activity", e);
3635                                 }
3636                             }
3637                         });
3638                     }
3639                     break;
3640                 case R.styleable.View_overScrollMode:
3641                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3642                     break;
3643                 case R.styleable.View_verticalScrollbarPosition:
3644                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3645                     break;
3646                 case R.styleable.View_layerType:
3647                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3648                     break;
3649                 case R.styleable.View_textDirection:
3650                     // Clear any text direction flag already set
3651                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
3652                     // Set the text direction flags depending on the value of the attribute
3653                     final int textDirection = a.getInt(attr, -1);
3654                     if (textDirection != -1) {
3655                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
3656                     }
3657                     break;
3658                 case R.styleable.View_textAlignment:
3659                     // Clear any text alignment flag already set
3660                     mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
3661                     // Set the text alignment flag depending on the value of the attribute
3662                     final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
3663                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
3664                     break;
3665                 case R.styleable.View_importantForAccessibility:
3666                     setImportantForAccessibility(a.getInt(attr,
3667                             IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
3668                     break;
3669             }
3670         }
3671 
3672         setOverScrollMode(overScrollMode);
3673 
3674         // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
3675         // the resolved layout direction). Those cached values will be used later during padding
3676         // resolution.
3677         mUserPaddingStart = startPadding;
3678         mUserPaddingEnd = endPadding;
3679 
3680         if (background != null) {
3681             setBackground(background);
3682         }
3683 
3684         if (padding >= 0) {
3685             leftPadding = padding;
3686             topPadding = padding;
3687             rightPadding = padding;
3688             bottomPadding = padding;
3689             mUserPaddingLeftInitial = padding;
3690             mUserPaddingRightInitial = padding;
3691         }
3692 
3693         if (isRtlCompatibilityMode()) {
3694             // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
3695             // left / right padding are used if defined (meaning here nothing to do). If they are not
3696             // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
3697             // start / end and resolve them as left / right (layout direction is not taken into account).
3698             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
3699             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
3700             // defined.
3701             if (!leftPaddingDefined && startPaddingDefined) {
3702                 leftPadding = startPadding;
3703             }
3704             mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
3705             if (!rightPaddingDefined && endPaddingDefined) {
3706                 rightPadding = endPadding;
3707             }
3708             mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
3709         } else {
3710             // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
3711             // values defined. Otherwise, left /right values are used.
3712             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
3713             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
3714             // defined.
3715             final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
3716 
3717             if (leftPaddingDefined && !hasRelativePadding) {
3718                 mUserPaddingLeftInitial = leftPadding;
3719             }
3720             if (rightPaddingDefined && !hasRelativePadding) {
3721                 mUserPaddingRightInitial = rightPadding;
3722             }
3723         }
3724 
3725         internalSetPadding(
3726                 mUserPaddingLeftInitial,
3727                 topPadding >= 0 ? topPadding : mPaddingTop,
3728                 mUserPaddingRightInitial,
3729                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
3730 
3731         if (viewFlagMasks != 0) {
3732             setFlags(viewFlagValues, viewFlagMasks);
3733         }
3734 
3735         if (initializeScrollbars) {
3736             initializeScrollbars(a);
3737         }
3738 
3739         a.recycle();
3740 
3741         // Needs to be called after mViewFlags is set
3742         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3743             recomputePadding();
3744         }
3745 
3746         if (x != 0 || y != 0) {
3747             scrollTo(x, y);
3748         }
3749 
3750         if (transformSet) {
3751             setTranslationX(tx);
3752             setTranslationY(ty);
3753             setRotation(rotation);
3754             setRotationX(rotationX);
3755             setRotationY(rotationY);
3756             setScaleX(sx);
3757             setScaleY(sy);
3758         }
3759 
3760         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
3761             setScrollContainer(true);
3762         }
3763 
3764         computeOpaqueFlags();
3765     }
3766 
3767     /**
3768      * Non-public constructor for use in testing
3769      */
View()3770     View() {
3771         mResources = null;
3772     }
3773 
toString()3774     public String toString() {
3775         StringBuilder out = new StringBuilder(128);
3776         out.append(getClass().getName());
3777         out.append('{');
3778         out.append(Integer.toHexString(System.identityHashCode(this)));
3779         out.append(' ');
3780         switch (mViewFlags&VISIBILITY_MASK) {
3781             case VISIBLE: out.append('V'); break;
3782             case INVISIBLE: out.append('I'); break;
3783             case GONE: out.append('G'); break;
3784             default: out.append('.'); break;
3785         }
3786         out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
3787         out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
3788         out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
3789         out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
3790         out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
3791         out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
3792         out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
3793         out.append(' ');
3794         out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
3795         out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
3796         out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
3797         if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
3798             out.append('p');
3799         } else {
3800             out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
3801         }
3802         out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
3803         out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
3804         out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
3805         out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
3806         out.append(' ');
3807         out.append(mLeft);
3808         out.append(',');
3809         out.append(mTop);
3810         out.append('-');
3811         out.append(mRight);
3812         out.append(',');
3813         out.append(mBottom);
3814         final int id = getId();
3815         if (id != NO_ID) {
3816             out.append(" #");
3817             out.append(Integer.toHexString(id));
3818             final Resources r = mResources;
3819             if (id != 0 && r != null) {
3820                 try {
3821                     String pkgname;
3822                     switch (id&0xff000000) {
3823                         case 0x7f000000:
3824                             pkgname="app";
3825                             break;
3826                         case 0x01000000:
3827                             pkgname="android";
3828                             break;
3829                         default:
3830                             pkgname = r.getResourcePackageName(id);
3831                             break;
3832                     }
3833                     String typename = r.getResourceTypeName(id);
3834                     String entryname = r.getResourceEntryName(id);
3835                     out.append(" ");
3836                     out.append(pkgname);
3837                     out.append(":");
3838                     out.append(typename);
3839                     out.append("/");
3840                     out.append(entryname);
3841                 } catch (Resources.NotFoundException e) {
3842                 }
3843             }
3844         }
3845         out.append("}");
3846         return out.toString();
3847     }
3848 
3849     /**
3850      * <p>
3851      * Initializes the fading edges from a given set of styled attributes. This
3852      * method should be called by subclasses that need fading edges and when an
3853      * instance of these subclasses is created programmatically rather than
3854      * being inflated from XML. This method is automatically called when the XML
3855      * is inflated.
3856      * </p>
3857      *
3858      * @param a the styled attributes set to initialize the fading edges from
3859      */
initializeFadingEdge(TypedArray a)3860     protected void initializeFadingEdge(TypedArray a) {
3861         initScrollCache();
3862 
3863         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
3864                 R.styleable.View_fadingEdgeLength,
3865                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
3866     }
3867 
3868     /**
3869      * Returns the size of the vertical faded edges used to indicate that more
3870      * content in this view is visible.
3871      *
3872      * @return The size in pixels of the vertical faded edge or 0 if vertical
3873      *         faded edges are not enabled for this view.
3874      * @attr ref android.R.styleable#View_fadingEdgeLength
3875      */
getVerticalFadingEdgeLength()3876     public int getVerticalFadingEdgeLength() {
3877         if (isVerticalFadingEdgeEnabled()) {
3878             ScrollabilityCache cache = mScrollCache;
3879             if (cache != null) {
3880                 return cache.fadingEdgeLength;
3881             }
3882         }
3883         return 0;
3884     }
3885 
3886     /**
3887      * Set the size of the faded edge used to indicate that more content in this
3888      * view is available.  Will not change whether the fading edge is enabled; use
3889      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
3890      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
3891      * for the vertical or horizontal fading edges.
3892      *
3893      * @param length The size in pixels of the faded edge used to indicate that more
3894      *        content in this view is visible.
3895      */
setFadingEdgeLength(int length)3896     public void setFadingEdgeLength(int length) {
3897         initScrollCache();
3898         mScrollCache.fadingEdgeLength = length;
3899     }
3900 
3901     /**
3902      * Returns the size of the horizontal faded edges used to indicate that more
3903      * content in this view is visible.
3904      *
3905      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
3906      *         faded edges are not enabled for this view.
3907      * @attr ref android.R.styleable#View_fadingEdgeLength
3908      */
getHorizontalFadingEdgeLength()3909     public int getHorizontalFadingEdgeLength() {
3910         if (isHorizontalFadingEdgeEnabled()) {
3911             ScrollabilityCache cache = mScrollCache;
3912             if (cache != null) {
3913                 return cache.fadingEdgeLength;
3914             }
3915         }
3916         return 0;
3917     }
3918 
3919     /**
3920      * Returns the width of the vertical scrollbar.
3921      *
3922      * @return The width in pixels of the vertical scrollbar or 0 if there
3923      *         is no vertical scrollbar.
3924      */
getVerticalScrollbarWidth()3925     public int getVerticalScrollbarWidth() {
3926         ScrollabilityCache cache = mScrollCache;
3927         if (cache != null) {
3928             ScrollBarDrawable scrollBar = cache.scrollBar;
3929             if (scrollBar != null) {
3930                 int size = scrollBar.getSize(true);
3931                 if (size <= 0) {
3932                     size = cache.scrollBarSize;
3933                 }
3934                 return size;
3935             }
3936             return 0;
3937         }
3938         return 0;
3939     }
3940 
3941     /**
3942      * Returns the height of the horizontal scrollbar.
3943      *
3944      * @return The height in pixels of the horizontal scrollbar or 0 if
3945      *         there is no horizontal scrollbar.
3946      */
getHorizontalScrollbarHeight()3947     protected int getHorizontalScrollbarHeight() {
3948         ScrollabilityCache cache = mScrollCache;
3949         if (cache != null) {
3950             ScrollBarDrawable scrollBar = cache.scrollBar;
3951             if (scrollBar != null) {
3952                 int size = scrollBar.getSize(false);
3953                 if (size <= 0) {
3954                     size = cache.scrollBarSize;
3955                 }
3956                 return size;
3957             }
3958             return 0;
3959         }
3960         return 0;
3961     }
3962 
3963     /**
3964      * <p>
3965      * Initializes the scrollbars from a given set of styled attributes. This
3966      * method should be called by subclasses that need scrollbars and when an
3967      * instance of these subclasses is created programmatically rather than
3968      * being inflated from XML. This method is automatically called when the XML
3969      * is inflated.
3970      * </p>
3971      *
3972      * @param a the styled attributes set to initialize the scrollbars from
3973      */
initializeScrollbars(TypedArray a)3974     protected void initializeScrollbars(TypedArray a) {
3975         initScrollCache();
3976 
3977         final ScrollabilityCache scrollabilityCache = mScrollCache;
3978 
3979         if (scrollabilityCache.scrollBar == null) {
3980             scrollabilityCache.scrollBar = new ScrollBarDrawable();
3981         }
3982 
3983         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
3984 
3985         if (!fadeScrollbars) {
3986             scrollabilityCache.state = ScrollabilityCache.ON;
3987         }
3988         scrollabilityCache.fadeScrollBars = fadeScrollbars;
3989 
3990 
3991         scrollabilityCache.scrollBarFadeDuration = a.getInt(
3992                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
3993                         .getScrollBarFadeDuration());
3994         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
3995                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
3996                 ViewConfiguration.getScrollDefaultDelay());
3997 
3998 
3999         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4000                 com.android.internal.R.styleable.View_scrollbarSize,
4001                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
4002 
4003         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4004         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4005 
4006         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4007         if (thumb != null) {
4008             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4009         }
4010 
4011         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4012                 false);
4013         if (alwaysDraw) {
4014             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4015         }
4016 
4017         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4018         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4019 
4020         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4021         if (thumb != null) {
4022             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4023         }
4024 
4025         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4026                 false);
4027         if (alwaysDraw) {
4028             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4029         }
4030 
4031         // Apply layout direction to the new Drawables if needed
4032         final int layoutDirection = getLayoutDirection();
4033         if (track != null) {
4034             track.setLayoutDirection(layoutDirection);
4035         }
4036         if (thumb != null) {
4037             thumb.setLayoutDirection(layoutDirection);
4038         }
4039 
4040         // Re-apply user/background padding so that scrollbar(s) get added
4041         resolvePadding();
4042     }
4043 
4044     /**
4045      * <p>
4046      * Initalizes the scrollability cache if necessary.
4047      * </p>
4048      */
initScrollCache()4049     private void initScrollCache() {
4050         if (mScrollCache == null) {
4051             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4052         }
4053     }
4054 
getScrollCache()4055     private ScrollabilityCache getScrollCache() {
4056         initScrollCache();
4057         return mScrollCache;
4058     }
4059 
4060     /**
4061      * Set the position of the vertical scroll bar. Should be one of
4062      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4063      * {@link #SCROLLBAR_POSITION_RIGHT}.
4064      *
4065      * @param position Where the vertical scroll bar should be positioned.
4066      */
setVerticalScrollbarPosition(int position)4067     public void setVerticalScrollbarPosition(int position) {
4068         if (mVerticalScrollbarPosition != position) {
4069             mVerticalScrollbarPosition = position;
4070             computeOpaqueFlags();
4071             resolvePadding();
4072         }
4073     }
4074 
4075     /**
4076      * @return The position where the vertical scroll bar will show, if applicable.
4077      * @see #setVerticalScrollbarPosition(int)
4078      */
getVerticalScrollbarPosition()4079     public int getVerticalScrollbarPosition() {
4080         return mVerticalScrollbarPosition;
4081     }
4082 
getListenerInfo()4083     ListenerInfo getListenerInfo() {
4084         if (mListenerInfo != null) {
4085             return mListenerInfo;
4086         }
4087         mListenerInfo = new ListenerInfo();
4088         return mListenerInfo;
4089     }
4090 
4091     /**
4092      * Register a callback to be invoked when focus of this view changed.
4093      *
4094      * @param l The callback that will run.
4095      */
setOnFocusChangeListener(OnFocusChangeListener l)4096     public void setOnFocusChangeListener(OnFocusChangeListener l) {
4097         getListenerInfo().mOnFocusChangeListener = l;
4098     }
4099 
4100     /**
4101      * Add a listener that will be called when the bounds of the view change due to
4102      * layout processing.
4103      *
4104      * @param listener The listener that will be called when layout bounds change.
4105      */
addOnLayoutChangeListener(OnLayoutChangeListener listener)4106     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4107         ListenerInfo li = getListenerInfo();
4108         if (li.mOnLayoutChangeListeners == null) {
4109             li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4110         }
4111         if (!li.mOnLayoutChangeListeners.contains(listener)) {
4112             li.mOnLayoutChangeListeners.add(listener);
4113         }
4114     }
4115 
4116     /**
4117      * Remove a listener for layout changes.
4118      *
4119      * @param listener The listener for layout bounds change.
4120      */
removeOnLayoutChangeListener(OnLayoutChangeListener listener)4121     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4122         ListenerInfo li = mListenerInfo;
4123         if (li == null || li.mOnLayoutChangeListeners == null) {
4124             return;
4125         }
4126         li.mOnLayoutChangeListeners.remove(listener);
4127     }
4128 
4129     /**
4130      * Add a listener for attach state changes.
4131      *
4132      * This listener will be called whenever this view is attached or detached
4133      * from a window. Remove the listener using
4134      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4135      *
4136      * @param listener Listener to attach
4137      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4138      */
addOnAttachStateChangeListener(OnAttachStateChangeListener listener)4139     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4140         ListenerInfo li = getListenerInfo();
4141         if (li.mOnAttachStateChangeListeners == null) {
4142             li.mOnAttachStateChangeListeners
4143                     = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4144         }
4145         li.mOnAttachStateChangeListeners.add(listener);
4146     }
4147 
4148     /**
4149      * Remove a listener for attach state changes. The listener will receive no further
4150      * notification of window attach/detach events.
4151      *
4152      * @param listener Listener to remove
4153      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4154      */
removeOnAttachStateChangeListener(OnAttachStateChangeListener listener)4155     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4156         ListenerInfo li = mListenerInfo;
4157         if (li == null || li.mOnAttachStateChangeListeners == null) {
4158             return;
4159         }
4160         li.mOnAttachStateChangeListeners.remove(listener);
4161     }
4162 
4163     /**
4164      * Returns the focus-change callback registered for this view.
4165      *
4166      * @return The callback, or null if one is not registered.
4167      */
getOnFocusChangeListener()4168     public OnFocusChangeListener getOnFocusChangeListener() {
4169         ListenerInfo li = mListenerInfo;
4170         return li != null ? li.mOnFocusChangeListener : null;
4171     }
4172 
4173     /**
4174      * Register a callback to be invoked when this view is clicked. If this view is not
4175      * clickable, it becomes clickable.
4176      *
4177      * @param l The callback that will run
4178      *
4179      * @see #setClickable(boolean)
4180      */
setOnClickListener(OnClickListener l)4181     public void setOnClickListener(OnClickListener l) {
4182         if (!isClickable()) {
4183             setClickable(true);
4184         }
4185         getListenerInfo().mOnClickListener = l;
4186     }
4187 
4188     /**
4189      * Return whether this view has an attached OnClickListener.  Returns
4190      * true if there is a listener, false if there is none.
4191      */
hasOnClickListeners()4192     public boolean hasOnClickListeners() {
4193         ListenerInfo li = mListenerInfo;
4194         return (li != null && li.mOnClickListener != null);
4195     }
4196 
4197     /**
4198      * Register a callback to be invoked when this view is clicked and held. If this view is not
4199      * long clickable, it becomes long clickable.
4200      *
4201      * @param l The callback that will run
4202      *
4203      * @see #setLongClickable(boolean)
4204      */
setOnLongClickListener(OnLongClickListener l)4205     public void setOnLongClickListener(OnLongClickListener l) {
4206         if (!isLongClickable()) {
4207             setLongClickable(true);
4208         }
4209         getListenerInfo().mOnLongClickListener = l;
4210     }
4211 
4212     /**
4213      * Register a callback to be invoked when the context menu for this view is
4214      * being built. If this view is not long clickable, it becomes long clickable.
4215      *
4216      * @param l The callback that will run
4217      *
4218      */
setOnCreateContextMenuListener(OnCreateContextMenuListener l)4219     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4220         if (!isLongClickable()) {
4221             setLongClickable(true);
4222         }
4223         getListenerInfo().mOnCreateContextMenuListener = l;
4224     }
4225 
4226     /**
4227      * Call this view's OnClickListener, if it is defined.  Performs all normal
4228      * actions associated with clicking: reporting accessibility event, playing
4229      * a sound, etc.
4230      *
4231      * @return True there was an assigned OnClickListener that was called, false
4232      *         otherwise is returned.
4233      */
performClick()4234     public boolean performClick() {
4235         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4236 
4237         ListenerInfo li = mListenerInfo;
4238         if (li != null && li.mOnClickListener != null) {
4239             playSoundEffect(SoundEffectConstants.CLICK);
4240             li.mOnClickListener.onClick(this);
4241             return true;
4242         }
4243 
4244         return false;
4245     }
4246 
4247     /**
4248      * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
4249      * this only calls the listener, and does not do any associated clicking
4250      * actions like reporting an accessibility event.
4251      *
4252      * @return True there was an assigned OnClickListener that was called, false
4253      *         otherwise is returned.
4254      */
callOnClick()4255     public boolean callOnClick() {
4256         ListenerInfo li = mListenerInfo;
4257         if (li != null && li.mOnClickListener != null) {
4258             li.mOnClickListener.onClick(this);
4259             return true;
4260         }
4261         return false;
4262     }
4263 
4264     /**
4265      * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4266      * OnLongClickListener did not consume the event.
4267      *
4268      * @return True if one of the above receivers consumed the event, false otherwise.
4269      */
performLongClick()4270     public boolean performLongClick() {
4271         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4272 
4273         boolean handled = false;
4274         ListenerInfo li = mListenerInfo;
4275         if (li != null && li.mOnLongClickListener != null) {
4276             handled = li.mOnLongClickListener.onLongClick(View.this);
4277         }
4278         if (!handled) {
4279             handled = showContextMenu();
4280         }
4281         if (handled) {
4282             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4283         }
4284         return handled;
4285     }
4286 
4287     /**
4288      * Performs button-related actions during a touch down event.
4289      *
4290      * @param event The event.
4291      * @return True if the down was consumed.
4292      *
4293      * @hide
4294      */
performButtonActionOnTouchDown(MotionEvent event)4295     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4296         if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4297             if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4298                 return true;
4299             }
4300         }
4301         return false;
4302     }
4303 
4304     /**
4305      * Bring up the context menu for this view.
4306      *
4307      * @return Whether a context menu was displayed.
4308      */
showContextMenu()4309     public boolean showContextMenu() {
4310         return getParent().showContextMenuForChild(this);
4311     }
4312 
4313     /**
4314      * Bring up the context menu for this view, referring to the item under the specified point.
4315      *
4316      * @param x The referenced x coordinate.
4317      * @param y The referenced y coordinate.
4318      * @param metaState The keyboard modifiers that were pressed.
4319      * @return Whether a context menu was displayed.
4320      *
4321      * @hide
4322      */
showContextMenu(float x, float y, int metaState)4323     public boolean showContextMenu(float x, float y, int metaState) {
4324         return showContextMenu();
4325     }
4326 
4327     /**
4328      * Start an action mode.
4329      *
4330      * @param callback Callback that will control the lifecycle of the action mode
4331      * @return The new action mode if it is started, null otherwise
4332      *
4333      * @see ActionMode
4334      */
startActionMode(ActionMode.Callback callback)4335     public ActionMode startActionMode(ActionMode.Callback callback) {
4336         ViewParent parent = getParent();
4337         if (parent == null) return null;
4338         return parent.startActionModeForChild(this, callback);
4339     }
4340 
4341     /**
4342      * Register a callback to be invoked when a hardware key is pressed in this view.
4343      * Key presses in software input methods will generally not trigger the methods of
4344      * this listener.
4345      * @param l the key listener to attach to this view
4346      */
setOnKeyListener(OnKeyListener l)4347     public void setOnKeyListener(OnKeyListener l) {
4348         getListenerInfo().mOnKeyListener = l;
4349     }
4350 
4351     /**
4352      * Register a callback to be invoked when a touch event is sent to this view.
4353      * @param l the touch listener to attach to this view
4354      */
setOnTouchListener(OnTouchListener l)4355     public void setOnTouchListener(OnTouchListener l) {
4356         getListenerInfo().mOnTouchListener = l;
4357     }
4358 
4359     /**
4360      * Register a callback to be invoked when a generic motion event is sent to this view.
4361      * @param l the generic motion listener to attach to this view
4362      */
setOnGenericMotionListener(OnGenericMotionListener l)4363     public void setOnGenericMotionListener(OnGenericMotionListener l) {
4364         getListenerInfo().mOnGenericMotionListener = l;
4365     }
4366 
4367     /**
4368      * Register a callback to be invoked when a hover event is sent to this view.
4369      * @param l the hover listener to attach to this view
4370      */
setOnHoverListener(OnHoverListener l)4371     public void setOnHoverListener(OnHoverListener l) {
4372         getListenerInfo().mOnHoverListener = l;
4373     }
4374 
4375     /**
4376      * Register a drag event listener callback object for this View. The parameter is
4377      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4378      * View, the system calls the
4379      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4380      * @param l An implementation of {@link android.view.View.OnDragListener}.
4381      */
setOnDragListener(OnDragListener l)4382     public void setOnDragListener(OnDragListener l) {
4383         getListenerInfo().mOnDragListener = l;
4384     }
4385 
4386     /**
4387      * Give this view focus. This will cause
4388      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
4389      *
4390      * Note: this does not check whether this {@link View} should get focus, it just
4391      * gives it focus no matter what.  It should only be called internally by framework
4392      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4393      *
4394      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4395      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
4396      *        focus moved when requestFocus() is called. It may not always
4397      *        apply, in which case use the default View.FOCUS_DOWN.
4398      * @param previouslyFocusedRect The rectangle of the view that had focus
4399      *        prior in this View's coordinate system.
4400      */
handleFocusGainInternal(int direction, Rect previouslyFocusedRect)4401     void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
4402         if (DBG) {
4403             System.out.println(this + " requestFocus()");
4404         }
4405 
4406         if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4407             mPrivateFlags |= PFLAG_FOCUSED;
4408 
4409             View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
4410 
4411             if (mParent != null) {
4412                 mParent.requestChildFocus(this, this);
4413             }
4414 
4415             if (mAttachInfo != null) {
4416                 mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
4417             }
4418 
4419             onFocusChanged(true, direction, previouslyFocusedRect);
4420             refreshDrawableState();
4421 
4422             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4423                 notifyAccessibilityStateChanged();
4424             }
4425         }
4426     }
4427 
4428     /**
4429      * Request that a rectangle of this view be visible on the screen,
4430      * scrolling if necessary just enough.
4431      *
4432      * <p>A View should call this if it maintains some notion of which part
4433      * of its content is interesting.  For example, a text editing view
4434      * should call this when its cursor moves.
4435      *
4436      * @param rectangle The rectangle.
4437      * @return Whether any parent scrolled.
4438      */
requestRectangleOnScreen(Rect rectangle)4439     public boolean requestRectangleOnScreen(Rect rectangle) {
4440         return requestRectangleOnScreen(rectangle, false);
4441     }
4442 
4443     /**
4444      * Request that a rectangle of this view be visible on the screen,
4445      * scrolling if necessary just enough.
4446      *
4447      * <p>A View should call this if it maintains some notion of which part
4448      * of its content is interesting.  For example, a text editing view
4449      * should call this when its cursor moves.
4450      *
4451      * <p>When <code>immediate</code> is set to true, scrolling will not be
4452      * animated.
4453      *
4454      * @param rectangle The rectangle.
4455      * @param immediate True to forbid animated scrolling, false otherwise
4456      * @return Whether any parent scrolled.
4457      */
requestRectangleOnScreen(Rect rectangle, boolean immediate)4458     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
4459         if (mParent == null) {
4460             return false;
4461         }
4462 
4463         View child = this;
4464 
4465         RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
4466         position.set(rectangle);
4467 
4468         ViewParent parent = mParent;
4469         boolean scrolled = false;
4470         while (parent != null) {
4471             rectangle.set((int) position.left, (int) position.top,
4472                     (int) position.right, (int) position.bottom);
4473 
4474             scrolled |= parent.requestChildRectangleOnScreen(child,
4475                     rectangle, immediate);
4476 
4477             if (!child.hasIdentityMatrix()) {
4478                 child.getMatrix().mapRect(position);
4479             }
4480 
4481             position.offset(child.mLeft, child.mTop);
4482 
4483             if (!(parent instanceof View)) {
4484                 break;
4485             }
4486 
4487             View parentView = (View) parent;
4488 
4489             position.offset(-parentView.getScrollX(), -parentView.getScrollY());
4490 
4491             child = parentView;
4492             parent = child.getParent();
4493         }
4494 
4495         return scrolled;
4496     }
4497 
4498     /**
4499      * Called when this view wants to give up focus. If focus is cleared
4500      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
4501      * <p>
4502      * <strong>Note:</strong> When a View clears focus the framework is trying
4503      * to give focus to the first focusable View from the top. Hence, if this
4504      * View is the first from the top that can take focus, then all callbacks
4505      * related to clearing focus will be invoked after wich the framework will
4506      * give focus to this view.
4507      * </p>
4508      */
clearFocus()4509     public void clearFocus() {
4510         if (DBG) {
4511             System.out.println(this + " clearFocus()");
4512         }
4513 
4514         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4515             mPrivateFlags &= ~PFLAG_FOCUSED;
4516 
4517             if (mParent != null) {
4518                 mParent.clearChildFocus(this);
4519             }
4520 
4521             onFocusChanged(false, 0, null);
4522 
4523             refreshDrawableState();
4524 
4525             if (!rootViewRequestFocus()) {
4526                 notifyGlobalFocusCleared(this);
4527             }
4528 
4529             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4530                 notifyAccessibilityStateChanged();
4531             }
4532         }
4533     }
4534 
notifyGlobalFocusCleared(View oldFocus)4535     void notifyGlobalFocusCleared(View oldFocus) {
4536         if (oldFocus != null && mAttachInfo != null) {
4537             mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
4538         }
4539     }
4540 
rootViewRequestFocus()4541     boolean rootViewRequestFocus() {
4542         View root = getRootView();
4543         if (root != null) {
4544             return root.requestFocus();
4545         }
4546         return false;
4547     }
4548 
4549     /**
4550      * Called internally by the view system when a new view is getting focus.
4551      * This is what clears the old focus.
4552      */
unFocus()4553     void unFocus() {
4554         if (DBG) {
4555             System.out.println(this + " unFocus()");
4556         }
4557 
4558         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4559             mPrivateFlags &= ~PFLAG_FOCUSED;
4560 
4561             onFocusChanged(false, 0, null);
4562             refreshDrawableState();
4563 
4564             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4565                 notifyAccessibilityStateChanged();
4566             }
4567         }
4568     }
4569 
4570     /**
4571      * Returns true if this view has focus iteself, or is the ancestor of the
4572      * view that has focus.
4573      *
4574      * @return True if this view has or contains focus, false otherwise.
4575      */
4576     @ViewDebug.ExportedProperty(category = "focus")
hasFocus()4577     public boolean hasFocus() {
4578         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
4579     }
4580 
4581     /**
4582      * Returns true if this view is focusable or if it contains a reachable View
4583      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
4584      * is a View whose parents do not block descendants focus.
4585      *
4586      * Only {@link #VISIBLE} views are considered focusable.
4587      *
4588      * @return True if the view is focusable or if the view contains a focusable
4589      *         View, false otherwise.
4590      *
4591      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
4592      */
hasFocusable()4593     public boolean hasFocusable() {
4594         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
4595     }
4596 
4597     /**
4598      * Called by the view system when the focus state of this view changes.
4599      * When the focus change event is caused by directional navigation, direction
4600      * and previouslyFocusedRect provide insight into where the focus is coming from.
4601      * When overriding, be sure to call up through to the super class so that
4602      * the standard focus handling will occur.
4603      *
4604      * @param gainFocus True if the View has focus; false otherwise.
4605      * @param direction The direction focus has moved when requestFocus()
4606      *                  is called to give this view focus. Values are
4607      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
4608      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
4609      *                  It may not always apply, in which case use the default.
4610      * @param previouslyFocusedRect The rectangle, in this view's coordinate
4611      *        system, of the previously focused view.  If applicable, this will be
4612      *        passed in as finer grained information about where the focus is coming
4613      *        from (in addition to direction).  Will be <code>null</code> otherwise.
4614      */
onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect)4615     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
4616         if (gainFocus) {
4617             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4618                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
4619             }
4620         }
4621 
4622         InputMethodManager imm = InputMethodManager.peekInstance();
4623         if (!gainFocus) {
4624             if (isPressed()) {
4625                 setPressed(false);
4626             }
4627             if (imm != null && mAttachInfo != null
4628                     && mAttachInfo.mHasWindowFocus) {
4629                 imm.focusOut(this);
4630             }
4631             onFocusLost();
4632         } else if (imm != null && mAttachInfo != null
4633                 && mAttachInfo.mHasWindowFocus) {
4634             imm.focusIn(this);
4635         }
4636 
4637         invalidate(true);
4638         ListenerInfo li = mListenerInfo;
4639         if (li != null && li.mOnFocusChangeListener != null) {
4640             li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
4641         }
4642 
4643         if (mAttachInfo != null) {
4644             mAttachInfo.mKeyDispatchState.reset(this);
4645         }
4646     }
4647 
4648     /**
4649      * Sends an accessibility event of the given type. If accessibility is
4650      * not enabled this method has no effect. The default implementation calls
4651      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
4652      * to populate information about the event source (this View), then calls
4653      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
4654      * populate the text content of the event source including its descendants,
4655      * and last calls
4656      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
4657      * on its parent to resuest sending of the event to interested parties.
4658      * <p>
4659      * If an {@link AccessibilityDelegate} has been specified via calling
4660      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4661      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
4662      * responsible for handling this call.
4663      * </p>
4664      *
4665      * @param eventType The type of the event to send, as defined by several types from
4666      * {@link android.view.accessibility.AccessibilityEvent}, such as
4667      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
4668      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
4669      *
4670      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4671      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4672      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
4673      * @see AccessibilityDelegate
4674      */
sendAccessibilityEvent(int eventType)4675     public void sendAccessibilityEvent(int eventType) {
4676         if (mAccessibilityDelegate != null) {
4677             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
4678         } else {
4679             sendAccessibilityEventInternal(eventType);
4680         }
4681     }
4682 
4683     /**
4684      * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
4685      * {@link AccessibilityEvent} to make an announcement which is related to some
4686      * sort of a context change for which none of the events representing UI transitions
4687      * is a good fit. For example, announcing a new page in a book. If accessibility
4688      * is not enabled this method does nothing.
4689      *
4690      * @param text The announcement text.
4691      */
announceForAccessibility(CharSequence text)4692     public void announceForAccessibility(CharSequence text) {
4693         if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
4694             AccessibilityEvent event = AccessibilityEvent.obtain(
4695                     AccessibilityEvent.TYPE_ANNOUNCEMENT);
4696             onInitializeAccessibilityEvent(event);
4697             event.getText().add(text);
4698             event.setContentDescription(null);
4699             mParent.requestSendAccessibilityEvent(this, event);
4700         }
4701     }
4702 
4703     /**
4704      * @see #sendAccessibilityEvent(int)
4705      *
4706      * Note: Called from the default {@link AccessibilityDelegate}.
4707      */
sendAccessibilityEventInternal(int eventType)4708     void sendAccessibilityEventInternal(int eventType) {
4709         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4710             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
4711         }
4712     }
4713 
4714     /**
4715      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
4716      * takes as an argument an empty {@link AccessibilityEvent} and does not
4717      * perform a check whether accessibility is enabled.
4718      * <p>
4719      * If an {@link AccessibilityDelegate} has been specified via calling
4720      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4721      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
4722      * is responsible for handling this call.
4723      * </p>
4724      *
4725      * @param event The event to send.
4726      *
4727      * @see #sendAccessibilityEvent(int)
4728      */
sendAccessibilityEventUnchecked(AccessibilityEvent event)4729     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
4730         if (mAccessibilityDelegate != null) {
4731             mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
4732         } else {
4733             sendAccessibilityEventUncheckedInternal(event);
4734         }
4735     }
4736 
4737     /**
4738      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
4739      *
4740      * Note: Called from the default {@link AccessibilityDelegate}.
4741      */
sendAccessibilityEventUncheckedInternal(AccessibilityEvent event)4742     void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
4743         if (!isShown()) {
4744             return;
4745         }
4746         onInitializeAccessibilityEvent(event);
4747         // Only a subset of accessibility events populates text content.
4748         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
4749             dispatchPopulateAccessibilityEvent(event);
4750         }
4751         // In the beginning we called #isShown(), so we know that getParent() is not null.
4752         getParent().requestSendAccessibilityEvent(this, event);
4753     }
4754 
4755     /**
4756      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
4757      * to its children for adding their text content to the event. Note that the
4758      * event text is populated in a separate dispatch path since we add to the
4759      * event not only the text of the source but also the text of all its descendants.
4760      * A typical implementation will call
4761      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
4762      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4763      * on each child. Override this method if custom population of the event text
4764      * content is required.
4765      * <p>
4766      * If an {@link AccessibilityDelegate} has been specified via calling
4767      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4768      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
4769      * is responsible for handling this call.
4770      * </p>
4771      * <p>
4772      * <em>Note:</em> Accessibility events of certain types are not dispatched for
4773      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
4774      * </p>
4775      *
4776      * @param event The event.
4777      *
4778      * @return True if the event population was completed.
4779      */
dispatchPopulateAccessibilityEvent(AccessibilityEvent event)4780     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
4781         if (mAccessibilityDelegate != null) {
4782             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
4783         } else {
4784             return dispatchPopulateAccessibilityEventInternal(event);
4785         }
4786     }
4787 
4788     /**
4789      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4790      *
4791      * Note: Called from the default {@link AccessibilityDelegate}.
4792      */
dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event)4793     boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4794         onPopulateAccessibilityEvent(event);
4795         return false;
4796     }
4797 
4798     /**
4799      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4800      * giving a chance to this View to populate the accessibility event with its
4801      * text content. While this method is free to modify event
4802      * attributes other than text content, doing so should normally be performed in
4803      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
4804      * <p>
4805      * Example: Adding formatted date string to an accessibility event in addition
4806      *          to the text added by the super implementation:
4807      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
4808      *     super.onPopulateAccessibilityEvent(event);
4809      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
4810      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
4811      *         mCurrentDate.getTimeInMillis(), flags);
4812      *     event.getText().add(selectedDateUtterance);
4813      * }</pre>
4814      * <p>
4815      * If an {@link AccessibilityDelegate} has been specified via calling
4816      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4817      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
4818      * is responsible for handling this call.
4819      * </p>
4820      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4821      * information to the event, in case the default implementation has basic information to add.
4822      * </p>
4823      *
4824      * @param event The accessibility event which to populate.
4825      *
4826      * @see #sendAccessibilityEvent(int)
4827      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4828      */
onPopulateAccessibilityEvent(AccessibilityEvent event)4829     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
4830         if (mAccessibilityDelegate != null) {
4831             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
4832         } else {
4833             onPopulateAccessibilityEventInternal(event);
4834         }
4835     }
4836 
4837     /**
4838      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
4839      *
4840      * Note: Called from the default {@link AccessibilityDelegate}.
4841      */
onPopulateAccessibilityEventInternal(AccessibilityEvent event)4842     void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4843 
4844     }
4845 
4846     /**
4847      * Initializes an {@link AccessibilityEvent} with information about
4848      * this View which is the event source. In other words, the source of
4849      * an accessibility event is the view whose state change triggered firing
4850      * the event.
4851      * <p>
4852      * Example: Setting the password property of an event in addition
4853      *          to properties set by the super implementation:
4854      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4855      *     super.onInitializeAccessibilityEvent(event);
4856      *     event.setPassword(true);
4857      * }</pre>
4858      * <p>
4859      * If an {@link AccessibilityDelegate} has been specified via calling
4860      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4861      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
4862      * is responsible for handling this call.
4863      * </p>
4864      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4865      * information to the event, in case the default implementation has basic information to add.
4866      * </p>
4867      * @param event The event to initialize.
4868      *
4869      * @see #sendAccessibilityEvent(int)
4870      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4871      */
onInitializeAccessibilityEvent(AccessibilityEvent event)4872     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4873         if (mAccessibilityDelegate != null) {
4874             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
4875         } else {
4876             onInitializeAccessibilityEventInternal(event);
4877         }
4878     }
4879 
4880     /**
4881      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4882      *
4883      * Note: Called from the default {@link AccessibilityDelegate}.
4884      */
onInitializeAccessibilityEventInternal(AccessibilityEvent event)4885     void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
4886         event.setSource(this);
4887         event.setClassName(View.class.getName());
4888         event.setPackageName(getContext().getPackageName());
4889         event.setEnabled(isEnabled());
4890         event.setContentDescription(mContentDescription);
4891 
4892         switch (event.getEventType()) {
4893             case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
4894                 ArrayList<View> focusablesTempList = (mAttachInfo != null)
4895                         ? mAttachInfo.mTempArrayList : new ArrayList<View>();
4896                 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
4897                 event.setItemCount(focusablesTempList.size());
4898                 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
4899                 if (mAttachInfo != null) {
4900                     focusablesTempList.clear();
4901                 }
4902             } break;
4903             case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
4904                 CharSequence text = getIterableTextForAccessibility();
4905                 if (text != null && text.length() > 0) {
4906                     event.setFromIndex(getAccessibilitySelectionStart());
4907                     event.setToIndex(getAccessibilitySelectionEnd());
4908                     event.setItemCount(text.length());
4909                 }
4910             } break;
4911         }
4912     }
4913 
4914     /**
4915      * Returns an {@link AccessibilityNodeInfo} representing this view from the
4916      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
4917      * This method is responsible for obtaining an accessibility node info from a
4918      * pool of reusable instances and calling
4919      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
4920      * initialize the former.
4921      * <p>
4922      * Note: The client is responsible for recycling the obtained instance by calling
4923      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
4924      * </p>
4925      *
4926      * @return A populated {@link AccessibilityNodeInfo}.
4927      *
4928      * @see AccessibilityNodeInfo
4929      */
createAccessibilityNodeInfo()4930     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
4931         if (mAccessibilityDelegate != null) {
4932             return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
4933         } else {
4934             return createAccessibilityNodeInfoInternal();
4935         }
4936     }
4937 
4938     /**
4939      * @see #createAccessibilityNodeInfo()
4940      */
createAccessibilityNodeInfoInternal()4941     AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
4942         AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
4943         if (provider != null) {
4944             return provider.createAccessibilityNodeInfo(View.NO_ID);
4945         } else {
4946             AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
4947             onInitializeAccessibilityNodeInfo(info);
4948             return info;
4949         }
4950     }
4951 
4952     /**
4953      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
4954      * The base implementation sets:
4955      * <ul>
4956      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
4957      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
4958      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
4959      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
4960      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
4961      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
4962      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
4963      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
4964      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
4965      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
4966      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
4967      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
4968      * </ul>
4969      * <p>
4970      * Subclasses should override this method, call the super implementation,
4971      * and set additional attributes.
4972      * </p>
4973      * <p>
4974      * If an {@link AccessibilityDelegate} has been specified via calling
4975      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4976      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
4977      * is responsible for handling this call.
4978      * </p>
4979      *
4980      * @param info The instance to initialize.
4981      */
onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)4982     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
4983         if (mAccessibilityDelegate != null) {
4984             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
4985         } else {
4986             onInitializeAccessibilityNodeInfoInternal(info);
4987         }
4988     }
4989 
4990     /**
4991      * Gets the location of this view in screen coordintates.
4992      *
4993      * @param outRect The output location
4994      */
getBoundsOnScreen(Rect outRect)4995     void getBoundsOnScreen(Rect outRect) {
4996         if (mAttachInfo == null) {
4997             return;
4998         }
4999 
5000         RectF position = mAttachInfo.mTmpTransformRect;
5001         position.set(0, 0, mRight - mLeft, mBottom - mTop);
5002 
5003         if (!hasIdentityMatrix()) {
5004             getMatrix().mapRect(position);
5005         }
5006 
5007         position.offset(mLeft, mTop);
5008 
5009         ViewParent parent = mParent;
5010         while (parent instanceof View) {
5011             View parentView = (View) parent;
5012 
5013             position.offset(-parentView.mScrollX, -parentView.mScrollY);
5014 
5015             if (!parentView.hasIdentityMatrix()) {
5016                 parentView.getMatrix().mapRect(position);
5017             }
5018 
5019             position.offset(parentView.mLeft, parentView.mTop);
5020 
5021             parent = parentView.mParent;
5022         }
5023 
5024         if (parent instanceof ViewRootImpl) {
5025             ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
5026             position.offset(0, -viewRootImpl.mCurScrollY);
5027         }
5028 
5029         position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
5030 
5031         outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
5032                 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
5033     }
5034 
5035     /**
5036      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
5037      *
5038      * Note: Called from the default {@link AccessibilityDelegate}.
5039      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)5040     void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
5041         Rect bounds = mAttachInfo.mTmpInvalRect;
5042 
5043         getDrawingRect(bounds);
5044         info.setBoundsInParent(bounds);
5045 
5046         getBoundsOnScreen(bounds);
5047         info.setBoundsInScreen(bounds);
5048 
5049         ViewParent parent = getParentForAccessibility();
5050         if (parent instanceof View) {
5051             info.setParent((View) parent);
5052         }
5053 
5054         if (mID != View.NO_ID) {
5055             View rootView = getRootView();
5056             if (rootView == null) {
5057                 rootView = this;
5058             }
5059             View label = rootView.findLabelForView(this, mID);
5060             if (label != null) {
5061                 info.setLabeledBy(label);
5062             }
5063 
5064             if ((mAttachInfo.mAccessibilityFetchFlags
5065                     & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
5066                     && Resources.resourceHasPackage(mID)) {
5067                 try {
5068                     String viewId = getResources().getResourceName(mID);
5069                     info.setViewIdResourceName(viewId);
5070                 } catch (Resources.NotFoundException nfe) {
5071                     /* ignore */
5072                 }
5073             }
5074         }
5075 
5076         if (mLabelForId != View.NO_ID) {
5077             View rootView = getRootView();
5078             if (rootView == null) {
5079                 rootView = this;
5080             }
5081             View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
5082             if (labeled != null) {
5083                 info.setLabelFor(labeled);
5084             }
5085         }
5086 
5087         info.setVisibleToUser(isVisibleToUser());
5088 
5089         info.setPackageName(mContext.getPackageName());
5090         info.setClassName(View.class.getName());
5091         info.setContentDescription(getContentDescription());
5092 
5093         info.setEnabled(isEnabled());
5094         info.setClickable(isClickable());
5095         info.setFocusable(isFocusable());
5096         info.setFocused(isFocused());
5097         info.setAccessibilityFocused(isAccessibilityFocused());
5098         info.setSelected(isSelected());
5099         info.setLongClickable(isLongClickable());
5100 
5101         // TODO: These make sense only if we are in an AdapterView but all
5102         // views can be selected. Maybe from accessibility perspective
5103         // we should report as selectable view in an AdapterView.
5104         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
5105         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
5106 
5107         if (isFocusable()) {
5108             if (isFocused()) {
5109                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
5110             } else {
5111                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
5112             }
5113         }
5114 
5115         if (!isAccessibilityFocused()) {
5116             info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
5117         } else {
5118             info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
5119         }
5120 
5121         if (isClickable() && isEnabled()) {
5122             info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
5123         }
5124 
5125         if (isLongClickable() && isEnabled()) {
5126             info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
5127         }
5128 
5129         CharSequence text = getIterableTextForAccessibility();
5130         if (text != null && text.length() > 0) {
5131             info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
5132 
5133             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
5134             info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
5135             info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
5136             info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
5137                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
5138                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
5139         }
5140     }
5141 
findLabelForView(View view, int labeledId)5142     private View findLabelForView(View view, int labeledId) {
5143         if (mMatchLabelForPredicate == null) {
5144             mMatchLabelForPredicate = new MatchLabelForPredicate();
5145         }
5146         mMatchLabelForPredicate.mLabeledId = labeledId;
5147         return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
5148     }
5149 
5150     /**
5151      * Computes whether this view is visible to the user. Such a view is
5152      * attached, visible, all its predecessors are visible, it is not clipped
5153      * entirely by its predecessors, and has an alpha greater than zero.
5154      *
5155      * @return Whether the view is visible on the screen.
5156      *
5157      * @hide
5158      */
isVisibleToUser()5159     protected boolean isVisibleToUser() {
5160         return isVisibleToUser(null);
5161     }
5162 
5163     /**
5164      * Computes whether the given portion of this view is visible to the user.
5165      * Such a view is attached, visible, all its predecessors are visible,
5166      * has an alpha greater than zero, and the specified portion is not
5167      * clipped entirely by its predecessors.
5168      *
5169      * @param boundInView the portion of the view to test; coordinates should be relative; may be
5170      *                    <code>null</code>, and the entire view will be tested in this case.
5171      *                    When <code>true</code> is returned by the function, the actual visible
5172      *                    region will be stored in this parameter; that is, if boundInView is fully
5173      *                    contained within the view, no modification will be made, otherwise regions
5174      *                    outside of the visible area of the view will be clipped.
5175      *
5176      * @return Whether the specified portion of the view is visible on the screen.
5177      *
5178      * @hide
5179      */
isVisibleToUser(Rect boundInView)5180     protected boolean isVisibleToUser(Rect boundInView) {
5181         if (mAttachInfo != null) {
5182             // Attached to invisible window means this view is not visible.
5183             if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
5184                 return false;
5185             }
5186             // An invisible predecessor or one with alpha zero means
5187             // that this view is not visible to the user.
5188             Object current = this;
5189             while (current instanceof View) {
5190                 View view = (View) current;
5191                 // We have attach info so this view is attached and there is no
5192                 // need to check whether we reach to ViewRootImpl on the way up.
5193                 if (view.getAlpha() <= 0 || view.getVisibility() != VISIBLE) {
5194                     return false;
5195                 }
5196                 current = view.mParent;
5197             }
5198             // Check if the view is entirely covered by its predecessors.
5199             Rect visibleRect = mAttachInfo.mTmpInvalRect;
5200             Point offset = mAttachInfo.mPoint;
5201             if (!getGlobalVisibleRect(visibleRect, offset)) {
5202                 return false;
5203             }
5204             // Check if the visible portion intersects the rectangle of interest.
5205             if (boundInView != null) {
5206                 visibleRect.offset(-offset.x, -offset.y);
5207                 return boundInView.intersect(visibleRect);
5208             }
5209             return true;
5210         }
5211         return false;
5212     }
5213 
5214     /**
5215      * Returns the delegate for implementing accessibility support via
5216      * composition. For more details see {@link AccessibilityDelegate}.
5217      *
5218      * @return The delegate, or null if none set.
5219      *
5220      * @hide
5221      */
getAccessibilityDelegate()5222     public AccessibilityDelegate getAccessibilityDelegate() {
5223         return mAccessibilityDelegate;
5224     }
5225 
5226     /**
5227      * Sets a delegate for implementing accessibility support via composition as
5228      * opposed to inheritance. The delegate's primary use is for implementing
5229      * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
5230      *
5231      * @param delegate The delegate instance.
5232      *
5233      * @see AccessibilityDelegate
5234      */
setAccessibilityDelegate(AccessibilityDelegate delegate)5235     public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
5236         mAccessibilityDelegate = delegate;
5237     }
5238 
5239     /**
5240      * Gets the provider for managing a virtual view hierarchy rooted at this View
5241      * and reported to {@link android.accessibilityservice.AccessibilityService}s
5242      * that explore the window content.
5243      * <p>
5244      * If this method returns an instance, this instance is responsible for managing
5245      * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
5246      * View including the one representing the View itself. Similarly the returned
5247      * instance is responsible for performing accessibility actions on any virtual
5248      * view or the root view itself.
5249      * </p>
5250      * <p>
5251      * If an {@link AccessibilityDelegate} has been specified via calling
5252      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5253      * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
5254      * is responsible for handling this call.
5255      * </p>
5256      *
5257      * @return The provider.
5258      *
5259      * @see AccessibilityNodeProvider
5260      */
getAccessibilityNodeProvider()5261     public AccessibilityNodeProvider getAccessibilityNodeProvider() {
5262         if (mAccessibilityDelegate != null) {
5263             return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
5264         } else {
5265             return null;
5266         }
5267     }
5268 
5269     /**
5270      * Gets the unique identifier of this view on the screen for accessibility purposes.
5271      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
5272      *
5273      * @return The view accessibility id.
5274      *
5275      * @hide
5276      */
getAccessibilityViewId()5277     public int getAccessibilityViewId() {
5278         if (mAccessibilityViewId == NO_ID) {
5279             mAccessibilityViewId = sNextAccessibilityViewId++;
5280         }
5281         return mAccessibilityViewId;
5282     }
5283 
5284     /**
5285      * Gets the unique identifier of the window in which this View reseides.
5286      *
5287      * @return The window accessibility id.
5288      *
5289      * @hide
5290      */
getAccessibilityWindowId()5291     public int getAccessibilityWindowId() {
5292         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
5293     }
5294 
5295     /**
5296      * Gets the {@link View} description. It briefly describes the view and is
5297      * primarily used for accessibility support. Set this property to enable
5298      * better accessibility support for your application. This is especially
5299      * true for views that do not have textual representation (For example,
5300      * ImageButton).
5301      *
5302      * @return The content description.
5303      *
5304      * @attr ref android.R.styleable#View_contentDescription
5305      */
5306     @ViewDebug.ExportedProperty(category = "accessibility")
getContentDescription()5307     public CharSequence getContentDescription() {
5308         return mContentDescription;
5309     }
5310 
5311     /**
5312      * Sets the {@link View} description. It briefly describes the view and is
5313      * primarily used for accessibility support. Set this property to enable
5314      * better accessibility support for your application. This is especially
5315      * true for views that do not have textual representation (For example,
5316      * ImageButton).
5317      *
5318      * @param contentDescription The content description.
5319      *
5320      * @attr ref android.R.styleable#View_contentDescription
5321      */
5322     @RemotableViewMethod
setContentDescription(CharSequence contentDescription)5323     public void setContentDescription(CharSequence contentDescription) {
5324         if (mContentDescription == null) {
5325             if (contentDescription == null) {
5326                 return;
5327             }
5328         } else if (mContentDescription.equals(contentDescription)) {
5329             return;
5330         }
5331         mContentDescription = contentDescription;
5332         final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
5333         if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
5334              setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
5335         }
5336         notifyAccessibilityStateChanged();
5337     }
5338 
5339     /**
5340      * Gets the id of a view for which this view serves as a label for
5341      * accessibility purposes.
5342      *
5343      * @return The labeled view id.
5344      */
5345     @ViewDebug.ExportedProperty(category = "accessibility")
getLabelFor()5346     public int getLabelFor() {
5347         return mLabelForId;
5348     }
5349 
5350     /**
5351      * Sets the id of a view for which this view serves as a label for
5352      * accessibility purposes.
5353      *
5354      * @param id The labeled view id.
5355      */
5356     @RemotableViewMethod
setLabelFor(int id)5357     public void setLabelFor(int id) {
5358         mLabelForId = id;
5359         if (mLabelForId != View.NO_ID
5360                 && mID == View.NO_ID) {
5361             mID = generateViewId();
5362         }
5363     }
5364 
5365     /**
5366      * Invoked whenever this view loses focus, either by losing window focus or by losing
5367      * focus within its window. This method can be used to clear any state tied to the
5368      * focus. For instance, if a button is held pressed with the trackball and the window
5369      * loses focus, this method can be used to cancel the press.
5370      *
5371      * Subclasses of View overriding this method should always call super.onFocusLost().
5372      *
5373      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
5374      * @see #onWindowFocusChanged(boolean)
5375      *
5376      * @hide pending API council approval
5377      */
onFocusLost()5378     protected void onFocusLost() {
5379         resetPressedState();
5380     }
5381 
resetPressedState()5382     private void resetPressedState() {
5383         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
5384             return;
5385         }
5386 
5387         if (isPressed()) {
5388             setPressed(false);
5389 
5390             if (!mHasPerformedLongPress) {
5391                 removeLongPressCallback();
5392             }
5393         }
5394     }
5395 
5396     /**
5397      * Returns true if this view has focus
5398      *
5399      * @return True if this view has focus, false otherwise.
5400      */
5401     @ViewDebug.ExportedProperty(category = "focus")
isFocused()5402     public boolean isFocused() {
5403         return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5404     }
5405 
5406     /**
5407      * Find the view in the hierarchy rooted at this view that currently has
5408      * focus.
5409      *
5410      * @return The view that currently has focus, or null if no focused view can
5411      *         be found.
5412      */
findFocus()5413     public View findFocus() {
5414         return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
5415     }
5416 
5417     /**
5418      * Indicates whether this view is one of the set of scrollable containers in
5419      * its window.
5420      *
5421      * @return whether this view is one of the set of scrollable containers in
5422      * its window
5423      *
5424      * @attr ref android.R.styleable#View_isScrollContainer
5425      */
isScrollContainer()5426     public boolean isScrollContainer() {
5427         return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
5428     }
5429 
5430     /**
5431      * Change whether this view is one of the set of scrollable containers in
5432      * its window.  This will be used to determine whether the window can
5433      * resize or must pan when a soft input area is open -- scrollable
5434      * containers allow the window to use resize mode since the container
5435      * will appropriately shrink.
5436      *
5437      * @attr ref android.R.styleable#View_isScrollContainer
5438      */
setScrollContainer(boolean isScrollContainer)5439     public void setScrollContainer(boolean isScrollContainer) {
5440         if (isScrollContainer) {
5441             if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
5442                 mAttachInfo.mScrollContainers.add(this);
5443                 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
5444             }
5445             mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
5446         } else {
5447             if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
5448                 mAttachInfo.mScrollContainers.remove(this);
5449             }
5450             mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
5451         }
5452     }
5453 
5454     /**
5455      * Returns the quality of the drawing cache.
5456      *
5457      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5458      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5459      *
5460      * @see #setDrawingCacheQuality(int)
5461      * @see #setDrawingCacheEnabled(boolean)
5462      * @see #isDrawingCacheEnabled()
5463      *
5464      * @attr ref android.R.styleable#View_drawingCacheQuality
5465      */
getDrawingCacheQuality()5466     public int getDrawingCacheQuality() {
5467         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
5468     }
5469 
5470     /**
5471      * Set the drawing cache quality of this view. This value is used only when the
5472      * drawing cache is enabled
5473      *
5474      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5475      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5476      *
5477      * @see #getDrawingCacheQuality()
5478      * @see #setDrawingCacheEnabled(boolean)
5479      * @see #isDrawingCacheEnabled()
5480      *
5481      * @attr ref android.R.styleable#View_drawingCacheQuality
5482      */
setDrawingCacheQuality(int quality)5483     public void setDrawingCacheQuality(int quality) {
5484         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
5485     }
5486 
5487     /**
5488      * Returns whether the screen should remain on, corresponding to the current
5489      * value of {@link #KEEP_SCREEN_ON}.
5490      *
5491      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
5492      *
5493      * @see #setKeepScreenOn(boolean)
5494      *
5495      * @attr ref android.R.styleable#View_keepScreenOn
5496      */
getKeepScreenOn()5497     public boolean getKeepScreenOn() {
5498         return (mViewFlags & KEEP_SCREEN_ON) != 0;
5499     }
5500 
5501     /**
5502      * Controls whether the screen should remain on, modifying the
5503      * value of {@link #KEEP_SCREEN_ON}.
5504      *
5505      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
5506      *
5507      * @see #getKeepScreenOn()
5508      *
5509      * @attr ref android.R.styleable#View_keepScreenOn
5510      */
setKeepScreenOn(boolean keepScreenOn)5511     public void setKeepScreenOn(boolean keepScreenOn) {
5512         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
5513     }
5514 
5515     /**
5516      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5517      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5518      *
5519      * @attr ref android.R.styleable#View_nextFocusLeft
5520      */
getNextFocusLeftId()5521     public int getNextFocusLeftId() {
5522         return mNextFocusLeftId;
5523     }
5524 
5525     /**
5526      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5527      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
5528      * decide automatically.
5529      *
5530      * @attr ref android.R.styleable#View_nextFocusLeft
5531      */
setNextFocusLeftId(int nextFocusLeftId)5532     public void setNextFocusLeftId(int nextFocusLeftId) {
5533         mNextFocusLeftId = nextFocusLeftId;
5534     }
5535 
5536     /**
5537      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5538      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5539      *
5540      * @attr ref android.R.styleable#View_nextFocusRight
5541      */
getNextFocusRightId()5542     public int getNextFocusRightId() {
5543         return mNextFocusRightId;
5544     }
5545 
5546     /**
5547      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5548      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
5549      * decide automatically.
5550      *
5551      * @attr ref android.R.styleable#View_nextFocusRight
5552      */
setNextFocusRightId(int nextFocusRightId)5553     public void setNextFocusRightId(int nextFocusRightId) {
5554         mNextFocusRightId = nextFocusRightId;
5555     }
5556 
5557     /**
5558      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5559      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5560      *
5561      * @attr ref android.R.styleable#View_nextFocusUp
5562      */
getNextFocusUpId()5563     public int getNextFocusUpId() {
5564         return mNextFocusUpId;
5565     }
5566 
5567     /**
5568      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5569      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
5570      * decide automatically.
5571      *
5572      * @attr ref android.R.styleable#View_nextFocusUp
5573      */
setNextFocusUpId(int nextFocusUpId)5574     public void setNextFocusUpId(int nextFocusUpId) {
5575         mNextFocusUpId = nextFocusUpId;
5576     }
5577 
5578     /**
5579      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5580      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5581      *
5582      * @attr ref android.R.styleable#View_nextFocusDown
5583      */
getNextFocusDownId()5584     public int getNextFocusDownId() {
5585         return mNextFocusDownId;
5586     }
5587 
5588     /**
5589      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5590      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
5591      * decide automatically.
5592      *
5593      * @attr ref android.R.styleable#View_nextFocusDown
5594      */
setNextFocusDownId(int nextFocusDownId)5595     public void setNextFocusDownId(int nextFocusDownId) {
5596         mNextFocusDownId = nextFocusDownId;
5597     }
5598 
5599     /**
5600      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5601      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5602      *
5603      * @attr ref android.R.styleable#View_nextFocusForward
5604      */
getNextFocusForwardId()5605     public int getNextFocusForwardId() {
5606         return mNextFocusForwardId;
5607     }
5608 
5609     /**
5610      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5611      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
5612      * decide automatically.
5613      *
5614      * @attr ref android.R.styleable#View_nextFocusForward
5615      */
setNextFocusForwardId(int nextFocusForwardId)5616     public void setNextFocusForwardId(int nextFocusForwardId) {
5617         mNextFocusForwardId = nextFocusForwardId;
5618     }
5619 
5620     /**
5621      * Returns the visibility of this view and all of its ancestors
5622      *
5623      * @return True if this view and all of its ancestors are {@link #VISIBLE}
5624      */
isShown()5625     public boolean isShown() {
5626         View current = this;
5627         //noinspection ConstantConditions
5628         do {
5629             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
5630                 return false;
5631             }
5632             ViewParent parent = current.mParent;
5633             if (parent == null) {
5634                 return false; // We are not attached to the view root
5635             }
5636             if (!(parent instanceof View)) {
5637                 return true;
5638             }
5639             current = (View) parent;
5640         } while (current != null);
5641 
5642         return false;
5643     }
5644 
5645     /**
5646      * Called by the view hierarchy when the content insets for a window have
5647      * changed, to allow it to adjust its content to fit within those windows.
5648      * The content insets tell you the space that the status bar, input method,
5649      * and other system windows infringe on the application's window.
5650      *
5651      * <p>You do not normally need to deal with this function, since the default
5652      * window decoration given to applications takes care of applying it to the
5653      * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
5654      * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
5655      * and your content can be placed under those system elements.  You can then
5656      * use this method within your view hierarchy if you have parts of your UI
5657      * which you would like to ensure are not being covered.
5658      *
5659      * <p>The default implementation of this method simply applies the content
5660      * inset's to the view's padding, consuming that content (modifying the
5661      * insets to be 0), and returning true.  This behavior is off by default, but can
5662      * be enabled through {@link #setFitsSystemWindows(boolean)}.
5663      *
5664      * <p>This function's traversal down the hierarchy is depth-first.  The same content
5665      * insets object is propagated down the hierarchy, so any changes made to it will
5666      * be seen by all following views (including potentially ones above in
5667      * the hierarchy since this is a depth-first traversal).  The first view
5668      * that returns true will abort the entire traversal.
5669      *
5670      * <p>The default implementation works well for a situation where it is
5671      * used with a container that covers the entire window, allowing it to
5672      * apply the appropriate insets to its content on all edges.  If you need
5673      * a more complicated layout (such as two different views fitting system
5674      * windows, one on the top of the window, and one on the bottom),
5675      * you can override the method and handle the insets however you would like.
5676      * Note that the insets provided by the framework are always relative to the
5677      * far edges of the window, not accounting for the location of the called view
5678      * within that window.  (In fact when this method is called you do not yet know
5679      * where the layout will place the view, as it is done before layout happens.)
5680      *
5681      * <p>Note: unlike many View methods, there is no dispatch phase to this
5682      * call.  If you are overriding it in a ViewGroup and want to allow the
5683      * call to continue to your children, you must be sure to call the super
5684      * implementation.
5685      *
5686      * <p>Here is a sample layout that makes use of fitting system windows
5687      * to have controls for a video view placed inside of the window decorations
5688      * that it hides and shows.  This can be used with code like the second
5689      * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
5690      *
5691      * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
5692      *
5693      * @param insets Current content insets of the window.  Prior to
5694      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
5695      * the insets or else you and Android will be unhappy.
5696      *
5697      * @return Return true if this view applied the insets and it should not
5698      * continue propagating further down the hierarchy, false otherwise.
5699      * @see #getFitsSystemWindows()
5700      * @see #setFitsSystemWindows(boolean)
5701      * @see #setSystemUiVisibility(int)
5702      */
fitSystemWindows(Rect insets)5703     protected boolean fitSystemWindows(Rect insets) {
5704         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
5705             mUserPaddingStart = UNDEFINED_PADDING;
5706             mUserPaddingEnd = UNDEFINED_PADDING;
5707             Rect localInsets = sThreadLocal.get();
5708             if (localInsets == null) {
5709                 localInsets = new Rect();
5710                 sThreadLocal.set(localInsets);
5711             }
5712             boolean res = computeFitSystemWindows(insets, localInsets);
5713             internalSetPadding(localInsets.left, localInsets.top,
5714                     localInsets.right, localInsets.bottom);
5715             return res;
5716         }
5717         return false;
5718     }
5719 
5720     /**
5721      * @hide Compute the insets that should be consumed by this view and the ones
5722      * that should propagate to those under it.
5723      */
computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets)5724     protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
5725         if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
5726                 || mAttachInfo == null
5727                 || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
5728                         && !mAttachInfo.mOverscanRequested)) {
5729             outLocalInsets.set(inoutInsets);
5730             inoutInsets.set(0, 0, 0, 0);
5731             return true;
5732         } else {
5733             // The application wants to take care of fitting system window for
5734             // the content...  however we still need to take care of any overscan here.
5735             final Rect overscan = mAttachInfo.mOverscanInsets;
5736             outLocalInsets.set(overscan);
5737             inoutInsets.left -= overscan.left;
5738             inoutInsets.top -= overscan.top;
5739             inoutInsets.right -= overscan.right;
5740             inoutInsets.bottom -= overscan.bottom;
5741             return false;
5742         }
5743     }
5744 
5745     /**
5746      * Sets whether or not this view should account for system screen decorations
5747      * such as the status bar and inset its content; that is, controlling whether
5748      * the default implementation of {@link #fitSystemWindows(Rect)} will be
5749      * executed.  See that method for more details.
5750      *
5751      * <p>Note that if you are providing your own implementation of
5752      * {@link #fitSystemWindows(Rect)}, then there is no need to set this
5753      * flag to true -- your implementation will be overriding the default
5754      * implementation that checks this flag.
5755      *
5756      * @param fitSystemWindows If true, then the default implementation of
5757      * {@link #fitSystemWindows(Rect)} will be executed.
5758      *
5759      * @attr ref android.R.styleable#View_fitsSystemWindows
5760      * @see #getFitsSystemWindows()
5761      * @see #fitSystemWindows(Rect)
5762      * @see #setSystemUiVisibility(int)
5763      */
setFitsSystemWindows(boolean fitSystemWindows)5764     public void setFitsSystemWindows(boolean fitSystemWindows) {
5765         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
5766     }
5767 
5768     /**
5769      * Check for state of {@link #setFitsSystemWindows(boolean). If this method
5770      * returns true, the default implementation of {@link #fitSystemWindows(Rect)}
5771      * will be executed.
5772      *
5773      * @return Returns true if the default implementation of
5774      * {@link #fitSystemWindows(Rect)} will be executed.
5775      *
5776      * @attr ref android.R.styleable#View_fitsSystemWindows
5777      * @see #setFitsSystemWindows()
5778      * @see #fitSystemWindows(Rect)
5779      * @see #setSystemUiVisibility(int)
5780      */
getFitsSystemWindows()5781     public boolean getFitsSystemWindows() {
5782         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
5783     }
5784 
5785     /** @hide */
fitsSystemWindows()5786     public boolean fitsSystemWindows() {
5787         return getFitsSystemWindows();
5788     }
5789 
5790     /**
5791      * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
5792      */
requestFitSystemWindows()5793     public void requestFitSystemWindows() {
5794         if (mParent != null) {
5795             mParent.requestFitSystemWindows();
5796         }
5797     }
5798 
5799     /**
5800      * For use by PhoneWindow to make its own system window fitting optional.
5801      * @hide
5802      */
makeOptionalFitsSystemWindows()5803     public void makeOptionalFitsSystemWindows() {
5804         setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
5805     }
5806 
5807     /**
5808      * Returns the visibility status for this view.
5809      *
5810      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5811      * @attr ref android.R.styleable#View_visibility
5812      */
5813     @ViewDebug.ExportedProperty(mapping = {
5814         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
5815         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
5816         @ViewDebug.IntToString(from = GONE,      to = "GONE")
5817     })
getVisibility()5818     public int getVisibility() {
5819         return mViewFlags & VISIBILITY_MASK;
5820     }
5821 
5822     /**
5823      * Set the enabled state of this view.
5824      *
5825      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5826      * @attr ref android.R.styleable#View_visibility
5827      */
5828     @RemotableViewMethod
setVisibility(int visibility)5829     public void setVisibility(int visibility) {
5830         setFlags(visibility, VISIBILITY_MASK);
5831         if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
5832     }
5833 
5834     /**
5835      * Returns the enabled status for this view. The interpretation of the
5836      * enabled state varies by subclass.
5837      *
5838      * @return True if this view is enabled, false otherwise.
5839      */
5840     @ViewDebug.ExportedProperty
isEnabled()5841     public boolean isEnabled() {
5842         return (mViewFlags & ENABLED_MASK) == ENABLED;
5843     }
5844 
5845     /**
5846      * Set the enabled state of this view. The interpretation of the enabled
5847      * state varies by subclass.
5848      *
5849      * @param enabled True if this view is enabled, false otherwise.
5850      */
5851     @RemotableViewMethod
setEnabled(boolean enabled)5852     public void setEnabled(boolean enabled) {
5853         if (enabled == isEnabled()) return;
5854 
5855         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
5856 
5857         /*
5858          * The View most likely has to change its appearance, so refresh
5859          * the drawable state.
5860          */
5861         refreshDrawableState();
5862 
5863         // Invalidate too, since the default behavior for views is to be
5864         // be drawn at 50% alpha rather than to change the drawable.
5865         invalidate(true);
5866     }
5867 
5868     /**
5869      * Set whether this view can receive the focus.
5870      *
5871      * Setting this to false will also ensure that this view is not focusable
5872      * in touch mode.
5873      *
5874      * @param focusable If true, this view can receive the focus.
5875      *
5876      * @see #setFocusableInTouchMode(boolean)
5877      * @attr ref android.R.styleable#View_focusable
5878      */
setFocusable(boolean focusable)5879     public void setFocusable(boolean focusable) {
5880         if (!focusable) {
5881             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
5882         }
5883         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
5884     }
5885 
5886     /**
5887      * Set whether this view can receive focus while in touch mode.
5888      *
5889      * Setting this to true will also ensure that this view is focusable.
5890      *
5891      * @param focusableInTouchMode If true, this view can receive the focus while
5892      *   in touch mode.
5893      *
5894      * @see #setFocusable(boolean)
5895      * @attr ref android.R.styleable#View_focusableInTouchMode
5896      */
setFocusableInTouchMode(boolean focusableInTouchMode)5897     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
5898         // Focusable in touch mode should always be set before the focusable flag
5899         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
5900         // which, in touch mode, will not successfully request focus on this view
5901         // because the focusable in touch mode flag is not set
5902         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
5903         if (focusableInTouchMode) {
5904             setFlags(FOCUSABLE, FOCUSABLE_MASK);
5905         }
5906     }
5907 
5908     /**
5909      * Set whether this view should have sound effects enabled for events such as
5910      * clicking and touching.
5911      *
5912      * <p>You may wish to disable sound effects for a view if you already play sounds,
5913      * for instance, a dial key that plays dtmf tones.
5914      *
5915      * @param soundEffectsEnabled whether sound effects are enabled for this view.
5916      * @see #isSoundEffectsEnabled()
5917      * @see #playSoundEffect(int)
5918      * @attr ref android.R.styleable#View_soundEffectsEnabled
5919      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)5920     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
5921         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
5922     }
5923 
5924     /**
5925      * @return whether this view should have sound effects enabled for events such as
5926      *     clicking and touching.
5927      *
5928      * @see #setSoundEffectsEnabled(boolean)
5929      * @see #playSoundEffect(int)
5930      * @attr ref android.R.styleable#View_soundEffectsEnabled
5931      */
5932     @ViewDebug.ExportedProperty
isSoundEffectsEnabled()5933     public boolean isSoundEffectsEnabled() {
5934         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
5935     }
5936 
5937     /**
5938      * Set whether this view should have haptic feedback for events such as
5939      * long presses.
5940      *
5941      * <p>You may wish to disable haptic feedback if your view already controls
5942      * its own haptic feedback.
5943      *
5944      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
5945      * @see #isHapticFeedbackEnabled()
5946      * @see #performHapticFeedback(int)
5947      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5948      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)5949     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
5950         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
5951     }
5952 
5953     /**
5954      * @return whether this view should have haptic feedback enabled for events
5955      * long presses.
5956      *
5957      * @see #setHapticFeedbackEnabled(boolean)
5958      * @see #performHapticFeedback(int)
5959      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5960      */
5961     @ViewDebug.ExportedProperty
isHapticFeedbackEnabled()5962     public boolean isHapticFeedbackEnabled() {
5963         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
5964     }
5965 
5966     /**
5967      * Returns the layout direction for this view.
5968      *
5969      * @return One of {@link #LAYOUT_DIRECTION_LTR},
5970      *   {@link #LAYOUT_DIRECTION_RTL},
5971      *   {@link #LAYOUT_DIRECTION_INHERIT} or
5972      *   {@link #LAYOUT_DIRECTION_LOCALE}.
5973      *
5974      * @attr ref android.R.styleable#View_layoutDirection
5975      *
5976      * @hide
5977      */
5978     @ViewDebug.ExportedProperty(category = "layout", mapping = {
5979         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
5980         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
5981         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
5982         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
5983     })
getRawLayoutDirection()5984     public int getRawLayoutDirection() {
5985         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
5986     }
5987 
5988     /**
5989      * Set the layout direction for this view. This will propagate a reset of layout direction
5990      * resolution to the view's children and resolve layout direction for this view.
5991      *
5992      * @param layoutDirection the layout direction to set. Should be one of:
5993      *
5994      * {@link #LAYOUT_DIRECTION_LTR},
5995      * {@link #LAYOUT_DIRECTION_RTL},
5996      * {@link #LAYOUT_DIRECTION_INHERIT},
5997      * {@link #LAYOUT_DIRECTION_LOCALE}.
5998      *
5999      * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
6000      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
6001      * will return the default {@link #LAYOUT_DIRECTION_LTR}.
6002      *
6003      * @attr ref android.R.styleable#View_layoutDirection
6004      */
6005     @RemotableViewMethod
setLayoutDirection(int layoutDirection)6006     public void setLayoutDirection(int layoutDirection) {
6007         if (getRawLayoutDirection() != layoutDirection) {
6008             // Reset the current layout direction and the resolved one
6009             mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
6010             resetRtlProperties();
6011             // Set the new layout direction (filtered)
6012             mPrivateFlags2 |=
6013                     ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
6014             // We need to resolve all RTL properties as they all depend on layout direction
6015             resolveRtlPropertiesIfNeeded();
6016             requestLayout();
6017             invalidate(true);
6018         }
6019     }
6020 
6021     /**
6022      * Returns the resolved layout direction for this view.
6023      *
6024      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
6025      * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
6026      *
6027      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
6028      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
6029      *
6030      * @attr ref android.R.styleable#View_layoutDirection
6031      */
6032     @ViewDebug.ExportedProperty(category = "layout", mapping = {
6033         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
6034         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
6035     })
getLayoutDirection()6036     public int getLayoutDirection() {
6037         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
6038         if (targetSdkVersion < JELLY_BEAN_MR1) {
6039             mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
6040             return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
6041         }
6042         return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
6043                 PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
6044     }
6045 
6046     /**
6047      * Indicates whether or not this view's layout is right-to-left. This is resolved from
6048      * layout attribute and/or the inherited value from the parent
6049      *
6050      * @return true if the layout is right-to-left.
6051      *
6052      * @hide
6053      */
6054     @ViewDebug.ExportedProperty(category = "layout")
isLayoutRtl()6055     public boolean isLayoutRtl() {
6056         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
6057     }
6058 
6059     /**
6060      * Indicates whether the view is currently tracking transient state that the
6061      * app should not need to concern itself with saving and restoring, but that
6062      * the framework should take special note to preserve when possible.
6063      *
6064      * <p>A view with transient state cannot be trivially rebound from an external
6065      * data source, such as an adapter binding item views in a list. This may be
6066      * because the view is performing an animation, tracking user selection
6067      * of content, or similar.</p>
6068      *
6069      * @return true if the view has transient state
6070      */
6071     @ViewDebug.ExportedProperty(category = "layout")
hasTransientState()6072     public boolean hasTransientState() {
6073         return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
6074     }
6075 
6076     /**
6077      * Set whether this view is currently tracking transient state that the
6078      * framework should attempt to preserve when possible. This flag is reference counted,
6079      * so every call to setHasTransientState(true) should be paired with a later call
6080      * to setHasTransientState(false).
6081      *
6082      * <p>A view with transient state cannot be trivially rebound from an external
6083      * data source, such as an adapter binding item views in a list. This may be
6084      * because the view is performing an animation, tracking user selection
6085      * of content, or similar.</p>
6086      *
6087      * @param hasTransientState true if this view has transient state
6088      */
setHasTransientState(boolean hasTransientState)6089     public void setHasTransientState(boolean hasTransientState) {
6090         mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
6091                 mTransientStateCount - 1;
6092         if (mTransientStateCount < 0) {
6093             mTransientStateCount = 0;
6094             Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
6095                     "unmatched pair of setHasTransientState calls");
6096         } else if ((hasTransientState && mTransientStateCount == 1) ||
6097                 (!hasTransientState && mTransientStateCount == 0)) {
6098             // update flag if we've just incremented up from 0 or decremented down to 0
6099             mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
6100                     (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
6101             if (mParent != null) {
6102                 try {
6103                     mParent.childHasTransientStateChanged(this, hasTransientState);
6104                 } catch (AbstractMethodError e) {
6105                     Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
6106                             " does not fully implement ViewParent", e);
6107                 }
6108             }
6109         }
6110     }
6111 
6112     /**
6113      * If this view doesn't do any drawing on its own, set this flag to
6114      * allow further optimizations. By default, this flag is not set on
6115      * View, but could be set on some View subclasses such as ViewGroup.
6116      *
6117      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
6118      * you should clear this flag.
6119      *
6120      * @param willNotDraw whether or not this View draw on its own
6121      */
setWillNotDraw(boolean willNotDraw)6122     public void setWillNotDraw(boolean willNotDraw) {
6123         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
6124     }
6125 
6126     /**
6127      * Returns whether or not this View draws on its own.
6128      *
6129      * @return true if this view has nothing to draw, false otherwise
6130      */
6131     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()6132     public boolean willNotDraw() {
6133         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
6134     }
6135 
6136     /**
6137      * When a View's drawing cache is enabled, drawing is redirected to an
6138      * offscreen bitmap. Some views, like an ImageView, must be able to
6139      * bypass this mechanism if they already draw a single bitmap, to avoid
6140      * unnecessary usage of the memory.
6141      *
6142      * @param willNotCacheDrawing true if this view does not cache its
6143      *        drawing, false otherwise
6144      */
setWillNotCacheDrawing(boolean willNotCacheDrawing)6145     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
6146         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
6147     }
6148 
6149     /**
6150      * Returns whether or not this View can cache its drawing or not.
6151      *
6152      * @return true if this view does not cache its drawing, false otherwise
6153      */
6154     @ViewDebug.ExportedProperty(category = "drawing")
willNotCacheDrawing()6155     public boolean willNotCacheDrawing() {
6156         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
6157     }
6158 
6159     /**
6160      * Indicates whether this view reacts to click events or not.
6161      *
6162      * @return true if the view is clickable, false otherwise
6163      *
6164      * @see #setClickable(boolean)
6165      * @attr ref android.R.styleable#View_clickable
6166      */
6167     @ViewDebug.ExportedProperty
isClickable()6168     public boolean isClickable() {
6169         return (mViewFlags & CLICKABLE) == CLICKABLE;
6170     }
6171 
6172     /**
6173      * Enables or disables click events for this view. When a view
6174      * is clickable it will change its state to "pressed" on every click.
6175      * Subclasses should set the view clickable to visually react to
6176      * user's clicks.
6177      *
6178      * @param clickable true to make the view clickable, false otherwise
6179      *
6180      * @see #isClickable()
6181      * @attr ref android.R.styleable#View_clickable
6182      */
setClickable(boolean clickable)6183     public void setClickable(boolean clickable) {
6184         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
6185     }
6186 
6187     /**
6188      * Indicates whether this view reacts to long click events or not.
6189      *
6190      * @return true if the view is long clickable, false otherwise
6191      *
6192      * @see #setLongClickable(boolean)
6193      * @attr ref android.R.styleable#View_longClickable
6194      */
isLongClickable()6195     public boolean isLongClickable() {
6196         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
6197     }
6198 
6199     /**
6200      * Enables or disables long click events for this view. When a view is long
6201      * clickable it reacts to the user holding down the button for a longer
6202      * duration than a tap. This event can either launch the listener or a
6203      * context menu.
6204      *
6205      * @param longClickable true to make the view long clickable, false otherwise
6206      * @see #isLongClickable()
6207      * @attr ref android.R.styleable#View_longClickable
6208      */
setLongClickable(boolean longClickable)6209     public void setLongClickable(boolean longClickable) {
6210         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
6211     }
6212 
6213     /**
6214      * Sets the pressed state for this view.
6215      *
6216      * @see #isClickable()
6217      * @see #setClickable(boolean)
6218      *
6219      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
6220      *        the View's internal state from a previously set "pressed" state.
6221      */
setPressed(boolean pressed)6222     public void setPressed(boolean pressed) {
6223         final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
6224 
6225         if (pressed) {
6226             mPrivateFlags |= PFLAG_PRESSED;
6227         } else {
6228             mPrivateFlags &= ~PFLAG_PRESSED;
6229         }
6230 
6231         if (needsRefresh) {
6232             refreshDrawableState();
6233         }
6234         dispatchSetPressed(pressed);
6235     }
6236 
6237     /**
6238      * Dispatch setPressed to all of this View's children.
6239      *
6240      * @see #setPressed(boolean)
6241      *
6242      * @param pressed The new pressed state
6243      */
dispatchSetPressed(boolean pressed)6244     protected void dispatchSetPressed(boolean pressed) {
6245     }
6246 
6247     /**
6248      * Indicates whether the view is currently in pressed state. Unless
6249      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
6250      * the pressed state.
6251      *
6252      * @see #setPressed(boolean)
6253      * @see #isClickable()
6254      * @see #setClickable(boolean)
6255      *
6256      * @return true if the view is currently pressed, false otherwise
6257      */
isPressed()6258     public boolean isPressed() {
6259         return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
6260     }
6261 
6262     /**
6263      * Indicates whether this view will save its state (that is,
6264      * whether its {@link #onSaveInstanceState} method will be called).
6265      *
6266      * @return Returns true if the view state saving is enabled, else false.
6267      *
6268      * @see #setSaveEnabled(boolean)
6269      * @attr ref android.R.styleable#View_saveEnabled
6270      */
isSaveEnabled()6271     public boolean isSaveEnabled() {
6272         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
6273     }
6274 
6275     /**
6276      * Controls whether the saving of this view's state is
6277      * enabled (that is, whether its {@link #onSaveInstanceState} method
6278      * will be called).  Note that even if freezing is enabled, the
6279      * view still must have an id assigned to it (via {@link #setId(int)})
6280      * for its state to be saved.  This flag can only disable the
6281      * saving of this view; any child views may still have their state saved.
6282      *
6283      * @param enabled Set to false to <em>disable</em> state saving, or true
6284      * (the default) to allow it.
6285      *
6286      * @see #isSaveEnabled()
6287      * @see #setId(int)
6288      * @see #onSaveInstanceState()
6289      * @attr ref android.R.styleable#View_saveEnabled
6290      */
setSaveEnabled(boolean enabled)6291     public void setSaveEnabled(boolean enabled) {
6292         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
6293     }
6294 
6295     /**
6296      * Gets whether the framework should discard touches when the view's
6297      * window is obscured by another visible window.
6298      * Refer to the {@link View} security documentation for more details.
6299      *
6300      * @return True if touch filtering is enabled.
6301      *
6302      * @see #setFilterTouchesWhenObscured(boolean)
6303      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
6304      */
6305     @ViewDebug.ExportedProperty
getFilterTouchesWhenObscured()6306     public boolean getFilterTouchesWhenObscured() {
6307         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
6308     }
6309 
6310     /**
6311      * Sets whether the framework should discard touches when the view's
6312      * window is obscured by another visible window.
6313      * Refer to the {@link View} security documentation for more details.
6314      *
6315      * @param enabled True if touch filtering should be enabled.
6316      *
6317      * @see #getFilterTouchesWhenObscured
6318      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
6319      */
setFilterTouchesWhenObscured(boolean enabled)6320     public void setFilterTouchesWhenObscured(boolean enabled) {
6321         setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
6322                 FILTER_TOUCHES_WHEN_OBSCURED);
6323     }
6324 
6325     /**
6326      * Indicates whether the entire hierarchy under this view will save its
6327      * state when a state saving traversal occurs from its parent.  The default
6328      * is true; if false, these views will not be saved unless
6329      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
6330      *
6331      * @return Returns true if the view state saving from parent is enabled, else false.
6332      *
6333      * @see #setSaveFromParentEnabled(boolean)
6334      */
isSaveFromParentEnabled()6335     public boolean isSaveFromParentEnabled() {
6336         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
6337     }
6338 
6339     /**
6340      * Controls whether the entire hierarchy under this view will save its
6341      * state when a state saving traversal occurs from its parent.  The default
6342      * is true; if false, these views will not be saved unless
6343      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
6344      *
6345      * @param enabled Set to false to <em>disable</em> state saving, or true
6346      * (the default) to allow it.
6347      *
6348      * @see #isSaveFromParentEnabled()
6349      * @see #setId(int)
6350      * @see #onSaveInstanceState()
6351      */
setSaveFromParentEnabled(boolean enabled)6352     public void setSaveFromParentEnabled(boolean enabled) {
6353         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
6354     }
6355 
6356 
6357     /**
6358      * Returns whether this View is able to take focus.
6359      *
6360      * @return True if this view can take focus, or false otherwise.
6361      * @attr ref android.R.styleable#View_focusable
6362      */
6363     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()6364     public final boolean isFocusable() {
6365         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
6366     }
6367 
6368     /**
6369      * When a view is focusable, it may not want to take focus when in touch mode.
6370      * For example, a button would like focus when the user is navigating via a D-pad
6371      * so that the user can click on it, but once the user starts touching the screen,
6372      * the button shouldn't take focus
6373      * @return Whether the view is focusable in touch mode.
6374      * @attr ref android.R.styleable#View_focusableInTouchMode
6375      */
6376     @ViewDebug.ExportedProperty
isFocusableInTouchMode()6377     public final boolean isFocusableInTouchMode() {
6378         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
6379     }
6380 
6381     /**
6382      * Find the nearest view in the specified direction that can take focus.
6383      * This does not actually give focus to that view.
6384      *
6385      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6386      *
6387      * @return The nearest focusable in the specified direction, or null if none
6388      *         can be found.
6389      */
focusSearch(int direction)6390     public View focusSearch(int direction) {
6391         if (mParent != null) {
6392             return mParent.focusSearch(this, direction);
6393         } else {
6394             return null;
6395         }
6396     }
6397 
6398     /**
6399      * This method is the last chance for the focused view and its ancestors to
6400      * respond to an arrow key. This is called when the focused view did not
6401      * consume the key internally, nor could the view system find a new view in
6402      * the requested direction to give focus to.
6403      *
6404      * @param focused The currently focused view.
6405      * @param direction The direction focus wants to move. One of FOCUS_UP,
6406      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
6407      * @return True if the this view consumed this unhandled move.
6408      */
dispatchUnhandledMove(View focused, int direction)6409     public boolean dispatchUnhandledMove(View focused, int direction) {
6410         return false;
6411     }
6412 
6413     /**
6414      * If a user manually specified the next view id for a particular direction,
6415      * use the root to look up the view.
6416      * @param root The root view of the hierarchy containing this view.
6417      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
6418      * or FOCUS_BACKWARD.
6419      * @return The user specified next view, or null if there is none.
6420      */
findUserSetNextFocus(View root, int direction)6421     View findUserSetNextFocus(View root, int direction) {
6422         switch (direction) {
6423             case FOCUS_LEFT:
6424                 if (mNextFocusLeftId == View.NO_ID) return null;
6425                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
6426             case FOCUS_RIGHT:
6427                 if (mNextFocusRightId == View.NO_ID) return null;
6428                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
6429             case FOCUS_UP:
6430                 if (mNextFocusUpId == View.NO_ID) return null;
6431                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
6432             case FOCUS_DOWN:
6433                 if (mNextFocusDownId == View.NO_ID) return null;
6434                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
6435             case FOCUS_FORWARD:
6436                 if (mNextFocusForwardId == View.NO_ID) return null;
6437                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
6438             case FOCUS_BACKWARD: {
6439                 if (mID == View.NO_ID) return null;
6440                 final int id = mID;
6441                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
6442                     @Override
6443                     public boolean apply(View t) {
6444                         return t.mNextFocusForwardId == id;
6445                     }
6446                 });
6447             }
6448         }
6449         return null;
6450     }
6451 
6452     private View findViewInsideOutShouldExist(View root, int id) {
6453         if (mMatchIdPredicate == null) {
6454             mMatchIdPredicate = new MatchIdPredicate();
6455         }
6456         mMatchIdPredicate.mId = id;
6457         View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
6458         if (result == null) {
6459             Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
6460         }
6461         return result;
6462     }
6463 
6464     /**
6465      * Find and return all focusable views that are descendants of this view,
6466      * possibly including this view if it is focusable itself.
6467      *
6468      * @param direction The direction of the focus
6469      * @return A list of focusable views
6470      */
6471     public ArrayList<View> getFocusables(int direction) {
6472         ArrayList<View> result = new ArrayList<View>(24);
6473         addFocusables(result, direction);
6474         return result;
6475     }
6476 
6477     /**
6478      * Add any focusable views that are descendants of this view (possibly
6479      * including this view if it is focusable itself) to views.  If we are in touch mode,
6480      * only add views that are also focusable in touch mode.
6481      *
6482      * @param views Focusable views found so far
6483      * @param direction The direction of the focus
6484      */
6485     public void addFocusables(ArrayList<View> views, int direction) {
6486         addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
6487     }
6488 
6489     /**
6490      * Adds any focusable views that are descendants of this view (possibly
6491      * including this view if it is focusable itself) to views. This method
6492      * adds all focusable views regardless if we are in touch mode or
6493      * only views focusable in touch mode if we are in touch mode or
6494      * only views that can take accessibility focus if accessibility is enabeld
6495      * depending on the focusable mode paramater.
6496      *
6497      * @param views Focusable views found so far or null if all we are interested is
6498      *        the number of focusables.
6499      * @param direction The direction of the focus.
6500      * @param focusableMode The type of focusables to be added.
6501      *
6502      * @see #FOCUSABLES_ALL
6503      * @see #FOCUSABLES_TOUCH_MODE
6504      */
6505     public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
6506         if (views == null) {
6507             return;
6508         }
6509         if (!isFocusable()) {
6510             return;
6511         }
6512         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
6513                 && isInTouchMode() && !isFocusableInTouchMode()) {
6514             return;
6515         }
6516         views.add(this);
6517     }
6518 
6519     /**
6520      * Finds the Views that contain given text. The containment is case insensitive.
6521      * The search is performed by either the text that the View renders or the content
6522      * description that describes the view for accessibility purposes and the view does
6523      * not render or both. Clients can specify how the search is to be performed via
6524      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
6525      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
6526      *
6527      * @param outViews The output list of matching Views.
6528      * @param searched The text to match against.
6529      *
6530      * @see #FIND_VIEWS_WITH_TEXT
6531      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
6532      * @see #setContentDescription(CharSequence)
6533      */
6534     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
6535         if (getAccessibilityNodeProvider() != null) {
6536             if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
6537                 outViews.add(this);
6538             }
6539         } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
6540                 && (searched != null && searched.length() > 0)
6541                 && (mContentDescription != null && mContentDescription.length() > 0)) {
6542             String searchedLowerCase = searched.toString().toLowerCase();
6543             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
6544             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
6545                 outViews.add(this);
6546             }
6547         }
6548     }
6549 
6550     /**
6551      * Find and return all touchable views that are descendants of this view,
6552      * possibly including this view if it is touchable itself.
6553      *
6554      * @return A list of touchable views
6555      */
6556     public ArrayList<View> getTouchables() {
6557         ArrayList<View> result = new ArrayList<View>();
6558         addTouchables(result);
6559         return result;
6560     }
6561 
6562     /**
6563      * Add any touchable views that are descendants of this view (possibly
6564      * including this view if it is touchable itself) to views.
6565      *
6566      * @param views Touchable views found so far
6567      */
6568     public void addTouchables(ArrayList<View> views) {
6569         final int viewFlags = mViewFlags;
6570 
6571         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
6572                 && (viewFlags & ENABLED_MASK) == ENABLED) {
6573             views.add(this);
6574         }
6575     }
6576 
6577     /**
6578      * Returns whether this View is accessibility focused.
6579      *
6580      * @return True if this View is accessibility focused.
6581      */
6582     boolean isAccessibilityFocused() {
6583         return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
6584     }
6585 
6586     /**
6587      * Call this to try to give accessibility focus to this view.
6588      *
6589      * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
6590      * returns false or the view is no visible or the view already has accessibility
6591      * focus.
6592      *
6593      * See also {@link #focusSearch(int)}, which is what you call to say that you
6594      * have focus, and you want your parent to look for the next one.
6595      *
6596      * @return Whether this view actually took accessibility focus.
6597      *
6598      * @hide
6599      */
6600     public boolean requestAccessibilityFocus() {
6601         AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
6602         if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
6603             return false;
6604         }
6605         if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6606             return false;
6607         }
6608         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
6609             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
6610             ViewRootImpl viewRootImpl = getViewRootImpl();
6611             if (viewRootImpl != null) {
6612                 viewRootImpl.setAccessibilityFocus(this, null);
6613             }
6614             invalidate();
6615             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
6616             notifyAccessibilityStateChanged();
6617             return true;
6618         }
6619         return false;
6620     }
6621 
6622     /**
6623      * Call this to try to clear accessibility focus of this view.
6624      *
6625      * See also {@link #focusSearch(int)}, which is what you call to say that you
6626      * have focus, and you want your parent to look for the next one.
6627      *
6628      * @hide
6629      */
6630     public void clearAccessibilityFocus() {
6631         clearAccessibilityFocusNoCallbacks();
6632         // Clear the global reference of accessibility focus if this
6633         // view or any of its descendants had accessibility focus.
6634         ViewRootImpl viewRootImpl = getViewRootImpl();
6635         if (viewRootImpl != null) {
6636             View focusHost = viewRootImpl.getAccessibilityFocusedHost();
6637             if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
6638                 viewRootImpl.setAccessibilityFocus(null, null);
6639             }
6640         }
6641     }
6642 
6643     private void sendAccessibilityHoverEvent(int eventType) {
6644         // Since we are not delivering to a client accessibility events from not
6645         // important views (unless the clinet request that) we need to fire the
6646         // event from the deepest view exposed to the client. As a consequence if
6647         // the user crosses a not exposed view the client will see enter and exit
6648         // of the exposed predecessor followed by and enter and exit of that same
6649         // predecessor when entering and exiting the not exposed descendant. This
6650         // is fine since the client has a clear idea which view is hovered at the
6651         // price of a couple more events being sent. This is a simple and
6652         // working solution.
6653         View source = this;
6654         while (true) {
6655             if (source.includeForAccessibility()) {
6656                 source.sendAccessibilityEvent(eventType);
6657                 return;
6658             }
6659             ViewParent parent = source.getParent();
6660             if (parent instanceof View) {
6661                 source = (View) parent;
6662             } else {
6663                 return;
6664             }
6665         }
6666     }
6667 
6668     /**
6669      * Clears accessibility focus without calling any callback methods
6670      * normally invoked in {@link #clearAccessibilityFocus()}. This method
6671      * is used for clearing accessibility focus when giving this focus to
6672      * another view.
6673      */
6674     void clearAccessibilityFocusNoCallbacks() {
6675         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
6676             mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
6677             invalidate();
6678             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
6679             notifyAccessibilityStateChanged();
6680         }
6681     }
6682 
6683     /**
6684      * Call this to try to give focus to a specific view or to one of its
6685      * descendants.
6686      *
6687      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6688      * false), or if it is focusable and it is not focusable in touch mode
6689      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
6690      *
6691      * See also {@link #focusSearch(int)}, which is what you call to say that you
6692      * have focus, and you want your parent to look for the next one.
6693      *
6694      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
6695      * {@link #FOCUS_DOWN} and <code>null</code>.
6696      *
6697      * @return Whether this view or one of its descendants actually took focus.
6698      */
6699     public final boolean requestFocus() {
6700         return requestFocus(View.FOCUS_DOWN);
6701     }
6702 
6703     /**
6704      * Call this to try to give focus to a specific view or to one of its
6705      * descendants and give it a hint about what direction focus is heading.
6706      *
6707      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6708      * false), or if it is focusable and it is not focusable in touch mode
6709      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
6710      *
6711      * See also {@link #focusSearch(int)}, which is what you call to say that you
6712      * have focus, and you want your parent to look for the next one.
6713      *
6714      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
6715      * <code>null</code> set for the previously focused rectangle.
6716      *
6717      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6718      * @return Whether this view or one of its descendants actually took focus.
6719      */
6720     public final boolean requestFocus(int direction) {
6721         return requestFocus(direction, null);
6722     }
6723 
6724     /**
6725      * Call this to try to give focus to a specific view or to one of its descendants
6726      * and give it hints about the direction and a specific rectangle that the focus
6727      * is coming from.  The rectangle can help give larger views a finer grained hint
6728      * about where focus is coming from, and therefore, where to show selection, or
6729      * forward focus change internally.
6730      *
6731      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6732      * false), or if it is focusable and it is not focusable in touch mode
6733      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
6734      *
6735      * A View will not take focus if it is not visible.
6736      *
6737      * A View will not take focus if one of its parents has
6738      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
6739      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
6740      *
6741      * See also {@link #focusSearch(int)}, which is what you call to say that you
6742      * have focus, and you want your parent to look for the next one.
6743      *
6744      * You may wish to override this method if your custom {@link View} has an internal
6745      * {@link View} that it wishes to forward the request to.
6746      *
6747      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6748      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
6749      *        to give a finer grained hint about where focus is coming from.  May be null
6750      *        if there is no hint.
6751      * @return Whether this view or one of its descendants actually took focus.
6752      */
6753     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
6754         return requestFocusNoSearch(direction, previouslyFocusedRect);
6755     }
6756 
6757     private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
6758         // need to be focusable
6759         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
6760                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6761             return false;
6762         }
6763 
6764         // need to be focusable in touch mode if in touch mode
6765         if (isInTouchMode() &&
6766             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
6767                return false;
6768         }
6769 
6770         // need to not have any parents blocking us
6771         if (hasAncestorThatBlocksDescendantFocus()) {
6772             return false;
6773         }
6774 
6775         handleFocusGainInternal(direction, previouslyFocusedRect);
6776         return true;
6777     }
6778 
6779     /**
6780      * Call this to try to give focus to a specific view or to one of its descendants. This is a
6781      * special variant of {@link #requestFocus() } that will allow views that are not focuable in
6782      * touch mode to request focus when they are touched.
6783      *
6784      * @return Whether this view or one of its descendants actually took focus.
6785      *
6786      * @see #isInTouchMode()
6787      *
6788      */
6789     public final boolean requestFocusFromTouch() {
6790         // Leave touch mode if we need to
6791         if (isInTouchMode()) {
6792             ViewRootImpl viewRoot = getViewRootImpl();
6793             if (viewRoot != null) {
6794                 viewRoot.ensureTouchMode(false);
6795             }
6796         }
6797         return requestFocus(View.FOCUS_DOWN);
6798     }
6799 
6800     /**
6801      * @return Whether any ancestor of this view blocks descendant focus.
6802      */
6803     private boolean hasAncestorThatBlocksDescendantFocus() {
6804         ViewParent ancestor = mParent;
6805         while (ancestor instanceof ViewGroup) {
6806             final ViewGroup vgAncestor = (ViewGroup) ancestor;
6807             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
6808                 return true;
6809             } else {
6810                 ancestor = vgAncestor.getParent();
6811             }
6812         }
6813         return false;
6814     }
6815 
6816     /**
6817      * Gets the mode for determining whether this View is important for accessibility
6818      * which is if it fires accessibility events and if it is reported to
6819      * accessibility services that query the screen.
6820      *
6821      * @return The mode for determining whether a View is important for accessibility.
6822      *
6823      * @attr ref android.R.styleable#View_importantForAccessibility
6824      *
6825      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6826      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6827      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6828      */
6829     @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
6830             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
6831             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
6832             @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
6833         })
6834     public int getImportantForAccessibility() {
6835         return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
6836                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
6837     }
6838 
6839     /**
6840      * Sets how to determine whether this view is important for accessibility
6841      * which is if it fires accessibility events and if it is reported to
6842      * accessibility services that query the screen.
6843      *
6844      * @param mode How to determine whether this view is important for accessibility.
6845      *
6846      * @attr ref android.R.styleable#View_importantForAccessibility
6847      *
6848      * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6849      * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6850      * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6851      */
6852     public void setImportantForAccessibility(int mode) {
6853         if (mode != getImportantForAccessibility()) {
6854             mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
6855             mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
6856                     & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
6857             notifyAccessibilityStateChanged();
6858         }
6859     }
6860 
6861     /**
6862      * Gets whether this view should be exposed for accessibility.
6863      *
6864      * @return Whether the view is exposed for accessibility.
6865      *
6866      * @hide
6867      */
6868     public boolean isImportantForAccessibility() {
6869         final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
6870                 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
6871         switch (mode) {
6872             case IMPORTANT_FOR_ACCESSIBILITY_YES:
6873                 return true;
6874             case IMPORTANT_FOR_ACCESSIBILITY_NO:
6875                 return false;
6876             case IMPORTANT_FOR_ACCESSIBILITY_AUTO:
6877                 return isActionableForAccessibility() || hasListenersForAccessibility()
6878                         || getAccessibilityNodeProvider() != null;
6879             default:
6880                 throw new IllegalArgumentException("Unknow important for accessibility mode: "
6881                         + mode);
6882         }
6883     }
6884 
6885     /**
6886      * Gets the parent for accessibility purposes. Note that the parent for
6887      * accessibility is not necessary the immediate parent. It is the first
6888      * predecessor that is important for accessibility.
6889      *
6890      * @return The parent for accessibility purposes.
6891      */
6892     public ViewParent getParentForAccessibility() {
6893         if (mParent instanceof View) {
6894             View parentView = (View) mParent;
6895             if (parentView.includeForAccessibility()) {
6896                 return mParent;
6897             } else {
6898                 return mParent.getParentForAccessibility();
6899             }
6900         }
6901         return null;
6902     }
6903 
6904     /**
6905      * Adds the children of a given View for accessibility. Since some Views are
6906      * not important for accessibility the children for accessibility are not
6907      * necessarily direct children of the view, rather they are the first level of
6908      * descendants important for accessibility.
6909      *
6910      * @param children The list of children for accessibility.
6911      */
6912     public void addChildrenForAccessibility(ArrayList<View> children) {
6913         if (includeForAccessibility()) {
6914             children.add(this);
6915         }
6916     }
6917 
6918     /**
6919      * Whether to regard this view for accessibility. A view is regarded for
6920      * accessibility if it is important for accessibility or the querying
6921      * accessibility service has explicitly requested that view not
6922      * important for accessibility are regarded.
6923      *
6924      * @return Whether to regard the view for accessibility.
6925      *
6926      * @hide
6927      */
6928     public boolean includeForAccessibility() {
6929         if (mAttachInfo != null) {
6930             return (mAttachInfo.mAccessibilityFetchFlags
6931                     & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
6932                     || isImportantForAccessibility();
6933         }
6934         return false;
6935     }
6936 
6937     /**
6938      * Returns whether the View is considered actionable from
6939      * accessibility perspective. Such view are important for
6940      * accessibility.
6941      *
6942      * @return True if the view is actionable for accessibility.
6943      *
6944      * @hide
6945      */
6946     public boolean isActionableForAccessibility() {
6947         return (isClickable() || isLongClickable() || isFocusable());
6948     }
6949 
6950     /**
6951      * Returns whether the View has registered callbacks wich makes it
6952      * important for accessibility.
6953      *
6954      * @return True if the view is actionable for accessibility.
6955      */
6956     private boolean hasListenersForAccessibility() {
6957         ListenerInfo info = getListenerInfo();
6958         return mTouchDelegate != null || info.mOnKeyListener != null
6959                 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
6960                 || info.mOnHoverListener != null || info.mOnDragListener != null;
6961     }
6962 
6963     /**
6964      * Notifies accessibility services that some view's important for
6965      * accessibility state has changed. Note that such notifications
6966      * are made at most once every
6967      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
6968      * to avoid unnecessary load to the system. Also once a view has
6969      * made a notifucation this method is a NOP until the notification has
6970      * been sent to clients.
6971      *
6972      * @hide
6973      *
6974      * TODO: Makse sure this method is called for any view state change
6975      *       that is interesting for accessilility purposes.
6976      */
6977     public void notifyAccessibilityStateChanged() {
6978         if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
6979             return;
6980         }
6981         if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_STATE_CHANGED) == 0) {
6982             mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_STATE_CHANGED;
6983             if (mParent != null) {
6984                 mParent.childAccessibilityStateChanged(this);
6985             }
6986         }
6987     }
6988 
6989     /**
6990      * Reset the state indicating the this view has requested clients
6991      * interested in its accessibility state to be notified.
6992      *
6993      * @hide
6994      */
6995     public void resetAccessibilityStateChanged() {
6996         mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_STATE_CHANGED;
6997     }
6998 
6999     /**
7000      * Performs the specified accessibility action on the view. For
7001      * possible accessibility actions look at {@link AccessibilityNodeInfo}.
7002      * <p>
7003      * If an {@link AccessibilityDelegate} has been specified via calling
7004      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7005      * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
7006      * is responsible for handling this call.
7007      * </p>
7008      *
7009      * @param action The action to perform.
7010      * @param arguments Optional action arguments.
7011      * @return Whether the action was performed.
7012      */
7013     public boolean performAccessibilityAction(int action, Bundle arguments) {
7014       if (mAccessibilityDelegate != null) {
7015           return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
7016       } else {
7017           return performAccessibilityActionInternal(action, arguments);
7018       }
7019     }
7020 
7021    /**
7022     * @see #performAccessibilityAction(int, Bundle)
7023     *
7024     * Note: Called from the default {@link AccessibilityDelegate}.
7025     */
7026     boolean performAccessibilityActionInternal(int action, Bundle arguments) {
7027         switch (action) {
7028             case AccessibilityNodeInfo.ACTION_CLICK: {
7029                 if (isClickable()) {
7030                     performClick();
7031                     return true;
7032                 }
7033             } break;
7034             case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
7035                 if (isLongClickable()) {
7036                     performLongClick();
7037                     return true;
7038                 }
7039             } break;
7040             case AccessibilityNodeInfo.ACTION_FOCUS: {
7041                 if (!hasFocus()) {
7042                     // Get out of touch mode since accessibility
7043                     // wants to move focus around.
7044                     getViewRootImpl().ensureTouchMode(false);
7045                     return requestFocus();
7046                 }
7047             } break;
7048             case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
7049                 if (hasFocus()) {
7050                     clearFocus();
7051                     return !isFocused();
7052                 }
7053             } break;
7054             case AccessibilityNodeInfo.ACTION_SELECT: {
7055                 if (!isSelected()) {
7056                     setSelected(true);
7057                     return isSelected();
7058                 }
7059             } break;
7060             case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
7061                 if (isSelected()) {
7062                     setSelected(false);
7063                     return !isSelected();
7064                 }
7065             } break;
7066             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
7067                 if (!isAccessibilityFocused()) {
7068                     return requestAccessibilityFocus();
7069                 }
7070             } break;
7071             case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
7072                 if (isAccessibilityFocused()) {
7073                     clearAccessibilityFocus();
7074                     return true;
7075                 }
7076             } break;
7077             case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
7078                 if (arguments != null) {
7079                     final int granularity = arguments.getInt(
7080                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
7081                     final boolean extendSelection = arguments.getBoolean(
7082                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
7083                     return traverseAtGranularity(granularity, true, extendSelection);
7084                 }
7085             } break;
7086             case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
7087                 if (arguments != null) {
7088                     final int granularity = arguments.getInt(
7089                             AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
7090                     final boolean extendSelection = arguments.getBoolean(
7091                             AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
7092                     return traverseAtGranularity(granularity, false, extendSelection);
7093                 }
7094             } break;
7095             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
7096                 CharSequence text = getIterableTextForAccessibility();
7097                 if (text == null) {
7098                     return false;
7099                 }
7100                 final int start = (arguments != null) ? arguments.getInt(
7101                         AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
7102                 final int end = (arguments != null) ? arguments.getInt(
7103                 AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
7104                 // Only cursor position can be specified (selection length == 0)
7105                 if ((getAccessibilitySelectionStart() != start
7106                         || getAccessibilitySelectionEnd() != end)
7107                         && (start == end)) {
7108                     setAccessibilitySelection(start, end);
7109                     notifyAccessibilityStateChanged();
7110                     return true;
7111                 }
7112             } break;
7113         }
7114         return false;
7115     }
7116 
7117     private boolean traverseAtGranularity(int granularity, boolean forward,
7118             boolean extendSelection) {
7119         CharSequence text = getIterableTextForAccessibility();
7120         if (text == null || text.length() == 0) {
7121             return false;
7122         }
7123         TextSegmentIterator iterator = getIteratorForGranularity(granularity);
7124         if (iterator == null) {
7125             return false;
7126         }
7127         int current = getAccessibilitySelectionEnd();
7128         if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
7129             current = forward ? 0 : text.length();
7130         }
7131         final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
7132         if (range == null) {
7133             return false;
7134         }
7135         final int segmentStart = range[0];
7136         final int segmentEnd = range[1];
7137         int selectionStart;
7138         int selectionEnd;
7139         if (extendSelection && isAccessibilitySelectionExtendable()) {
7140             selectionStart = getAccessibilitySelectionStart();
7141             if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
7142                 selectionStart = forward ? segmentStart : segmentEnd;
7143             }
7144             selectionEnd = forward ? segmentEnd : segmentStart;
7145         } else {
7146             selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
7147         }
7148         setAccessibilitySelection(selectionStart, selectionEnd);
7149         final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
7150                 : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
7151         sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
7152         return true;
7153     }
7154 
7155     /**
7156      * Gets the text reported for accessibility purposes.
7157      *
7158      * @return The accessibility text.
7159      *
7160      * @hide
7161      */
7162     public CharSequence getIterableTextForAccessibility() {
7163         return getContentDescription();
7164     }
7165 
7166     /**
7167      * Gets whether accessibility selection can be extended.
7168      *
7169      * @return If selection is extensible.
7170      *
7171      * @hide
7172      */
7173     public boolean isAccessibilitySelectionExtendable() {
7174         return false;
7175     }
7176 
7177     /**
7178      * @hide
7179      */
7180     public int getAccessibilitySelectionStart() {
7181         return mAccessibilityCursorPosition;
7182     }
7183 
7184     /**
7185      * @hide
7186      */
7187     public int getAccessibilitySelectionEnd() {
7188         return getAccessibilitySelectionStart();
7189     }
7190 
7191     /**
7192      * @hide
7193      */
7194     public void setAccessibilitySelection(int start, int end) {
7195         if (start ==  end && end == mAccessibilityCursorPosition) {
7196             return;
7197         }
7198         if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
7199             mAccessibilityCursorPosition = start;
7200         } else {
7201             mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
7202         }
7203         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
7204     }
7205 
7206     private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
7207             int fromIndex, int toIndex) {
7208         if (mParent == null) {
7209             return;
7210         }
7211         AccessibilityEvent event = AccessibilityEvent.obtain(
7212                 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
7213         onInitializeAccessibilityEvent(event);
7214         onPopulateAccessibilityEvent(event);
7215         event.setFromIndex(fromIndex);
7216         event.setToIndex(toIndex);
7217         event.setAction(action);
7218         event.setMovementGranularity(granularity);
7219         mParent.requestSendAccessibilityEvent(this, event);
7220     }
7221 
7222     /**
7223      * @hide
7224      */
7225     public TextSegmentIterator getIteratorForGranularity(int granularity) {
7226         switch (granularity) {
7227             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
7228                 CharSequence text = getIterableTextForAccessibility();
7229                 if (text != null && text.length() > 0) {
7230                     CharacterTextSegmentIterator iterator =
7231                         CharacterTextSegmentIterator.getInstance(
7232                                 mContext.getResources().getConfiguration().locale);
7233                     iterator.initialize(text.toString());
7234                     return iterator;
7235                 }
7236             } break;
7237             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
7238                 CharSequence text = getIterableTextForAccessibility();
7239                 if (text != null && text.length() > 0) {
7240                     WordTextSegmentIterator iterator =
7241                         WordTextSegmentIterator.getInstance(
7242                                 mContext.getResources().getConfiguration().locale);
7243                     iterator.initialize(text.toString());
7244                     return iterator;
7245                 }
7246             } break;
7247             case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
7248                 CharSequence text = getIterableTextForAccessibility();
7249                 if (text != null && text.length() > 0) {
7250                     ParagraphTextSegmentIterator iterator =
7251                         ParagraphTextSegmentIterator.getInstance();
7252                     iterator.initialize(text.toString());
7253                     return iterator;
7254                 }
7255             } break;
7256         }
7257         return null;
7258     }
7259 
7260     /**
7261      * @hide
7262      */
7263     public void dispatchStartTemporaryDetach() {
7264         clearAccessibilityFocus();
7265         clearDisplayList();
7266 
7267         onStartTemporaryDetach();
7268     }
7269 
7270     /**
7271      * This is called when a container is going to temporarily detach a child, with
7272      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
7273      * It will either be followed by {@link #onFinishTemporaryDetach()} or
7274      * {@link #onDetachedFromWindow()} when the container is done.
7275      */
7276     public void onStartTemporaryDetach() {
7277         removeUnsetPressCallback();
7278         mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
7279     }
7280 
7281     /**
7282      * @hide
7283      */
7284     public void dispatchFinishTemporaryDetach() {
7285         onFinishTemporaryDetach();
7286     }
7287 
7288     /**
7289      * Called after {@link #onStartTemporaryDetach} when the container is done
7290      * changing the view.
7291      */
7292     public void onFinishTemporaryDetach() {
7293     }
7294 
7295     /**
7296      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
7297      * for this view's window.  Returns null if the view is not currently attached
7298      * to the window.  Normally you will not need to use this directly, but
7299      * just use the standard high-level event callbacks like
7300      * {@link #onKeyDown(int, KeyEvent)}.
7301      */
7302     public KeyEvent.DispatcherState getKeyDispatcherState() {
7303         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
7304     }
7305 
7306     /**
7307      * Dispatch a key event before it is processed by any input method
7308      * associated with the view hierarchy.  This can be used to intercept
7309      * key events in special situations before the IME consumes them; a
7310      * typical example would be handling the BACK key to update the application's
7311      * UI instead of allowing the IME to see it and close itself.
7312      *
7313      * @param event The key event to be dispatched.
7314      * @return True if the event was handled, false otherwise.
7315      */
7316     public boolean dispatchKeyEventPreIme(KeyEvent event) {
7317         return onKeyPreIme(event.getKeyCode(), event);
7318     }
7319 
7320     /**
7321      * Dispatch a key event to the next view on the focus path. This path runs
7322      * from the top of the view tree down to the currently focused view. If this
7323      * view has focus, it will dispatch to itself. Otherwise it will dispatch
7324      * the next node down the focus path. This method also fires any key
7325      * listeners.
7326      *
7327      * @param event The key event to be dispatched.
7328      * @return True if the event was handled, false otherwise.
7329      */
7330     public boolean dispatchKeyEvent(KeyEvent event) {
7331         if (mInputEventConsistencyVerifier != null) {
7332             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
7333         }
7334 
7335         // Give any attached key listener a first crack at the event.
7336         //noinspection SimplifiableIfStatement
7337         ListenerInfo li = mListenerInfo;
7338         if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
7339                 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
7340             return true;
7341         }
7342 
7343         if (event.dispatch(this, mAttachInfo != null
7344                 ? mAttachInfo.mKeyDispatchState : null, this)) {
7345             return true;
7346         }
7347 
7348         if (mInputEventConsistencyVerifier != null) {
7349             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7350         }
7351         return false;
7352     }
7353 
7354     /**
7355      * Dispatches a key shortcut event.
7356      *
7357      * @param event The key event to be dispatched.
7358      * @return True if the event was handled by the view, false otherwise.
7359      */
7360     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7361         return onKeyShortcut(event.getKeyCode(), event);
7362     }
7363 
7364     /**
7365      * Pass the touch screen motion event down to the target view, or this
7366      * view if it is the target.
7367      *
7368      * @param event The motion event to be dispatched.
7369      * @return True if the event was handled by the view, false otherwise.
7370      */
7371     public boolean dispatchTouchEvent(MotionEvent event) {
7372         if (mInputEventConsistencyVerifier != null) {
7373             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
7374         }
7375 
7376         if (onFilterTouchEventForSecurity(event)) {
7377             //noinspection SimplifiableIfStatement
7378             ListenerInfo li = mListenerInfo;
7379             if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
7380                     && li.mOnTouchListener.onTouch(this, event)) {
7381                 return true;
7382             }
7383 
7384             if (onTouchEvent(event)) {
7385                 return true;
7386             }
7387         }
7388 
7389         if (mInputEventConsistencyVerifier != null) {
7390             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7391         }
7392         return false;
7393     }
7394 
7395     /**
7396      * Filter the touch event to apply security policies.
7397      *
7398      * @param event The motion event to be filtered.
7399      * @return True if the event should be dispatched, false if the event should be dropped.
7400      *
7401      * @see #getFilterTouchesWhenObscured
7402      */
7403     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
7404         //noinspection RedundantIfStatement
7405         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
7406                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
7407             // Window is obscured, drop this touch.
7408             return false;
7409         }
7410         return true;
7411     }
7412 
7413     /**
7414      * Pass a trackball motion event down to the focused view.
7415      *
7416      * @param event The motion event to be dispatched.
7417      * @return True if the event was handled by the view, false otherwise.
7418      */
7419     public boolean dispatchTrackballEvent(MotionEvent event) {
7420         if (mInputEventConsistencyVerifier != null) {
7421             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
7422         }
7423 
7424         return onTrackballEvent(event);
7425     }
7426 
7427     /**
7428      * Dispatch a generic motion event.
7429      * <p>
7430      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
7431      * are delivered to the view under the pointer.  All other generic motion events are
7432      * delivered to the focused view.  Hover events are handled specially and are delivered
7433      * to {@link #onHoverEvent(MotionEvent)}.
7434      * </p>
7435      *
7436      * @param event The motion event to be dispatched.
7437      * @return True if the event was handled by the view, false otherwise.
7438      */
7439     public boolean dispatchGenericMotionEvent(MotionEvent event) {
7440         if (mInputEventConsistencyVerifier != null) {
7441             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
7442         }
7443 
7444         final int source = event.getSource();
7445         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
7446             final int action = event.getAction();
7447             if (action == MotionEvent.ACTION_HOVER_ENTER
7448                     || action == MotionEvent.ACTION_HOVER_MOVE
7449                     || action == MotionEvent.ACTION_HOVER_EXIT) {
7450                 if (dispatchHoverEvent(event)) {
7451                     return true;
7452                 }
7453             } else if (dispatchGenericPointerEvent(event)) {
7454                 return true;
7455             }
7456         } else if (dispatchGenericFocusedEvent(event)) {
7457             return true;
7458         }
7459 
7460         if (dispatchGenericMotionEventInternal(event)) {
7461             return true;
7462         }
7463 
7464         if (mInputEventConsistencyVerifier != null) {
7465             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7466         }
7467         return false;
7468     }
7469 
7470     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
7471         //noinspection SimplifiableIfStatement
7472         ListenerInfo li = mListenerInfo;
7473         if (li != null && li.mOnGenericMotionListener != null
7474                 && (mViewFlags & ENABLED_MASK) == ENABLED
7475                 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
7476             return true;
7477         }
7478 
7479         if (onGenericMotionEvent(event)) {
7480             return true;
7481         }
7482 
7483         if (mInputEventConsistencyVerifier != null) {
7484             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7485         }
7486         return false;
7487     }
7488 
7489     /**
7490      * Dispatch a hover event.
7491      * <p>
7492      * Do not call this method directly.
7493      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
7494      * </p>
7495      *
7496      * @param event The motion event to be dispatched.
7497      * @return True if the event was handled by the view, false otherwise.
7498      */
7499     protected boolean dispatchHoverEvent(MotionEvent event) {
7500         //noinspection SimplifiableIfStatement
7501         ListenerInfo li = mListenerInfo;
7502         if (li != null && li.mOnHoverListener != null
7503                 && (mViewFlags & ENABLED_MASK) == ENABLED
7504                 && li.mOnHoverListener.onHover(this, event)) {
7505             return true;
7506         }
7507 
7508         return onHoverEvent(event);
7509     }
7510 
7511     /**
7512      * Returns true if the view has a child to which it has recently sent
7513      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
7514      * it does not have a hovered child, then it must be the innermost hovered view.
7515      * @hide
7516      */
7517     protected boolean hasHoveredChild() {
7518         return false;
7519     }
7520 
7521     /**
7522      * Dispatch a generic motion event to the view under the first pointer.
7523      * <p>
7524      * Do not call this method directly.
7525      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
7526      * </p>
7527      *
7528      * @param event The motion event to be dispatched.
7529      * @return True if the event was handled by the view, false otherwise.
7530      */
7531     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
7532         return false;
7533     }
7534 
7535     /**
7536      * Dispatch a generic motion event to the currently focused view.
7537      * <p>
7538      * Do not call this method directly.
7539      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
7540      * </p>
7541      *
7542      * @param event The motion event to be dispatched.
7543      * @return True if the event was handled by the view, false otherwise.
7544      */
7545     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
7546         return false;
7547     }
7548 
7549     /**
7550      * Dispatch a pointer event.
7551      * <p>
7552      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
7553      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
7554      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
7555      * and should not be expected to handle other pointing device features.
7556      * </p>
7557      *
7558      * @param event The motion event to be dispatched.
7559      * @return True if the event was handled by the view, false otherwise.
7560      * @hide
7561      */
7562     public final boolean dispatchPointerEvent(MotionEvent event) {
7563         if (event.isTouchEvent()) {
7564             return dispatchTouchEvent(event);
7565         } else {
7566             return dispatchGenericMotionEvent(event);
7567         }
7568     }
7569 
7570     /**
7571      * Called when the window containing this view gains or loses window focus.
7572      * ViewGroups should override to route to their children.
7573      *
7574      * @param hasFocus True if the window containing this view now has focus,
7575      *        false otherwise.
7576      */
7577     public void dispatchWindowFocusChanged(boolean hasFocus) {
7578         onWindowFocusChanged(hasFocus);
7579     }
7580 
7581     /**
7582      * Called when the window containing this view gains or loses focus.  Note
7583      * that this is separate from view focus: to receive key events, both
7584      * your view and its window must have focus.  If a window is displayed
7585      * on top of yours that takes input focus, then your own window will lose
7586      * focus but the view focus will remain unchanged.
7587      *
7588      * @param hasWindowFocus True if the window containing this view now has
7589      *        focus, false otherwise.
7590      */
7591     public void onWindowFocusChanged(boolean hasWindowFocus) {
7592         InputMethodManager imm = InputMethodManager.peekInstance();
7593         if (!hasWindowFocus) {
7594             if (isPressed()) {
7595                 setPressed(false);
7596             }
7597             if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
7598                 imm.focusOut(this);
7599             }
7600             removeLongPressCallback();
7601             removeTapCallback();
7602             onFocusLost();
7603         } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
7604             imm.focusIn(this);
7605         }
7606         refreshDrawableState();
7607     }
7608 
7609     /**
7610      * Returns true if this view is in a window that currently has window focus.
7611      * Note that this is not the same as the view itself having focus.
7612      *
7613      * @return True if this view is in a window that currently has window focus.
7614      */
7615     public boolean hasWindowFocus() {
7616         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
7617     }
7618 
7619     /**
7620      * Dispatch a view visibility change down the view hierarchy.
7621      * ViewGroups should override to route to their children.
7622      * @param changedView The view whose visibility changed. Could be 'this' or
7623      * an ancestor view.
7624      * @param visibility The new visibility of changedView: {@link #VISIBLE},
7625      * {@link #INVISIBLE} or {@link #GONE}.
7626      */
7627     protected void dispatchVisibilityChanged(View changedView, int visibility) {
7628         onVisibilityChanged(changedView, visibility);
7629     }
7630 
7631     /**
7632      * Called when the visibility of the view or an ancestor of the view is changed.
7633      * @param changedView The view whose visibility changed. Could be 'this' or
7634      * an ancestor view.
7635      * @param visibility The new visibility of changedView: {@link #VISIBLE},
7636      * {@link #INVISIBLE} or {@link #GONE}.
7637      */
7638     protected void onVisibilityChanged(View changedView, int visibility) {
7639         if (visibility == VISIBLE) {
7640             if (mAttachInfo != null) {
7641                 initialAwakenScrollBars();
7642             } else {
7643                 mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
7644             }
7645         }
7646     }
7647 
7648     /**
7649      * Dispatch a hint about whether this view is displayed. For instance, when
7650      * a View moves out of the screen, it might receives a display hint indicating
7651      * the view is not displayed. Applications should not <em>rely</em> on this hint
7652      * as there is no guarantee that they will receive one.
7653      *
7654      * @param hint A hint about whether or not this view is displayed:
7655      * {@link #VISIBLE} or {@link #INVISIBLE}.
7656      */
7657     public void dispatchDisplayHint(int hint) {
7658         onDisplayHint(hint);
7659     }
7660 
7661     /**
7662      * Gives this view a hint about whether is displayed or not. For instance, when
7663      * a View moves out of the screen, it might receives a display hint indicating
7664      * the view is not displayed. Applications should not <em>rely</em> on this hint
7665      * as there is no guarantee that they will receive one.
7666      *
7667      * @param hint A hint about whether or not this view is displayed:
7668      * {@link #VISIBLE} or {@link #INVISIBLE}.
7669      */
7670     protected void onDisplayHint(int hint) {
7671     }
7672 
7673     /**
7674      * Dispatch a window visibility change down the view hierarchy.
7675      * ViewGroups should override to route to their children.
7676      *
7677      * @param visibility The new visibility of the window.
7678      *
7679      * @see #onWindowVisibilityChanged(int)
7680      */
7681     public void dispatchWindowVisibilityChanged(int visibility) {
7682         onWindowVisibilityChanged(visibility);
7683     }
7684 
7685     /**
7686      * Called when the window containing has change its visibility
7687      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
7688      * that this tells you whether or not your window is being made visible
7689      * to the window manager; this does <em>not</em> tell you whether or not
7690      * your window is obscured by other windows on the screen, even if it
7691      * is itself visible.
7692      *
7693      * @param visibility The new visibility of the window.
7694      */
7695     protected void onWindowVisibilityChanged(int visibility) {
7696         if (visibility == VISIBLE) {
7697             initialAwakenScrollBars();
7698         }
7699     }
7700 
7701     /**
7702      * Returns the current visibility of the window this view is attached to
7703      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
7704      *
7705      * @return Returns the current visibility of the view's window.
7706      */
7707     public int getWindowVisibility() {
7708         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
7709     }
7710 
7711     /**
7712      * Retrieve the overall visible display size in which the window this view is
7713      * attached to has been positioned in.  This takes into account screen
7714      * decorations above the window, for both cases where the window itself
7715      * is being position inside of them or the window is being placed under
7716      * then and covered insets are used for the window to position its content
7717      * inside.  In effect, this tells you the available area where content can
7718      * be placed and remain visible to users.
7719      *
7720      * <p>This function requires an IPC back to the window manager to retrieve
7721      * the requested information, so should not be used in performance critical
7722      * code like drawing.
7723      *
7724      * @param outRect Filled in with the visible display frame.  If the view
7725      * is not attached to a window, this is simply the raw display size.
7726      */
7727     public void getWindowVisibleDisplayFrame(Rect outRect) {
7728         if (mAttachInfo != null) {
7729             try {
7730                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
7731             } catch (RemoteException e) {
7732                 return;
7733             }
7734             // XXX This is really broken, and probably all needs to be done
7735             // in the window manager, and we need to know more about whether
7736             // we want the area behind or in front of the IME.
7737             final Rect insets = mAttachInfo.mVisibleInsets;
7738             outRect.left += insets.left;
7739             outRect.top += insets.top;
7740             outRect.right -= insets.right;
7741             outRect.bottom -= insets.bottom;
7742             return;
7743         }
7744         // The view is not attached to a display so we don't have a context.
7745         // Make a best guess about the display size.
7746         Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
7747         d.getRectSize(outRect);
7748     }
7749 
7750     /**
7751      * Dispatch a notification about a resource configuration change down
7752      * the view hierarchy.
7753      * ViewGroups should override to route to their children.
7754      *
7755      * @param newConfig The new resource configuration.
7756      *
7757      * @see #onConfigurationChanged(android.content.res.Configuration)
7758      */
7759     public void dispatchConfigurationChanged(Configuration newConfig) {
7760         onConfigurationChanged(newConfig);
7761     }
7762 
7763     /**
7764      * Called when the current configuration of the resources being used
7765      * by the application have changed.  You can use this to decide when
7766      * to reload resources that can changed based on orientation and other
7767      * configuration characterstics.  You only need to use this if you are
7768      * not relying on the normal {@link android.app.Activity} mechanism of
7769      * recreating the activity instance upon a configuration change.
7770      *
7771      * @param newConfig The new resource configuration.
7772      */
7773     protected void onConfigurationChanged(Configuration newConfig) {
7774     }
7775 
7776     /**
7777      * Private function to aggregate all per-view attributes in to the view
7778      * root.
7779      */
7780     void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7781         performCollectViewAttributes(attachInfo, visibility);
7782     }
7783 
7784     void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7785         if ((visibility & VISIBILITY_MASK) == VISIBLE) {
7786             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
7787                 attachInfo.mKeepScreenOn = true;
7788             }
7789             attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
7790             ListenerInfo li = mListenerInfo;
7791             if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
7792                 attachInfo.mHasSystemUiListeners = true;
7793             }
7794         }
7795     }
7796 
7797     void needGlobalAttributesUpdate(boolean force) {
7798         final AttachInfo ai = mAttachInfo;
7799         if (ai != null && !ai.mRecomputeGlobalAttributes) {
7800             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
7801                     || ai.mHasSystemUiListeners) {
7802                 ai.mRecomputeGlobalAttributes = true;
7803             }
7804         }
7805     }
7806 
7807     /**
7808      * Returns whether the device is currently in touch mode.  Touch mode is entered
7809      * once the user begins interacting with the device by touch, and affects various
7810      * things like whether focus is always visible to the user.
7811      *
7812      * @return Whether the device is in touch mode.
7813      */
7814     @ViewDebug.ExportedProperty
7815     public boolean isInTouchMode() {
7816         if (mAttachInfo != null) {
7817             return mAttachInfo.mInTouchMode;
7818         } else {
7819             return ViewRootImpl.isInTouchMode();
7820         }
7821     }
7822 
7823     /**
7824      * Returns the context the view is running in, through which it can
7825      * access the current theme, resources, etc.
7826      *
7827      * @return The view's Context.
7828      */
7829     @ViewDebug.CapturedViewProperty
7830     public final Context getContext() {
7831         return mContext;
7832     }
7833 
7834     /**
7835      * Handle a key event before it is processed by any input method
7836      * associated with the view hierarchy.  This can be used to intercept
7837      * key events in special situations before the IME consumes them; a
7838      * typical example would be handling the BACK key to update the application's
7839      * UI instead of allowing the IME to see it and close itself.
7840      *
7841      * @param keyCode The value in event.getKeyCode().
7842      * @param event Description of the key event.
7843      * @return If you handled the event, return true. If you want to allow the
7844      *         event to be handled by the next receiver, return false.
7845      */
7846     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
7847         return false;
7848     }
7849 
7850     /**
7851      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
7852      * KeyEvent.Callback.onKeyDown()}: perform press of the view
7853      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
7854      * is released, if the view is enabled and clickable.
7855      *
7856      * <p>Key presses in software keyboards will generally NOT trigger this listener,
7857      * although some may elect to do so in some situations. Do not rely on this to
7858      * catch software key presses.
7859      *
7860      * @param keyCode A key code that represents the button pressed, from
7861      *                {@link android.view.KeyEvent}.
7862      * @param event   The KeyEvent object that defines the button action.
7863      */
7864     public boolean onKeyDown(int keyCode, KeyEvent event) {
7865         boolean result = false;
7866 
7867         switch (keyCode) {
7868             case KeyEvent.KEYCODE_DPAD_CENTER:
7869             case KeyEvent.KEYCODE_ENTER: {
7870                 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7871                     return true;
7872                 }
7873                 // Long clickable items don't necessarily have to be clickable
7874                 if (((mViewFlags & CLICKABLE) == CLICKABLE ||
7875                         (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
7876                         (event.getRepeatCount() == 0)) {
7877                     setPressed(true);
7878                     checkForLongClick(0);
7879                     return true;
7880                 }
7881                 break;
7882             }
7883         }
7884         return result;
7885     }
7886 
7887     /**
7888      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
7889      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
7890      * the event).
7891      * <p>Key presses in software keyboards will generally NOT trigger this listener,
7892      * although some may elect to do so in some situations. Do not rely on this to
7893      * catch software key presses.
7894      */
7895     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
7896         return false;
7897     }
7898 
7899     /**
7900      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
7901      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
7902      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
7903      * {@link KeyEvent#KEYCODE_ENTER} is released.
7904      * <p>Key presses in software keyboards will generally NOT trigger this listener,
7905      * although some may elect to do so in some situations. Do not rely on this to
7906      * catch software key presses.
7907      *
7908      * @param keyCode A key code that represents the button pressed, from
7909      *                {@link android.view.KeyEvent}.
7910      * @param event   The KeyEvent object that defines the button action.
7911      */
7912     public boolean onKeyUp(int keyCode, KeyEvent event) {
7913         boolean result = false;
7914 
7915         switch (keyCode) {
7916             case KeyEvent.KEYCODE_DPAD_CENTER:
7917             case KeyEvent.KEYCODE_ENTER: {
7918                 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7919                     return true;
7920                 }
7921                 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
7922                     setPressed(false);
7923 
7924                     if (!mHasPerformedLongPress) {
7925                         // This is a tap, so remove the longpress check
7926                         removeLongPressCallback();
7927 
7928                         result = performClick();
7929                     }
7930                 }
7931                 break;
7932             }
7933         }
7934         return result;
7935     }
7936 
7937     /**
7938      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
7939      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
7940      * the event).
7941      * <p>Key presses in software keyboards will generally NOT trigger this listener,
7942      * although some may elect to do so in some situations. Do not rely on this to
7943      * catch software key presses.
7944      *
7945      * @param keyCode     A key code that represents the button pressed, from
7946      *                    {@link android.view.KeyEvent}.
7947      * @param repeatCount The number of times the action was made.
7948      * @param event       The KeyEvent object that defines the button action.
7949      */
7950     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
7951         return false;
7952     }
7953 
7954     /**
7955      * Called on the focused view when a key shortcut event is not handled.
7956      * Override this method to implement local key shortcuts for the View.
7957      * Key shortcuts can also be implemented by setting the
7958      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
7959      *
7960      * @param keyCode The value in event.getKeyCode().
7961      * @param event Description of the key event.
7962      * @return If you handled the event, return true. If you want to allow the
7963      *         event to be handled by the next receiver, return false.
7964      */
7965     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
7966         return false;
7967     }
7968 
7969     /**
7970      * Check whether the called view is a text editor, in which case it
7971      * would make sense to automatically display a soft input window for
7972      * it.  Subclasses should override this if they implement
7973      * {@link #onCreateInputConnection(EditorInfo)} to return true if
7974      * a call on that method would return a non-null InputConnection, and
7975      * they are really a first-class editor that the user would normally
7976      * start typing on when the go into a window containing your view.
7977      *
7978      * <p>The default implementation always returns false.  This does
7979      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
7980      * will not be called or the user can not otherwise perform edits on your
7981      * view; it is just a hint to the system that this is not the primary
7982      * purpose of this view.
7983      *
7984      * @return Returns true if this view is a text editor, else false.
7985      */
7986     public boolean onCheckIsTextEditor() {
7987         return false;
7988     }
7989 
7990     /**
7991      * Create a new InputConnection for an InputMethod to interact
7992      * with the view.  The default implementation returns null, since it doesn't
7993      * support input methods.  You can override this to implement such support.
7994      * This is only needed for views that take focus and text input.
7995      *
7996      * <p>When implementing this, you probably also want to implement
7997      * {@link #onCheckIsTextEditor()} to indicate you will return a
7998      * non-null InputConnection.
7999      *
8000      * @param outAttrs Fill in with attribute information about the connection.
8001      */
8002     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
8003         return null;
8004     }
8005 
8006     /**
8007      * Called by the {@link android.view.inputmethod.InputMethodManager}
8008      * when a view who is not the current
8009      * input connection target is trying to make a call on the manager.  The
8010      * default implementation returns false; you can override this to return
8011      * true for certain views if you are performing InputConnection proxying
8012      * to them.
8013      * @param view The View that is making the InputMethodManager call.
8014      * @return Return true to allow the call, false to reject.
8015      */
8016     public boolean checkInputConnectionProxy(View view) {
8017         return false;
8018     }
8019 
8020     /**
8021      * Show the context menu for this view. It is not safe to hold on to the
8022      * menu after returning from this method.
8023      *
8024      * You should normally not overload this method. Overload
8025      * {@link #onCreateContextMenu(ContextMenu)} or define an
8026      * {@link OnCreateContextMenuListener} to add items to the context menu.
8027      *
8028      * @param menu The context menu to populate
8029      */
8030     public void createContextMenu(ContextMenu menu) {
8031         ContextMenuInfo menuInfo = getContextMenuInfo();
8032 
8033         // Sets the current menu info so all items added to menu will have
8034         // my extra info set.
8035         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
8036 
8037         onCreateContextMenu(menu);
8038         ListenerInfo li = mListenerInfo;
8039         if (li != null && li.mOnCreateContextMenuListener != null) {
8040             li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
8041         }
8042 
8043         // Clear the extra information so subsequent items that aren't mine don't
8044         // have my extra info.
8045         ((MenuBuilder)menu).setCurrentMenuInfo(null);
8046 
8047         if (mParent != null) {
8048             mParent.createContextMenu(menu);
8049         }
8050     }
8051 
8052     /**
8053      * Views should implement this if they have extra information to associate
8054      * with the context menu. The return result is supplied as a parameter to
8055      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
8056      * callback.
8057      *
8058      * @return Extra information about the item for which the context menu
8059      *         should be shown. This information will vary across different
8060      *         subclasses of View.
8061      */
8062     protected ContextMenuInfo getContextMenuInfo() {
8063         return null;
8064     }
8065 
8066     /**
8067      * Views should implement this if the view itself is going to add items to
8068      * the context menu.
8069      *
8070      * @param menu the context menu to populate
8071      */
8072     protected void onCreateContextMenu(ContextMenu menu) {
8073     }
8074 
8075     /**
8076      * Implement this method to handle trackball motion events.  The
8077      * <em>relative</em> movement of the trackball since the last event
8078      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
8079      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
8080      * that a movement of 1 corresponds to the user pressing one DPAD key (so
8081      * they will often be fractional values, representing the more fine-grained
8082      * movement information available from a trackball).
8083      *
8084      * @param event The motion event.
8085      * @return True if the event was handled, false otherwise.
8086      */
8087     public boolean onTrackballEvent(MotionEvent event) {
8088         return false;
8089     }
8090 
8091     /**
8092      * Implement this method to handle generic motion events.
8093      * <p>
8094      * Generic motion events describe joystick movements, mouse hovers, track pad
8095      * touches, scroll wheel movements and other input events.  The
8096      * {@link MotionEvent#getSource() source} of the motion event specifies
8097      * the class of input that was received.  Implementations of this method
8098      * must examine the bits in the source before processing the event.
8099      * The following code example shows how this is done.
8100      * </p><p>
8101      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8102      * are delivered to the view under the pointer.  All other generic motion events are
8103      * delivered to the focused view.
8104      * </p>
8105      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
8106      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
8107      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
8108      *             // process the joystick movement...
8109      *             return true;
8110      *         }
8111      *     }
8112      *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
8113      *         switch (event.getAction()) {
8114      *             case MotionEvent.ACTION_HOVER_MOVE:
8115      *                 // process the mouse hover movement...
8116      *                 return true;
8117      *             case MotionEvent.ACTION_SCROLL:
8118      *                 // process the scroll wheel movement...
8119      *                 return true;
8120      *         }
8121      *     }
8122      *     return super.onGenericMotionEvent(event);
8123      * }</pre>
8124      *
8125      * @param event The generic motion event being processed.
8126      * @return True if the event was handled, false otherwise.
8127      */
8128     public boolean onGenericMotionEvent(MotionEvent event) {
8129         return false;
8130     }
8131 
8132     /**
8133      * Implement this method to handle hover events.
8134      * <p>
8135      * This method is called whenever a pointer is hovering into, over, or out of the
8136      * bounds of a view and the view is not currently being touched.
8137      * Hover events are represented as pointer events with action
8138      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
8139      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
8140      * </p>
8141      * <ul>
8142      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
8143      * when the pointer enters the bounds of the view.</li>
8144      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
8145      * when the pointer has already entered the bounds of the view and has moved.</li>
8146      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
8147      * when the pointer has exited the bounds of the view or when the pointer is
8148      * about to go down due to a button click, tap, or similar user action that
8149      * causes the view to be touched.</li>
8150      * </ul>
8151      * <p>
8152      * The view should implement this method to return true to indicate that it is
8153      * handling the hover event, such as by changing its drawable state.
8154      * </p><p>
8155      * The default implementation calls {@link #setHovered} to update the hovered state
8156      * of the view when a hover enter or hover exit event is received, if the view
8157      * is enabled and is clickable.  The default implementation also sends hover
8158      * accessibility events.
8159      * </p>
8160      *
8161      * @param event The motion event that describes the hover.
8162      * @return True if the view handled the hover event.
8163      *
8164      * @see #isHovered
8165      * @see #setHovered
8166      * @see #onHoverChanged
8167      */
8168     public boolean onHoverEvent(MotionEvent event) {
8169         // The root view may receive hover (or touch) events that are outside the bounds of
8170         // the window.  This code ensures that we only send accessibility events for
8171         // hovers that are actually within the bounds of the root view.
8172         final int action = event.getActionMasked();
8173         if (!mSendingHoverAccessibilityEvents) {
8174             if ((action == MotionEvent.ACTION_HOVER_ENTER
8175                     || action == MotionEvent.ACTION_HOVER_MOVE)
8176                     && !hasHoveredChild()
8177                     && pointInView(event.getX(), event.getY())) {
8178                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
8179                 mSendingHoverAccessibilityEvents = true;
8180             }
8181         } else {
8182             if (action == MotionEvent.ACTION_HOVER_EXIT
8183                     || (action == MotionEvent.ACTION_MOVE
8184                             && !pointInView(event.getX(), event.getY()))) {
8185                 mSendingHoverAccessibilityEvents = false;
8186                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
8187                 // If the window does not have input focus we take away accessibility
8188                 // focus as soon as the user stop hovering over the view.
8189                 if (mAttachInfo != null && !mAttachInfo.mHasWindowFocus) {
8190                     getViewRootImpl().setAccessibilityFocus(null, null);
8191                 }
8192             }
8193         }
8194 
8195         if (isHoverable()) {
8196             switch (action) {
8197                 case MotionEvent.ACTION_HOVER_ENTER:
8198                     setHovered(true);
8199                     break;
8200                 case MotionEvent.ACTION_HOVER_EXIT:
8201                     setHovered(false);
8202                     break;
8203             }
8204 
8205             // Dispatch the event to onGenericMotionEvent before returning true.
8206             // This is to provide compatibility with existing applications that
8207             // handled HOVER_MOVE events in onGenericMotionEvent and that would
8208             // break because of the new default handling for hoverable views
8209             // in onHoverEvent.
8210             // Note that onGenericMotionEvent will be called by default when
8211             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
8212             dispatchGenericMotionEventInternal(event);
8213             // The event was already handled by calling setHovered(), so always
8214             // return true.
8215             return true;
8216         }
8217 
8218         return false;
8219     }
8220 
8221     /**
8222      * Returns true if the view should handle {@link #onHoverEvent}
8223      * by calling {@link #setHovered} to change its hovered state.
8224      *
8225      * @return True if the view is hoverable.
8226      */
8227     private boolean isHoverable() {
8228         final int viewFlags = mViewFlags;
8229         if ((viewFlags & ENABLED_MASK) == DISABLED) {
8230             return false;
8231         }
8232 
8233         return (viewFlags & CLICKABLE) == CLICKABLE
8234                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8235     }
8236 
8237     /**
8238      * Returns true if the view is currently hovered.
8239      *
8240      * @return True if the view is currently hovered.
8241      *
8242      * @see #setHovered
8243      * @see #onHoverChanged
8244      */
8245     @ViewDebug.ExportedProperty
8246     public boolean isHovered() {
8247         return (mPrivateFlags & PFLAG_HOVERED) != 0;
8248     }
8249 
8250     /**
8251      * Sets whether the view is currently hovered.
8252      * <p>
8253      * Calling this method also changes the drawable state of the view.  This
8254      * enables the view to react to hover by using different drawable resources
8255      * to change its appearance.
8256      * </p><p>
8257      * The {@link #onHoverChanged} method is called when the hovered state changes.
8258      * </p>
8259      *
8260      * @param hovered True if the view is hovered.
8261      *
8262      * @see #isHovered
8263      * @see #onHoverChanged
8264      */
8265     public void setHovered(boolean hovered) {
8266         if (hovered) {
8267             if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
8268                 mPrivateFlags |= PFLAG_HOVERED;
8269                 refreshDrawableState();
8270                 onHoverChanged(true);
8271             }
8272         } else {
8273             if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
8274                 mPrivateFlags &= ~PFLAG_HOVERED;
8275                 refreshDrawableState();
8276                 onHoverChanged(false);
8277             }
8278         }
8279     }
8280 
8281     /**
8282      * Implement this method to handle hover state changes.
8283      * <p>
8284      * This method is called whenever the hover state changes as a result of a
8285      * call to {@link #setHovered}.
8286      * </p>
8287      *
8288      * @param hovered The current hover state, as returned by {@link #isHovered}.
8289      *
8290      * @see #isHovered
8291      * @see #setHovered
8292      */
8293     public void onHoverChanged(boolean hovered) {
8294     }
8295 
8296     /**
8297      * Implement this method to handle touch screen motion events.
8298      *
8299      * @param event The motion event.
8300      * @return True if the event was handled, false otherwise.
8301      */
8302     public boolean onTouchEvent(MotionEvent event) {
8303         final int viewFlags = mViewFlags;
8304 
8305         if ((viewFlags & ENABLED_MASK) == DISABLED) {
8306             if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
8307                 setPressed(false);
8308             }
8309             // A disabled view that is clickable still consumes the touch
8310             // events, it just doesn't respond to them.
8311             return (((viewFlags & CLICKABLE) == CLICKABLE ||
8312                     (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
8313         }
8314 
8315         if (mTouchDelegate != null) {
8316             if (mTouchDelegate.onTouchEvent(event)) {
8317                 return true;
8318             }
8319         }
8320 
8321         if (((viewFlags & CLICKABLE) == CLICKABLE ||
8322                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
8323             switch (event.getAction()) {
8324                 case MotionEvent.ACTION_UP:
8325                     boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
8326                     if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
8327                         // take focus if we don't have it already and we should in
8328                         // touch mode.
8329                         boolean focusTaken = false;
8330                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
8331                             focusTaken = requestFocus();
8332                         }
8333 
8334                         if (prepressed) {
8335                             // The button is being released before we actually
8336                             // showed it as pressed.  Make it show the pressed
8337                             // state now (before scheduling the click) to ensure
8338                             // the user sees it.
8339                             setPressed(true);
8340                        }
8341 
8342                         if (!mHasPerformedLongPress) {
8343                             // This is a tap, so remove the longpress check
8344                             removeLongPressCallback();
8345 
8346                             // Only perform take click actions if we were in the pressed state
8347                             if (!focusTaken) {
8348                                 // Use a Runnable and post this rather than calling
8349                                 // performClick directly. This lets other visual state
8350                                 // of the view update before click actions start.
8351                                 if (mPerformClick == null) {
8352                                     mPerformClick = new PerformClick();
8353                                 }
8354                                 if (!post(mPerformClick)) {
8355                                     performClick();
8356                                 }
8357                             }
8358                         }
8359 
8360                         if (mUnsetPressedState == null) {
8361                             mUnsetPressedState = new UnsetPressedState();
8362                         }
8363 
8364                         if (prepressed) {
8365                             postDelayed(mUnsetPressedState,
8366                                     ViewConfiguration.getPressedStateDuration());
8367                         } else if (!post(mUnsetPressedState)) {
8368                             // If the post failed, unpress right now
8369                             mUnsetPressedState.run();
8370                         }
8371                         removeTapCallback();
8372                     }
8373                     break;
8374 
8375                 case MotionEvent.ACTION_DOWN:
8376                     mHasPerformedLongPress = false;
8377 
8378                     if (performButtonActionOnTouchDown(event)) {
8379                         break;
8380                     }
8381 
8382                     // Walk up the hierarchy to determine if we're inside a scrolling container.
8383                     boolean isInScrollingContainer = isInScrollingContainer();
8384 
8385                     // For views inside a scrolling container, delay the pressed feedback for
8386                     // a short period in case this is a scroll.
8387                     if (isInScrollingContainer) {
8388                         mPrivateFlags |= PFLAG_PREPRESSED;
8389                         if (mPendingCheckForTap == null) {
8390                             mPendingCheckForTap = new CheckForTap();
8391                         }
8392                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
8393                     } else {
8394                         // Not inside a scrolling container, so show the feedback right away
8395                         setPressed(true);
8396                         checkForLongClick(0);
8397                     }
8398                     break;
8399 
8400                 case MotionEvent.ACTION_CANCEL:
8401                     setPressed(false);
8402                     removeTapCallback();
8403                     removeLongPressCallback();
8404                     break;
8405 
8406                 case MotionEvent.ACTION_MOVE:
8407                     final int x = (int) event.getX();
8408                     final int y = (int) event.getY();
8409 
8410                     // Be lenient about moving outside of buttons
8411                     if (!pointInView(x, y, mTouchSlop)) {
8412                         // Outside button
8413                         removeTapCallback();
8414                         if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
8415                             // Remove any future long press/tap checks
8416                             removeLongPressCallback();
8417 
8418                             setPressed(false);
8419                         }
8420                     }
8421                     break;
8422             }
8423             return true;
8424         }
8425 
8426         return false;
8427     }
8428 
8429     /**
8430      * @hide
8431      */
8432     public boolean isInScrollingContainer() {
8433         ViewParent p = getParent();
8434         while (p != null && p instanceof ViewGroup) {
8435             if (((ViewGroup) p).shouldDelayChildPressedState()) {
8436                 return true;
8437             }
8438             p = p.getParent();
8439         }
8440         return false;
8441     }
8442 
8443     /**
8444      * Remove the longpress detection timer.
8445      */
8446     private void removeLongPressCallback() {
8447         if (mPendingCheckForLongPress != null) {
8448           removeCallbacks(mPendingCheckForLongPress);
8449         }
8450     }
8451 
8452     /**
8453      * Remove the pending click action
8454      */
8455     private void removePerformClickCallback() {
8456         if (mPerformClick != null) {
8457             removeCallbacks(mPerformClick);
8458         }
8459     }
8460 
8461     /**
8462      * Remove the prepress detection timer.
8463      */
8464     private void removeUnsetPressCallback() {
8465         if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
8466             setPressed(false);
8467             removeCallbacks(mUnsetPressedState);
8468         }
8469     }
8470 
8471     /**
8472      * Remove the tap detection timer.
8473      */
8474     private void removeTapCallback() {
8475         if (mPendingCheckForTap != null) {
8476             mPrivateFlags &= ~PFLAG_PREPRESSED;
8477             removeCallbacks(mPendingCheckForTap);
8478         }
8479     }
8480 
8481     /**
8482      * Cancels a pending long press.  Your subclass can use this if you
8483      * want the context menu to come up if the user presses and holds
8484      * at the same place, but you don't want it to come up if they press
8485      * and then move around enough to cause scrolling.
8486      */
8487     public void cancelLongPress() {
8488         removeLongPressCallback();
8489 
8490         /*
8491          * The prepressed state handled by the tap callback is a display
8492          * construct, but the tap callback will post a long press callback
8493          * less its own timeout. Remove it here.
8494          */
8495         removeTapCallback();
8496     }
8497 
8498     /**
8499      * Remove the pending callback for sending a
8500      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
8501      */
8502     private void removeSendViewScrolledAccessibilityEventCallback() {
8503         if (mSendViewScrolledAccessibilityEvent != null) {
8504             removeCallbacks(mSendViewScrolledAccessibilityEvent);
8505             mSendViewScrolledAccessibilityEvent.mIsPending = false;
8506         }
8507     }
8508 
8509     /**
8510      * Sets the TouchDelegate for this View.
8511      */
8512     public void setTouchDelegate(TouchDelegate delegate) {
8513         mTouchDelegate = delegate;
8514     }
8515 
8516     /**
8517      * Gets the TouchDelegate for this View.
8518      */
8519     public TouchDelegate getTouchDelegate() {
8520         return mTouchDelegate;
8521     }
8522 
8523     /**
8524      * Set flags controlling behavior of this view.
8525      *
8526      * @param flags Constant indicating the value which should be set
8527      * @param mask Constant indicating the bit range that should be changed
8528      */
8529     void setFlags(int flags, int mask) {
8530         int old = mViewFlags;
8531         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
8532 
8533         int changed = mViewFlags ^ old;
8534         if (changed == 0) {
8535             return;
8536         }
8537         int privateFlags = mPrivateFlags;
8538 
8539         /* Check if the FOCUSABLE bit has changed */
8540         if (((changed & FOCUSABLE_MASK) != 0) &&
8541                 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
8542             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
8543                     && ((privateFlags & PFLAG_FOCUSED) != 0)) {
8544                 /* Give up focus if we are no longer focusable */
8545                 clearFocus();
8546             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
8547                     && ((privateFlags & PFLAG_FOCUSED) == 0)) {
8548                 /*
8549                  * Tell the view system that we are now available to take focus
8550                  * if no one else already has it.
8551                  */
8552                 if (mParent != null) mParent.focusableViewAvailable(this);
8553             }
8554             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8555                 notifyAccessibilityStateChanged();
8556             }
8557         }
8558 
8559         if ((flags & VISIBILITY_MASK) == VISIBLE) {
8560             if ((changed & VISIBILITY_MASK) != 0) {
8561                 /*
8562                  * If this view is becoming visible, invalidate it in case it changed while
8563                  * it was not visible. Marking it drawn ensures that the invalidation will
8564                  * go through.
8565                  */
8566                 mPrivateFlags |= PFLAG_DRAWN;
8567                 invalidate(true);
8568 
8569                 needGlobalAttributesUpdate(true);
8570 
8571                 // a view becoming visible is worth notifying the parent
8572                 // about in case nothing has focus.  even if this specific view
8573                 // isn't focusable, it may contain something that is, so let
8574                 // the root view try to give this focus if nothing else does.
8575                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
8576                     mParent.focusableViewAvailable(this);
8577                 }
8578             }
8579         }
8580 
8581         /* Check if the GONE bit has changed */
8582         if ((changed & GONE) != 0) {
8583             needGlobalAttributesUpdate(false);
8584             requestLayout();
8585 
8586             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
8587                 if (hasFocus()) clearFocus();
8588                 clearAccessibilityFocus();
8589                 destroyDrawingCache();
8590                 if (mParent instanceof View) {
8591                     // GONE views noop invalidation, so invalidate the parent
8592                     ((View) mParent).invalidate(true);
8593                 }
8594                 // Mark the view drawn to ensure that it gets invalidated properly the next
8595                 // time it is visible and gets invalidated
8596                 mPrivateFlags |= PFLAG_DRAWN;
8597             }
8598             if (mAttachInfo != null) {
8599                 mAttachInfo.mViewVisibilityChanged = true;
8600             }
8601         }
8602 
8603         /* Check if the VISIBLE bit has changed */
8604         if ((changed & INVISIBLE) != 0) {
8605             needGlobalAttributesUpdate(false);
8606             /*
8607              * If this view is becoming invisible, set the DRAWN flag so that
8608              * the next invalidate() will not be skipped.
8609              */
8610             mPrivateFlags |= PFLAG_DRAWN;
8611 
8612             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
8613                 // root view becoming invisible shouldn't clear focus and accessibility focus
8614                 if (getRootView() != this) {
8615                     clearFocus();
8616                     clearAccessibilityFocus();
8617                 }
8618             }
8619             if (mAttachInfo != null) {
8620                 mAttachInfo.mViewVisibilityChanged = true;
8621             }
8622         }
8623 
8624         if ((changed & VISIBILITY_MASK) != 0) {
8625             if (mParent instanceof ViewGroup) {
8626                 ((ViewGroup) mParent).onChildVisibilityChanged(this,
8627                         (changed & VISIBILITY_MASK), (flags & VISIBILITY_MASK));
8628                 ((View) mParent).invalidate(true);
8629             } else if (mParent != null) {
8630                 mParent.invalidateChild(this, null);
8631             }
8632             dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
8633         }
8634 
8635         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
8636             destroyDrawingCache();
8637         }
8638 
8639         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
8640             destroyDrawingCache();
8641             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
8642             invalidateParentCaches();
8643         }
8644 
8645         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
8646             destroyDrawingCache();
8647             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
8648         }
8649 
8650         if ((changed & DRAW_MASK) != 0) {
8651             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
8652                 if (mBackground != null) {
8653                     mPrivateFlags &= ~PFLAG_SKIP_DRAW;
8654                     mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
8655                 } else {
8656                     mPrivateFlags |= PFLAG_SKIP_DRAW;
8657                 }
8658             } else {
8659                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
8660             }
8661             requestLayout();
8662             invalidate(true);
8663         }
8664 
8665         if ((changed & KEEP_SCREEN_ON) != 0) {
8666             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
8667                 mParent.recomputeViewAttributes(this);
8668             }
8669         }
8670 
8671         if (AccessibilityManager.getInstance(mContext).isEnabled()
8672                 && ((changed & FOCUSABLE) != 0 || (changed & CLICKABLE) != 0
8673                         || (changed & LONG_CLICKABLE) != 0 || (changed & ENABLED) != 0)) {
8674             notifyAccessibilityStateChanged();
8675         }
8676     }
8677 
8678     /**
8679      * Change the view's z order in the tree, so it's on top of other sibling
8680      * views. This ordering change may affect layout, if the parent container
8681      * uses an order-dependent layout scheme (e.g., LinearLayout). This
8682      * method should be followed by calls to {@link #requestLayout()} and
8683      * {@link View#invalidate()} on the parent.
8684      *
8685      * @see ViewGroup#bringChildToFront(View)
8686      */
8687     public void bringToFront() {
8688         if (mParent != null) {
8689             mParent.bringChildToFront(this);
8690         }
8691     }
8692 
8693     /**
8694      * This is called in response to an internal scroll in this view (i.e., the
8695      * view scrolled its own contents). This is typically as a result of
8696      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
8697      * called.
8698      *
8699      * @param l Current horizontal scroll origin.
8700      * @param t Current vertical scroll origin.
8701      * @param oldl Previous horizontal scroll origin.
8702      * @param oldt Previous vertical scroll origin.
8703      */
8704     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
8705         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8706             postSendViewScrolledAccessibilityEventCallback();
8707         }
8708 
8709         mBackgroundSizeChanged = true;
8710 
8711         final AttachInfo ai = mAttachInfo;
8712         if (ai != null) {
8713             ai.mViewScrollChanged = true;
8714         }
8715     }
8716 
8717     /**
8718      * Interface definition for a callback to be invoked when the layout bounds of a view
8719      * changes due to layout processing.
8720      */
8721     public interface OnLayoutChangeListener {
8722         /**
8723          * Called when the focus state of a view has changed.
8724          *
8725          * @param v The view whose state has changed.
8726          * @param left The new value of the view's left property.
8727          * @param top The new value of the view's top property.
8728          * @param right The new value of the view's right property.
8729          * @param bottom The new value of the view's bottom property.
8730          * @param oldLeft The previous value of the view's left property.
8731          * @param oldTop The previous value of the view's top property.
8732          * @param oldRight The previous value of the view's right property.
8733          * @param oldBottom The previous value of the view's bottom property.
8734          */
8735         void onLayoutChange(View v, int left, int top, int right, int bottom,
8736             int oldLeft, int oldTop, int oldRight, int oldBottom);
8737     }
8738 
8739     /**
8740      * This is called during layout when the size of this view has changed. If
8741      * you were just added to the view hierarchy, you're called with the old
8742      * values of 0.
8743      *
8744      * @param w Current width of this view.
8745      * @param h Current height of this view.
8746      * @param oldw Old width of this view.
8747      * @param oldh Old height of this view.
8748      */
8749     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
8750     }
8751 
8752     /**
8753      * Called by draw to draw the child views. This may be overridden
8754      * by derived classes to gain control just before its children are drawn
8755      * (but after its own view has been drawn).
8756      * @param canvas the canvas on which to draw the view
8757      */
8758     protected void dispatchDraw(Canvas canvas) {
8759 
8760     }
8761 
8762     /**
8763      * Gets the parent of this view. Note that the parent is a
8764      * ViewParent and not necessarily a View.
8765      *
8766      * @return Parent of this view.
8767      */
8768     public final ViewParent getParent() {
8769         return mParent;
8770     }
8771 
8772     /**
8773      * Set the horizontal scrolled position of your view. This will cause a call to
8774      * {@link #onScrollChanged(int, int, int, int)} and the view will be
8775      * invalidated.
8776      * @param value the x position to scroll to
8777      */
8778     public void setScrollX(int value) {
8779         scrollTo(value, mScrollY);
8780     }
8781 
8782     /**
8783      * Set the vertical scrolled position of your view. This will cause a call to
8784      * {@link #onScrollChanged(int, int, int, int)} and the view will be
8785      * invalidated.
8786      * @param value the y position to scroll to
8787      */
8788     public void setScrollY(int value) {
8789         scrollTo(mScrollX, value);
8790     }
8791 
8792     /**
8793      * Return the scrolled left position of this view. This is the left edge of
8794      * the displayed part of your view. You do not need to draw any pixels
8795      * farther left, since those are outside of the frame of your view on
8796      * screen.
8797      *
8798      * @return The left edge of the displayed part of your view, in pixels.
8799      */
8800     public final int getScrollX() {
8801         return mScrollX;
8802     }
8803 
8804     /**
8805      * Return the scrolled top position of this view. This is the top edge of
8806      * the displayed part of your view. You do not need to draw any pixels above
8807      * it, since those are outside of the frame of your view on screen.
8808      *
8809      * @return The top edge of the displayed part of your view, in pixels.
8810      */
8811     public final int getScrollY() {
8812         return mScrollY;
8813     }
8814 
8815     /**
8816      * Return the width of the your view.
8817      *
8818      * @return The width of your view, in pixels.
8819      */
8820     @ViewDebug.ExportedProperty(category = "layout")
8821     public final int getWidth() {
8822         return mRight - mLeft;
8823     }
8824 
8825     /**
8826      * Return the height of your view.
8827      *
8828      * @return The height of your view, in pixels.
8829      */
8830     @ViewDebug.ExportedProperty(category = "layout")
8831     public final int getHeight() {
8832         return mBottom - mTop;
8833     }
8834 
8835     /**
8836      * Return the visible drawing bounds of your view. Fills in the output
8837      * rectangle with the values from getScrollX(), getScrollY(),
8838      * getWidth(), and getHeight(). These bounds do not account for any
8839      * transformation properties currently set on the view, such as
8840      * {@link #setScaleX(float)} or {@link #setRotation(float)}.
8841      *
8842      * @param outRect The (scrolled) drawing bounds of the view.
8843      */
8844     public void getDrawingRect(Rect outRect) {
8845         outRect.left = mScrollX;
8846         outRect.top = mScrollY;
8847         outRect.right = mScrollX + (mRight - mLeft);
8848         outRect.bottom = mScrollY + (mBottom - mTop);
8849     }
8850 
8851     /**
8852      * Like {@link #getMeasuredWidthAndState()}, but only returns the
8853      * raw width component (that is the result is masked by
8854      * {@link #MEASURED_SIZE_MASK}).
8855      *
8856      * @return The raw measured width of this view.
8857      */
8858     public final int getMeasuredWidth() {
8859         return mMeasuredWidth & MEASURED_SIZE_MASK;
8860     }
8861 
8862     /**
8863      * Return the full width measurement information for this view as computed
8864      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
8865      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
8866      * This should be used during measurement and layout calculations only. Use
8867      * {@link #getWidth()} to see how wide a view is after layout.
8868      *
8869      * @return The measured width of this view as a bit mask.
8870      */
8871     public final int getMeasuredWidthAndState() {
8872         return mMeasuredWidth;
8873     }
8874 
8875     /**
8876      * Like {@link #getMeasuredHeightAndState()}, but only returns the
8877      * raw width component (that is the result is masked by
8878      * {@link #MEASURED_SIZE_MASK}).
8879      *
8880      * @return The raw measured height of this view.
8881      */
8882     public final int getMeasuredHeight() {
8883         return mMeasuredHeight & MEASURED_SIZE_MASK;
8884     }
8885 
8886     /**
8887      * Return the full height measurement information for this view as computed
8888      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
8889      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
8890      * This should be used during measurement and layout calculations only. Use
8891      * {@link #getHeight()} to see how wide a view is after layout.
8892      *
8893      * @return The measured width of this view as a bit mask.
8894      */
8895     public final int getMeasuredHeightAndState() {
8896         return mMeasuredHeight;
8897     }
8898 
8899     /**
8900      * Return only the state bits of {@link #getMeasuredWidthAndState()}
8901      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
8902      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
8903      * and the height component is at the shifted bits
8904      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
8905      */
8906     public final int getMeasuredState() {
8907         return (mMeasuredWidth&MEASURED_STATE_MASK)
8908                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
8909                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
8910     }
8911 
8912     /**
8913      * The transform matrix of this view, which is calculated based on the current
8914      * roation, scale, and pivot properties.
8915      *
8916      * @see #getRotation()
8917      * @see #getScaleX()
8918      * @see #getScaleY()
8919      * @see #getPivotX()
8920      * @see #getPivotY()
8921      * @return The current transform matrix for the view
8922      */
8923     public Matrix getMatrix() {
8924         if (mTransformationInfo != null) {
8925             updateMatrix();
8926             return mTransformationInfo.mMatrix;
8927         }
8928         return Matrix.IDENTITY_MATRIX;
8929     }
8930 
8931     /**
8932      * Utility function to determine if the value is far enough away from zero to be
8933      * considered non-zero.
8934      * @param value A floating point value to check for zero-ness
8935      * @return whether the passed-in value is far enough away from zero to be considered non-zero
8936      */
8937     private static boolean nonzero(float value) {
8938         return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
8939     }
8940 
8941     /**
8942      * Returns true if the transform matrix is the identity matrix.
8943      * Recomputes the matrix if necessary.
8944      *
8945      * @return True if the transform matrix is the identity matrix, false otherwise.
8946      */
8947     final boolean hasIdentityMatrix() {
8948         if (mTransformationInfo != null) {
8949             updateMatrix();
8950             return mTransformationInfo.mMatrixIsIdentity;
8951         }
8952         return true;
8953     }
8954 
8955     void ensureTransformationInfo() {
8956         if (mTransformationInfo == null) {
8957             mTransformationInfo = new TransformationInfo();
8958         }
8959     }
8960 
8961     /**
8962      * Recomputes the transform matrix if necessary.
8963      */
8964     private void updateMatrix() {
8965         final TransformationInfo info = mTransformationInfo;
8966         if (info == null) {
8967             return;
8968         }
8969         if (info.mMatrixDirty) {
8970             // transform-related properties have changed since the last time someone
8971             // asked for the matrix; recalculate it with the current values
8972 
8973             // Figure out if we need to update the pivot point
8974             if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
8975                 if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
8976                     info.mPrevWidth = mRight - mLeft;
8977                     info.mPrevHeight = mBottom - mTop;
8978                     info.mPivotX = info.mPrevWidth / 2f;
8979                     info.mPivotY = info.mPrevHeight / 2f;
8980                 }
8981             }
8982             info.mMatrix.reset();
8983             if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
8984                 info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
8985                 info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
8986                 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
8987             } else {
8988                 if (info.mCamera == null) {
8989                     info.mCamera = new Camera();
8990                     info.matrix3D = new Matrix();
8991                 }
8992                 info.mCamera.save();
8993                 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
8994                 info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
8995                 info.mCamera.getMatrix(info.matrix3D);
8996                 info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
8997                 info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
8998                         info.mPivotY + info.mTranslationY);
8999                 info.mMatrix.postConcat(info.matrix3D);
9000                 info.mCamera.restore();
9001             }
9002             info.mMatrixDirty = false;
9003             info.mMatrixIsIdentity = info.mMatrix.isIdentity();
9004             info.mInverseMatrixDirty = true;
9005         }
9006     }
9007 
9008    /**
9009      * Utility method to retrieve the inverse of the current mMatrix property.
9010      * We cache the matrix to avoid recalculating it when transform properties
9011      * have not changed.
9012      *
9013      * @return The inverse of the current matrix of this view.
9014      */
9015     final Matrix getInverseMatrix() {
9016         final TransformationInfo info = mTransformationInfo;
9017         if (info != null) {
9018             updateMatrix();
9019             if (info.mInverseMatrixDirty) {
9020                 if (info.mInverseMatrix == null) {
9021                     info.mInverseMatrix = new Matrix();
9022                 }
9023                 info.mMatrix.invert(info.mInverseMatrix);
9024                 info.mInverseMatrixDirty = false;
9025             }
9026             return info.mInverseMatrix;
9027         }
9028         return Matrix.IDENTITY_MATRIX;
9029     }
9030 
9031     /**
9032      * Gets the distance along the Z axis from the camera to this view.
9033      *
9034      * @see #setCameraDistance(float)
9035      *
9036      * @return The distance along the Z axis.
9037      */
9038     public float getCameraDistance() {
9039         ensureTransformationInfo();
9040         final float dpi = mResources.getDisplayMetrics().densityDpi;
9041         final TransformationInfo info = mTransformationInfo;
9042         if (info.mCamera == null) {
9043             info.mCamera = new Camera();
9044             info.matrix3D = new Matrix();
9045         }
9046         return -(info.mCamera.getLocationZ() * dpi);
9047     }
9048 
9049     /**
9050      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
9051      * views are drawn) from the camera to this view. The camera's distance
9052      * affects 3D transformations, for instance rotations around the X and Y
9053      * axis. If the rotationX or rotationY properties are changed and this view is
9054      * large (more than half the size of the screen), it is recommended to always
9055      * use a camera distance that's greater than the height (X axis rotation) or
9056      * the width (Y axis rotation) of this view.</p>
9057      *
9058      * <p>The distance of the camera from the view plane can have an affect on the
9059      * perspective distortion of the view when it is rotated around the x or y axis.
9060      * For example, a large distance will result in a large viewing angle, and there
9061      * will not be much perspective distortion of the view as it rotates. A short
9062      * distance may cause much more perspective distortion upon rotation, and can
9063      * also result in some drawing artifacts if the rotated view ends up partially
9064      * behind the camera (which is why the recommendation is to use a distance at
9065      * least as far as the size of the view, if the view is to be rotated.)</p>
9066      *
9067      * <p>The distance is expressed in "depth pixels." The default distance depends
9068      * on the screen density. For instance, on a medium density display, the
9069      * default distance is 1280. On a high density display, the default distance
9070      * is 1920.</p>
9071      *
9072      * <p>If you want to specify a distance that leads to visually consistent
9073      * results across various densities, use the following formula:</p>
9074      * <pre>
9075      * float scale = context.getResources().getDisplayMetrics().density;
9076      * view.setCameraDistance(distance * scale);
9077      * </pre>
9078      *
9079      * <p>The density scale factor of a high density display is 1.5,
9080      * and 1920 = 1280 * 1.5.</p>
9081      *
9082      * @param distance The distance in "depth pixels", if negative the opposite
9083      *        value is used
9084      *
9085      * @see #setRotationX(float)
9086      * @see #setRotationY(float)
9087      */
9088     public void setCameraDistance(float distance) {
9089         invalidateViewProperty(true, false);
9090 
9091         ensureTransformationInfo();
9092         final float dpi = mResources.getDisplayMetrics().densityDpi;
9093         final TransformationInfo info = mTransformationInfo;
9094         if (info.mCamera == null) {
9095             info.mCamera = new Camera();
9096             info.matrix3D = new Matrix();
9097         }
9098 
9099         info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
9100         info.mMatrixDirty = true;
9101 
9102         invalidateViewProperty(false, false);
9103         if (mDisplayList != null) {
9104             mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
9105         }
9106         if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9107             // View was rejected last time it was drawn by its parent; this may have changed
9108             invalidateParentIfNeeded();
9109         }
9110     }
9111 
9112     /**
9113      * The degrees that the view is rotated around the pivot point.
9114      *
9115      * @see #setRotation(float)
9116      * @see #getPivotX()
9117      * @see #getPivotY()
9118      *
9119      * @return The degrees of rotation.
9120      */
9121     @ViewDebug.ExportedProperty(category = "drawing")
9122     public float getRotation() {
9123         return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
9124     }
9125 
9126     /**
9127      * Sets the degrees that the view is rotated around the pivot point. Increasing values
9128      * result in clockwise rotation.
9129      *
9130      * @param rotation The degrees of rotation.
9131      *
9132      * @see #getRotation()
9133      * @see #getPivotX()
9134      * @see #getPivotY()
9135      * @see #setRotationX(float)
9136      * @see #setRotationY(float)
9137      *
9138      * @attr ref android.R.styleable#View_rotation
9139      */
9140     public void setRotation(float rotation) {
9141         ensureTransformationInfo();
9142         final TransformationInfo info = mTransformationInfo;
9143         if (info.mRotation != rotation) {
9144             // Double-invalidation is necessary to capture view's old and new areas
9145             invalidateViewProperty(true, false);
9146             info.mRotation = rotation;
9147             info.mMatrixDirty = true;
9148             invalidateViewProperty(false, true);
9149             if (mDisplayList != null) {
9150                 mDisplayList.setRotation(rotation);
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 degrees that the view is rotated around the vertical axis through the pivot point.
9161      *
9162      * @see #getPivotX()
9163      * @see #getPivotY()
9164      * @see #setRotationY(float)
9165      *
9166      * @return The degrees of Y rotation.
9167      */
9168     @ViewDebug.ExportedProperty(category = "drawing")
9169     public float getRotationY() {
9170         return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
9171     }
9172 
9173     /**
9174      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
9175      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
9176      * down the y axis.
9177      *
9178      * When rotating large views, it is recommended to adjust the camera distance
9179      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
9180      *
9181      * @param rotationY The degrees of Y rotation.
9182      *
9183      * @see #getRotationY()
9184      * @see #getPivotX()
9185      * @see #getPivotY()
9186      * @see #setRotation(float)
9187      * @see #setRotationX(float)
9188      * @see #setCameraDistance(float)
9189      *
9190      * @attr ref android.R.styleable#View_rotationY
9191      */
9192     public void setRotationY(float rotationY) {
9193         ensureTransformationInfo();
9194         final TransformationInfo info = mTransformationInfo;
9195         if (info.mRotationY != rotationY) {
9196             invalidateViewProperty(true, false);
9197             info.mRotationY = rotationY;
9198             info.mMatrixDirty = true;
9199             invalidateViewProperty(false, true);
9200             if (mDisplayList != null) {
9201                 mDisplayList.setRotationY(rotationY);
9202             }
9203             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9204                 // View was rejected last time it was drawn by its parent; this may have changed
9205                 invalidateParentIfNeeded();
9206             }
9207         }
9208     }
9209 
9210     /**
9211      * The degrees that the view is rotated around the horizontal axis through the pivot point.
9212      *
9213      * @see #getPivotX()
9214      * @see #getPivotY()
9215      * @see #setRotationX(float)
9216      *
9217      * @return The degrees of X rotation.
9218      */
9219     @ViewDebug.ExportedProperty(category = "drawing")
9220     public float getRotationX() {
9221         return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
9222     }
9223 
9224     /**
9225      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
9226      * Increasing values result in clockwise rotation from the viewpoint of looking down the
9227      * x axis.
9228      *
9229      * When rotating large views, it is recommended to adjust the camera distance
9230      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
9231      *
9232      * @param rotationX The degrees of X rotation.
9233      *
9234      * @see #getRotationX()
9235      * @see #getPivotX()
9236      * @see #getPivotY()
9237      * @see #setRotation(float)
9238      * @see #setRotationY(float)
9239      * @see #setCameraDistance(float)
9240      *
9241      * @attr ref android.R.styleable#View_rotationX
9242      */
9243     public void setRotationX(float rotationX) {
9244         ensureTransformationInfo();
9245         final TransformationInfo info = mTransformationInfo;
9246         if (info.mRotationX != rotationX) {
9247             invalidateViewProperty(true, false);
9248             info.mRotationX = rotationX;
9249             info.mMatrixDirty = true;
9250             invalidateViewProperty(false, true);
9251             if (mDisplayList != null) {
9252                 mDisplayList.setRotationX(rotationX);
9253             }
9254             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9255                 // View was rejected last time it was drawn by its parent; this may have changed
9256                 invalidateParentIfNeeded();
9257             }
9258         }
9259     }
9260 
9261     /**
9262      * The amount that the view is scaled in x around the pivot point, as a proportion of
9263      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
9264      *
9265      * <p>By default, this is 1.0f.
9266      *
9267      * @see #getPivotX()
9268      * @see #getPivotY()
9269      * @return The scaling factor.
9270      */
9271     @ViewDebug.ExportedProperty(category = "drawing")
9272     public float getScaleX() {
9273         return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
9274     }
9275 
9276     /**
9277      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
9278      * the view's unscaled width. A value of 1 means that no scaling is applied.
9279      *
9280      * @param scaleX The scaling factor.
9281      * @see #getPivotX()
9282      * @see #getPivotY()
9283      *
9284      * @attr ref android.R.styleable#View_scaleX
9285      */
9286     public void setScaleX(float scaleX) {
9287         ensureTransformationInfo();
9288         final TransformationInfo info = mTransformationInfo;
9289         if (info.mScaleX != scaleX) {
9290             invalidateViewProperty(true, false);
9291             info.mScaleX = scaleX;
9292             info.mMatrixDirty = true;
9293             invalidateViewProperty(false, true);
9294             if (mDisplayList != null) {
9295                 mDisplayList.setScaleX(scaleX);
9296             }
9297             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9298                 // View was rejected last time it was drawn by its parent; this may have changed
9299                 invalidateParentIfNeeded();
9300             }
9301         }
9302     }
9303 
9304     /**
9305      * The amount that the view is scaled in y around the pivot point, as a proportion of
9306      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
9307      *
9308      * <p>By default, this is 1.0f.
9309      *
9310      * @see #getPivotX()
9311      * @see #getPivotY()
9312      * @return The scaling factor.
9313      */
9314     @ViewDebug.ExportedProperty(category = "drawing")
9315     public float getScaleY() {
9316         return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
9317     }
9318 
9319     /**
9320      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
9321      * the view's unscaled width. A value of 1 means that no scaling is applied.
9322      *
9323      * @param scaleY The scaling factor.
9324      * @see #getPivotX()
9325      * @see #getPivotY()
9326      *
9327      * @attr ref android.R.styleable#View_scaleY
9328      */
9329     public void setScaleY(float scaleY) {
9330         ensureTransformationInfo();
9331         final TransformationInfo info = mTransformationInfo;
9332         if (info.mScaleY != scaleY) {
9333             invalidateViewProperty(true, false);
9334             info.mScaleY = scaleY;
9335             info.mMatrixDirty = true;
9336             invalidateViewProperty(false, true);
9337             if (mDisplayList != null) {
9338                 mDisplayList.setScaleY(scaleY);
9339             }
9340             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9341                 // View was rejected last time it was drawn by its parent; this may have changed
9342                 invalidateParentIfNeeded();
9343             }
9344         }
9345     }
9346 
9347     /**
9348      * The x location of the point around which the view is {@link #setRotation(float) rotated}
9349      * and {@link #setScaleX(float) scaled}.
9350      *
9351      * @see #getRotation()
9352      * @see #getScaleX()
9353      * @see #getScaleY()
9354      * @see #getPivotY()
9355      * @return The x location of the pivot point.
9356      *
9357      * @attr ref android.R.styleable#View_transformPivotX
9358      */
9359     @ViewDebug.ExportedProperty(category = "drawing")
9360     public float getPivotX() {
9361         return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
9362     }
9363 
9364     /**
9365      * Sets the x location of the point around which the view is
9366      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
9367      * By default, the pivot point is centered on the object.
9368      * Setting this property disables this behavior and causes the view to use only the
9369      * explicitly set pivotX and pivotY values.
9370      *
9371      * @param pivotX The x location of the pivot point.
9372      * @see #getRotation()
9373      * @see #getScaleX()
9374      * @see #getScaleY()
9375      * @see #getPivotY()
9376      *
9377      * @attr ref android.R.styleable#View_transformPivotX
9378      */
9379     public void setPivotX(float pivotX) {
9380         ensureTransformationInfo();
9381         mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
9382         final TransformationInfo info = mTransformationInfo;
9383         if (info.mPivotX != pivotX) {
9384             invalidateViewProperty(true, false);
9385             info.mPivotX = pivotX;
9386             info.mMatrixDirty = true;
9387             invalidateViewProperty(false, true);
9388             if (mDisplayList != null) {
9389                 mDisplayList.setPivotX(pivotX);
9390             }
9391             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9392                 // View was rejected last time it was drawn by its parent; this may have changed
9393                 invalidateParentIfNeeded();
9394             }
9395         }
9396     }
9397 
9398     /**
9399      * The y location of the point around which the view is {@link #setRotation(float) rotated}
9400      * and {@link #setScaleY(float) scaled}.
9401      *
9402      * @see #getRotation()
9403      * @see #getScaleX()
9404      * @see #getScaleY()
9405      * @see #getPivotY()
9406      * @return The y location of the pivot point.
9407      *
9408      * @attr ref android.R.styleable#View_transformPivotY
9409      */
9410     @ViewDebug.ExportedProperty(category = "drawing")
9411     public float getPivotY() {
9412         return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
9413     }
9414 
9415     /**
9416      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
9417      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
9418      * Setting this property disables this behavior and causes the view to use only the
9419      * explicitly set pivotX and pivotY values.
9420      *
9421      * @param pivotY The y location of the pivot point.
9422      * @see #getRotation()
9423      * @see #getScaleX()
9424      * @see #getScaleY()
9425      * @see #getPivotY()
9426      *
9427      * @attr ref android.R.styleable#View_transformPivotY
9428      */
9429     public void setPivotY(float pivotY) {
9430         ensureTransformationInfo();
9431         mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
9432         final TransformationInfo info = mTransformationInfo;
9433         if (info.mPivotY != pivotY) {
9434             invalidateViewProperty(true, false);
9435             info.mPivotY = pivotY;
9436             info.mMatrixDirty = true;
9437             invalidateViewProperty(false, true);
9438             if (mDisplayList != null) {
9439                 mDisplayList.setPivotY(pivotY);
9440             }
9441             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9442                 // View was rejected last time it was drawn by its parent; this may have changed
9443                 invalidateParentIfNeeded();
9444             }
9445         }
9446     }
9447 
9448     /**
9449      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
9450      * completely transparent and 1 means the view is completely opaque.
9451      *
9452      * <p>By default this is 1.0f.
9453      * @return The opacity of the view.
9454      */
9455     @ViewDebug.ExportedProperty(category = "drawing")
9456     public float getAlpha() {
9457         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
9458     }
9459 
9460     /**
9461      * Returns whether this View has content which overlaps. This function, intended to be
9462      * overridden by specific View types, is an optimization when alpha is set on a view. If
9463      * rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer
9464      * and then composited it into place, which can be expensive. If the view has no overlapping
9465      * rendering, the view can draw each primitive with the appropriate alpha value directly.
9466      * An example of overlapping rendering is a TextView with a background image, such as a
9467      * Button. An example of non-overlapping rendering is a TextView with no background, or
9468      * an ImageView with only the foreground image. The default implementation returns true;
9469      * subclasses should override if they have cases which can be optimized.
9470      *
9471      * @return true if the content in this view might overlap, false otherwise.
9472      */
9473     public boolean hasOverlappingRendering() {
9474         return true;
9475     }
9476 
9477     /**
9478      * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
9479      * completely transparent and 1 means the view is completely opaque.</p>
9480      *
9481      * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
9482      * performance implications, especially for large views. It is best to use the alpha property
9483      * sparingly and transiently, as in the case of fading animations.</p>
9484      *
9485      * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
9486      * strongly recommended for performance reasons to either override
9487      * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
9488      * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
9489      *
9490      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
9491      * responsible for applying the opacity itself.</p>
9492      *
9493      * <p>Note that if the view is backed by a
9494      * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
9495      * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
9496      * 1.0 will supercede the alpha of the layer paint.</p>
9497      *
9498      * @param alpha The opacity of the view.
9499      *
9500      * @see #hasOverlappingRendering()
9501      * @see #setLayerType(int, android.graphics.Paint)
9502      *
9503      * @attr ref android.R.styleable#View_alpha
9504      */
9505     public void setAlpha(float alpha) {
9506         ensureTransformationInfo();
9507         if (mTransformationInfo.mAlpha != alpha) {
9508             mTransformationInfo.mAlpha = alpha;
9509             if (onSetAlpha((int) (alpha * 255))) {
9510                 mPrivateFlags |= PFLAG_ALPHA_SET;
9511                 // subclass is handling alpha - don't optimize rendering cache invalidation
9512                 invalidateParentCaches();
9513                 invalidate(true);
9514             } else {
9515                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
9516                 invalidateViewProperty(true, false);
9517                 if (mDisplayList != null) {
9518                     mDisplayList.setAlpha(alpha);
9519                 }
9520             }
9521         }
9522     }
9523 
9524     /**
9525      * Faster version of setAlpha() which performs the same steps except there are
9526      * no calls to invalidate(). The caller of this function should perform proper invalidation
9527      * on the parent and this object. The return value indicates whether the subclass handles
9528      * alpha (the return value for onSetAlpha()).
9529      *
9530      * @param alpha The new value for the alpha property
9531      * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
9532      *         the new value for the alpha property is different from the old value
9533      */
9534     boolean setAlphaNoInvalidation(float alpha) {
9535         ensureTransformationInfo();
9536         if (mTransformationInfo.mAlpha != alpha) {
9537             mTransformationInfo.mAlpha = alpha;
9538             boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
9539             if (subclassHandlesAlpha) {
9540                 mPrivateFlags |= PFLAG_ALPHA_SET;
9541                 return true;
9542             } else {
9543                 mPrivateFlags &= ~PFLAG_ALPHA_SET;
9544                 if (mDisplayList != null) {
9545                     mDisplayList.setAlpha(alpha);
9546                 }
9547             }
9548         }
9549         return false;
9550     }
9551 
9552     /**
9553      * Top position of this view relative to its parent.
9554      *
9555      * @return The top of this view, in pixels.
9556      */
9557     @ViewDebug.CapturedViewProperty
9558     public final int getTop() {
9559         return mTop;
9560     }
9561 
9562     /**
9563      * Sets the top position of this view relative to its parent. This method is meant to be called
9564      * by the layout system and should not generally be called otherwise, because the property
9565      * may be changed at any time by the layout.
9566      *
9567      * @param top The top of this view, in pixels.
9568      */
9569     public final void setTop(int top) {
9570         if (top != mTop) {
9571             updateMatrix();
9572             final boolean matrixIsIdentity = mTransformationInfo == null
9573                     || mTransformationInfo.mMatrixIsIdentity;
9574             if (matrixIsIdentity) {
9575                 if (mAttachInfo != null) {
9576                     int minTop;
9577                     int yLoc;
9578                     if (top < mTop) {
9579                         minTop = top;
9580                         yLoc = top - mTop;
9581                     } else {
9582                         minTop = mTop;
9583                         yLoc = 0;
9584                     }
9585                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
9586                 }
9587             } else {
9588                 // Double-invalidation is necessary to capture view's old and new areas
9589                 invalidate(true);
9590             }
9591 
9592             int width = mRight - mLeft;
9593             int oldHeight = mBottom - mTop;
9594 
9595             mTop = top;
9596             if (mDisplayList != null) {
9597                 mDisplayList.setTop(mTop);
9598             }
9599 
9600             sizeChange(width, mBottom - mTop, width, oldHeight);
9601 
9602             if (!matrixIsIdentity) {
9603                 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9604                     // A change in dimension means an auto-centered pivot point changes, too
9605                     mTransformationInfo.mMatrixDirty = true;
9606                 }
9607                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9608                 invalidate(true);
9609             }
9610             mBackgroundSizeChanged = true;
9611             invalidateParentIfNeeded();
9612             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9613                 // View was rejected last time it was drawn by its parent; this may have changed
9614                 invalidateParentIfNeeded();
9615             }
9616         }
9617     }
9618 
9619     /**
9620      * Bottom position of this view relative to its parent.
9621      *
9622      * @return The bottom of this view, in pixels.
9623      */
9624     @ViewDebug.CapturedViewProperty
9625     public final int getBottom() {
9626         return mBottom;
9627     }
9628 
9629     /**
9630      * True if this view has changed since the last time being drawn.
9631      *
9632      * @return The dirty state of this view.
9633      */
9634     public boolean isDirty() {
9635         return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
9636     }
9637 
9638     /**
9639      * Sets the bottom position of this view relative to its parent. This method is meant to be
9640      * called by the layout system and should not generally be called otherwise, because the
9641      * property may be changed at any time by the layout.
9642      *
9643      * @param bottom The bottom of this view, in pixels.
9644      */
9645     public final void setBottom(int bottom) {
9646         if (bottom != mBottom) {
9647             updateMatrix();
9648             final boolean matrixIsIdentity = mTransformationInfo == null
9649                     || mTransformationInfo.mMatrixIsIdentity;
9650             if (matrixIsIdentity) {
9651                 if (mAttachInfo != null) {
9652                     int maxBottom;
9653                     if (bottom < mBottom) {
9654                         maxBottom = mBottom;
9655                     } else {
9656                         maxBottom = bottom;
9657                     }
9658                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
9659                 }
9660             } else {
9661                 // Double-invalidation is necessary to capture view's old and new areas
9662                 invalidate(true);
9663             }
9664 
9665             int width = mRight - mLeft;
9666             int oldHeight = mBottom - mTop;
9667 
9668             mBottom = bottom;
9669             if (mDisplayList != null) {
9670                 mDisplayList.setBottom(mBottom);
9671             }
9672 
9673             sizeChange(width, mBottom - mTop, width, oldHeight);
9674 
9675             if (!matrixIsIdentity) {
9676                 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9677                     // A change in dimension means an auto-centered pivot point changes, too
9678                     mTransformationInfo.mMatrixDirty = true;
9679                 }
9680                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9681                 invalidate(true);
9682             }
9683             mBackgroundSizeChanged = true;
9684             invalidateParentIfNeeded();
9685             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9686                 // View was rejected last time it was drawn by its parent; this may have changed
9687                 invalidateParentIfNeeded();
9688             }
9689         }
9690     }
9691 
9692     /**
9693      * Left position of this view relative to its parent.
9694      *
9695      * @return The left edge of this view, in pixels.
9696      */
9697     @ViewDebug.CapturedViewProperty
9698     public final int getLeft() {
9699         return mLeft;
9700     }
9701 
9702     /**
9703      * Sets the left position of this view relative to its parent. This method is meant to be called
9704      * by the layout system and should not generally be called otherwise, because the property
9705      * may be changed at any time by the layout.
9706      *
9707      * @param left The bottom of this view, in pixels.
9708      */
9709     public final void setLeft(int left) {
9710         if (left != mLeft) {
9711             updateMatrix();
9712             final boolean matrixIsIdentity = mTransformationInfo == null
9713                     || mTransformationInfo.mMatrixIsIdentity;
9714             if (matrixIsIdentity) {
9715                 if (mAttachInfo != null) {
9716                     int minLeft;
9717                     int xLoc;
9718                     if (left < mLeft) {
9719                         minLeft = left;
9720                         xLoc = left - mLeft;
9721                     } else {
9722                         minLeft = mLeft;
9723                         xLoc = 0;
9724                     }
9725                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
9726                 }
9727             } else {
9728                 // Double-invalidation is necessary to capture view's old and new areas
9729                 invalidate(true);
9730             }
9731 
9732             int oldWidth = mRight - mLeft;
9733             int height = mBottom - mTop;
9734 
9735             mLeft = left;
9736             if (mDisplayList != null) {
9737                 mDisplayList.setLeft(left);
9738             }
9739 
9740             sizeChange(mRight - mLeft, height, oldWidth, height);
9741 
9742             if (!matrixIsIdentity) {
9743                 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9744                     // A change in dimension means an auto-centered pivot point changes, too
9745                     mTransformationInfo.mMatrixDirty = true;
9746                 }
9747                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9748                 invalidate(true);
9749             }
9750             mBackgroundSizeChanged = true;
9751             invalidateParentIfNeeded();
9752             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9753                 // View was rejected last time it was drawn by its parent; this may have changed
9754                 invalidateParentIfNeeded();
9755             }
9756         }
9757     }
9758 
9759     /**
9760      * Right position of this view relative to its parent.
9761      *
9762      * @return The right edge of this view, in pixels.
9763      */
9764     @ViewDebug.CapturedViewProperty
9765     public final int getRight() {
9766         return mRight;
9767     }
9768 
9769     /**
9770      * Sets the right position of this view relative to its parent. This method is meant to be called
9771      * by the layout system and should not generally be called otherwise, because the property
9772      * may be changed at any time by the layout.
9773      *
9774      * @param right The bottom of this view, in pixels.
9775      */
9776     public final void setRight(int right) {
9777         if (right != mRight) {
9778             updateMatrix();
9779             final boolean matrixIsIdentity = mTransformationInfo == null
9780                     || mTransformationInfo.mMatrixIsIdentity;
9781             if (matrixIsIdentity) {
9782                 if (mAttachInfo != null) {
9783                     int maxRight;
9784                     if (right < mRight) {
9785                         maxRight = mRight;
9786                     } else {
9787                         maxRight = right;
9788                     }
9789                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
9790                 }
9791             } else {
9792                 // Double-invalidation is necessary to capture view's old and new areas
9793                 invalidate(true);
9794             }
9795 
9796             int oldWidth = mRight - mLeft;
9797             int height = mBottom - mTop;
9798 
9799             mRight = right;
9800             if (mDisplayList != null) {
9801                 mDisplayList.setRight(mRight);
9802             }
9803 
9804             sizeChange(mRight - mLeft, height, oldWidth, height);
9805 
9806             if (!matrixIsIdentity) {
9807                 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9808                     // A change in dimension means an auto-centered pivot point changes, too
9809                     mTransformationInfo.mMatrixDirty = true;
9810                 }
9811                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9812                 invalidate(true);
9813             }
9814             mBackgroundSizeChanged = true;
9815             invalidateParentIfNeeded();
9816             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9817                 // View was rejected last time it was drawn by its parent; this may have changed
9818                 invalidateParentIfNeeded();
9819             }
9820         }
9821     }
9822 
9823     /**
9824      * The visual x position of this view, in pixels. This is equivalent to the
9825      * {@link #setTranslationX(float) translationX} property plus the current
9826      * {@link #getLeft() left} property.
9827      *
9828      * @return The visual x position of this view, in pixels.
9829      */
9830     @ViewDebug.ExportedProperty(category = "drawing")
9831     public float getX() {
9832         return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
9833     }
9834 
9835     /**
9836      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
9837      * {@link #setTranslationX(float) translationX} property to be the difference between
9838      * the x value passed in and the current {@link #getLeft() left} property.
9839      *
9840      * @param x The visual x position of this view, in pixels.
9841      */
9842     public void setX(float x) {
9843         setTranslationX(x - mLeft);
9844     }
9845 
9846     /**
9847      * The visual y position of this view, in pixels. This is equivalent to the
9848      * {@link #setTranslationY(float) translationY} property plus the current
9849      * {@link #getTop() top} property.
9850      *
9851      * @return The visual y position of this view, in pixels.
9852      */
9853     @ViewDebug.ExportedProperty(category = "drawing")
9854     public float getY() {
9855         return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
9856     }
9857 
9858     /**
9859      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
9860      * {@link #setTranslationY(float) translationY} property to be the difference between
9861      * the y value passed in and the current {@link #getTop() top} property.
9862      *
9863      * @param y The visual y position of this view, in pixels.
9864      */
9865     public void setY(float y) {
9866         setTranslationY(y - mTop);
9867     }
9868 
9869 
9870     /**
9871      * The horizontal location of this view relative to its {@link #getLeft() left} position.
9872      * This position is post-layout, in addition to wherever the object's
9873      * layout placed it.
9874      *
9875      * @return The horizontal position of this view relative to its left position, in pixels.
9876      */
9877     @ViewDebug.ExportedProperty(category = "drawing")
9878     public float getTranslationX() {
9879         return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
9880     }
9881 
9882     /**
9883      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
9884      * This effectively positions the object post-layout, in addition to wherever the object's
9885      * layout placed it.
9886      *
9887      * @param translationX The horizontal position of this view relative to its left position,
9888      * in pixels.
9889      *
9890      * @attr ref android.R.styleable#View_translationX
9891      */
9892     public void setTranslationX(float translationX) {
9893         ensureTransformationInfo();
9894         final TransformationInfo info = mTransformationInfo;
9895         if (info.mTranslationX != translationX) {
9896             // Double-invalidation is necessary to capture view's old and new areas
9897             invalidateViewProperty(true, false);
9898             info.mTranslationX = translationX;
9899             info.mMatrixDirty = true;
9900             invalidateViewProperty(false, true);
9901             if (mDisplayList != null) {
9902                 mDisplayList.setTranslationX(translationX);
9903             }
9904             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9905                 // View was rejected last time it was drawn by its parent; this may have changed
9906                 invalidateParentIfNeeded();
9907             }
9908         }
9909     }
9910 
9911     /**
9912      * The horizontal location of this view relative to its {@link #getTop() top} position.
9913      * This position is post-layout, in addition to wherever the object's
9914      * layout placed it.
9915      *
9916      * @return The vertical position of this view relative to its top position,
9917      * in pixels.
9918      */
9919     @ViewDebug.ExportedProperty(category = "drawing")
9920     public float getTranslationY() {
9921         return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
9922     }
9923 
9924     /**
9925      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
9926      * This effectively positions the object post-layout, in addition to wherever the object's
9927      * layout placed it.
9928      *
9929      * @param translationY The vertical position of this view relative to its top position,
9930      * in pixels.
9931      *
9932      * @attr ref android.R.styleable#View_translationY
9933      */
9934     public void setTranslationY(float translationY) {
9935         ensureTransformationInfo();
9936         final TransformationInfo info = mTransformationInfo;
9937         if (info.mTranslationY != translationY) {
9938             invalidateViewProperty(true, false);
9939             info.mTranslationY = translationY;
9940             info.mMatrixDirty = true;
9941             invalidateViewProperty(false, true);
9942             if (mDisplayList != null) {
9943                 mDisplayList.setTranslationY(translationY);
9944             }
9945             if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9946                 // View was rejected last time it was drawn by its parent; this may have changed
9947                 invalidateParentIfNeeded();
9948             }
9949         }
9950     }
9951 
9952     /**
9953      * Hit rectangle in parent's coordinates
9954      *
9955      * @param outRect The hit rectangle of the view.
9956      */
9957     public void getHitRect(Rect outRect) {
9958         updateMatrix();
9959         final TransformationInfo info = mTransformationInfo;
9960         if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
9961             outRect.set(mLeft, mTop, mRight, mBottom);
9962         } else {
9963             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
9964             tmpRect.set(0, 0, getWidth(), getHeight());
9965             info.mMatrix.mapRect(tmpRect);
9966             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
9967                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
9968         }
9969     }
9970 
9971     /**
9972      * Determines whether the given point, in local coordinates is inside the view.
9973      */
9974     /*package*/ final boolean pointInView(float localX, float localY) {
9975         return localX >= 0 && localX < (mRight - mLeft)
9976                 && localY >= 0 && localY < (mBottom - mTop);
9977     }
9978 
9979     /**
9980      * Utility method to determine whether the given point, in local coordinates,
9981      * is inside the view, where the area of the view is expanded by the slop factor.
9982      * This method is called while processing touch-move events to determine if the event
9983      * is still within the view.
9984      */
9985     private boolean pointInView(float localX, float localY, float slop) {
9986         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
9987                 localY < ((mBottom - mTop) + slop);
9988     }
9989 
9990     /**
9991      * When a view has focus and the user navigates away from it, the next view is searched for
9992      * starting from the rectangle filled in by this method.
9993      *
9994      * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
9995      * of the view.  However, if your view maintains some idea of internal selection,
9996      * such as a cursor, or a selected row or column, you should override this method and
9997      * fill in a more specific rectangle.
9998      *
9999      * @param r The rectangle to fill in, in this view's coordinates.
10000      */
10001     public void getFocusedRect(Rect r) {
10002         getDrawingRect(r);
10003     }
10004 
10005     /**
10006      * If some part of this view is not clipped by any of its parents, then
10007      * return that area in r in global (root) coordinates. To convert r to local
10008      * coordinates (without taking possible View rotations into account), offset
10009      * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
10010      * If the view is completely clipped or translated out, return false.
10011      *
10012      * @param r If true is returned, r holds the global coordinates of the
10013      *        visible portion of this view.
10014      * @param globalOffset If true is returned, globalOffset holds the dx,dy
10015      *        between this view and its root. globalOffet may be null.
10016      * @return true if r is non-empty (i.e. part of the view is visible at the
10017      *         root level.
10018      */
10019     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
10020         int width = mRight - mLeft;
10021         int height = mBottom - mTop;
10022         if (width > 0 && height > 0) {
10023             r.set(0, 0, width, height);
10024             if (globalOffset != null) {
10025                 globalOffset.set(-mScrollX, -mScrollY);
10026             }
10027             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
10028         }
10029         return false;
10030     }
10031 
10032     public final boolean getGlobalVisibleRect(Rect r) {
10033         return getGlobalVisibleRect(r, null);
10034     }
10035 
10036     public final boolean getLocalVisibleRect(Rect r) {
10037         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
10038         if (getGlobalVisibleRect(r, offset)) {
10039             r.offset(-offset.x, -offset.y); // make r local
10040             return true;
10041         }
10042         return false;
10043     }
10044 
10045     /**
10046      * Offset this view's vertical location by the specified number of pixels.
10047      *
10048      * @param offset the number of pixels to offset the view by
10049      */
10050     public void offsetTopAndBottom(int offset) {
10051         if (offset != 0) {
10052             updateMatrix();
10053             final boolean matrixIsIdentity = mTransformationInfo == null
10054                     || mTransformationInfo.mMatrixIsIdentity;
10055             if (matrixIsIdentity) {
10056                 if (mDisplayList != null) {
10057                     invalidateViewProperty(false, false);
10058                 } else {
10059                     final ViewParent p = mParent;
10060                     if (p != null && mAttachInfo != null) {
10061                         final Rect r = mAttachInfo.mTmpInvalRect;
10062                         int minTop;
10063                         int maxBottom;
10064                         int yLoc;
10065                         if (offset < 0) {
10066                             minTop = mTop + offset;
10067                             maxBottom = mBottom;
10068                             yLoc = offset;
10069                         } else {
10070                             minTop = mTop;
10071                             maxBottom = mBottom + offset;
10072                             yLoc = 0;
10073                         }
10074                         r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
10075                         p.invalidateChild(this, r);
10076                     }
10077                 }
10078             } else {
10079                 invalidateViewProperty(false, false);
10080             }
10081 
10082             mTop += offset;
10083             mBottom += offset;
10084             if (mDisplayList != null) {
10085                 mDisplayList.offsetTopAndBottom(offset);
10086                 invalidateViewProperty(false, false);
10087             } else {
10088                 if (!matrixIsIdentity) {
10089                     invalidateViewProperty(false, true);
10090                 }
10091                 invalidateParentIfNeeded();
10092             }
10093         }
10094     }
10095 
10096     /**
10097      * Offset this view's horizontal location by the specified amount of pixels.
10098      *
10099      * @param offset the number of pixels to offset the view by
10100      */
10101     public void offsetLeftAndRight(int offset) {
10102         if (offset != 0) {
10103             updateMatrix();
10104             final boolean matrixIsIdentity = mTransformationInfo == null
10105                     || mTransformationInfo.mMatrixIsIdentity;
10106             if (matrixIsIdentity) {
10107                 if (mDisplayList != null) {
10108                     invalidateViewProperty(false, false);
10109                 } else {
10110                     final ViewParent p = mParent;
10111                     if (p != null && mAttachInfo != null) {
10112                         final Rect r = mAttachInfo.mTmpInvalRect;
10113                         int minLeft;
10114                         int maxRight;
10115                         if (offset < 0) {
10116                             minLeft = mLeft + offset;
10117                             maxRight = mRight;
10118                         } else {
10119                             minLeft = mLeft;
10120                             maxRight = mRight + offset;
10121                         }
10122                         r.set(0, 0, maxRight - minLeft, mBottom - mTop);
10123                         p.invalidateChild(this, r);
10124                     }
10125                 }
10126             } else {
10127                 invalidateViewProperty(false, false);
10128             }
10129 
10130             mLeft += offset;
10131             mRight += offset;
10132             if (mDisplayList != null) {
10133                 mDisplayList.offsetLeftAndRight(offset);
10134                 invalidateViewProperty(false, false);
10135             } else {
10136                 if (!matrixIsIdentity) {
10137                     invalidateViewProperty(false, true);
10138                 }
10139                 invalidateParentIfNeeded();
10140             }
10141         }
10142     }
10143 
10144     /**
10145      * Get the LayoutParams associated with this view. All views should have
10146      * layout parameters. These supply parameters to the <i>parent</i> of this
10147      * view specifying how it should be arranged. There are many subclasses of
10148      * ViewGroup.LayoutParams, and these correspond to the different subclasses
10149      * of ViewGroup that are responsible for arranging their children.
10150      *
10151      * This method may return null if this View is not attached to a parent
10152      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
10153      * was not invoked successfully. When a View is attached to a parent
10154      * ViewGroup, this method must not return null.
10155      *
10156      * @return The LayoutParams associated with this view, or null if no
10157      *         parameters have been set yet
10158      */
10159     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
10160     public ViewGroup.LayoutParams getLayoutParams() {
10161         return mLayoutParams;
10162     }
10163 
10164     /**
10165      * Set the layout parameters associated with this view. These supply
10166      * parameters to the <i>parent</i> of this view specifying how it should be
10167      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
10168      * correspond to the different subclasses of ViewGroup that are responsible
10169      * for arranging their children.
10170      *
10171      * @param params The layout parameters for this view, cannot be null
10172      */
10173     public void setLayoutParams(ViewGroup.LayoutParams params) {
10174         if (params == null) {
10175             throw new NullPointerException("Layout parameters cannot be null");
10176         }
10177         mLayoutParams = params;
10178         resolveLayoutParams();
10179         if (mParent instanceof ViewGroup) {
10180             ((ViewGroup) mParent).onSetLayoutParams(this, params);
10181         }
10182         requestLayout();
10183     }
10184 
10185     /**
10186      * Resolve the layout parameters depending on the resolved layout direction
10187      *
10188      * @hide
10189      */
10190     public void resolveLayoutParams() {
10191         if (mLayoutParams != null) {
10192             mLayoutParams.resolveLayoutDirection(getLayoutDirection());
10193         }
10194     }
10195 
10196     /**
10197      * Set the scrolled position of your view. This will cause a call to
10198      * {@link #onScrollChanged(int, int, int, int)} and the view will be
10199      * invalidated.
10200      * @param x the x position to scroll to
10201      * @param y the y position to scroll to
10202      */
10203     public void scrollTo(int x, int y) {
10204         if (mScrollX != x || mScrollY != y) {
10205             int oldX = mScrollX;
10206             int oldY = mScrollY;
10207             mScrollX = x;
10208             mScrollY = y;
10209             invalidateParentCaches();
10210             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
10211             if (!awakenScrollBars()) {
10212                 postInvalidateOnAnimation();
10213             }
10214         }
10215     }
10216 
10217     /**
10218      * Move the scrolled position of your view. This will cause a call to
10219      * {@link #onScrollChanged(int, int, int, int)} and the view will be
10220      * invalidated.
10221      * @param x the amount of pixels to scroll by horizontally
10222      * @param y the amount of pixels to scroll by vertically
10223      */
10224     public void scrollBy(int x, int y) {
10225         scrollTo(mScrollX + x, mScrollY + y);
10226     }
10227 
10228     /**
10229      * <p>Trigger the scrollbars to draw. When invoked this method starts an
10230      * animation to fade the scrollbars out after a default delay. If a subclass
10231      * provides animated scrolling, the start delay should equal the duration
10232      * of the scrolling animation.</p>
10233      *
10234      * <p>The animation starts only if at least one of the scrollbars is
10235      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
10236      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
10237      * this method returns true, and false otherwise. If the animation is
10238      * started, this method calls {@link #invalidate()}; in that case the
10239      * caller should not call {@link #invalidate()}.</p>
10240      *
10241      * <p>This method should be invoked every time a subclass directly updates
10242      * the scroll parameters.</p>
10243      *
10244      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
10245      * and {@link #scrollTo(int, int)}.</p>
10246      *
10247      * @return true if the animation is played, false otherwise
10248      *
10249      * @see #awakenScrollBars(int)
10250      * @see #scrollBy(int, int)
10251      * @see #scrollTo(int, int)
10252      * @see #isHorizontalScrollBarEnabled()
10253      * @see #isVerticalScrollBarEnabled()
10254      * @see #setHorizontalScrollBarEnabled(boolean)
10255      * @see #setVerticalScrollBarEnabled(boolean)
10256      */
10257     protected boolean awakenScrollBars() {
10258         return mScrollCache != null &&
10259                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
10260     }
10261 
10262     /**
10263      * Trigger the scrollbars to draw.
10264      * This method differs from awakenScrollBars() only in its default duration.
10265      * initialAwakenScrollBars() will show the scroll bars for longer than
10266      * usual to give the user more of a chance to notice them.
10267      *
10268      * @return true if the animation is played, false otherwise.
10269      */
10270     private boolean initialAwakenScrollBars() {
10271         return mScrollCache != null &&
10272                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
10273     }
10274 
10275     /**
10276      * <p>
10277      * Trigger the scrollbars to draw. When invoked this method starts an
10278      * animation to fade the scrollbars out after a fixed delay. If a subclass
10279      * provides animated scrolling, the start delay should equal the duration of
10280      * the scrolling animation.
10281      * </p>
10282      *
10283      * <p>
10284      * The animation starts only if at least one of the scrollbars is enabled,
10285      * as specified by {@link #isHorizontalScrollBarEnabled()} and
10286      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
10287      * this method returns true, and false otherwise. If the animation is
10288      * started, this method calls {@link #invalidate()}; in that case the caller
10289      * should not call {@link #invalidate()}.
10290      * </p>
10291      *
10292      * <p>
10293      * This method should be invoked everytime a subclass directly updates the
10294      * scroll parameters.
10295      * </p>
10296      *
10297      * @param startDelay the delay, in milliseconds, after which the animation
10298      *        should start; when the delay is 0, the animation starts
10299      *        immediately
10300      * @return true if the animation is played, false otherwise
10301      *
10302      * @see #scrollBy(int, int)
10303      * @see #scrollTo(int, int)
10304      * @see #isHorizontalScrollBarEnabled()
10305      * @see #isVerticalScrollBarEnabled()
10306      * @see #setHorizontalScrollBarEnabled(boolean)
10307      * @see #setVerticalScrollBarEnabled(boolean)
10308      */
10309     protected boolean awakenScrollBars(int startDelay) {
10310         return awakenScrollBars(startDelay, true);
10311     }
10312 
10313     /**
10314      * <p>
10315      * Trigger the scrollbars to draw. When invoked this method starts an
10316      * animation to fade the scrollbars out after a fixed delay. If a subclass
10317      * provides animated scrolling, the start delay should equal the duration of
10318      * the scrolling animation.
10319      * </p>
10320      *
10321      * <p>
10322      * The animation starts only if at least one of the scrollbars is enabled,
10323      * as specified by {@link #isHorizontalScrollBarEnabled()} and
10324      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
10325      * this method returns true, and false otherwise. If the animation is
10326      * started, this method calls {@link #invalidate()} if the invalidate parameter
10327      * is set to true; in that case the caller
10328      * should not call {@link #invalidate()}.
10329      * </p>
10330      *
10331      * <p>
10332      * This method should be invoked everytime a subclass directly updates the
10333      * scroll parameters.
10334      * </p>
10335      *
10336      * @param startDelay the delay, in milliseconds, after which the animation
10337      *        should start; when the delay is 0, the animation starts
10338      *        immediately
10339      *
10340      * @param invalidate Wheter this method should call invalidate
10341      *
10342      * @return true if the animation is played, false otherwise
10343      *
10344      * @see #scrollBy(int, int)
10345      * @see #scrollTo(int, int)
10346      * @see #isHorizontalScrollBarEnabled()
10347      * @see #isVerticalScrollBarEnabled()
10348      * @see #setHorizontalScrollBarEnabled(boolean)
10349      * @see #setVerticalScrollBarEnabled(boolean)
10350      */
10351     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
10352         final ScrollabilityCache scrollCache = mScrollCache;
10353 
10354         if (scrollCache == null || !scrollCache.fadeScrollBars) {
10355             return false;
10356         }
10357 
10358         if (scrollCache.scrollBar == null) {
10359             scrollCache.scrollBar = new ScrollBarDrawable();
10360         }
10361 
10362         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
10363 
10364             if (invalidate) {
10365                 // Invalidate to show the scrollbars
10366                 postInvalidateOnAnimation();
10367             }
10368 
10369             if (scrollCache.state == ScrollabilityCache.OFF) {
10370                 // FIXME: this is copied from WindowManagerService.
10371                 // We should get this value from the system when it
10372                 // is possible to do so.
10373                 final int KEY_REPEAT_FIRST_DELAY = 750;
10374                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
10375             }
10376 
10377             // Tell mScrollCache when we should start fading. This may
10378             // extend the fade start time if one was already scheduled
10379             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
10380             scrollCache.fadeStartTime = fadeStartTime;
10381             scrollCache.state = ScrollabilityCache.ON;
10382 
10383             // Schedule our fader to run, unscheduling any old ones first
10384             if (mAttachInfo != null) {
10385                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
10386                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
10387             }
10388 
10389             return true;
10390         }
10391 
10392         return false;
10393     }
10394 
10395     /**
10396      * Do not invalidate views which are not visible and which are not running an animation. They
10397      * will not get drawn and they should not set dirty flags as if they will be drawn
10398      */
10399     private boolean skipInvalidate() {
10400         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
10401                 (!(mParent instanceof ViewGroup) ||
10402                         !((ViewGroup) mParent).isViewTransitioning(this));
10403     }
10404     /**
10405      * Mark the area defined by dirty as needing to be drawn. If the view is
10406      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
10407      * in the future. This must be called from a UI thread. To call from a non-UI
10408      * thread, call {@link #postInvalidate()}.
10409      *
10410      * WARNING: This method is destructive to dirty.
10411      * @param dirty the rectangle representing the bounds of the dirty region
10412      */
10413     public void invalidate(Rect dirty) {
10414         if (skipInvalidate()) {
10415             return;
10416         }
10417         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10418                 (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
10419                 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
10420             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10421             mPrivateFlags |= PFLAG_INVALIDATED;
10422             mPrivateFlags |= PFLAG_DIRTY;
10423             final ViewParent p = mParent;
10424             final AttachInfo ai = mAttachInfo;
10425             //noinspection PointlessBooleanExpression,ConstantConditions
10426             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10427                 if (p != null && ai != null && ai.mHardwareAccelerated) {
10428                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10429                     // with a null dirty rect, which tells the ViewAncestor to redraw everything
10430                     p.invalidateChild(this, null);
10431                     return;
10432                 }
10433             }
10434             if (p != null && ai != null) {
10435                 final int scrollX = mScrollX;
10436                 final int scrollY = mScrollY;
10437                 final Rect r = ai.mTmpInvalRect;
10438                 r.set(dirty.left - scrollX, dirty.top - scrollY,
10439                         dirty.right - scrollX, dirty.bottom - scrollY);
10440                 mParent.invalidateChild(this, r);
10441             }
10442         }
10443     }
10444 
10445     /**
10446      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn.
10447      * The coordinates of the dirty rect are relative to the view.
10448      * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
10449      * will be called at some point in the future. This must be called from
10450      * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
10451      * @param l the left position of the dirty region
10452      * @param t the top position of the dirty region
10453      * @param r the right position of the dirty region
10454      * @param b the bottom position of the dirty region
10455      */
10456     public void invalidate(int l, int t, int r, int b) {
10457         if (skipInvalidate()) {
10458             return;
10459         }
10460         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10461                 (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
10462                 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
10463             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10464             mPrivateFlags |= PFLAG_INVALIDATED;
10465             mPrivateFlags |= PFLAG_DIRTY;
10466             final ViewParent p = mParent;
10467             final AttachInfo ai = mAttachInfo;
10468             //noinspection PointlessBooleanExpression,ConstantConditions
10469             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10470                 if (p != null && ai != null && ai.mHardwareAccelerated) {
10471                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10472                     // with a null dirty rect, which tells the ViewAncestor to redraw everything
10473                     p.invalidateChild(this, null);
10474                     return;
10475                 }
10476             }
10477             if (p != null && ai != null && l < r && t < b) {
10478                 final int scrollX = mScrollX;
10479                 final int scrollY = mScrollY;
10480                 final Rect tmpr = ai.mTmpInvalRect;
10481                 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
10482                 p.invalidateChild(this, tmpr);
10483             }
10484         }
10485     }
10486 
10487     /**
10488      * Invalidate the whole view. If the view is visible,
10489      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
10490      * the future. This must be called from a UI thread. To call from a non-UI thread,
10491      * call {@link #postInvalidate()}.
10492      */
10493     public void invalidate() {
10494         invalidate(true);
10495     }
10496 
10497     /**
10498      * This is where the invalidate() work actually happens. A full invalidate()
10499      * causes the drawing cache to be invalidated, but this function can be called with
10500      * invalidateCache set to false to skip that invalidation step for cases that do not
10501      * need it (for example, a component that remains at the same dimensions with the same
10502      * content).
10503      *
10504      * @param invalidateCache Whether the drawing cache for this view should be invalidated as
10505      * well. This is usually true for a full invalidate, but may be set to false if the
10506      * View's contents or dimensions have not changed.
10507      */
10508     void invalidate(boolean invalidateCache) {
10509         if (skipInvalidate()) {
10510             return;
10511         }
10512         if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10513                 (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
10514                 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
10515             mLastIsOpaque = isOpaque();
10516             mPrivateFlags &= ~PFLAG_DRAWN;
10517             mPrivateFlags |= PFLAG_DIRTY;
10518             if (invalidateCache) {
10519                 mPrivateFlags |= PFLAG_INVALIDATED;
10520                 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10521             }
10522             final AttachInfo ai = mAttachInfo;
10523             final ViewParent p = mParent;
10524             //noinspection PointlessBooleanExpression,ConstantConditions
10525             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10526                 if (p != null && ai != null && ai.mHardwareAccelerated) {
10527                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10528                     // with a null dirty rect, which tells the ViewAncestor to redraw everything
10529                     p.invalidateChild(this, null);
10530                     return;
10531                 }
10532             }
10533 
10534             if (p != null && ai != null) {
10535                 final Rect r = ai.mTmpInvalRect;
10536                 r.set(0, 0, mRight - mLeft, mBottom - mTop);
10537                 // Don't call invalidate -- we don't want to internally scroll
10538                 // our own bounds
10539                 p.invalidateChild(this, r);
10540             }
10541         }
10542     }
10543 
10544     /**
10545      * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
10546      * set any flags or handle all of the cases handled by the default invalidation methods.
10547      * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
10548      * dirty rect. This method calls into fast invalidation methods in ViewGroup that
10549      * walk up the hierarchy, transforming the dirty rect as necessary.
10550      *
10551      * The method also handles normal invalidation logic if display list properties are not
10552      * being used in this view. The invalidateParent and forceRedraw flags are used by that
10553      * backup approach, to handle these cases used in the various property-setting methods.
10554      *
10555      * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
10556      * are not being used in this view
10557      * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
10558      * list properties are not being used in this view
10559      */
10560     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
10561         if (mDisplayList == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) {
10562             if (invalidateParent) {
10563                 invalidateParentCaches();
10564             }
10565             if (forceRedraw) {
10566                 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10567             }
10568             invalidate(false);
10569         } else {
10570             final AttachInfo ai = mAttachInfo;
10571             final ViewParent p = mParent;
10572             if (p != null && ai != null) {
10573                 final Rect r = ai.mTmpInvalRect;
10574                 r.set(0, 0, mRight - mLeft, mBottom - mTop);
10575                 if (mParent instanceof ViewGroup) {
10576                     ((ViewGroup) mParent).invalidateChildFast(this, r);
10577                 } else {
10578                     mParent.invalidateChild(this, r);
10579                 }
10580             }
10581         }
10582     }
10583 
10584     /**
10585      * Utility method to transform a given Rect by the current matrix of this view.
10586      */
10587     void transformRect(final Rect rect) {
10588         if (!getMatrix().isIdentity()) {
10589             RectF boundingRect = mAttachInfo.mTmpTransformRect;
10590             boundingRect.set(rect);
10591             getMatrix().mapRect(boundingRect);
10592             rect.set((int) Math.floor(boundingRect.left),
10593                     (int) Math.floor(boundingRect.top),
10594                     (int) Math.ceil(boundingRect.right),
10595                     (int) Math.ceil(boundingRect.bottom));
10596         }
10597     }
10598 
10599     /**
10600      * Used to indicate that the parent of this view should clear its caches. This functionality
10601      * is used to force the parent to rebuild its display list (when hardware-accelerated),
10602      * which is necessary when various parent-managed properties of the view change, such as
10603      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
10604      * clears the parent caches and does not causes an invalidate event.
10605      *
10606      * @hide
10607      */
10608     protected void invalidateParentCaches() {
10609         if (mParent instanceof View) {
10610             ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
10611         }
10612     }
10613 
10614     /**
10615      * Used to indicate that the parent of this view should be invalidated. This functionality
10616      * is used to force the parent to rebuild its display list (when hardware-accelerated),
10617      * which is necessary when various parent-managed properties of the view change, such as
10618      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
10619      * an invalidation event to the parent.
10620      *
10621      * @hide
10622      */
10623     protected void invalidateParentIfNeeded() {
10624         if (isHardwareAccelerated() && mParent instanceof View) {
10625             ((View) mParent).invalidate(true);
10626         }
10627     }
10628 
10629     /**
10630      * Indicates whether this View is opaque. An opaque View guarantees that it will
10631      * draw all the pixels overlapping its bounds using a fully opaque color.
10632      *
10633      * Subclasses of View should override this method whenever possible to indicate
10634      * whether an instance is opaque. Opaque Views are treated in a special way by
10635      * the View hierarchy, possibly allowing it to perform optimizations during
10636      * invalidate/draw passes.
10637      *
10638      * @return True if this View is guaranteed to be fully opaque, false otherwise.
10639      */
10640     @ViewDebug.ExportedProperty(category = "drawing")
10641     public boolean isOpaque() {
10642         return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
10643                 ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f);
10644     }
10645 
10646     /**
10647      * @hide
10648      */
10649     protected void computeOpaqueFlags() {
10650         // Opaque if:
10651         //   - Has a background
10652         //   - Background is opaque
10653         //   - Doesn't have scrollbars or scrollbars overlay
10654 
10655         if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
10656             mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
10657         } else {
10658             mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
10659         }
10660 
10661         final int flags = mViewFlags;
10662         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
10663                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
10664                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
10665             mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
10666         } else {
10667             mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
10668         }
10669     }
10670 
10671     /**
10672      * @hide
10673      */
10674     protected boolean hasOpaqueScrollbars() {
10675         return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
10676     }
10677 
10678     /**
10679      * @return A handler associated with the thread running the View. This
10680      * handler can be used to pump events in the UI events queue.
10681      */
10682     public Handler getHandler() {
10683         if (mAttachInfo != null) {
10684             return mAttachInfo.mHandler;
10685         }
10686         return null;
10687     }
10688 
10689     /**
10690      * Gets the view root associated with the View.
10691      * @return The view root, or null if none.
10692      * @hide
10693      */
10694     public ViewRootImpl getViewRootImpl() {
10695         if (mAttachInfo != null) {
10696             return mAttachInfo.mViewRootImpl;
10697         }
10698         return null;
10699     }
10700 
10701     /**
10702      * <p>Causes the Runnable to be added to the message queue.
10703      * The runnable will be run on the user interface thread.</p>
10704      *
10705      * @param action The Runnable that will be executed.
10706      *
10707      * @return Returns true if the Runnable was successfully placed in to the
10708      *         message queue.  Returns false on failure, usually because the
10709      *         looper processing the message queue is exiting.
10710      *
10711      * @see #postDelayed
10712      * @see #removeCallbacks
10713      */
10714     public boolean post(Runnable action) {
10715         final AttachInfo attachInfo = mAttachInfo;
10716         if (attachInfo != null) {
10717             return attachInfo.mHandler.post(action);
10718         }
10719         // Assume that post will succeed later
10720         ViewRootImpl.getRunQueue().post(action);
10721         return true;
10722     }
10723 
10724     /**
10725      * <p>Causes the Runnable to be added to the message queue, to be run
10726      * after the specified amount of time elapses.
10727      * The runnable will be run on the user interface thread.</p>
10728      *
10729      * @param action The Runnable that will be executed.
10730      * @param delayMillis The delay (in milliseconds) until the Runnable
10731      *        will be executed.
10732      *
10733      * @return true if the Runnable was successfully placed in to the
10734      *         message queue.  Returns false on failure, usually because the
10735      *         looper processing the message queue is exiting.  Note that a
10736      *         result of true does not mean the Runnable will be processed --
10737      *         if the looper is quit before the delivery time of the message
10738      *         occurs then the message will be dropped.
10739      *
10740      * @see #post
10741      * @see #removeCallbacks
10742      */
10743     public boolean postDelayed(Runnable action, long delayMillis) {
10744         final AttachInfo attachInfo = mAttachInfo;
10745         if (attachInfo != null) {
10746             return attachInfo.mHandler.postDelayed(action, delayMillis);
10747         }
10748         // Assume that post will succeed later
10749         ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10750         return true;
10751     }
10752 
10753     /**
10754      * <p>Causes the Runnable to execute on the next animation time step.
10755      * The runnable will be run on the user interface thread.</p>
10756      *
10757      * @param action The Runnable that will be executed.
10758      *
10759      * @see #postOnAnimationDelayed
10760      * @see #removeCallbacks
10761      */
10762     public void postOnAnimation(Runnable action) {
10763         final AttachInfo attachInfo = mAttachInfo;
10764         if (attachInfo != null) {
10765             attachInfo.mViewRootImpl.mChoreographer.postCallback(
10766                     Choreographer.CALLBACK_ANIMATION, action, null);
10767         } else {
10768             // Assume that post will succeed later
10769             ViewRootImpl.getRunQueue().post(action);
10770         }
10771     }
10772 
10773     /**
10774      * <p>Causes the Runnable to execute on the next animation time step,
10775      * after the specified amount of time elapses.
10776      * The runnable will be run on the user interface thread.</p>
10777      *
10778      * @param action The Runnable that will be executed.
10779      * @param delayMillis The delay (in milliseconds) until the Runnable
10780      *        will be executed.
10781      *
10782      * @see #postOnAnimation
10783      * @see #removeCallbacks
10784      */
10785     public void postOnAnimationDelayed(Runnable action, long delayMillis) {
10786         final AttachInfo attachInfo = mAttachInfo;
10787         if (attachInfo != null) {
10788             attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
10789                     Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
10790         } else {
10791             // Assume that post will succeed later
10792             ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10793         }
10794     }
10795 
10796     /**
10797      * <p>Removes the specified Runnable from the message queue.</p>
10798      *
10799      * @param action The Runnable to remove from the message handling queue
10800      *
10801      * @return true if this view could ask the Handler to remove the Runnable,
10802      *         false otherwise. When the returned value is true, the Runnable
10803      *         may or may not have been actually removed from the message queue
10804      *         (for instance, if the Runnable was not in the queue already.)
10805      *
10806      * @see #post
10807      * @see #postDelayed
10808      * @see #postOnAnimation
10809      * @see #postOnAnimationDelayed
10810      */
10811     public boolean removeCallbacks(Runnable action) {
10812         if (action != null) {
10813             final AttachInfo attachInfo = mAttachInfo;
10814             if (attachInfo != null) {
10815                 attachInfo.mHandler.removeCallbacks(action);
10816                 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
10817                         Choreographer.CALLBACK_ANIMATION, action, null);
10818             } else {
10819                 // Assume that post will succeed later
10820                 ViewRootImpl.getRunQueue().removeCallbacks(action);
10821             }
10822         }
10823         return true;
10824     }
10825 
10826     /**
10827      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
10828      * Use this to invalidate the View from a non-UI thread.</p>
10829      *
10830      * <p>This method can be invoked from outside of the UI thread
10831      * only when this View is attached to a window.</p>
10832      *
10833      * @see #invalidate()
10834      * @see #postInvalidateDelayed(long)
10835      */
10836     public void postInvalidate() {
10837         postInvalidateDelayed(0);
10838     }
10839 
10840     /**
10841      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10842      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
10843      *
10844      * <p>This method can be invoked from outside of the UI thread
10845      * only when this View is attached to a window.</p>
10846      *
10847      * @param left The left coordinate of the rectangle to invalidate.
10848      * @param top The top coordinate of the rectangle to invalidate.
10849      * @param right The right coordinate of the rectangle to invalidate.
10850      * @param bottom The bottom coordinate of the rectangle to invalidate.
10851      *
10852      * @see #invalidate(int, int, int, int)
10853      * @see #invalidate(Rect)
10854      * @see #postInvalidateDelayed(long, int, int, int, int)
10855      */
10856     public void postInvalidate(int left, int top, int right, int bottom) {
10857         postInvalidateDelayed(0, left, top, right, bottom);
10858     }
10859 
10860     /**
10861      * <p>Cause an invalidate to happen on a subsequent cycle through the event
10862      * loop. Waits for the specified amount of time.</p>
10863      *
10864      * <p>This method can be invoked from outside of the UI thread
10865      * only when this View is attached to a window.</p>
10866      *
10867      * @param delayMilliseconds the duration in milliseconds to delay the
10868      *         invalidation by
10869      *
10870      * @see #invalidate()
10871      * @see #postInvalidate()
10872      */
10873     public void postInvalidateDelayed(long delayMilliseconds) {
10874         // We try only with the AttachInfo because there's no point in invalidating
10875         // if we are not attached to our window
10876         final AttachInfo attachInfo = mAttachInfo;
10877         if (attachInfo != null) {
10878             attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
10879         }
10880     }
10881 
10882     /**
10883      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10884      * through the event loop. Waits for the specified amount of time.</p>
10885      *
10886      * <p>This method can be invoked from outside of the UI thread
10887      * only when this View is attached to a window.</p>
10888      *
10889      * @param delayMilliseconds the duration in milliseconds to delay the
10890      *         invalidation by
10891      * @param left The left coordinate of the rectangle to invalidate.
10892      * @param top The top coordinate of the rectangle to invalidate.
10893      * @param right The right coordinate of the rectangle to invalidate.
10894      * @param bottom The bottom coordinate of the rectangle to invalidate.
10895      *
10896      * @see #invalidate(int, int, int, int)
10897      * @see #invalidate(Rect)
10898      * @see #postInvalidate(int, int, int, int)
10899      */
10900     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
10901             int right, int bottom) {
10902 
10903         // We try only with the AttachInfo because there's no point in invalidating
10904         // if we are not attached to our window
10905         final AttachInfo attachInfo = mAttachInfo;
10906         if (attachInfo != null) {
10907             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
10908             info.target = this;
10909             info.left = left;
10910             info.top = top;
10911             info.right = right;
10912             info.bottom = bottom;
10913 
10914             attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
10915         }
10916     }
10917 
10918     /**
10919      * <p>Cause an invalidate to happen on the next animation time step, typically the
10920      * next display frame.</p>
10921      *
10922      * <p>This method can be invoked from outside of the UI thread
10923      * only when this View is attached to a window.</p>
10924      *
10925      * @see #invalidate()
10926      */
10927     public void postInvalidateOnAnimation() {
10928         // We try only with the AttachInfo because there's no point in invalidating
10929         // if we are not attached to our window
10930         final AttachInfo attachInfo = mAttachInfo;
10931         if (attachInfo != null) {
10932             attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
10933         }
10934     }
10935 
10936     /**
10937      * <p>Cause an invalidate of the specified area to happen on the next animation
10938      * time step, typically the next display frame.</p>
10939      *
10940      * <p>This method can be invoked from outside of the UI thread
10941      * only when this View is attached to a window.</p>
10942      *
10943      * @param left The left coordinate of the rectangle to invalidate.
10944      * @param top The top coordinate of the rectangle to invalidate.
10945      * @param right The right coordinate of the rectangle to invalidate.
10946      * @param bottom The bottom coordinate of the rectangle to invalidate.
10947      *
10948      * @see #invalidate(int, int, int, int)
10949      * @see #invalidate(Rect)
10950      */
10951     public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
10952         // We try only with the AttachInfo because there's no point in invalidating
10953         // if we are not attached to our window
10954         final AttachInfo attachInfo = mAttachInfo;
10955         if (attachInfo != null) {
10956             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
10957             info.target = this;
10958             info.left = left;
10959             info.top = top;
10960             info.right = right;
10961             info.bottom = bottom;
10962 
10963             attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
10964         }
10965     }
10966 
10967     /**
10968      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
10969      * This event is sent at most once every
10970      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
10971      */
10972     private void postSendViewScrolledAccessibilityEventCallback() {
10973         if (mSendViewScrolledAccessibilityEvent == null) {
10974             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
10975         }
10976         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
10977             mSendViewScrolledAccessibilityEvent.mIsPending = true;
10978             postDelayed(mSendViewScrolledAccessibilityEvent,
10979                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
10980         }
10981     }
10982 
10983     /**
10984      * Called by a parent to request that a child update its values for mScrollX
10985      * and mScrollY if necessary. This will typically be done if the child is
10986      * animating a scroll using a {@link android.widget.Scroller Scroller}
10987      * object.
10988      */
10989     public void computeScroll() {
10990     }
10991 
10992     /**
10993      * <p>Indicate whether the horizontal edges are faded when the view is
10994      * scrolled horizontally.</p>
10995      *
10996      * @return true if the horizontal edges should are faded on scroll, false
10997      *         otherwise
10998      *
10999      * @see #setHorizontalFadingEdgeEnabled(boolean)
11000      *
11001      * @attr ref android.R.styleable#View_requiresFadingEdge
11002      */
11003     public boolean isHorizontalFadingEdgeEnabled() {
11004         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
11005     }
11006 
11007     /**
11008      * <p>Define whether the horizontal edges should be faded when this view
11009      * is scrolled horizontally.</p>
11010      *
11011      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
11012      *                                    be faded when the view is scrolled
11013      *                                    horizontally
11014      *
11015      * @see #isHorizontalFadingEdgeEnabled()
11016      *
11017      * @attr ref android.R.styleable#View_requiresFadingEdge
11018      */
11019     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
11020         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
11021             if (horizontalFadingEdgeEnabled) {
11022                 initScrollCache();
11023             }
11024 
11025             mViewFlags ^= FADING_EDGE_HORIZONTAL;
11026         }
11027     }
11028 
11029     /**
11030      * <p>Indicate whether the vertical edges are faded when the view is
11031      * scrolled horizontally.</p>
11032      *
11033      * @return true if the vertical edges should are faded on scroll, false
11034      *         otherwise
11035      *
11036      * @see #setVerticalFadingEdgeEnabled(boolean)
11037      *
11038      * @attr ref android.R.styleable#View_requiresFadingEdge
11039      */
11040     public boolean isVerticalFadingEdgeEnabled() {
11041         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
11042     }
11043 
11044     /**
11045      * <p>Define whether the vertical edges should be faded when this view
11046      * is scrolled vertically.</p>
11047      *
11048      * @param verticalFadingEdgeEnabled true if the vertical edges should
11049      *                                  be faded when the view is scrolled
11050      *                                  vertically
11051      *
11052      * @see #isVerticalFadingEdgeEnabled()
11053      *
11054      * @attr ref android.R.styleable#View_requiresFadingEdge
11055      */
11056     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
11057         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
11058             if (verticalFadingEdgeEnabled) {
11059                 initScrollCache();
11060             }
11061 
11062             mViewFlags ^= FADING_EDGE_VERTICAL;
11063         }
11064     }
11065 
11066     /**
11067      * Returns the strength, or intensity, of the top faded edge. The strength is
11068      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
11069      * returns 0.0 or 1.0 but no value in between.
11070      *
11071      * Subclasses should override this method to provide a smoother fade transition
11072      * when scrolling occurs.
11073      *
11074      * @return the intensity of the top fade as a float between 0.0f and 1.0f
11075      */
11076     protected float getTopFadingEdgeStrength() {
11077         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
11078     }
11079 
11080     /**
11081      * Returns the strength, or intensity, of the bottom faded edge. The strength is
11082      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
11083      * returns 0.0 or 1.0 but no value in between.
11084      *
11085      * Subclasses should override this method to provide a smoother fade transition
11086      * when scrolling occurs.
11087      *
11088      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
11089      */
11090     protected float getBottomFadingEdgeStrength() {
11091         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
11092                 computeVerticalScrollRange() ? 1.0f : 0.0f;
11093     }
11094 
11095     /**
11096      * Returns the strength, or intensity, of the left faded edge. The strength is
11097      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
11098      * returns 0.0 or 1.0 but no value in between.
11099      *
11100      * Subclasses should override this method to provide a smoother fade transition
11101      * when scrolling occurs.
11102      *
11103      * @return the intensity of the left fade as a float between 0.0f and 1.0f
11104      */
11105     protected float getLeftFadingEdgeStrength() {
11106         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
11107     }
11108 
11109     /**
11110      * Returns the strength, or intensity, of the right faded edge. The strength is
11111      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
11112      * returns 0.0 or 1.0 but no value in between.
11113      *
11114      * Subclasses should override this method to provide a smoother fade transition
11115      * when scrolling occurs.
11116      *
11117      * @return the intensity of the right fade as a float between 0.0f and 1.0f
11118      */
11119     protected float getRightFadingEdgeStrength() {
11120         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
11121                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
11122     }
11123 
11124     /**
11125      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
11126      * scrollbar is not drawn by default.</p>
11127      *
11128      * @return true if the horizontal scrollbar should be painted, false
11129      *         otherwise
11130      *
11131      * @see #setHorizontalScrollBarEnabled(boolean)
11132      */
11133     public boolean isHorizontalScrollBarEnabled() {
11134         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
11135     }
11136 
11137     /**
11138      * <p>Define whether the horizontal scrollbar should be drawn or not. The
11139      * scrollbar is not drawn by default.</p>
11140      *
11141      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
11142      *                                   be painted
11143      *
11144      * @see #isHorizontalScrollBarEnabled()
11145      */
11146     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
11147         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
11148             mViewFlags ^= SCROLLBARS_HORIZONTAL;
11149             computeOpaqueFlags();
11150             resolvePadding();
11151         }
11152     }
11153 
11154     /**
11155      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
11156      * scrollbar is not drawn by default.</p>
11157      *
11158      * @return true if the vertical scrollbar should be painted, false
11159      *         otherwise
11160      *
11161      * @see #setVerticalScrollBarEnabled(boolean)
11162      */
11163     public boolean isVerticalScrollBarEnabled() {
11164         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
11165     }
11166 
11167     /**
11168      * <p>Define whether the vertical scrollbar should be drawn or not. The
11169      * scrollbar is not drawn by default.</p>
11170      *
11171      * @param verticalScrollBarEnabled true if the vertical scrollbar should
11172      *                                 be painted
11173      *
11174      * @see #isVerticalScrollBarEnabled()
11175      */
11176     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
11177         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
11178             mViewFlags ^= SCROLLBARS_VERTICAL;
11179             computeOpaqueFlags();
11180             resolvePadding();
11181         }
11182     }
11183 
11184     /**
11185      * @hide
11186      */
11187     protected void recomputePadding() {
11188         internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
11189     }
11190 
11191     /**
11192      * Define whether scrollbars will fade when the view is not scrolling.
11193      *
11194      * @param fadeScrollbars wheter to enable fading
11195      *
11196      * @attr ref android.R.styleable#View_fadeScrollbars
11197      */
11198     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
11199         initScrollCache();
11200         final ScrollabilityCache scrollabilityCache = mScrollCache;
11201         scrollabilityCache.fadeScrollBars = fadeScrollbars;
11202         if (fadeScrollbars) {
11203             scrollabilityCache.state = ScrollabilityCache.OFF;
11204         } else {
11205             scrollabilityCache.state = ScrollabilityCache.ON;
11206         }
11207     }
11208 
11209     /**
11210      *
11211      * Returns true if scrollbars will fade when this view is not scrolling
11212      *
11213      * @return true if scrollbar fading is enabled
11214      *
11215      * @attr ref android.R.styleable#View_fadeScrollbars
11216      */
11217     public boolean isScrollbarFadingEnabled() {
11218         return mScrollCache != null && mScrollCache.fadeScrollBars;
11219     }
11220 
11221     /**
11222      *
11223      * Returns the delay before scrollbars fade.
11224      *
11225      * @return the delay before scrollbars fade
11226      *
11227      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
11228      */
11229     public int getScrollBarDefaultDelayBeforeFade() {
11230         return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
11231                 mScrollCache.scrollBarDefaultDelayBeforeFade;
11232     }
11233 
11234     /**
11235      * Define the delay before scrollbars fade.
11236      *
11237      * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
11238      *
11239      * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
11240      */
11241     public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
11242         getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
11243     }
11244 
11245     /**
11246      *
11247      * Returns the scrollbar fade duration.
11248      *
11249      * @return the scrollbar fade duration
11250      *
11251      * @attr ref android.R.styleable#View_scrollbarFadeDuration
11252      */
11253     public int getScrollBarFadeDuration() {
11254         return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
11255                 mScrollCache.scrollBarFadeDuration;
11256     }
11257 
11258     /**
11259      * Define the scrollbar fade duration.
11260      *
11261      * @param scrollBarFadeDuration - the scrollbar fade duration
11262      *
11263      * @attr ref android.R.styleable#View_scrollbarFadeDuration
11264      */
11265     public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
11266         getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
11267     }
11268 
11269     /**
11270      *
11271      * Returns the scrollbar size.
11272      *
11273      * @return the scrollbar size
11274      *
11275      * @attr ref android.R.styleable#View_scrollbarSize
11276      */
11277     public int getScrollBarSize() {
11278         return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
11279                 mScrollCache.scrollBarSize;
11280     }
11281 
11282     /**
11283      * Define the scrollbar size.
11284      *
11285      * @param scrollBarSize - the scrollbar size
11286      *
11287      * @attr ref android.R.styleable#View_scrollbarSize
11288      */
11289     public void setScrollBarSize(int scrollBarSize) {
11290         getScrollCache().scrollBarSize = scrollBarSize;
11291     }
11292 
11293     /**
11294      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
11295      * inset. When inset, they add to the padding of the view. And the scrollbars
11296      * can be drawn inside the padding area or on the edge of the view. For example,
11297      * if a view has a background drawable and you want to draw the scrollbars
11298      * inside the padding specified by the drawable, you can use
11299      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
11300      * appear at the edge of the view, ignoring the padding, then you can use
11301      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
11302      * @param style the style of the scrollbars. Should be one of
11303      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
11304      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
11305      * @see #SCROLLBARS_INSIDE_OVERLAY
11306      * @see #SCROLLBARS_INSIDE_INSET
11307      * @see #SCROLLBARS_OUTSIDE_OVERLAY
11308      * @see #SCROLLBARS_OUTSIDE_INSET
11309      *
11310      * @attr ref android.R.styleable#View_scrollbarStyle
11311      */
11312     public void setScrollBarStyle(int style) {
11313         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
11314             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
11315             computeOpaqueFlags();
11316             resolvePadding();
11317         }
11318     }
11319 
11320     /**
11321      * <p>Returns the current scrollbar style.</p>
11322      * @return the current scrollbar style
11323      * @see #SCROLLBARS_INSIDE_OVERLAY
11324      * @see #SCROLLBARS_INSIDE_INSET
11325      * @see #SCROLLBARS_OUTSIDE_OVERLAY
11326      * @see #SCROLLBARS_OUTSIDE_INSET
11327      *
11328      * @attr ref android.R.styleable#View_scrollbarStyle
11329      */
11330     @ViewDebug.ExportedProperty(mapping = {
11331             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
11332             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
11333             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
11334             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
11335     })
11336     public int getScrollBarStyle() {
11337         return mViewFlags & SCROLLBARS_STYLE_MASK;
11338     }
11339 
11340     /**
11341      * <p>Compute the horizontal range that the horizontal scrollbar
11342      * represents.</p>
11343      *
11344      * <p>The range is expressed in arbitrary units that must be the same as the
11345      * units used by {@link #computeHorizontalScrollExtent()} and
11346      * {@link #computeHorizontalScrollOffset()}.</p>
11347      *
11348      * <p>The default range is the drawing width of this view.</p>
11349      *
11350      * @return the total horizontal range represented by the horizontal
11351      *         scrollbar
11352      *
11353      * @see #computeHorizontalScrollExtent()
11354      * @see #computeHorizontalScrollOffset()
11355      * @see android.widget.ScrollBarDrawable
11356      */
11357     protected int computeHorizontalScrollRange() {
11358         return getWidth();
11359     }
11360 
11361     /**
11362      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
11363      * within the horizontal range. This value is used to compute the position
11364      * of the thumb within the scrollbar's track.</p>
11365      *
11366      * <p>The range is expressed in arbitrary units that must be the same as the
11367      * units used by {@link #computeHorizontalScrollRange()} and
11368      * {@link #computeHorizontalScrollExtent()}.</p>
11369      *
11370      * <p>The default offset is the scroll offset of this view.</p>
11371      *
11372      * @return the horizontal offset of the scrollbar's thumb
11373      *
11374      * @see #computeHorizontalScrollRange()
11375      * @see #computeHorizontalScrollExtent()
11376      * @see android.widget.ScrollBarDrawable
11377      */
11378     protected int computeHorizontalScrollOffset() {
11379         return mScrollX;
11380     }
11381 
11382     /**
11383      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
11384      * within the horizontal range. This value is used to compute the length
11385      * of the thumb within the scrollbar's track.</p>
11386      *
11387      * <p>The range is expressed in arbitrary units that must be the same as the
11388      * units used by {@link #computeHorizontalScrollRange()} and
11389      * {@link #computeHorizontalScrollOffset()}.</p>
11390      *
11391      * <p>The default extent is the drawing width of this view.</p>
11392      *
11393      * @return the horizontal extent of the scrollbar's thumb
11394      *
11395      * @see #computeHorizontalScrollRange()
11396      * @see #computeHorizontalScrollOffset()
11397      * @see android.widget.ScrollBarDrawable
11398      */
11399     protected int computeHorizontalScrollExtent() {
11400         return getWidth();
11401     }
11402 
11403     /**
11404      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
11405      *
11406      * <p>The range is expressed in arbitrary units that must be the same as the
11407      * units used by {@link #computeVerticalScrollExtent()} and
11408      * {@link #computeVerticalScrollOffset()}.</p>
11409      *
11410      * @return the total vertical range represented by the vertical scrollbar
11411      *
11412      * <p>The default range is the drawing height of this view.</p>
11413      *
11414      * @see #computeVerticalScrollExtent()
11415      * @see #computeVerticalScrollOffset()
11416      * @see android.widget.ScrollBarDrawable
11417      */
11418     protected int computeVerticalScrollRange() {
11419         return getHeight();
11420     }
11421 
11422     /**
11423      * <p>Compute the vertical offset of the vertical scrollbar's thumb
11424      * within the horizontal range. This value is used to compute the position
11425      * of the thumb within the scrollbar's track.</p>
11426      *
11427      * <p>The range is expressed in arbitrary units that must be the same as the
11428      * units used by {@link #computeVerticalScrollRange()} and
11429      * {@link #computeVerticalScrollExtent()}.</p>
11430      *
11431      * <p>The default offset is the scroll offset of this view.</p>
11432      *
11433      * @return the vertical offset of the scrollbar's thumb
11434      *
11435      * @see #computeVerticalScrollRange()
11436      * @see #computeVerticalScrollExtent()
11437      * @see android.widget.ScrollBarDrawable
11438      */
11439     protected int computeVerticalScrollOffset() {
11440         return mScrollY;
11441     }
11442 
11443     /**
11444      * <p>Compute the vertical extent of the horizontal scrollbar's thumb
11445      * within the vertical range. This value is used to compute the length
11446      * of the thumb within the scrollbar's track.</p>
11447      *
11448      * <p>The range is expressed in arbitrary units that must be the same as the
11449      * units used by {@link #computeVerticalScrollRange()} and
11450      * {@link #computeVerticalScrollOffset()}.</p>
11451      *
11452      * <p>The default extent is the drawing height of this view.</p>
11453      *
11454      * @return the vertical extent of the scrollbar's thumb
11455      *
11456      * @see #computeVerticalScrollRange()
11457      * @see #computeVerticalScrollOffset()
11458      * @see android.widget.ScrollBarDrawable
11459      */
11460     protected int computeVerticalScrollExtent() {
11461         return getHeight();
11462     }
11463 
11464     /**
11465      * Check if this view can be scrolled horizontally in a certain direction.
11466      *
11467      * @param direction Negative to check scrolling left, positive to check scrolling right.
11468      * @return true if this view can be scrolled in the specified direction, false otherwise.
11469      */
11470     public boolean canScrollHorizontally(int direction) {
11471         final int offset = computeHorizontalScrollOffset();
11472         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
11473         if (range == 0) return false;
11474         if (direction < 0) {
11475             return offset > 0;
11476         } else {
11477             return offset < range - 1;
11478         }
11479     }
11480 
11481     /**
11482      * Check if this view can be scrolled vertically in a certain direction.
11483      *
11484      * @param direction Negative to check scrolling up, positive to check scrolling down.
11485      * @return true if this view can be scrolled in the specified direction, false otherwise.
11486      */
11487     public boolean canScrollVertically(int direction) {
11488         final int offset = computeVerticalScrollOffset();
11489         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
11490         if (range == 0) return false;
11491         if (direction < 0) {
11492             return offset > 0;
11493         } else {
11494             return offset < range - 1;
11495         }
11496     }
11497 
11498     /**
11499      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
11500      * scrollbars are painted only if they have been awakened first.</p>
11501      *
11502      * @param canvas the canvas on which to draw the scrollbars
11503      *
11504      * @see #awakenScrollBars(int)
11505      */
11506     protected final void onDrawScrollBars(Canvas canvas) {
11507         // scrollbars are drawn only when the animation is running
11508         final ScrollabilityCache cache = mScrollCache;
11509         if (cache != null) {
11510 
11511             int state = cache.state;
11512 
11513             if (state == ScrollabilityCache.OFF) {
11514                 return;
11515             }
11516 
11517             boolean invalidate = false;
11518 
11519             if (state == ScrollabilityCache.FADING) {
11520                 // We're fading -- get our fade interpolation
11521                 if (cache.interpolatorValues == null) {
11522                     cache.interpolatorValues = new float[1];
11523                 }
11524 
11525                 float[] values = cache.interpolatorValues;
11526 
11527                 // Stops the animation if we're done
11528                 if (cache.scrollBarInterpolator.timeToValues(values) ==
11529                         Interpolator.Result.FREEZE_END) {
11530                     cache.state = ScrollabilityCache.OFF;
11531                 } else {
11532                     cache.scrollBar.setAlpha(Math.round(values[0]));
11533                 }
11534 
11535                 // This will make the scroll bars inval themselves after
11536                 // drawing. We only want this when we're fading so that
11537                 // we prevent excessive redraws
11538                 invalidate = true;
11539             } else {
11540                 // We're just on -- but we may have been fading before so
11541                 // reset alpha
11542                 cache.scrollBar.setAlpha(255);
11543             }
11544 
11545 
11546             final int viewFlags = mViewFlags;
11547 
11548             final boolean drawHorizontalScrollBar =
11549                 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
11550             final boolean drawVerticalScrollBar =
11551                 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
11552                 && !isVerticalScrollBarHidden();
11553 
11554             if (drawVerticalScrollBar || drawHorizontalScrollBar) {
11555                 final int width = mRight - mLeft;
11556                 final int height = mBottom - mTop;
11557 
11558                 final ScrollBarDrawable scrollBar = cache.scrollBar;
11559 
11560                 final int scrollX = mScrollX;
11561                 final int scrollY = mScrollY;
11562                 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
11563 
11564                 int left;
11565                 int top;
11566                 int right;
11567                 int bottom;
11568 
11569                 if (drawHorizontalScrollBar) {
11570                     int size = scrollBar.getSize(false);
11571                     if (size <= 0) {
11572                         size = cache.scrollBarSize;
11573                     }
11574 
11575                     scrollBar.setParameters(computeHorizontalScrollRange(),
11576                                             computeHorizontalScrollOffset(),
11577                                             computeHorizontalScrollExtent(), false);
11578                     final int verticalScrollBarGap = drawVerticalScrollBar ?
11579                             getVerticalScrollbarWidth() : 0;
11580                     top = scrollY + height - size - (mUserPaddingBottom & inside);
11581                     left = scrollX + (mPaddingLeft & inside);
11582                     right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
11583                     bottom = top + size;
11584                     onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
11585                     if (invalidate) {
11586                         invalidate(left, top, right, bottom);
11587                     }
11588                 }
11589 
11590                 if (drawVerticalScrollBar) {
11591                     int size = scrollBar.getSize(true);
11592                     if (size <= 0) {
11593                         size = cache.scrollBarSize;
11594                     }
11595 
11596                     scrollBar.setParameters(computeVerticalScrollRange(),
11597                                             computeVerticalScrollOffset(),
11598                                             computeVerticalScrollExtent(), true);
11599                     int verticalScrollbarPosition = mVerticalScrollbarPosition;
11600                     if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
11601                         verticalScrollbarPosition = isLayoutRtl() ?
11602                                 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
11603                     }
11604                     switch (verticalScrollbarPosition) {
11605                         default:
11606                         case SCROLLBAR_POSITION_RIGHT:
11607                             left = scrollX + width - size - (mUserPaddingRight & inside);
11608                             break;
11609                         case SCROLLBAR_POSITION_LEFT:
11610                             left = scrollX + (mUserPaddingLeft & inside);
11611                             break;
11612                     }
11613                     top = scrollY + (mPaddingTop & inside);
11614                     right = left + size;
11615                     bottom = scrollY + height - (mUserPaddingBottom & inside);
11616                     onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
11617                     if (invalidate) {
11618                         invalidate(left, top, right, bottom);
11619                     }
11620                 }
11621             }
11622         }
11623     }
11624 
11625     /**
11626      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
11627      * FastScroller is visible.
11628      * @return whether to temporarily hide the vertical scrollbar
11629      * @hide
11630      */
11631     protected boolean isVerticalScrollBarHidden() {
11632         return false;
11633     }
11634 
11635     /**
11636      * <p>Draw the horizontal scrollbar if
11637      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
11638      *
11639      * @param canvas the canvas on which to draw the scrollbar
11640      * @param scrollBar the scrollbar's drawable
11641      *
11642      * @see #isHorizontalScrollBarEnabled()
11643      * @see #computeHorizontalScrollRange()
11644      * @see #computeHorizontalScrollExtent()
11645      * @see #computeHorizontalScrollOffset()
11646      * @see android.widget.ScrollBarDrawable
11647      * @hide
11648      */
11649     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
11650             int l, int t, int r, int b) {
11651         scrollBar.setBounds(l, t, r, b);
11652         scrollBar.draw(canvas);
11653     }
11654 
11655     /**
11656      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
11657      * returns true.</p>
11658      *
11659      * @param canvas the canvas on which to draw the scrollbar
11660      * @param scrollBar the scrollbar's drawable
11661      *
11662      * @see #isVerticalScrollBarEnabled()
11663      * @see #computeVerticalScrollRange()
11664      * @see #computeVerticalScrollExtent()
11665      * @see #computeVerticalScrollOffset()
11666      * @see android.widget.ScrollBarDrawable
11667      * @hide
11668      */
11669     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
11670             int l, int t, int r, int b) {
11671         scrollBar.setBounds(l, t, r, b);
11672         scrollBar.draw(canvas);
11673     }
11674 
11675     /**
11676      * Implement this to do your drawing.
11677      *
11678      * @param canvas the canvas on which the background will be drawn
11679      */
11680     protected void onDraw(Canvas canvas) {
11681     }
11682 
11683     /*
11684      * Caller is responsible for calling requestLayout if necessary.
11685      * (This allows addViewInLayout to not request a new layout.)
11686      */
11687     void assignParent(ViewParent parent) {
11688         if (mParent == null) {
11689             mParent = parent;
11690         } else if (parent == null) {
11691             mParent = null;
11692         } else {
11693             throw new RuntimeException("view " + this + " being added, but"
11694                     + " it already has a parent");
11695         }
11696     }
11697 
11698     /**
11699      * This is called when the view is attached to a window.  At this point it
11700      * has a Surface and will start drawing.  Note that this function is
11701      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
11702      * however it may be called any time before the first onDraw -- including
11703      * before or after {@link #onMeasure(int, int)}.
11704      *
11705      * @see #onDetachedFromWindow()
11706      */
11707     protected void onAttachedToWindow() {
11708         if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
11709             mParent.requestTransparentRegion(this);
11710         }
11711 
11712         if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
11713             initialAwakenScrollBars();
11714             mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
11715         }
11716 
11717         jumpDrawablesToCurrentState();
11718 
11719         clearAccessibilityFocus();
11720         if (isFocused()) {
11721             InputMethodManager imm = InputMethodManager.peekInstance();
11722             imm.focusIn(this);
11723         }
11724 
11725         if (mDisplayList != null) {
11726             mDisplayList.clearDirty();
11727         }
11728     }
11729 
11730     /**
11731      * Resolve all RTL related properties.
11732      *
11733      * @return true if resolution of RTL properties has been done
11734      *
11735      * @hide
11736      */
11737     public boolean resolveRtlPropertiesIfNeeded() {
11738         if (!needRtlPropertiesResolution()) return false;
11739 
11740         // Order is important here: LayoutDirection MUST be resolved first
11741         if (!isLayoutDirectionResolved()) {
11742             resolveLayoutDirection();
11743             resolveLayoutParams();
11744         }
11745         // ... then we can resolve the others properties depending on the resolved LayoutDirection.
11746         if (!isTextDirectionResolved()) {
11747             resolveTextDirection();
11748         }
11749         if (!isTextAlignmentResolved()) {
11750             resolveTextAlignment();
11751         }
11752         if (!isPaddingResolved()) {
11753             resolvePadding();
11754         }
11755         if (!isDrawablesResolved()) {
11756             resolveDrawables();
11757         }
11758         onRtlPropertiesChanged(getLayoutDirection());
11759         return true;
11760     }
11761 
11762     /**
11763      * Reset resolution of all RTL related properties.
11764      *
11765      * @hide
11766      */
11767     public void resetRtlProperties() {
11768         resetResolvedLayoutDirection();
11769         resetResolvedTextDirection();
11770         resetResolvedTextAlignment();
11771         resetResolvedPadding();
11772         resetResolvedDrawables();
11773     }
11774 
11775     /**
11776      * @see #onScreenStateChanged(int)
11777      */
11778     void dispatchScreenStateChanged(int screenState) {
11779         onScreenStateChanged(screenState);
11780     }
11781 
11782     /**
11783      * This method is called whenever the state of the screen this view is
11784      * attached to changes. A state change will usually occurs when the screen
11785      * turns on or off (whether it happens automatically or the user does it
11786      * manually.)
11787      *
11788      * @param screenState The new state of the screen. Can be either
11789      *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
11790      */
11791     public void onScreenStateChanged(int screenState) {
11792     }
11793 
11794     /**
11795      * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
11796      */
11797     private boolean hasRtlSupport() {
11798         return mContext.getApplicationInfo().hasRtlSupport();
11799     }
11800 
11801     /**
11802      * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
11803      * RTL not supported)
11804      */
11805     private boolean isRtlCompatibilityMode() {
11806         final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
11807         return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
11808     }
11809 
11810     /**
11811      * @return true if RTL properties need resolution.
11812      *
11813      */
11814     private boolean needRtlPropertiesResolution() {
11815         return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
11816     }
11817 
11818     /**
11819      * Called when any RTL property (layout direction or text direction or text alignment) has
11820      * been changed.
11821      *
11822      * Subclasses need to override this method to take care of cached information that depends on the
11823      * resolved layout direction, or to inform child views that inherit their layout direction.
11824      *
11825      * The default implementation does nothing.
11826      *
11827      * @param layoutDirection the direction of the layout
11828      *
11829      * @see #LAYOUT_DIRECTION_LTR
11830      * @see #LAYOUT_DIRECTION_RTL
11831      */
11832     public void onRtlPropertiesChanged(int layoutDirection) {
11833     }
11834 
11835     /**
11836      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
11837      * that the parent directionality can and will be resolved before its children.
11838      *
11839      * @return true if resolution has been done, false otherwise.
11840      *
11841      * @hide
11842      */
11843     public boolean resolveLayoutDirection() {
11844         // Clear any previous layout direction resolution
11845         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
11846 
11847         if (hasRtlSupport()) {
11848             // Set resolved depending on layout direction
11849             switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
11850                     PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
11851                 case LAYOUT_DIRECTION_INHERIT:
11852                     // We cannot resolve yet. LTR is by default and let the resolution happen again
11853                     // later to get the correct resolved value
11854                     if (!canResolveLayoutDirection()) return false;
11855 
11856                     // Parent has not yet resolved, LTR is still the default
11857                     if (!mParent.isLayoutDirectionResolved()) return false;
11858 
11859                     if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
11860                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
11861                     }
11862                     break;
11863                 case LAYOUT_DIRECTION_RTL:
11864                     mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
11865                     break;
11866                 case LAYOUT_DIRECTION_LOCALE:
11867                     if((LAYOUT_DIRECTION_RTL ==
11868                             TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
11869                         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
11870                     }
11871                     break;
11872                 default:
11873                     // Nothing to do, LTR by default
11874             }
11875         }
11876 
11877         // Set to resolved
11878         mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
11879         return true;
11880     }
11881 
11882     /**
11883      * Check if layout direction resolution can be done.
11884      *
11885      * @return true if layout direction resolution can be done otherwise return false.
11886      *
11887      * @hide
11888      */
11889     public boolean canResolveLayoutDirection() {
11890         switch (getRawLayoutDirection()) {
11891             case LAYOUT_DIRECTION_INHERIT:
11892                 return (mParent != null) && mParent.canResolveLayoutDirection();
11893             default:
11894                 return true;
11895         }
11896     }
11897 
11898     /**
11899      * Reset the resolved layout direction. Layout direction will be resolved during a call to
11900      * {@link #onMeasure(int, int)}.
11901      *
11902      * @hide
11903      */
11904     public void resetResolvedLayoutDirection() {
11905         // Reset the current resolved bits
11906         mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
11907     }
11908 
11909     /**
11910      * @return true if the layout direction is inherited.
11911      *
11912      * @hide
11913      */
11914     public boolean isLayoutDirectionInherited() {
11915         return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
11916     }
11917 
11918     /**
11919      * @return true if layout direction has been resolved.
11920      * @hide
11921      */
11922     public boolean isLayoutDirectionResolved() {
11923         return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
11924     }
11925 
11926     /**
11927      * Return if padding has been resolved
11928      *
11929      * @hide
11930      */
11931     boolean isPaddingResolved() {
11932         return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
11933     }
11934 
11935     /**
11936      * Resolve padding depending on layout direction.
11937      *
11938      * @hide
11939      */
11940     public void resolvePadding() {
11941         if (!isRtlCompatibilityMode()) {
11942             // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
11943             // If start / end padding are defined, they will be resolved (hence overriding) to
11944             // left / right or right / left depending on the resolved layout direction.
11945             // If start / end padding are not defined, use the left / right ones.
11946             int resolvedLayoutDirection = getLayoutDirection();
11947             switch (resolvedLayoutDirection) {
11948                 case LAYOUT_DIRECTION_RTL:
11949                     if (mUserPaddingStart != UNDEFINED_PADDING) {
11950                         mUserPaddingRight = mUserPaddingStart;
11951                     } else {
11952                         mUserPaddingRight = mUserPaddingRightInitial;
11953                     }
11954                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
11955                         mUserPaddingLeft = mUserPaddingEnd;
11956                     } else {
11957                         mUserPaddingLeft = mUserPaddingLeftInitial;
11958                     }
11959                     break;
11960                 case LAYOUT_DIRECTION_LTR:
11961                 default:
11962                     if (mUserPaddingStart != UNDEFINED_PADDING) {
11963                         mUserPaddingLeft = mUserPaddingStart;
11964                     } else {
11965                         mUserPaddingLeft = mUserPaddingLeftInitial;
11966                     }
11967                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
11968                         mUserPaddingRight = mUserPaddingEnd;
11969                     } else {
11970                         mUserPaddingRight = mUserPaddingRightInitial;
11971                     }
11972             }
11973 
11974             mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11975 
11976             internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11977                     mUserPaddingBottom);
11978             onRtlPropertiesChanged(resolvedLayoutDirection);
11979         }
11980 
11981         mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
11982     }
11983 
11984     /**
11985      * Reset the resolved layout direction.
11986      *
11987      * @hide
11988      */
11989     public void resetResolvedPadding() {
11990         mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
11991     }
11992 
11993     /**
11994      * This is called when the view is detached from a window.  At this point it
11995      * no longer has a surface for drawing.
11996      *
11997      * @see #onAttachedToWindow()
11998      */
11999     protected void onDetachedFromWindow() {
12000         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
12001 
12002         removeUnsetPressCallback();
12003         removeLongPressCallback();
12004         removePerformClickCallback();
12005         removeSendViewScrolledAccessibilityEventCallback();
12006 
12007         destroyDrawingCache();
12008 
12009         destroyLayer(false);
12010 
12011         if (mAttachInfo != null) {
12012             if (mDisplayList != null) {
12013                 mDisplayList.markDirty();
12014                 mAttachInfo.mViewRootImpl.enqueueDisplayList(mDisplayList);
12015             }
12016             mAttachInfo.mViewRootImpl.cancelInvalidate(this);
12017         } else {
12018             // Should never happen
12019             clearDisplayList();
12020         }
12021 
12022         mCurrentAnimation = null;
12023 
12024         resetAccessibilityStateChanged();
12025     }
12026 
12027     /**
12028      * @return The number of times this view has been attached to a window
12029      */
12030     protected int getWindowAttachCount() {
12031         return mWindowAttachCount;
12032     }
12033 
12034     /**
12035      * Retrieve a unique token identifying the window this view is attached to.
12036      * @return Return the window's token for use in
12037      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
12038      */
12039     public IBinder getWindowToken() {
12040         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
12041     }
12042 
12043     /**
12044      * Retrieve the {@link WindowId} for the window this view is
12045      * currently attached to.
12046      */
12047     public WindowId getWindowId() {
12048         if (mAttachInfo == null) {
12049             return null;
12050         }
12051         if (mAttachInfo.mWindowId == null) {
12052             try {
12053                 mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
12054                         mAttachInfo.mWindowToken);
12055                 mAttachInfo.mWindowId = new WindowId(
12056                         mAttachInfo.mIWindowId);
12057             } catch (RemoteException e) {
12058             }
12059         }
12060         return mAttachInfo.mWindowId;
12061     }
12062 
12063     /**
12064      * Retrieve a unique token identifying the top-level "real" window of
12065      * the window that this view is attached to.  That is, this is like
12066      * {@link #getWindowToken}, except if the window this view in is a panel
12067      * window (attached to another containing window), then the token of
12068      * the containing window is returned instead.
12069      *
12070      * @return Returns the associated window token, either
12071      * {@link #getWindowToken()} or the containing window's token.
12072      */
12073     public IBinder getApplicationWindowToken() {
12074         AttachInfo ai = mAttachInfo;
12075         if (ai != null) {
12076             IBinder appWindowToken = ai.mPanelParentWindowToken;
12077             if (appWindowToken == null) {
12078                 appWindowToken = ai.mWindowToken;
12079             }
12080             return appWindowToken;
12081         }
12082         return null;
12083     }
12084 
12085     /**
12086      * Gets the logical display to which the view's window has been attached.
12087      *
12088      * @return The logical display, or null if the view is not currently attached to a window.
12089      */
12090     public Display getDisplay() {
12091         return mAttachInfo != null ? mAttachInfo.mDisplay : null;
12092     }
12093 
12094     /**
12095      * Retrieve private session object this view hierarchy is using to
12096      * communicate with the window manager.
12097      * @return the session object to communicate with the window manager
12098      */
12099     /*package*/ IWindowSession getWindowSession() {
12100         return mAttachInfo != null ? mAttachInfo.mSession : null;
12101     }
12102 
12103     /**
12104      * @param info the {@link android.view.View.AttachInfo} to associated with
12105      *        this view
12106      */
12107     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
12108         //System.out.println("Attached! " + this);
12109         mAttachInfo = info;
12110         if (mOverlay != null) {
12111             mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
12112         }
12113         mWindowAttachCount++;
12114         // We will need to evaluate the drawable state at least once.
12115         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
12116         if (mFloatingTreeObserver != null) {
12117             info.mTreeObserver.merge(mFloatingTreeObserver);
12118             mFloatingTreeObserver = null;
12119         }
12120         if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
12121             mAttachInfo.mScrollContainers.add(this);
12122             mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
12123         }
12124         performCollectViewAttributes(mAttachInfo, visibility);
12125         onAttachedToWindow();
12126 
12127         ListenerInfo li = mListenerInfo;
12128         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
12129                 li != null ? li.mOnAttachStateChangeListeners : null;
12130         if (listeners != null && listeners.size() > 0) {
12131             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
12132             // perform the dispatching. The iterator is a safe guard against listeners that
12133             // could mutate the list by calling the various add/remove methods. This prevents
12134             // the array from being modified while we iterate it.
12135             for (OnAttachStateChangeListener listener : listeners) {
12136                 listener.onViewAttachedToWindow(this);
12137             }
12138         }
12139 
12140         int vis = info.mWindowVisibility;
12141         if (vis != GONE) {
12142             onWindowVisibilityChanged(vis);
12143         }
12144         if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
12145             // If nobody has evaluated the drawable state yet, then do it now.
12146             refreshDrawableState();
12147         }
12148         needGlobalAttributesUpdate(false);
12149     }
12150 
12151     void dispatchDetachedFromWindow() {
12152         AttachInfo info = mAttachInfo;
12153         if (info != null) {
12154             int vis = info.mWindowVisibility;
12155             if (vis != GONE) {
12156                 onWindowVisibilityChanged(GONE);
12157             }
12158         }
12159 
12160         onDetachedFromWindow();
12161 
12162         ListenerInfo li = mListenerInfo;
12163         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
12164                 li != null ? li.mOnAttachStateChangeListeners : null;
12165         if (listeners != null && listeners.size() > 0) {
12166             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
12167             // perform the dispatching. The iterator is a safe guard against listeners that
12168             // could mutate the list by calling the various add/remove methods. This prevents
12169             // the array from being modified while we iterate it.
12170             for (OnAttachStateChangeListener listener : listeners) {
12171                 listener.onViewDetachedFromWindow(this);
12172             }
12173         }
12174 
12175         if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
12176             mAttachInfo.mScrollContainers.remove(this);
12177             mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
12178         }
12179 
12180         mAttachInfo = null;
12181         if (mOverlay != null) {
12182             mOverlay.getOverlayView().dispatchDetachedFromWindow();
12183         }
12184     }
12185 
12186     /**
12187      * Store this view hierarchy's frozen state into the given container.
12188      *
12189      * @param container The SparseArray in which to save the view's state.
12190      *
12191      * @see #restoreHierarchyState(android.util.SparseArray)
12192      * @see #dispatchSaveInstanceState(android.util.SparseArray)
12193      * @see #onSaveInstanceState()
12194      */
12195     public void saveHierarchyState(SparseArray<Parcelable> container) {
12196         dispatchSaveInstanceState(container);
12197     }
12198 
12199     /**
12200      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
12201      * this view and its children. May be overridden to modify how freezing happens to a
12202      * view's children; for example, some views may want to not store state for their children.
12203      *
12204      * @param container The SparseArray in which to save the view's state.
12205      *
12206      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
12207      * @see #saveHierarchyState(android.util.SparseArray)
12208      * @see #onSaveInstanceState()
12209      */
12210     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
12211         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
12212             mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
12213             Parcelable state = onSaveInstanceState();
12214             if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
12215                 throw new IllegalStateException(
12216                         "Derived class did not call super.onSaveInstanceState()");
12217             }
12218             if (state != null) {
12219                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
12220                 // + ": " + state);
12221                 container.put(mID, state);
12222             }
12223         }
12224     }
12225 
12226     /**
12227      * Hook allowing a view to generate a representation of its internal state
12228      * that can later be used to create a new instance with that same state.
12229      * This state should only contain information that is not persistent or can
12230      * not be reconstructed later. For example, you will never store your
12231      * current position on screen because that will be computed again when a
12232      * new instance of the view is placed in its view hierarchy.
12233      * <p>
12234      * Some examples of things you may store here: the current cursor position
12235      * in a text view (but usually not the text itself since that is stored in a
12236      * content provider or other persistent storage), the currently selected
12237      * item in a list view.
12238      *
12239      * @return Returns a Parcelable object containing the view's current dynamic
12240      *         state, or null if there is nothing interesting to save. The
12241      *         default implementation returns null.
12242      * @see #onRestoreInstanceState(android.os.Parcelable)
12243      * @see #saveHierarchyState(android.util.SparseArray)
12244      * @see #dispatchSaveInstanceState(android.util.SparseArray)
12245      * @see #setSaveEnabled(boolean)
12246      */
12247     protected Parcelable onSaveInstanceState() {
12248         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
12249         return BaseSavedState.EMPTY_STATE;
12250     }
12251 
12252     /**
12253      * Restore this view hierarchy's frozen state from the given container.
12254      *
12255      * @param container The SparseArray which holds previously frozen states.
12256      *
12257      * @see #saveHierarchyState(android.util.SparseArray)
12258      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
12259      * @see #onRestoreInstanceState(android.os.Parcelable)
12260      */
12261     public void restoreHierarchyState(SparseArray<Parcelable> container) {
12262         dispatchRestoreInstanceState(container);
12263     }
12264 
12265     /**
12266      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
12267      * state for this view and its children. May be overridden to modify how restoring
12268      * happens to a view's children; for example, some views may want to not store state
12269      * for their children.
12270      *
12271      * @param container The SparseArray which holds previously saved state.
12272      *
12273      * @see #dispatchSaveInstanceState(android.util.SparseArray)
12274      * @see #restoreHierarchyState(android.util.SparseArray)
12275      * @see #onRestoreInstanceState(android.os.Parcelable)
12276      */
12277     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
12278         if (mID != NO_ID) {
12279             Parcelable state = container.get(mID);
12280             if (state != null) {
12281                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
12282                 // + ": " + state);
12283                 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
12284                 onRestoreInstanceState(state);
12285                 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
12286                     throw new IllegalStateException(
12287                             "Derived class did not call super.onRestoreInstanceState()");
12288                 }
12289             }
12290         }
12291     }
12292 
12293     /**
12294      * Hook allowing a view to re-apply a representation of its internal state that had previously
12295      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
12296      * null state.
12297      *
12298      * @param state The frozen state that had previously been returned by
12299      *        {@link #onSaveInstanceState}.
12300      *
12301      * @see #onSaveInstanceState()
12302      * @see #restoreHierarchyState(android.util.SparseArray)
12303      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
12304      */
12305     protected void onRestoreInstanceState(Parcelable state) {
12306         mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
12307         if (state != BaseSavedState.EMPTY_STATE && state != null) {
12308             throw new IllegalArgumentException("Wrong state class, expecting View State but "
12309                     + "received " + state.getClass().toString() + " instead. This usually happens "
12310                     + "when two views of different type have the same id in the same hierarchy. "
12311                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
12312                     + "other views do not use the same id.");
12313         }
12314     }
12315 
12316     /**
12317      * <p>Return the time at which the drawing of the view hierarchy started.</p>
12318      *
12319      * @return the drawing start time in milliseconds
12320      */
12321     public long getDrawingTime() {
12322         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
12323     }
12324 
12325     /**
12326      * <p>Enables or disables the duplication of the parent's state into this view. When
12327      * duplication is enabled, this view gets its drawable state from its parent rather
12328      * than from its own internal properties.</p>
12329      *
12330      * <p>Note: in the current implementation, setting this property to true after the
12331      * view was added to a ViewGroup might have no effect at all. This property should
12332      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
12333      *
12334      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
12335      * property is enabled, an exception will be thrown.</p>
12336      *
12337      * <p>Note: if the child view uses and updates additionnal states which are unknown to the
12338      * parent, these states should not be affected by this method.</p>
12339      *
12340      * @param enabled True to enable duplication of the parent's drawable state, false
12341      *                to disable it.
12342      *
12343      * @see #getDrawableState()
12344      * @see #isDuplicateParentStateEnabled()
12345      */
12346     public void setDuplicateParentStateEnabled(boolean enabled) {
12347         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
12348     }
12349 
12350     /**
12351      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
12352      *
12353      * @return True if this view's drawable state is duplicated from the parent,
12354      *         false otherwise
12355      *
12356      * @see #getDrawableState()
12357      * @see #setDuplicateParentStateEnabled(boolean)
12358      */
12359     public boolean isDuplicateParentStateEnabled() {
12360         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
12361     }
12362 
12363     /**
12364      * <p>Specifies the type of layer backing this view. The layer can be
12365      * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
12366      * {@link #LAYER_TYPE_HARDWARE}.</p>
12367      *
12368      * <p>A layer is associated with an optional {@link android.graphics.Paint}
12369      * instance that controls how the layer is composed on screen. The following
12370      * properties of the paint are taken into account when composing the layer:</p>
12371      * <ul>
12372      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
12373      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
12374      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
12375      * </ul>
12376      *
12377      * <p>If this view has an alpha value set to < 1.0 by calling
12378      * {@link #setAlpha(float)}, the alpha value of the layer's paint is superceded
12379      * by this view's alpha value.</p>
12380      *
12381      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
12382      * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
12383      * for more information on when and how to use layers.</p>
12384      *
12385      * @param layerType The type of layer to use with this view, must be one of
12386      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
12387      *        {@link #LAYER_TYPE_HARDWARE}
12388      * @param paint The paint used to compose the layer. This argument is optional
12389      *        and can be null. It is ignored when the layer type is
12390      *        {@link #LAYER_TYPE_NONE}
12391      *
12392      * @see #getLayerType()
12393      * @see #LAYER_TYPE_NONE
12394      * @see #LAYER_TYPE_SOFTWARE
12395      * @see #LAYER_TYPE_HARDWARE
12396      * @see #setAlpha(float)
12397      *
12398      * @attr ref android.R.styleable#View_layerType
12399      */
12400     public void setLayerType(int layerType, Paint paint) {
12401         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
12402             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
12403                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
12404         }
12405 
12406         if (layerType == mLayerType) {
12407             if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
12408                 mLayerPaint = paint == null ? new Paint() : paint;
12409                 invalidateParentCaches();
12410                 invalidate(true);
12411             }
12412             return;
12413         }
12414 
12415         // Destroy any previous software drawing cache if needed
12416         switch (mLayerType) {
12417             case LAYER_TYPE_HARDWARE:
12418                 destroyLayer(false);
12419                 // fall through - non-accelerated views may use software layer mechanism instead
12420             case LAYER_TYPE_SOFTWARE:
12421                 destroyDrawingCache();
12422                 break;
12423             default:
12424                 break;
12425         }
12426 
12427         mLayerType = layerType;
12428         final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
12429         mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
12430         mLocalDirtyRect = layerDisabled ? null : new Rect();
12431 
12432         invalidateParentCaches();
12433         invalidate(true);
12434     }
12435 
12436     /**
12437      * Updates the {@link Paint} object used with the current layer (used only if the current
12438      * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
12439      * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
12440      * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
12441      * ensure that the view gets redrawn immediately.
12442      *
12443      * <p>A layer is associated with an optional {@link android.graphics.Paint}
12444      * instance that controls how the layer is composed on screen. The following
12445      * properties of the paint are taken into account when composing the layer:</p>
12446      * <ul>
12447      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
12448      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
12449      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
12450      * </ul>
12451      *
12452      * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
12453      * alpha value of the layer's paint is superceded by this view's alpha value.</p>
12454      *
12455      * @param paint The paint used to compose the layer. This argument is optional
12456      *        and can be null. It is ignored when the layer type is
12457      *        {@link #LAYER_TYPE_NONE}
12458      *
12459      * @see #setLayerType(int, android.graphics.Paint)
12460      */
12461     public void setLayerPaint(Paint paint) {
12462         int layerType = getLayerType();
12463         if (layerType != LAYER_TYPE_NONE) {
12464             mLayerPaint = paint == null ? new Paint() : paint;
12465             if (layerType == LAYER_TYPE_HARDWARE) {
12466                 HardwareLayer layer = getHardwareLayer();
12467                 if (layer != null) {
12468                     layer.setLayerPaint(paint);
12469                 }
12470                 invalidateViewProperty(false, false);
12471             } else {
12472                 invalidate();
12473             }
12474         }
12475     }
12476 
12477     /**
12478      * Indicates whether this view has a static layer. A view with layer type
12479      * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
12480      * dynamic.
12481      */
12482     boolean hasStaticLayer() {
12483         return true;
12484     }
12485 
12486     /**
12487      * Indicates what type of layer is currently associated with this view. By default
12488      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
12489      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
12490      * for more information on the different types of layers.
12491      *
12492      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
12493      *         {@link #LAYER_TYPE_HARDWARE}
12494      *
12495      * @see #setLayerType(int, android.graphics.Paint)
12496      * @see #buildLayer()
12497      * @see #LAYER_TYPE_NONE
12498      * @see #LAYER_TYPE_SOFTWARE
12499      * @see #LAYER_TYPE_HARDWARE
12500      */
12501     public int getLayerType() {
12502         return mLayerType;
12503     }
12504 
12505     /**
12506      * Forces this view's layer to be created and this view to be rendered
12507      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
12508      * invoking this method will have no effect.
12509      *
12510      * This method can for instance be used to render a view into its layer before
12511      * starting an animation. If this view is complex, rendering into the layer
12512      * before starting the animation will avoid skipping frames.
12513      *
12514      * @throws IllegalStateException If this view is not attached to a window
12515      *
12516      * @see #setLayerType(int, android.graphics.Paint)
12517      */
12518     public void buildLayer() {
12519         if (mLayerType == LAYER_TYPE_NONE) return;
12520 
12521         if (mAttachInfo == null) {
12522             throw new IllegalStateException("This view must be attached to a window first");
12523         }
12524 
12525         switch (mLayerType) {
12526             case LAYER_TYPE_HARDWARE:
12527                 if (mAttachInfo.mHardwareRenderer != null &&
12528                         mAttachInfo.mHardwareRenderer.isEnabled() &&
12529                         mAttachInfo.mHardwareRenderer.validate()) {
12530                     getHardwareLayer();
12531                 }
12532                 break;
12533             case LAYER_TYPE_SOFTWARE:
12534                 buildDrawingCache(true);
12535                 break;
12536         }
12537     }
12538 
12539     /**
12540      * <p>Returns a hardware layer that can be used to draw this view again
12541      * without executing its draw method.</p>
12542      *
12543      * @return A HardwareLayer ready to render, or null if an error occurred.
12544      */
12545     HardwareLayer getHardwareLayer() {
12546         if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
12547                 !mAttachInfo.mHardwareRenderer.isEnabled()) {
12548             return null;
12549         }
12550 
12551         if (!mAttachInfo.mHardwareRenderer.validate()) return null;
12552 
12553         final int width = mRight - mLeft;
12554         final int height = mBottom - mTop;
12555 
12556         if (width == 0 || height == 0) {
12557             return null;
12558         }
12559 
12560         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
12561             if (mHardwareLayer == null) {
12562                 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
12563                         width, height, isOpaque());
12564                 mLocalDirtyRect.set(0, 0, width, height);
12565             } else {
12566                 if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
12567                     if (mHardwareLayer.resize(width, height)) {
12568                         mLocalDirtyRect.set(0, 0, width, height);
12569                     }
12570                 }
12571 
12572                 // This should not be necessary but applications that change
12573                 // the parameters of their background drawable without calling
12574                 // this.setBackground(Drawable) can leave the view in a bad state
12575                 // (for instance isOpaque() returns true, but the background is
12576                 // not opaque.)
12577                 computeOpaqueFlags();
12578 
12579                 final boolean opaque = isOpaque();
12580                 if (mHardwareLayer.isValid() && mHardwareLayer.isOpaque() != opaque) {
12581                     mHardwareLayer.setOpaque(opaque);
12582                     mLocalDirtyRect.set(0, 0, width, height);
12583                 }
12584             }
12585 
12586             // The layer is not valid if the underlying GPU resources cannot be allocated
12587             if (!mHardwareLayer.isValid()) {
12588                 return null;
12589             }
12590 
12591             mHardwareLayer.setLayerPaint(mLayerPaint);
12592             mHardwareLayer.redrawLater(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
12593             ViewRootImpl viewRoot = getViewRootImpl();
12594             if (viewRoot != null) viewRoot.pushHardwareLayerUpdate(mHardwareLayer);
12595 
12596             mLocalDirtyRect.setEmpty();
12597         }
12598 
12599         return mHardwareLayer;
12600     }
12601 
12602     /**
12603      * Destroys this View's hardware layer if possible.
12604      *
12605      * @return True if the layer was destroyed, false otherwise.
12606      *
12607      * @see #setLayerType(int, android.graphics.Paint)
12608      * @see #LAYER_TYPE_HARDWARE
12609      */
12610     boolean destroyLayer(boolean valid) {
12611         if (mHardwareLayer != null) {
12612             AttachInfo info = mAttachInfo;
12613             if (info != null && info.mHardwareRenderer != null &&
12614                     info.mHardwareRenderer.isEnabled() &&
12615                     (valid || info.mHardwareRenderer.validate())) {
12616                 mHardwareLayer.destroy();
12617                 mHardwareLayer = null;
12618 
12619                 if (mDisplayList != null) {
12620                     mDisplayList.reset();
12621                 }
12622                 invalidate(true);
12623                 invalidateParentCaches();
12624             }
12625             return true;
12626         }
12627         return false;
12628     }
12629 
12630     /**
12631      * Destroys all hardware rendering resources. This method is invoked
12632      * when the system needs to reclaim resources. Upon execution of this
12633      * method, you should free any OpenGL resources created by the view.
12634      *
12635      * Note: you <strong>must</strong> call
12636      * <code>super.destroyHardwareResources()</code> when overriding
12637      * this method.
12638      *
12639      * @hide
12640      */
12641     protected void destroyHardwareResources() {
12642         destroyLayer(true);
12643     }
12644 
12645     /**
12646      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
12647      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
12648      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
12649      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
12650      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
12651      * null.</p>
12652      *
12653      * <p>Enabling the drawing cache is similar to
12654      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
12655      * acceleration is turned off. When hardware acceleration is turned on, enabling the
12656      * drawing cache has no effect on rendering because the system uses a different mechanism
12657      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
12658      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
12659      * for information on how to enable software and hardware layers.</p>
12660      *
12661      * <p>This API can be used to manually generate
12662      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
12663      * {@link #getDrawingCache()}.</p>
12664      *
12665      * @param enabled true to enable the drawing cache, false otherwise
12666      *
12667      * @see #isDrawingCacheEnabled()
12668      * @see #getDrawingCache()
12669      * @see #buildDrawingCache()
12670      * @see #setLayerType(int, android.graphics.Paint)
12671      */
12672     public void setDrawingCacheEnabled(boolean enabled) {
12673         mCachingFailed = false;
12674         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
12675     }
12676 
12677     /**
12678      * <p>Indicates whether the drawing cache is enabled for this view.</p>
12679      *
12680      * @return true if the drawing cache is enabled
12681      *
12682      * @see #setDrawingCacheEnabled(boolean)
12683      * @see #getDrawingCache()
12684      */
12685     @ViewDebug.ExportedProperty(category = "drawing")
12686     public boolean isDrawingCacheEnabled() {
12687         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
12688     }
12689 
12690     /**
12691      * Debugging utility which recursively outputs the dirty state of a view and its
12692      * descendants.
12693      *
12694      * @hide
12695      */
12696     @SuppressWarnings({"UnusedDeclaration"})
12697     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
12698         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
12699                 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
12700                 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
12701                 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
12702         if (clear) {
12703             mPrivateFlags &= clearMask;
12704         }
12705         if (this instanceof ViewGroup) {
12706             ViewGroup parent = (ViewGroup) this;
12707             final int count = parent.getChildCount();
12708             for (int i = 0; i < count; i++) {
12709                 final View child = parent.getChildAt(i);
12710                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
12711             }
12712         }
12713     }
12714 
12715     /**
12716      * This method is used by ViewGroup to cause its children to restore or recreate their
12717      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
12718      * to recreate its own display list, which would happen if it went through the normal
12719      * draw/dispatchDraw mechanisms.
12720      *
12721      * @hide
12722      */
12723     protected void dispatchGetDisplayList() {}
12724 
12725     /**
12726      * A view that is not attached or hardware accelerated cannot create a display list.
12727      * This method checks these conditions and returns the appropriate result.
12728      *
12729      * @return true if view has the ability to create a display list, false otherwise.
12730      *
12731      * @hide
12732      */
12733     public boolean canHaveDisplayList() {
12734         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
12735     }
12736 
12737     /**
12738      * @return The {@link HardwareRenderer} associated with that view or null if
12739      *         hardware rendering is not supported or this view is not attached
12740      *         to a window.
12741      *
12742      * @hide
12743      */
12744     public HardwareRenderer getHardwareRenderer() {
12745         if (mAttachInfo != null) {
12746             return mAttachInfo.mHardwareRenderer;
12747         }
12748         return null;
12749     }
12750 
12751     /**
12752      * Returns a DisplayList. If the incoming displayList is null, one will be created.
12753      * Otherwise, the same display list will be returned (after having been rendered into
12754      * along the way, depending on the invalidation state of the view).
12755      *
12756      * @param displayList The previous version of this displayList, could be null.
12757      * @param isLayer Whether the requester of the display list is a layer. If so,
12758      * the view will avoid creating a layer inside the resulting display list.
12759      * @return A new or reused DisplayList object.
12760      */
12761     private DisplayList getDisplayList(DisplayList displayList, boolean isLayer) {
12762         if (!canHaveDisplayList()) {
12763             return null;
12764         }
12765 
12766         if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 ||
12767                 displayList == null || !displayList.isValid() ||
12768                 (!isLayer && mRecreateDisplayList))) {
12769             // Don't need to recreate the display list, just need to tell our
12770             // children to restore/recreate theirs
12771             if (displayList != null && displayList.isValid() &&
12772                     !isLayer && !mRecreateDisplayList) {
12773                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12774                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12775                 dispatchGetDisplayList();
12776 
12777                 return displayList;
12778             }
12779 
12780             if (!isLayer) {
12781                 // If we got here, we're recreating it. Mark it as such to ensure that
12782                 // we copy in child display lists into ours in drawChild()
12783                 mRecreateDisplayList = true;
12784             }
12785             if (displayList == null) {
12786                 final String name = getClass().getSimpleName();
12787                 displayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
12788                 // If we're creating a new display list, make sure our parent gets invalidated
12789                 // since they will need to recreate their display list to account for this
12790                 // new child display list.
12791                 invalidateParentCaches();
12792             }
12793 
12794             boolean caching = false;
12795             int width = mRight - mLeft;
12796             int height = mBottom - mTop;
12797             int layerType = getLayerType();
12798 
12799             final HardwareCanvas canvas = displayList.start(width, height);
12800 
12801             try {
12802                 if (!isLayer && layerType != LAYER_TYPE_NONE) {
12803                     if (layerType == LAYER_TYPE_HARDWARE) {
12804                         final HardwareLayer layer = getHardwareLayer();
12805                         if (layer != null && layer.isValid()) {
12806                             canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
12807                         } else {
12808                             canvas.saveLayer(0, 0, mRight - mLeft, mBottom - mTop, mLayerPaint,
12809                                     Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
12810                                             Canvas.CLIP_TO_LAYER_SAVE_FLAG);
12811                         }
12812                         caching = true;
12813                     } else {
12814                         buildDrawingCache(true);
12815                         Bitmap cache = getDrawingCache(true);
12816                         if (cache != null) {
12817                             canvas.drawBitmap(cache, 0, 0, mLayerPaint);
12818                             caching = true;
12819                         }
12820                     }
12821                 } else {
12822 
12823                     computeScroll();
12824 
12825                     canvas.translate(-mScrollX, -mScrollY);
12826                     if (!isLayer) {
12827                         mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12828                         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12829                     }
12830 
12831                     // Fast path for layouts with no backgrounds
12832                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
12833                         dispatchDraw(canvas);
12834                         if (mOverlay != null && !mOverlay.isEmpty()) {
12835                             mOverlay.getOverlayView().draw(canvas);
12836                         }
12837                     } else {
12838                         draw(canvas);
12839                     }
12840                 }
12841             } finally {
12842                 displayList.end();
12843                 displayList.setCaching(caching);
12844                 if (isLayer) {
12845                     displayList.setLeftTopRightBottom(0, 0, width, height);
12846                 } else {
12847                     setDisplayListProperties(displayList);
12848                 }
12849             }
12850         } else if (!isLayer) {
12851             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12852             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12853         }
12854 
12855         return displayList;
12856     }
12857 
12858     /**
12859      * Get the DisplayList for the HardwareLayer
12860      *
12861      * @param layer The HardwareLayer whose DisplayList we want
12862      * @return A DisplayList fopr the specified HardwareLayer
12863      */
12864     private DisplayList getHardwareLayerDisplayList(HardwareLayer layer) {
12865         DisplayList displayList = getDisplayList(layer.getDisplayList(), true);
12866         layer.setDisplayList(displayList);
12867         return displayList;
12868     }
12869 
12870 
12871     /**
12872      * <p>Returns a display list that can be used to draw this view again
12873      * without executing its draw method.</p>
12874      *
12875      * @return A DisplayList ready to replay, or null if caching is not enabled.
12876      *
12877      * @hide
12878      */
12879     public DisplayList getDisplayList() {
12880         mDisplayList = getDisplayList(mDisplayList, false);
12881         return mDisplayList;
12882     }
12883 
12884     private void clearDisplayList() {
12885         if (mDisplayList != null) {
12886             mDisplayList.clear();
12887         }
12888     }
12889 
12890     /**
12891      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
12892      *
12893      * @return A non-scaled bitmap representing this view or null if cache is disabled.
12894      *
12895      * @see #getDrawingCache(boolean)
12896      */
12897     public Bitmap getDrawingCache() {
12898         return getDrawingCache(false);
12899     }
12900 
12901     /**
12902      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
12903      * is null when caching is disabled. If caching is enabled and the cache is not ready,
12904      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
12905      * draw from the cache when the cache is enabled. To benefit from the cache, you must
12906      * request the drawing cache by calling this method and draw it on screen if the
12907      * returned bitmap is not null.</p>
12908      *
12909      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12910      * this method will create a bitmap of the same size as this view. Because this bitmap
12911      * will be drawn scaled by the parent ViewGroup, the result on screen might show
12912      * scaling artifacts. To avoid such artifacts, you should call this method by setting
12913      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12914      * size than the view. This implies that your application must be able to handle this
12915      * size.</p>
12916      *
12917      * @param autoScale Indicates whether the generated bitmap should be scaled based on
12918      *        the current density of the screen when the application is in compatibility
12919      *        mode.
12920      *
12921      * @return A bitmap representing this view or null if cache is disabled.
12922      *
12923      * @see #setDrawingCacheEnabled(boolean)
12924      * @see #isDrawingCacheEnabled()
12925      * @see #buildDrawingCache(boolean)
12926      * @see #destroyDrawingCache()
12927      */
12928     public Bitmap getDrawingCache(boolean autoScale) {
12929         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
12930             return null;
12931         }
12932         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
12933             buildDrawingCache(autoScale);
12934         }
12935         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
12936     }
12937 
12938     /**
12939      * <p>Frees the resources used by the drawing cache. If you call
12940      * {@link #buildDrawingCache()} manually without calling
12941      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12942      * should cleanup the cache with this method afterwards.</p>
12943      *
12944      * @see #setDrawingCacheEnabled(boolean)
12945      * @see #buildDrawingCache()
12946      * @see #getDrawingCache()
12947      */
12948     public void destroyDrawingCache() {
12949         if (mDrawingCache != null) {
12950             mDrawingCache.recycle();
12951             mDrawingCache = null;
12952         }
12953         if (mUnscaledDrawingCache != null) {
12954             mUnscaledDrawingCache.recycle();
12955             mUnscaledDrawingCache = null;
12956         }
12957     }
12958 
12959     /**
12960      * Setting a solid background color for the drawing cache's bitmaps will improve
12961      * performance and memory usage. Note, though that this should only be used if this
12962      * view will always be drawn on top of a solid color.
12963      *
12964      * @param color The background color to use for the drawing cache's bitmap
12965      *
12966      * @see #setDrawingCacheEnabled(boolean)
12967      * @see #buildDrawingCache()
12968      * @see #getDrawingCache()
12969      */
12970     public void setDrawingCacheBackgroundColor(int color) {
12971         if (color != mDrawingCacheBackgroundColor) {
12972             mDrawingCacheBackgroundColor = color;
12973             mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12974         }
12975     }
12976 
12977     /**
12978      * @see #setDrawingCacheBackgroundColor(int)
12979      *
12980      * @return The background color to used for the drawing cache's bitmap
12981      */
12982     public int getDrawingCacheBackgroundColor() {
12983         return mDrawingCacheBackgroundColor;
12984     }
12985 
12986     /**
12987      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
12988      *
12989      * @see #buildDrawingCache(boolean)
12990      */
12991     public void buildDrawingCache() {
12992         buildDrawingCache(false);
12993     }
12994 
12995     /**
12996      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
12997      *
12998      * <p>If you call {@link #buildDrawingCache()} manually without calling
12999      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
13000      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
13001      *
13002      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
13003      * this method will create a bitmap of the same size as this view. Because this bitmap
13004      * will be drawn scaled by the parent ViewGroup, the result on screen might show
13005      * scaling artifacts. To avoid such artifacts, you should call this method by setting
13006      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
13007      * size than the view. This implies that your application must be able to handle this
13008      * size.</p>
13009      *
13010      * <p>You should avoid calling this method when hardware acceleration is enabled. If
13011      * you do not need the drawing cache bitmap, calling this method will increase memory
13012      * usage and cause the view to be rendered in software once, thus negatively impacting
13013      * performance.</p>
13014      *
13015      * @see #getDrawingCache()
13016      * @see #destroyDrawingCache()
13017      */
13018     public void buildDrawingCache(boolean autoScale) {
13019         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
13020                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
13021             mCachingFailed = false;
13022 
13023             int width = mRight - mLeft;
13024             int height = mBottom - mTop;
13025 
13026             final AttachInfo attachInfo = mAttachInfo;
13027             final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
13028 
13029             if (autoScale && scalingRequired) {
13030                 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
13031                 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
13032             }
13033 
13034             final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
13035             final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
13036             final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
13037 
13038             final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
13039             final long drawingCacheSize =
13040                     ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
13041             if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
13042                 if (width > 0 && height > 0) {
13043                     Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
13044                             + projectedBitmapSize + " bytes, only "
13045                             + drawingCacheSize + " available");
13046                 }
13047                 destroyDrawingCache();
13048                 mCachingFailed = true;
13049                 return;
13050             }
13051 
13052             boolean clear = true;
13053             Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
13054 
13055             if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
13056                 Bitmap.Config quality;
13057                 if (!opaque) {
13058                     // Never pick ARGB_4444 because it looks awful
13059                     // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
13060                     switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
13061                         case DRAWING_CACHE_QUALITY_AUTO:
13062                             quality = Bitmap.Config.ARGB_8888;
13063                             break;
13064                         case DRAWING_CACHE_QUALITY_LOW:
13065                             quality = Bitmap.Config.ARGB_8888;
13066                             break;
13067                         case DRAWING_CACHE_QUALITY_HIGH:
13068                             quality = Bitmap.Config.ARGB_8888;
13069                             break;
13070                         default:
13071                             quality = Bitmap.Config.ARGB_8888;
13072                             break;
13073                     }
13074                 } else {
13075                     // Optimization for translucent windows
13076                     // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
13077                     quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
13078                 }
13079 
13080                 // Try to cleanup memory
13081                 if (bitmap != null) bitmap.recycle();
13082 
13083                 try {
13084                     bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
13085                             width, height, quality);
13086                     bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
13087                     if (autoScale) {
13088                         mDrawingCache = bitmap;
13089                     } else {
13090                         mUnscaledDrawingCache = bitmap;
13091                     }
13092                     if (opaque && use32BitCache) bitmap.setHasAlpha(false);
13093                 } catch (OutOfMemoryError e) {
13094                     // If there is not enough memory to create the bitmap cache, just
13095                     // ignore the issue as bitmap caches are not required to draw the
13096                     // view hierarchy
13097                     if (autoScale) {
13098                         mDrawingCache = null;
13099                     } else {
13100                         mUnscaledDrawingCache = null;
13101                     }
13102                     mCachingFailed = true;
13103                     return;
13104                 }
13105 
13106                 clear = drawingCacheBackgroundColor != 0;
13107             }
13108 
13109             Canvas canvas;
13110             if (attachInfo != null) {
13111                 canvas = attachInfo.mCanvas;
13112                 if (canvas == null) {
13113                     canvas = new Canvas();
13114                 }
13115                 canvas.setBitmap(bitmap);
13116                 // Temporarily clobber the cached Canvas in case one of our children
13117                 // is also using a drawing cache. Without this, the children would
13118                 // steal the canvas by attaching their own bitmap to it and bad, bad
13119                 // thing would happen (invisible views, corrupted drawings, etc.)
13120                 attachInfo.mCanvas = null;
13121             } else {
13122                 // This case should hopefully never or seldom happen
13123                 canvas = new Canvas(bitmap);
13124             }
13125 
13126             if (clear) {
13127                 bitmap.eraseColor(drawingCacheBackgroundColor);
13128             }
13129 
13130             computeScroll();
13131             final int restoreCount = canvas.save();
13132 
13133             if (autoScale && scalingRequired) {
13134                 final float scale = attachInfo.mApplicationScale;
13135                 canvas.scale(scale, scale);
13136             }
13137 
13138             canvas.translate(-mScrollX, -mScrollY);
13139 
13140             mPrivateFlags |= PFLAG_DRAWN;
13141             if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
13142                     mLayerType != LAYER_TYPE_NONE) {
13143                 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
13144             }
13145 
13146             // Fast path for layouts with no backgrounds
13147             if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13148                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13149                 dispatchDraw(canvas);
13150                 if (mOverlay != null && !mOverlay.isEmpty()) {
13151                     mOverlay.getOverlayView().draw(canvas);
13152                 }
13153             } else {
13154                 draw(canvas);
13155             }
13156 
13157             canvas.restoreToCount(restoreCount);
13158             canvas.setBitmap(null);
13159 
13160             if (attachInfo != null) {
13161                 // Restore the cached Canvas for our siblings
13162                 attachInfo.mCanvas = canvas;
13163             }
13164         }
13165     }
13166 
13167     /**
13168      * Create a snapshot of the view into a bitmap.  We should probably make
13169      * some form of this public, but should think about the API.
13170      */
13171     Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
13172         int width = mRight - mLeft;
13173         int height = mBottom - mTop;
13174 
13175         final AttachInfo attachInfo = mAttachInfo;
13176         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
13177         width = (int) ((width * scale) + 0.5f);
13178         height = (int) ((height * scale) + 0.5f);
13179 
13180         Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
13181                 width > 0 ? width : 1, height > 0 ? height : 1, quality);
13182         if (bitmap == null) {
13183             throw new OutOfMemoryError();
13184         }
13185 
13186         Resources resources = getResources();
13187         if (resources != null) {
13188             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
13189         }
13190 
13191         Canvas canvas;
13192         if (attachInfo != null) {
13193             canvas = attachInfo.mCanvas;
13194             if (canvas == null) {
13195                 canvas = new Canvas();
13196             }
13197             canvas.setBitmap(bitmap);
13198             // Temporarily clobber the cached Canvas in case one of our children
13199             // is also using a drawing cache. Without this, the children would
13200             // steal the canvas by attaching their own bitmap to it and bad, bad
13201             // things would happen (invisible views, corrupted drawings, etc.)
13202             attachInfo.mCanvas = null;
13203         } else {
13204             // This case should hopefully never or seldom happen
13205             canvas = new Canvas(bitmap);
13206         }
13207 
13208         if ((backgroundColor & 0xff000000) != 0) {
13209             bitmap.eraseColor(backgroundColor);
13210         }
13211 
13212         computeScroll();
13213         final int restoreCount = canvas.save();
13214         canvas.scale(scale, scale);
13215         canvas.translate(-mScrollX, -mScrollY);
13216 
13217         // Temporarily remove the dirty mask
13218         int flags = mPrivateFlags;
13219         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13220 
13221         // Fast path for layouts with no backgrounds
13222         if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13223             dispatchDraw(canvas);
13224         } else {
13225             draw(canvas);
13226         }
13227 
13228         mPrivateFlags = flags;
13229 
13230         canvas.restoreToCount(restoreCount);
13231         canvas.setBitmap(null);
13232 
13233         if (attachInfo != null) {
13234             // Restore the cached Canvas for our siblings
13235             attachInfo.mCanvas = canvas;
13236         }
13237 
13238         return bitmap;
13239     }
13240 
13241     /**
13242      * Indicates whether this View is currently in edit mode. A View is usually
13243      * in edit mode when displayed within a developer tool. For instance, if
13244      * this View is being drawn by a visual user interface builder, this method
13245      * should return true.
13246      *
13247      * Subclasses should check the return value of this method to provide
13248      * different behaviors if their normal behavior might interfere with the
13249      * host environment. For instance: the class spawns a thread in its
13250      * constructor, the drawing code relies on device-specific features, etc.
13251      *
13252      * This method is usually checked in the drawing code of custom widgets.
13253      *
13254      * @return True if this View is in edit mode, false otherwise.
13255      */
13256     public boolean isInEditMode() {
13257         return false;
13258     }
13259 
13260     /**
13261      * If the View draws content inside its padding and enables fading edges,
13262      * it needs to support padding offsets. Padding offsets are added to the
13263      * fading edges to extend the length of the fade so that it covers pixels
13264      * drawn inside the padding.
13265      *
13266      * Subclasses of this class should override this method if they need
13267      * to draw content inside the padding.
13268      *
13269      * @return True if padding offset must be applied, false otherwise.
13270      *
13271      * @see #getLeftPaddingOffset()
13272      * @see #getRightPaddingOffset()
13273      * @see #getTopPaddingOffset()
13274      * @see #getBottomPaddingOffset()
13275      *
13276      * @since CURRENT
13277      */
13278     protected boolean isPaddingOffsetRequired() {
13279         return false;
13280     }
13281 
13282     /**
13283      * Amount by which to extend the left fading region. Called only when
13284      * {@link #isPaddingOffsetRequired()} returns true.
13285      *
13286      * @return The left padding offset in pixels.
13287      *
13288      * @see #isPaddingOffsetRequired()
13289      *
13290      * @since CURRENT
13291      */
13292     protected int getLeftPaddingOffset() {
13293         return 0;
13294     }
13295 
13296     /**
13297      * Amount by which to extend the right fading region. Called only when
13298      * {@link #isPaddingOffsetRequired()} returns true.
13299      *
13300      * @return The right padding offset in pixels.
13301      *
13302      * @see #isPaddingOffsetRequired()
13303      *
13304      * @since CURRENT
13305      */
13306     protected int getRightPaddingOffset() {
13307         return 0;
13308     }
13309 
13310     /**
13311      * Amount by which to extend the top fading region. Called only when
13312      * {@link #isPaddingOffsetRequired()} returns true.
13313      *
13314      * @return The top padding offset in pixels.
13315      *
13316      * @see #isPaddingOffsetRequired()
13317      *
13318      * @since CURRENT
13319      */
13320     protected int getTopPaddingOffset() {
13321         return 0;
13322     }
13323 
13324     /**
13325      * Amount by which to extend the bottom fading region. Called only when
13326      * {@link #isPaddingOffsetRequired()} returns true.
13327      *
13328      * @return The bottom padding offset in pixels.
13329      *
13330      * @see #isPaddingOffsetRequired()
13331      *
13332      * @since CURRENT
13333      */
13334     protected int getBottomPaddingOffset() {
13335         return 0;
13336     }
13337 
13338     /**
13339      * @hide
13340      * @param offsetRequired
13341      */
13342     protected int getFadeTop(boolean offsetRequired) {
13343         int top = mPaddingTop;
13344         if (offsetRequired) top += getTopPaddingOffset();
13345         return top;
13346     }
13347 
13348     /**
13349      * @hide
13350      * @param offsetRequired
13351      */
13352     protected int getFadeHeight(boolean offsetRequired) {
13353         int padding = mPaddingTop;
13354         if (offsetRequired) padding += getTopPaddingOffset();
13355         return mBottom - mTop - mPaddingBottom - padding;
13356     }
13357 
13358     /**
13359      * <p>Indicates whether this view is attached to a hardware accelerated
13360      * window or not.</p>
13361      *
13362      * <p>Even if this method returns true, it does not mean that every call
13363      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
13364      * accelerated {@link android.graphics.Canvas}. For instance, if this view
13365      * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
13366      * window is hardware accelerated,
13367      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
13368      * return false, and this method will return true.</p>
13369      *
13370      * @return True if the view is attached to a window and the window is
13371      *         hardware accelerated; false in any other case.
13372      */
13373     public boolean isHardwareAccelerated() {
13374         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
13375     }
13376 
13377     /**
13378      * Sets a rectangular area on this view to which the view will be clipped
13379      * when it is drawn. Setting the value to null will remove the clip bounds
13380      * and the view will draw normally, using its full bounds.
13381      *
13382      * @param clipBounds The rectangular area, in the local coordinates of
13383      * this view, to which future drawing operations will be clipped.
13384      */
13385     public void setClipBounds(Rect clipBounds) {
13386         if (clipBounds != null) {
13387             if (clipBounds.equals(mClipBounds)) {
13388                 return;
13389             }
13390             if (mClipBounds == null) {
13391                 invalidate();
13392                 mClipBounds = new Rect(clipBounds);
13393             } else {
13394                 invalidate(Math.min(mClipBounds.left, clipBounds.left),
13395                         Math.min(mClipBounds.top, clipBounds.top),
13396                         Math.max(mClipBounds.right, clipBounds.right),
13397                         Math.max(mClipBounds.bottom, clipBounds.bottom));
13398                 mClipBounds.set(clipBounds);
13399             }
13400         } else {
13401             if (mClipBounds != null) {
13402                 invalidate();
13403                 mClipBounds = null;
13404             }
13405         }
13406     }
13407 
13408     /**
13409      * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
13410      *
13411      * @return A copy of the current clip bounds if clip bounds are set,
13412      * otherwise null.
13413      */
13414     public Rect getClipBounds() {
13415         return (mClipBounds != null) ? new Rect(mClipBounds) : null;
13416     }
13417 
13418     /**
13419      * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
13420      * case of an active Animation being run on the view.
13421      */
13422     private boolean drawAnimation(ViewGroup parent, long drawingTime,
13423             Animation a, boolean scalingRequired) {
13424         Transformation invalidationTransform;
13425         final int flags = parent.mGroupFlags;
13426         final boolean initialized = a.isInitialized();
13427         if (!initialized) {
13428             a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
13429             a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
13430             if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
13431             onAnimationStart();
13432         }
13433 
13434         boolean more = a.getTransformation(drawingTime, parent.mChildTransformation, 1f);
13435         if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
13436             if (parent.mInvalidationTransformation == null) {
13437                 parent.mInvalidationTransformation = new Transformation();
13438             }
13439             invalidationTransform = parent.mInvalidationTransformation;
13440             a.getTransformation(drawingTime, invalidationTransform, 1f);
13441         } else {
13442             invalidationTransform = parent.mChildTransformation;
13443         }
13444 
13445         if (more) {
13446             if (!a.willChangeBounds()) {
13447                 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
13448                         ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
13449                     parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
13450                 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
13451                     // The child need to draw an animation, potentially offscreen, so
13452                     // make sure we do not cancel invalidate requests
13453                     parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
13454                     parent.invalidate(mLeft, mTop, mRight, mBottom);
13455                 }
13456             } else {
13457                 if (parent.mInvalidateRegion == null) {
13458                     parent.mInvalidateRegion = new RectF();
13459                 }
13460                 final RectF region = parent.mInvalidateRegion;
13461                 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
13462                         invalidationTransform);
13463 
13464                 // The child need to draw an animation, potentially offscreen, so
13465                 // make sure we do not cancel invalidate requests
13466                 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
13467 
13468                 final int left = mLeft + (int) region.left;
13469                 final int top = mTop + (int) region.top;
13470                 parent.invalidate(left, top, left + (int) (region.width() + .5f),
13471                         top + (int) (region.height() + .5f));
13472             }
13473         }
13474         return more;
13475     }
13476 
13477     /**
13478      * This method is called by getDisplayList() when a display list is created or re-rendered.
13479      * It sets or resets the current value of all properties on that display list (resetting is
13480      * necessary when a display list is being re-created, because we need to make sure that
13481      * previously-set transform values
13482      */
13483     void setDisplayListProperties(DisplayList displayList) {
13484         if (displayList != null) {
13485             displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
13486             displayList.setHasOverlappingRendering(hasOverlappingRendering());
13487             if (mParent instanceof ViewGroup) {
13488                 displayList.setClipToBounds(
13489                         (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
13490             }
13491             float alpha = 1;
13492             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
13493                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
13494                 ViewGroup parentVG = (ViewGroup) mParent;
13495                 final boolean hasTransform =
13496                         parentVG.getChildStaticTransformation(this, parentVG.mChildTransformation);
13497                 if (hasTransform) {
13498                     Transformation transform = parentVG.mChildTransformation;
13499                     final int transformType = parentVG.mChildTransformation.getTransformationType();
13500                     if (transformType != Transformation.TYPE_IDENTITY) {
13501                         if ((transformType & Transformation.TYPE_ALPHA) != 0) {
13502                             alpha = transform.getAlpha();
13503                         }
13504                         if ((transformType & Transformation.TYPE_MATRIX) != 0) {
13505                             displayList.setMatrix(transform.getMatrix());
13506                         }
13507                     }
13508                 }
13509             }
13510             if (mTransformationInfo != null) {
13511                 alpha *= mTransformationInfo.mAlpha;
13512                 if (alpha < 1) {
13513                     final int multipliedAlpha = (int) (255 * alpha);
13514                     if (onSetAlpha(multipliedAlpha)) {
13515                         alpha = 1;
13516                     }
13517                 }
13518                 displayList.setTransformationInfo(alpha,
13519                         mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY,
13520                         mTransformationInfo.mRotation, mTransformationInfo.mRotationX,
13521                         mTransformationInfo.mRotationY, mTransformationInfo.mScaleX,
13522                         mTransformationInfo.mScaleY);
13523                 if (mTransformationInfo.mCamera == null) {
13524                     mTransformationInfo.mCamera = new Camera();
13525                     mTransformationInfo.matrix3D = new Matrix();
13526                 }
13527                 displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ());
13528                 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) {
13529                     displayList.setPivotX(getPivotX());
13530                     displayList.setPivotY(getPivotY());
13531                 }
13532             } else if (alpha < 1) {
13533                 displayList.setAlpha(alpha);
13534             }
13535         }
13536     }
13537 
13538     /**
13539      * This method is called by ViewGroup.drawChild() to have each child view draw itself.
13540      * This draw() method is an implementation detail and is not intended to be overridden or
13541      * to be called from anywhere else other than ViewGroup.drawChild().
13542      */
13543     boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
13544         boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
13545         boolean more = false;
13546         final boolean childHasIdentityMatrix = hasIdentityMatrix();
13547         final int flags = parent.mGroupFlags;
13548 
13549         if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
13550             parent.mChildTransformation.clear();
13551             parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13552         }
13553 
13554         Transformation transformToApply = null;
13555         boolean concatMatrix = false;
13556 
13557         boolean scalingRequired = false;
13558         boolean caching;
13559         int layerType = getLayerType();
13560 
13561         final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
13562         if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
13563                 (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
13564             caching = true;
13565             // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
13566             if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
13567         } else {
13568             caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
13569         }
13570 
13571         final Animation a = getAnimation();
13572         if (a != null) {
13573             more = drawAnimation(parent, drawingTime, a, scalingRequired);
13574             concatMatrix = a.willChangeTransformationMatrix();
13575             if (concatMatrix) {
13576                 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
13577             }
13578             transformToApply = parent.mChildTransformation;
13579         } else {
13580             if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) ==
13581                     PFLAG3_VIEW_IS_ANIMATING_TRANSFORM && mDisplayList != null) {
13582                 // No longer animating: clear out old animation matrix
13583                 mDisplayList.setAnimationMatrix(null);
13584                 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
13585             }
13586             if (!useDisplayListProperties &&
13587                     (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
13588                 final boolean hasTransform =
13589                         parent.getChildStaticTransformation(this, parent.mChildTransformation);
13590                 if (hasTransform) {
13591                     final int transformType = parent.mChildTransformation.getTransformationType();
13592                     transformToApply = transformType != Transformation.TYPE_IDENTITY ?
13593                             parent.mChildTransformation : null;
13594                     concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
13595                 }
13596             }
13597         }
13598 
13599         concatMatrix |= !childHasIdentityMatrix;
13600 
13601         // Sets the flag as early as possible to allow draw() implementations
13602         // to call invalidate() successfully when doing animations
13603         mPrivateFlags |= PFLAG_DRAWN;
13604 
13605         if (!concatMatrix &&
13606                 (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
13607                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
13608                 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
13609                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
13610             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
13611             return more;
13612         }
13613         mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
13614 
13615         if (hardwareAccelerated) {
13616             // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
13617             // retain the flag's value temporarily in the mRecreateDisplayList flag
13618             mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
13619             mPrivateFlags &= ~PFLAG_INVALIDATED;
13620         }
13621 
13622         DisplayList displayList = null;
13623         Bitmap cache = null;
13624         boolean hasDisplayList = false;
13625         if (caching) {
13626             if (!hardwareAccelerated) {
13627                 if (layerType != LAYER_TYPE_NONE) {
13628                     layerType = LAYER_TYPE_SOFTWARE;
13629                     buildDrawingCache(true);
13630                 }
13631                 cache = getDrawingCache(true);
13632             } else {
13633                 switch (layerType) {
13634                     case LAYER_TYPE_SOFTWARE:
13635                         if (useDisplayListProperties) {
13636                             hasDisplayList = canHaveDisplayList();
13637                         } else {
13638                             buildDrawingCache(true);
13639                             cache = getDrawingCache(true);
13640                         }
13641                         break;
13642                     case LAYER_TYPE_HARDWARE:
13643                         if (useDisplayListProperties) {
13644                             hasDisplayList = canHaveDisplayList();
13645                         }
13646                         break;
13647                     case LAYER_TYPE_NONE:
13648                         // Delay getting the display list until animation-driven alpha values are
13649                         // set up and possibly passed on to the view
13650                         hasDisplayList = canHaveDisplayList();
13651                         break;
13652                 }
13653             }
13654         }
13655         useDisplayListProperties &= hasDisplayList;
13656         if (useDisplayListProperties) {
13657             displayList = getDisplayList();
13658             if (!displayList.isValid()) {
13659                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
13660                 // to getDisplayList(), the display list will be marked invalid and we should not
13661                 // try to use it again.
13662                 displayList = null;
13663                 hasDisplayList = false;
13664                 useDisplayListProperties = false;
13665             }
13666         }
13667 
13668         int sx = 0;
13669         int sy = 0;
13670         if (!hasDisplayList) {
13671             computeScroll();
13672             sx = mScrollX;
13673             sy = mScrollY;
13674         }
13675 
13676         final boolean hasNoCache = cache == null || hasDisplayList;
13677         final boolean offsetForScroll = cache == null && !hasDisplayList &&
13678                 layerType != LAYER_TYPE_HARDWARE;
13679 
13680         int restoreTo = -1;
13681         if (!useDisplayListProperties || transformToApply != null) {
13682             restoreTo = canvas.save();
13683         }
13684         if (offsetForScroll) {
13685             canvas.translate(mLeft - sx, mTop - sy);
13686         } else {
13687             if (!useDisplayListProperties) {
13688                 canvas.translate(mLeft, mTop);
13689             }
13690             if (scalingRequired) {
13691                 if (useDisplayListProperties) {
13692                     // TODO: Might not need this if we put everything inside the DL
13693                     restoreTo = canvas.save();
13694                 }
13695                 // mAttachInfo cannot be null, otherwise scalingRequired == false
13696                 final float scale = 1.0f / mAttachInfo.mApplicationScale;
13697                 canvas.scale(scale, scale);
13698             }
13699         }
13700 
13701         float alpha = useDisplayListProperties ? 1 : getAlpha();
13702         if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
13703                 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
13704             if (transformToApply != null || !childHasIdentityMatrix) {
13705                 int transX = 0;
13706                 int transY = 0;
13707 
13708                 if (offsetForScroll) {
13709                     transX = -sx;
13710                     transY = -sy;
13711                 }
13712 
13713                 if (transformToApply != null) {
13714                     if (concatMatrix) {
13715                         if (useDisplayListProperties) {
13716                             displayList.setAnimationMatrix(transformToApply.getMatrix());
13717                         } else {
13718                             // Undo the scroll translation, apply the transformation matrix,
13719                             // then redo the scroll translate to get the correct result.
13720                             canvas.translate(-transX, -transY);
13721                             canvas.concat(transformToApply.getMatrix());
13722                             canvas.translate(transX, transY);
13723                         }
13724                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13725                     }
13726 
13727                     float transformAlpha = transformToApply.getAlpha();
13728                     if (transformAlpha < 1) {
13729                         alpha *= transformAlpha;
13730                         parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13731                     }
13732                 }
13733 
13734                 if (!childHasIdentityMatrix && !useDisplayListProperties) {
13735                     canvas.translate(-transX, -transY);
13736                     canvas.concat(getMatrix());
13737                     canvas.translate(transX, transY);
13738                 }
13739             }
13740 
13741             // Deal with alpha if it is or used to be <1
13742             if (alpha < 1 ||
13743                     (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
13744                 if (alpha < 1) {
13745                     mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
13746                 } else {
13747                     mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
13748                 }
13749                 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13750                 if (hasNoCache) {
13751                     final int multipliedAlpha = (int) (255 * alpha);
13752                     if (!onSetAlpha(multipliedAlpha)) {
13753                         int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
13754                         if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
13755                                 layerType != LAYER_TYPE_NONE) {
13756                             layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
13757                         }
13758                         if (useDisplayListProperties) {
13759                             displayList.setAlpha(alpha * getAlpha());
13760                         } else  if (layerType == LAYER_TYPE_NONE) {
13761                             final int scrollX = hasDisplayList ? 0 : sx;
13762                             final int scrollY = hasDisplayList ? 0 : sy;
13763                             canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
13764                                     scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
13765                         }
13766                     } else {
13767                         // Alpha is handled by the child directly, clobber the layer's alpha
13768                         mPrivateFlags |= PFLAG_ALPHA_SET;
13769                     }
13770                 }
13771             }
13772         } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
13773             onSetAlpha(255);
13774             mPrivateFlags &= ~PFLAG_ALPHA_SET;
13775         }
13776 
13777         if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
13778                 !useDisplayListProperties && cache == null) {
13779             if (offsetForScroll) {
13780                 canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
13781             } else {
13782                 if (!scalingRequired || cache == null) {
13783                     canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
13784                 } else {
13785                     canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
13786                 }
13787             }
13788         }
13789 
13790         if (!useDisplayListProperties && hasDisplayList) {
13791             displayList = getDisplayList();
13792             if (!displayList.isValid()) {
13793                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
13794                 // to getDisplayList(), the display list will be marked invalid and we should not
13795                 // try to use it again.
13796                 displayList = null;
13797                 hasDisplayList = false;
13798             }
13799         }
13800 
13801         if (hasNoCache) {
13802             boolean layerRendered = false;
13803             if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) {
13804                 final HardwareLayer layer = getHardwareLayer();
13805                 if (layer != null && layer.isValid()) {
13806                     mLayerPaint.setAlpha((int) (alpha * 255));
13807                     ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
13808                     layerRendered = true;
13809                 } else {
13810                     final int scrollX = hasDisplayList ? 0 : sx;
13811                     final int scrollY = hasDisplayList ? 0 : sy;
13812                     canvas.saveLayer(scrollX, scrollY,
13813                             scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
13814                             Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
13815                 }
13816             }
13817 
13818             if (!layerRendered) {
13819                 if (!hasDisplayList) {
13820                     // Fast path for layouts with no backgrounds
13821                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13822                         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13823                         dispatchDraw(canvas);
13824                     } else {
13825                         draw(canvas);
13826                     }
13827                 } else {
13828                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13829                     ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
13830                 }
13831             }
13832         } else if (cache != null) {
13833             mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13834             Paint cachePaint;
13835 
13836             if (layerType == LAYER_TYPE_NONE) {
13837                 cachePaint = parent.mCachePaint;
13838                 if (cachePaint == null) {
13839                     cachePaint = new Paint();
13840                     cachePaint.setDither(false);
13841                     parent.mCachePaint = cachePaint;
13842                 }
13843                 if (alpha < 1) {
13844                     cachePaint.setAlpha((int) (alpha * 255));
13845                     parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
13846                 } else if  ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) {
13847                     cachePaint.setAlpha(255);
13848                     parent.mGroupFlags &= ~ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
13849                 }
13850             } else {
13851                 cachePaint = mLayerPaint;
13852                 cachePaint.setAlpha((int) (alpha * 255));
13853             }
13854             canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
13855         }
13856 
13857         if (restoreTo >= 0) {
13858             canvas.restoreToCount(restoreTo);
13859         }
13860 
13861         if (a != null && !more) {
13862             if (!hardwareAccelerated && !a.getFillAfter()) {
13863                 onSetAlpha(255);
13864             }
13865             parent.finishAnimatingView(this, a);
13866         }
13867 
13868         if (more && hardwareAccelerated) {
13869             // invalidation is the trigger to recreate display lists, so if we're using
13870             // display lists to render, force an invalidate to allow the animation to
13871             // continue drawing another frame
13872             parent.invalidate(true);
13873             if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
13874                 // alpha animations should cause the child to recreate its display list
13875                 invalidate(true);
13876             }
13877         }
13878 
13879         mRecreateDisplayList = false;
13880 
13881         return more;
13882     }
13883 
13884     /**
13885      * Manually render this view (and all of its children) to the given Canvas.
13886      * The view must have already done a full layout before this function is
13887      * called.  When implementing a view, implement
13888      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
13889      * If you do need to override this method, call the superclass version.
13890      *
13891      * @param canvas The Canvas to which the View is rendered.
13892      */
13893     public void draw(Canvas canvas) {
13894         if (mClipBounds != null) {
13895             canvas.clipRect(mClipBounds);
13896         }
13897         final int privateFlags = mPrivateFlags;
13898         final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
13899                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
13900         mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
13901 
13902         /*
13903          * Draw traversal performs several drawing steps which must be executed
13904          * in the appropriate order:
13905          *
13906          *      1. Draw the background
13907          *      2. If necessary, save the canvas' layers to prepare for fading
13908          *      3. Draw view's content
13909          *      4. Draw children
13910          *      5. If necessary, draw the fading edges and restore layers
13911          *      6. Draw decorations (scrollbars for instance)
13912          */
13913 
13914         // Step 1, draw the background, if needed
13915         int saveCount;
13916 
13917         if (!dirtyOpaque) {
13918             final Drawable background = mBackground;
13919             if (background != null) {
13920                 final int scrollX = mScrollX;
13921                 final int scrollY = mScrollY;
13922 
13923                 if (mBackgroundSizeChanged) {
13924                     background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
13925                     mBackgroundSizeChanged = false;
13926                 }
13927 
13928                 if ((scrollX | scrollY) == 0) {
13929                     background.draw(canvas);
13930                 } else {
13931                     canvas.translate(scrollX, scrollY);
13932                     background.draw(canvas);
13933                     canvas.translate(-scrollX, -scrollY);
13934                 }
13935             }
13936         }
13937 
13938         // skip step 2 & 5 if possible (common case)
13939         final int viewFlags = mViewFlags;
13940         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
13941         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
13942         if (!verticalEdges && !horizontalEdges) {
13943             // Step 3, draw the content
13944             if (!dirtyOpaque) onDraw(canvas);
13945 
13946             // Step 4, draw the children
13947             dispatchDraw(canvas);
13948 
13949             // Step 6, draw decorations (scrollbars)
13950             onDrawScrollBars(canvas);
13951 
13952             if (mOverlay != null && !mOverlay.isEmpty()) {
13953                 mOverlay.getOverlayView().dispatchDraw(canvas);
13954             }
13955 
13956             // we're done...
13957             return;
13958         }
13959 
13960         /*
13961          * Here we do the full fledged routine...
13962          * (this is an uncommon case where speed matters less,
13963          * this is why we repeat some of the tests that have been
13964          * done above)
13965          */
13966 
13967         boolean drawTop = false;
13968         boolean drawBottom = false;
13969         boolean drawLeft = false;
13970         boolean drawRight = false;
13971 
13972         float topFadeStrength = 0.0f;
13973         float bottomFadeStrength = 0.0f;
13974         float leftFadeStrength = 0.0f;
13975         float rightFadeStrength = 0.0f;
13976 
13977         // Step 2, save the canvas' layers
13978         int paddingLeft = mPaddingLeft;
13979 
13980         final boolean offsetRequired = isPaddingOffsetRequired();
13981         if (offsetRequired) {
13982             paddingLeft += getLeftPaddingOffset();
13983         }
13984 
13985         int left = mScrollX + paddingLeft;
13986         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
13987         int top = mScrollY + getFadeTop(offsetRequired);
13988         int bottom = top + getFadeHeight(offsetRequired);
13989 
13990         if (offsetRequired) {
13991             right += getRightPaddingOffset();
13992             bottom += getBottomPaddingOffset();
13993         }
13994 
13995         final ScrollabilityCache scrollabilityCache = mScrollCache;
13996         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
13997         int length = (int) fadeHeight;
13998 
13999         // clip the fade length if top and bottom fades overlap
14000         // overlapping fades produce odd-looking artifacts
14001         if (verticalEdges && (top + length > bottom - length)) {
14002             length = (bottom - top) / 2;
14003         }
14004 
14005         // also clip horizontal fades if necessary
14006         if (horizontalEdges && (left + length > right - length)) {
14007             length = (right - left) / 2;
14008         }
14009 
14010         if (verticalEdges) {
14011             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
14012             drawTop = topFadeStrength * fadeHeight > 1.0f;
14013             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
14014             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
14015         }
14016 
14017         if (horizontalEdges) {
14018             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
14019             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
14020             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
14021             drawRight = rightFadeStrength * fadeHeight > 1.0f;
14022         }
14023 
14024         saveCount = canvas.getSaveCount();
14025 
14026         int solidColor = getSolidColor();
14027         if (solidColor == 0) {
14028             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
14029 
14030             if (drawTop) {
14031                 canvas.saveLayer(left, top, right, top + length, null, flags);
14032             }
14033 
14034             if (drawBottom) {
14035                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
14036             }
14037 
14038             if (drawLeft) {
14039                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
14040             }
14041 
14042             if (drawRight) {
14043                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
14044             }
14045         } else {
14046             scrollabilityCache.setFadeColor(solidColor);
14047         }
14048 
14049         // Step 3, draw the content
14050         if (!dirtyOpaque) onDraw(canvas);
14051 
14052         // Step 4, draw the children
14053         dispatchDraw(canvas);
14054 
14055         // Step 5, draw the fade effect and restore layers
14056         final Paint p = scrollabilityCache.paint;
14057         final Matrix matrix = scrollabilityCache.matrix;
14058         final Shader fade = scrollabilityCache.shader;
14059 
14060         if (drawTop) {
14061             matrix.setScale(1, fadeHeight * topFadeStrength);
14062             matrix.postTranslate(left, top);
14063             fade.setLocalMatrix(matrix);
14064             canvas.drawRect(left, top, right, top + length, p);
14065         }
14066 
14067         if (drawBottom) {
14068             matrix.setScale(1, fadeHeight * bottomFadeStrength);
14069             matrix.postRotate(180);
14070             matrix.postTranslate(left, bottom);
14071             fade.setLocalMatrix(matrix);
14072             canvas.drawRect(left, bottom - length, right, bottom, p);
14073         }
14074 
14075         if (drawLeft) {
14076             matrix.setScale(1, fadeHeight * leftFadeStrength);
14077             matrix.postRotate(-90);
14078             matrix.postTranslate(left, top);
14079             fade.setLocalMatrix(matrix);
14080             canvas.drawRect(left, top, left + length, bottom, p);
14081         }
14082 
14083         if (drawRight) {
14084             matrix.setScale(1, fadeHeight * rightFadeStrength);
14085             matrix.postRotate(90);
14086             matrix.postTranslate(right, top);
14087             fade.setLocalMatrix(matrix);
14088             canvas.drawRect(right - length, top, right, bottom, p);
14089         }
14090 
14091         canvas.restoreToCount(saveCount);
14092 
14093         // Step 6, draw decorations (scrollbars)
14094         onDrawScrollBars(canvas);
14095 
14096         if (mOverlay != null && !mOverlay.isEmpty()) {
14097             mOverlay.getOverlayView().dispatchDraw(canvas);
14098         }
14099     }
14100 
14101     /**
14102      * Returns the overlay for this view, creating it if it does not yet exist.
14103      * Adding drawables to the overlay will cause them to be displayed whenever
14104      * the view itself is redrawn. Objects in the overlay should be actively
14105      * managed: remove them when they should not be displayed anymore. The
14106      * overlay will always have the same size as its host view.
14107      *
14108      * <p>Note: Overlays do not currently work correctly with {@link
14109      * SurfaceView} or {@link TextureView}; contents in overlays for these
14110      * types of views may not display correctly.</p>
14111      *
14112      * @return The ViewOverlay object for this view.
14113      * @see ViewOverlay
14114      */
14115     public ViewOverlay getOverlay() {
14116         if (mOverlay == null) {
14117             mOverlay = new ViewOverlay(mContext, this);
14118         }
14119         return mOverlay;
14120     }
14121 
14122     /**
14123      * Override this if your view is known to always be drawn on top of a solid color background,
14124      * and needs to draw fading edges. Returning a non-zero color enables the view system to
14125      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
14126      * should be set to 0xFF.
14127      *
14128      * @see #setVerticalFadingEdgeEnabled(boolean)
14129      * @see #setHorizontalFadingEdgeEnabled(boolean)
14130      *
14131      * @return The known solid color background for this view, or 0 if the color may vary
14132      */
14133     @ViewDebug.ExportedProperty(category = "drawing")
14134     public int getSolidColor() {
14135         return 0;
14136     }
14137 
14138     /**
14139      * Build a human readable string representation of the specified view flags.
14140      *
14141      * @param flags the view flags to convert to a string
14142      * @return a String representing the supplied flags
14143      */
14144     private static String printFlags(int flags) {
14145         String output = "";
14146         int numFlags = 0;
14147         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
14148             output += "TAKES_FOCUS";
14149             numFlags++;
14150         }
14151 
14152         switch (flags & VISIBILITY_MASK) {
14153         case INVISIBLE:
14154             if (numFlags > 0) {
14155                 output += " ";
14156             }
14157             output += "INVISIBLE";
14158             // USELESS HERE numFlags++;
14159             break;
14160         case GONE:
14161             if (numFlags > 0) {
14162                 output += " ";
14163             }
14164             output += "GONE";
14165             // USELESS HERE numFlags++;
14166             break;
14167         default:
14168             break;
14169         }
14170         return output;
14171     }
14172 
14173     /**
14174      * Build a human readable string representation of the specified private
14175      * view flags.
14176      *
14177      * @param privateFlags the private view flags to convert to a string
14178      * @return a String representing the supplied flags
14179      */
14180     private static String printPrivateFlags(int privateFlags) {
14181         String output = "";
14182         int numFlags = 0;
14183 
14184         if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
14185             output += "WANTS_FOCUS";
14186             numFlags++;
14187         }
14188 
14189         if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
14190             if (numFlags > 0) {
14191                 output += " ";
14192             }
14193             output += "FOCUSED";
14194             numFlags++;
14195         }
14196 
14197         if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
14198             if (numFlags > 0) {
14199                 output += " ";
14200             }
14201             output += "SELECTED";
14202             numFlags++;
14203         }
14204 
14205         if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
14206             if (numFlags > 0) {
14207                 output += " ";
14208             }
14209             output += "IS_ROOT_NAMESPACE";
14210             numFlags++;
14211         }
14212 
14213         if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
14214             if (numFlags > 0) {
14215                 output += " ";
14216             }
14217             output += "HAS_BOUNDS";
14218             numFlags++;
14219         }
14220 
14221         if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
14222             if (numFlags > 0) {
14223                 output += " ";
14224             }
14225             output += "DRAWN";
14226             // USELESS HERE numFlags++;
14227         }
14228         return output;
14229     }
14230 
14231     /**
14232      * <p>Indicates whether or not this view's layout will be requested during
14233      * the next hierarchy layout pass.</p>
14234      *
14235      * @return true if the layout will be forced during next layout pass
14236      */
14237     public boolean isLayoutRequested() {
14238         return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
14239     }
14240 
14241     /**
14242      * Return true if o is a ViewGroup that is laying out using optical bounds.
14243      * @hide
14244      */
14245     public static boolean isLayoutModeOptical(Object o) {
14246         return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
14247     }
14248 
14249     private boolean setOpticalFrame(int left, int top, int right, int bottom) {
14250         Insets parentInsets = mParent instanceof View ?
14251                 ((View) mParent).getOpticalInsets() : Insets.NONE;
14252         Insets childInsets = getOpticalInsets();
14253         return setFrame(
14254                 left   + parentInsets.left - childInsets.left,
14255                 top    + parentInsets.top  - childInsets.top,
14256                 right  + parentInsets.left + childInsets.right,
14257                 bottom + parentInsets.top  + childInsets.bottom);
14258     }
14259 
14260     /**
14261      * Assign a size and position to a view and all of its
14262      * descendants
14263      *
14264      * <p>This is the second phase of the layout mechanism.
14265      * (The first is measuring). In this phase, each parent calls
14266      * layout on all of its children to position them.
14267      * This is typically done using the child measurements
14268      * that were stored in the measure pass().</p>
14269      *
14270      * <p>Derived classes should not override this method.
14271      * Derived classes with children should override
14272      * onLayout. In that method, they should
14273      * call layout on each of their children.</p>
14274      *
14275      * @param l Left position, relative to parent
14276      * @param t Top position, relative to parent
14277      * @param r Right position, relative to parent
14278      * @param b Bottom position, relative to parent
14279      */
14280     @SuppressWarnings({"unchecked"})
14281     public void layout(int l, int t, int r, int b) {
14282         int oldL = mLeft;
14283         int oldT = mTop;
14284         int oldB = mBottom;
14285         int oldR = mRight;
14286         boolean changed = isLayoutModeOptical(mParent) ?
14287                 setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
14288         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
14289             onLayout(changed, l, t, r, b);
14290             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
14291 
14292             ListenerInfo li = mListenerInfo;
14293             if (li != null && li.mOnLayoutChangeListeners != null) {
14294                 ArrayList<OnLayoutChangeListener> listenersCopy =
14295                         (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
14296                 int numListeners = listenersCopy.size();
14297                 for (int i = 0; i < numListeners; ++i) {
14298                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
14299                 }
14300             }
14301         }
14302         mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
14303     }
14304 
14305     /**
14306      * Called from layout when this view should
14307      * assign a size and position to each of its children.
14308      *
14309      * Derived classes with children should override
14310      * this method and call layout on each of
14311      * their children.
14312      * @param changed This is a new size or position for this view
14313      * @param left Left position, relative to parent
14314      * @param top Top position, relative to parent
14315      * @param right Right position, relative to parent
14316      * @param bottom Bottom position, relative to parent
14317      */
14318     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
14319     }
14320 
14321     /**
14322      * Assign a size and position to this view.
14323      *
14324      * This is called from layout.
14325      *
14326      * @param left Left position, relative to parent
14327      * @param top Top position, relative to parent
14328      * @param right Right position, relative to parent
14329      * @param bottom Bottom position, relative to parent
14330      * @return true if the new size and position are different than the
14331      *         previous ones
14332      * {@hide}
14333      */
14334     protected boolean setFrame(int left, int top, int right, int bottom) {
14335         boolean changed = false;
14336 
14337         if (DBG) {
14338             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
14339                     + right + "," + bottom + ")");
14340         }
14341 
14342         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
14343             changed = true;
14344 
14345             // Remember our drawn bit
14346             int drawn = mPrivateFlags & PFLAG_DRAWN;
14347 
14348             int oldWidth = mRight - mLeft;
14349             int oldHeight = mBottom - mTop;
14350             int newWidth = right - left;
14351             int newHeight = bottom - top;
14352             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
14353 
14354             // Invalidate our old position
14355             invalidate(sizeChanged);
14356 
14357             mLeft = left;
14358             mTop = top;
14359             mRight = right;
14360             mBottom = bottom;
14361             if (mDisplayList != null) {
14362                 mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
14363             }
14364 
14365             mPrivateFlags |= PFLAG_HAS_BOUNDS;
14366 
14367 
14368             if (sizeChanged) {
14369                 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
14370                     // A change in dimension means an auto-centered pivot point changes, too
14371                     if (mTransformationInfo != null) {
14372                         mTransformationInfo.mMatrixDirty = true;
14373                     }
14374                 }
14375                 sizeChange(newWidth, newHeight, oldWidth, oldHeight);
14376             }
14377 
14378             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
14379                 // If we are visible, force the DRAWN bit to on so that
14380                 // this invalidate will go through (at least to our parent).
14381                 // This is because someone may have invalidated this view
14382                 // before this call to setFrame came in, thereby clearing
14383                 // the DRAWN bit.
14384                 mPrivateFlags |= PFLAG_DRAWN;
14385                 invalidate(sizeChanged);
14386                 // parent display list may need to be recreated based on a change in the bounds
14387                 // of any child
14388                 invalidateParentCaches();
14389             }
14390 
14391             // Reset drawn bit to original value (invalidate turns it off)
14392             mPrivateFlags |= drawn;
14393 
14394             mBackgroundSizeChanged = true;
14395         }
14396         return changed;
14397     }
14398 
14399     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
14400         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
14401         if (mOverlay != null) {
14402             mOverlay.getOverlayView().setRight(newWidth);
14403             mOverlay.getOverlayView().setBottom(newHeight);
14404         }
14405     }
14406 
14407     /**
14408      * Finalize inflating a view from XML.  This is called as the last phase
14409      * of inflation, after all child views have been added.
14410      *
14411      * <p>Even if the subclass overrides onFinishInflate, they should always be
14412      * sure to call the super method, so that we get called.
14413      */
14414     protected void onFinishInflate() {
14415     }
14416 
14417     /**
14418      * Returns the resources associated with this view.
14419      *
14420      * @return Resources object.
14421      */
14422     public Resources getResources() {
14423         return mResources;
14424     }
14425 
14426     /**
14427      * Invalidates the specified Drawable.
14428      *
14429      * @param drawable the drawable to invalidate
14430      */
14431     public void invalidateDrawable(Drawable drawable) {
14432         if (verifyDrawable(drawable)) {
14433             final Rect dirty = drawable.getBounds();
14434             final int scrollX = mScrollX;
14435             final int scrollY = mScrollY;
14436 
14437             invalidate(dirty.left + scrollX, dirty.top + scrollY,
14438                     dirty.right + scrollX, dirty.bottom + scrollY);
14439         }
14440     }
14441 
14442     /**
14443      * Schedules an action on a drawable to occur at a specified time.
14444      *
14445      * @param who the recipient of the action
14446      * @param what the action to run on the drawable
14447      * @param when the time at which the action must occur. Uses the
14448      *        {@link SystemClock#uptimeMillis} timebase.
14449      */
14450     public void scheduleDrawable(Drawable who, Runnable what, long when) {
14451         if (verifyDrawable(who) && what != null) {
14452             final long delay = when - SystemClock.uptimeMillis();
14453             if (mAttachInfo != null) {
14454                 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
14455                         Choreographer.CALLBACK_ANIMATION, what, who,
14456                         Choreographer.subtractFrameDelay(delay));
14457             } else {
14458                 ViewRootImpl.getRunQueue().postDelayed(what, delay);
14459             }
14460         }
14461     }
14462 
14463     /**
14464      * Cancels a scheduled action on a drawable.
14465      *
14466      * @param who the recipient of the action
14467      * @param what the action to cancel
14468      */
14469     public void unscheduleDrawable(Drawable who, Runnable what) {
14470         if (verifyDrawable(who) && what != null) {
14471             if (mAttachInfo != null) {
14472                 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14473                         Choreographer.CALLBACK_ANIMATION, what, who);
14474             } else {
14475                 ViewRootImpl.getRunQueue().removeCallbacks(what);
14476             }
14477         }
14478     }
14479 
14480     /**
14481      * Unschedule any events associated with the given Drawable.  This can be
14482      * used when selecting a new Drawable into a view, so that the previous
14483      * one is completely unscheduled.
14484      *
14485      * @param who The Drawable to unschedule.
14486      *
14487      * @see #drawableStateChanged
14488      */
14489     public void unscheduleDrawable(Drawable who) {
14490         if (mAttachInfo != null && who != null) {
14491             mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14492                     Choreographer.CALLBACK_ANIMATION, null, who);
14493         }
14494     }
14495 
14496     /**
14497      * Resolve the Drawables depending on the layout direction. This is implicitly supposing
14498      * that the View directionality can and will be resolved before its Drawables.
14499      *
14500      * Will call {@link View#onResolveDrawables} when resolution is done.
14501      *
14502      * @hide
14503      */
14504     protected void resolveDrawables() {
14505         if (canResolveLayoutDirection()) {
14506             if (mBackground != null) {
14507                 mBackground.setLayoutDirection(getLayoutDirection());
14508             }
14509             mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
14510             onResolveDrawables(getLayoutDirection());
14511         }
14512     }
14513 
14514     /**
14515      * Called when layout direction has been resolved.
14516      *
14517      * The default implementation does nothing.
14518      *
14519      * @param layoutDirection The resolved layout direction.
14520      *
14521      * @see #LAYOUT_DIRECTION_LTR
14522      * @see #LAYOUT_DIRECTION_RTL
14523      *
14524      * @hide
14525      */
14526     public void onResolveDrawables(int layoutDirection) {
14527     }
14528 
14529     /**
14530      * @hide
14531      */
14532     protected void resetResolvedDrawables() {
14533         mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
14534     }
14535 
14536     private boolean isDrawablesResolved() {
14537         return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
14538     }
14539 
14540     /**
14541      * If your view subclass is displaying its own Drawable objects, it should
14542      * override this function and return true for any Drawable it is
14543      * displaying.  This allows animations for those drawables to be
14544      * scheduled.
14545      *
14546      * <p>Be sure to call through to the super class when overriding this
14547      * function.
14548      *
14549      * @param who The Drawable to verify.  Return true if it is one you are
14550      *            displaying, else return the result of calling through to the
14551      *            super class.
14552      *
14553      * @return boolean If true than the Drawable is being displayed in the
14554      *         view; else false and it is not allowed to animate.
14555      *
14556      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
14557      * @see #drawableStateChanged()
14558      */
14559     protected boolean verifyDrawable(Drawable who) {
14560         return who == mBackground;
14561     }
14562 
14563     /**
14564      * This function is called whenever the state of the view changes in such
14565      * a way that it impacts the state of drawables being shown.
14566      *
14567      * <p>Be sure to call through to the superclass when overriding this
14568      * function.
14569      *
14570      * @see Drawable#setState(int[])
14571      */
14572     protected void drawableStateChanged() {
14573         Drawable d = mBackground;
14574         if (d != null && d.isStateful()) {
14575             d.setState(getDrawableState());
14576         }
14577     }
14578 
14579     /**
14580      * Call this to force a view to update its drawable state. This will cause
14581      * drawableStateChanged to be called on this view. Views that are interested
14582      * in the new state should call getDrawableState.
14583      *
14584      * @see #drawableStateChanged
14585      * @see #getDrawableState
14586      */
14587     public void refreshDrawableState() {
14588         mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14589         drawableStateChanged();
14590 
14591         ViewParent parent = mParent;
14592         if (parent != null) {
14593             parent.childDrawableStateChanged(this);
14594         }
14595     }
14596 
14597     /**
14598      * Return an array of resource IDs of the drawable states representing the
14599      * current state of the view.
14600      *
14601      * @return The current drawable state
14602      *
14603      * @see Drawable#setState(int[])
14604      * @see #drawableStateChanged()
14605      * @see #onCreateDrawableState(int)
14606      */
14607     public final int[] getDrawableState() {
14608         if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
14609             return mDrawableState;
14610         } else {
14611             mDrawableState = onCreateDrawableState(0);
14612             mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
14613             return mDrawableState;
14614         }
14615     }
14616 
14617     /**
14618      * Generate the new {@link android.graphics.drawable.Drawable} state for
14619      * this view. This is called by the view
14620      * system when the cached Drawable state is determined to be invalid.  To
14621      * retrieve the current state, you should use {@link #getDrawableState}.
14622      *
14623      * @param extraSpace if non-zero, this is the number of extra entries you
14624      * would like in the returned array in which you can place your own
14625      * states.
14626      *
14627      * @return Returns an array holding the current {@link Drawable} state of
14628      * the view.
14629      *
14630      * @see #mergeDrawableStates(int[], int[])
14631      */
14632     protected int[] onCreateDrawableState(int extraSpace) {
14633         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
14634                 mParent instanceof View) {
14635             return ((View) mParent).onCreateDrawableState(extraSpace);
14636         }
14637 
14638         int[] drawableState;
14639 
14640         int privateFlags = mPrivateFlags;
14641 
14642         int viewStateIndex = 0;
14643         if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
14644         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
14645         if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
14646         if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
14647         if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
14648         if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
14649         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
14650                 HardwareRenderer.isAvailable()) {
14651             // This is set if HW acceleration is requested, even if the current
14652             // process doesn't allow it.  This is just to allow app preview
14653             // windows to better match their app.
14654             viewStateIndex |= VIEW_STATE_ACCELERATED;
14655         }
14656         if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
14657 
14658         final int privateFlags2 = mPrivateFlags2;
14659         if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
14660         if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
14661 
14662         drawableState = VIEW_STATE_SETS[viewStateIndex];
14663 
14664         //noinspection ConstantIfStatement
14665         if (false) {
14666             Log.i("View", "drawableStateIndex=" + viewStateIndex);
14667             Log.i("View", toString()
14668                     + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
14669                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
14670                     + " fo=" + hasFocus()
14671                     + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
14672                     + " wf=" + hasWindowFocus()
14673                     + ": " + Arrays.toString(drawableState));
14674         }
14675 
14676         if (extraSpace == 0) {
14677             return drawableState;
14678         }
14679 
14680         final int[] fullState;
14681         if (drawableState != null) {
14682             fullState = new int[drawableState.length + extraSpace];
14683             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
14684         } else {
14685             fullState = new int[extraSpace];
14686         }
14687 
14688         return fullState;
14689     }
14690 
14691     /**
14692      * Merge your own state values in <var>additionalState</var> into the base
14693      * state values <var>baseState</var> that were returned by
14694      * {@link #onCreateDrawableState(int)}.
14695      *
14696      * @param baseState The base state values returned by
14697      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
14698      * own additional state values.
14699      *
14700      * @param additionalState The additional state values you would like
14701      * added to <var>baseState</var>; this array is not modified.
14702      *
14703      * @return As a convenience, the <var>baseState</var> array you originally
14704      * passed into the function is returned.
14705      *
14706      * @see #onCreateDrawableState(int)
14707      */
14708     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
14709         final int N = baseState.length;
14710         int i = N - 1;
14711         while (i >= 0 && baseState[i] == 0) {
14712             i--;
14713         }
14714         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
14715         return baseState;
14716     }
14717 
14718     /**
14719      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
14720      * on all Drawable objects associated with this view.
14721      */
14722     public void jumpDrawablesToCurrentState() {
14723         if (mBackground != null) {
14724             mBackground.jumpToCurrentState();
14725         }
14726     }
14727 
14728     /**
14729      * Sets the background color for this view.
14730      * @param color the color of the background
14731      */
14732     @RemotableViewMethod
14733     public void setBackgroundColor(int color) {
14734         if (mBackground instanceof ColorDrawable) {
14735             ((ColorDrawable) mBackground.mutate()).setColor(color);
14736             computeOpaqueFlags();
14737             mBackgroundResource = 0;
14738         } else {
14739             setBackground(new ColorDrawable(color));
14740         }
14741     }
14742 
14743     /**
14744      * Set the background to a given resource. The resource should refer to
14745      * a Drawable object or 0 to remove the background.
14746      * @param resid The identifier of the resource.
14747      *
14748      * @attr ref android.R.styleable#View_background
14749      */
14750     @RemotableViewMethod
14751     public void setBackgroundResource(int resid) {
14752         if (resid != 0 && resid == mBackgroundResource) {
14753             return;
14754         }
14755 
14756         Drawable d= null;
14757         if (resid != 0) {
14758             d = mResources.getDrawable(resid);
14759         }
14760         setBackground(d);
14761 
14762         mBackgroundResource = resid;
14763     }
14764 
14765     /**
14766      * Set the background to a given Drawable, or remove the background. If the
14767      * background has padding, this View's padding is set to the background's
14768      * padding. However, when a background is removed, this View's padding isn't
14769      * touched. If setting the padding is desired, please use
14770      * {@link #setPadding(int, int, int, int)}.
14771      *
14772      * @param background The Drawable to use as the background, or null to remove the
14773      *        background
14774      */
14775     public void setBackground(Drawable background) {
14776         //noinspection deprecation
14777         setBackgroundDrawable(background);
14778     }
14779 
14780     /**
14781      * @deprecated use {@link #setBackground(Drawable)} instead
14782      */
14783     @Deprecated
14784     public void setBackgroundDrawable(Drawable background) {
14785         computeOpaqueFlags();
14786 
14787         if (background == mBackground) {
14788             return;
14789         }
14790 
14791         boolean requestLayout = false;
14792 
14793         mBackgroundResource = 0;
14794 
14795         /*
14796          * Regardless of whether we're setting a new background or not, we want
14797          * to clear the previous drawable.
14798          */
14799         if (mBackground != null) {
14800             mBackground.setCallback(null);
14801             unscheduleDrawable(mBackground);
14802         }
14803 
14804         if (background != null) {
14805             Rect padding = sThreadLocal.get();
14806             if (padding == null) {
14807                 padding = new Rect();
14808                 sThreadLocal.set(padding);
14809             }
14810             resetResolvedDrawables();
14811             background.setLayoutDirection(getLayoutDirection());
14812             if (background.getPadding(padding)) {
14813                 resetResolvedPadding();
14814                 switch (background.getLayoutDirection()) {
14815                     case LAYOUT_DIRECTION_RTL:
14816                         mUserPaddingLeftInitial = padding.right;
14817                         mUserPaddingRightInitial = padding.left;
14818                         internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
14819                         break;
14820                     case LAYOUT_DIRECTION_LTR:
14821                     default:
14822                         mUserPaddingLeftInitial = padding.left;
14823                         mUserPaddingRightInitial = padding.right;
14824                         internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
14825                 }
14826             }
14827 
14828             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
14829             // if it has a different minimum size, we should layout again
14830             if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() ||
14831                     mBackground.getMinimumWidth() != background.getMinimumWidth()) {
14832                 requestLayout = true;
14833             }
14834 
14835             background.setCallback(this);
14836             if (background.isStateful()) {
14837                 background.setState(getDrawableState());
14838             }
14839             background.setVisible(getVisibility() == VISIBLE, false);
14840             mBackground = background;
14841 
14842             if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
14843                 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
14844                 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
14845                 requestLayout = true;
14846             }
14847         } else {
14848             /* Remove the background */
14849             mBackground = null;
14850 
14851             if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
14852                 /*
14853                  * This view ONLY drew the background before and we're removing
14854                  * the background, so now it won't draw anything
14855                  * (hence we SKIP_DRAW)
14856                  */
14857                 mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
14858                 mPrivateFlags |= PFLAG_SKIP_DRAW;
14859             }
14860 
14861             /*
14862              * When the background is set, we try to apply its padding to this
14863              * View. When the background is removed, we don't touch this View's
14864              * padding. This is noted in the Javadocs. Hence, we don't need to
14865              * requestLayout(), the invalidate() below is sufficient.
14866              */
14867 
14868             // The old background's minimum size could have affected this
14869             // View's layout, so let's requestLayout
14870             requestLayout = true;
14871         }
14872 
14873         computeOpaqueFlags();
14874 
14875         if (requestLayout) {
14876             requestLayout();
14877         }
14878 
14879         mBackgroundSizeChanged = true;
14880         invalidate(true);
14881     }
14882 
14883     /**
14884      * Gets the background drawable
14885      *
14886      * @return The drawable used as the background for this view, if any.
14887      *
14888      * @see #setBackground(Drawable)
14889      *
14890      * @attr ref android.R.styleable#View_background
14891      */
14892     public Drawable getBackground() {
14893         return mBackground;
14894     }
14895 
14896     /**
14897      * Sets the padding. The view may add on the space required to display
14898      * the scrollbars, depending on the style and visibility of the scrollbars.
14899      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
14900      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
14901      * from the values set in this call.
14902      *
14903      * @attr ref android.R.styleable#View_padding
14904      * @attr ref android.R.styleable#View_paddingBottom
14905      * @attr ref android.R.styleable#View_paddingLeft
14906      * @attr ref android.R.styleable#View_paddingRight
14907      * @attr ref android.R.styleable#View_paddingTop
14908      * @param left the left padding in pixels
14909      * @param top the top padding in pixels
14910      * @param right the right padding in pixels
14911      * @param bottom the bottom padding in pixels
14912      */
14913     public void setPadding(int left, int top, int right, int bottom) {
14914         resetResolvedPadding();
14915 
14916         mUserPaddingStart = UNDEFINED_PADDING;
14917         mUserPaddingEnd = UNDEFINED_PADDING;
14918 
14919         mUserPaddingLeftInitial = left;
14920         mUserPaddingRightInitial = right;
14921 
14922         internalSetPadding(left, top, right, bottom);
14923     }
14924 
14925     /**
14926      * @hide
14927      */
14928     protected void internalSetPadding(int left, int top, int right, int bottom) {
14929         mUserPaddingLeft = left;
14930         mUserPaddingRight = right;
14931         mUserPaddingBottom = bottom;
14932 
14933         final int viewFlags = mViewFlags;
14934         boolean changed = false;
14935 
14936         // Common case is there are no scroll bars.
14937         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
14938             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
14939                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
14940                         ? 0 : getVerticalScrollbarWidth();
14941                 switch (mVerticalScrollbarPosition) {
14942                     case SCROLLBAR_POSITION_DEFAULT:
14943                         if (isLayoutRtl()) {
14944                             left += offset;
14945                         } else {
14946                             right += offset;
14947                         }
14948                         break;
14949                     case SCROLLBAR_POSITION_RIGHT:
14950                         right += offset;
14951                         break;
14952                     case SCROLLBAR_POSITION_LEFT:
14953                         left += offset;
14954                         break;
14955                 }
14956             }
14957             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
14958                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
14959                         ? 0 : getHorizontalScrollbarHeight();
14960             }
14961         }
14962 
14963         if (mPaddingLeft != left) {
14964             changed = true;
14965             mPaddingLeft = left;
14966         }
14967         if (mPaddingTop != top) {
14968             changed = true;
14969             mPaddingTop = top;
14970         }
14971         if (mPaddingRight != right) {
14972             changed = true;
14973             mPaddingRight = right;
14974         }
14975         if (mPaddingBottom != bottom) {
14976             changed = true;
14977             mPaddingBottom = bottom;
14978         }
14979 
14980         if (changed) {
14981             requestLayout();
14982         }
14983     }
14984 
14985     /**
14986      * Sets the relative padding. The view may add on the space required to display
14987      * the scrollbars, depending on the style and visibility of the scrollbars.
14988      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
14989      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
14990      * from the values set in this call.
14991      *
14992      * @attr ref android.R.styleable#View_padding
14993      * @attr ref android.R.styleable#View_paddingBottom
14994      * @attr ref android.R.styleable#View_paddingStart
14995      * @attr ref android.R.styleable#View_paddingEnd
14996      * @attr ref android.R.styleable#View_paddingTop
14997      * @param start the start padding in pixels
14998      * @param top the top padding in pixels
14999      * @param end the end padding in pixels
15000      * @param bottom the bottom padding in pixels
15001      */
15002     public void setPaddingRelative(int start, int top, int end, int bottom) {
15003         resetResolvedPadding();
15004 
15005         mUserPaddingStart = start;
15006         mUserPaddingEnd = end;
15007 
15008         switch(getLayoutDirection()) {
15009             case LAYOUT_DIRECTION_RTL:
15010                 mUserPaddingLeftInitial = end;
15011                 mUserPaddingRightInitial = start;
15012                 internalSetPadding(end, top, start, bottom);
15013                 break;
15014             case LAYOUT_DIRECTION_LTR:
15015             default:
15016                 mUserPaddingLeftInitial = start;
15017                 mUserPaddingRightInitial = end;
15018                 internalSetPadding(start, top, end, bottom);
15019         }
15020     }
15021 
15022     /**
15023      * Returns the top padding of this view.
15024      *
15025      * @return the top padding in pixels
15026      */
15027     public int getPaddingTop() {
15028         return mPaddingTop;
15029     }
15030 
15031     /**
15032      * Returns the bottom padding of this view. If there are inset and enabled
15033      * scrollbars, this value may include the space required to display the
15034      * scrollbars as well.
15035      *
15036      * @return the bottom padding in pixels
15037      */
15038     public int getPaddingBottom() {
15039         return mPaddingBottom;
15040     }
15041 
15042     /**
15043      * Returns the left padding of this view. If there are inset and enabled
15044      * scrollbars, this value may include the space required to display the
15045      * scrollbars as well.
15046      *
15047      * @return the left padding in pixels
15048      */
15049     public int getPaddingLeft() {
15050         if (!isPaddingResolved()) {
15051             resolvePadding();
15052         }
15053         return mPaddingLeft;
15054     }
15055 
15056     /**
15057      * Returns the start padding of this view depending on its resolved layout direction.
15058      * If there are inset and enabled scrollbars, this value may include the space
15059      * required to display the scrollbars as well.
15060      *
15061      * @return the start padding in pixels
15062      */
15063     public int getPaddingStart() {
15064         if (!isPaddingResolved()) {
15065             resolvePadding();
15066         }
15067         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
15068                 mPaddingRight : mPaddingLeft;
15069     }
15070 
15071     /**
15072      * Returns the right padding of this view. If there are inset and enabled
15073      * scrollbars, this value may include the space required to display the
15074      * scrollbars as well.
15075      *
15076      * @return the right padding in pixels
15077      */
15078     public int getPaddingRight() {
15079         if (!isPaddingResolved()) {
15080             resolvePadding();
15081         }
15082         return mPaddingRight;
15083     }
15084 
15085     /**
15086      * Returns the end padding of this view depending on its resolved layout direction.
15087      * If there are inset and enabled scrollbars, this value may include the space
15088      * required to display the scrollbars as well.
15089      *
15090      * @return the end padding in pixels
15091      */
15092     public int getPaddingEnd() {
15093         if (!isPaddingResolved()) {
15094             resolvePadding();
15095         }
15096         return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
15097                 mPaddingLeft : mPaddingRight;
15098     }
15099 
15100     /**
15101      * Return if the padding as been set thru relative values
15102      * {@link #setPaddingRelative(int, int, int, int)} or thru
15103      * @attr ref android.R.styleable#View_paddingStart or
15104      * @attr ref android.R.styleable#View_paddingEnd
15105      *
15106      * @return true if the padding is relative or false if it is not.
15107      */
15108     public boolean isPaddingRelative() {
15109         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
15110     }
15111 
15112     Insets computeOpticalInsets() {
15113         return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
15114     }
15115 
15116     /**
15117      * @hide
15118      */
15119     public void resetPaddingToInitialValues() {
15120         if (isRtlCompatibilityMode()) {
15121             mPaddingLeft = mUserPaddingLeftInitial;
15122             mPaddingRight = mUserPaddingRightInitial;
15123             return;
15124         }
15125         if (isLayoutRtl()) {
15126             mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
15127             mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
15128         } else {
15129             mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
15130             mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
15131         }
15132     }
15133 
15134     /**
15135      * @hide
15136      */
15137     public Insets getOpticalInsets() {
15138         if (mLayoutInsets == null) {
15139             mLayoutInsets = computeOpticalInsets();
15140         }
15141         return mLayoutInsets;
15142     }
15143 
15144     /**
15145      * Changes the selection state of this view. A view can be selected or not.
15146      * Note that selection is not the same as focus. Views are typically
15147      * selected in the context of an AdapterView like ListView or GridView;
15148      * the selected view is the view that is highlighted.
15149      *
15150      * @param selected true if the view must be selected, false otherwise
15151      */
15152     public void setSelected(boolean selected) {
15153         if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
15154             mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
15155             if (!selected) resetPressedState();
15156             invalidate(true);
15157             refreshDrawableState();
15158             dispatchSetSelected(selected);
15159             if (AccessibilityManager.getInstance(mContext).isEnabled()) {
15160                 notifyAccessibilityStateChanged();
15161             }
15162         }
15163     }
15164 
15165     /**
15166      * Dispatch setSelected to all of this View's children.
15167      *
15168      * @see #setSelected(boolean)
15169      *
15170      * @param selected The new selected state
15171      */
15172     protected void dispatchSetSelected(boolean selected) {
15173     }
15174 
15175     /**
15176      * Indicates the selection state of this view.
15177      *
15178      * @return true if the view is selected, false otherwise
15179      */
15180     @ViewDebug.ExportedProperty
15181     public boolean isSelected() {
15182         return (mPrivateFlags & PFLAG_SELECTED) != 0;
15183     }
15184 
15185     /**
15186      * Changes the activated state of this view. A view can be activated or not.
15187      * Note that activation is not the same as selection.  Selection is
15188      * a transient property, representing the view (hierarchy) the user is
15189      * currently interacting with.  Activation is a longer-term state that the
15190      * user can move views in and out of.  For example, in a list view with
15191      * single or multiple selection enabled, the views in the current selection
15192      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
15193      * here.)  The activated state is propagated down to children of the view it
15194      * is set on.
15195      *
15196      * @param activated true if the view must be activated, false otherwise
15197      */
15198     public void setActivated(boolean activated) {
15199         if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
15200             mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
15201             invalidate(true);
15202             refreshDrawableState();
15203             dispatchSetActivated(activated);
15204         }
15205     }
15206 
15207     /**
15208      * Dispatch setActivated to all of this View's children.
15209      *
15210      * @see #setActivated(boolean)
15211      *
15212      * @param activated The new activated state
15213      */
15214     protected void dispatchSetActivated(boolean activated) {
15215     }
15216 
15217     /**
15218      * Indicates the activation state of this view.
15219      *
15220      * @return true if the view is activated, false otherwise
15221      */
15222     @ViewDebug.ExportedProperty
15223     public boolean isActivated() {
15224         return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
15225     }
15226 
15227     /**
15228      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
15229      * observer can be used to get notifications when global events, like
15230      * layout, happen.
15231      *
15232      * The returned ViewTreeObserver observer is not guaranteed to remain
15233      * valid for the lifetime of this View. If the caller of this method keeps
15234      * a long-lived reference to ViewTreeObserver, it should always check for
15235      * the return value of {@link ViewTreeObserver#isAlive()}.
15236      *
15237      * @return The ViewTreeObserver for this view's hierarchy.
15238      */
15239     public ViewTreeObserver getViewTreeObserver() {
15240         if (mAttachInfo != null) {
15241             return mAttachInfo.mTreeObserver;
15242         }
15243         if (mFloatingTreeObserver == null) {
15244             mFloatingTreeObserver = new ViewTreeObserver();
15245         }
15246         return mFloatingTreeObserver;
15247     }
15248 
15249     /**
15250      * <p>Finds the topmost view in the current view hierarchy.</p>
15251      *
15252      * @return the topmost view containing this view
15253      */
15254     public View getRootView() {
15255         if (mAttachInfo != null) {
15256             final View v = mAttachInfo.mRootView;
15257             if (v != null) {
15258                 return v;
15259             }
15260         }
15261 
15262         View parent = this;
15263 
15264         while (parent.mParent != null && parent.mParent instanceof View) {
15265             parent = (View) parent.mParent;
15266         }
15267 
15268         return parent;
15269     }
15270 
15271     /**
15272      * <p>Computes the coordinates of this view on the screen. The argument
15273      * must be an array of two integers. After the method returns, the array
15274      * contains the x and y location in that order.</p>
15275      *
15276      * @param location an array of two integers in which to hold the coordinates
15277      */
15278     public void getLocationOnScreen(int[] location) {
15279         getLocationInWindow(location);
15280 
15281         final AttachInfo info = mAttachInfo;
15282         if (info != null) {
15283             location[0] += info.mWindowLeft;
15284             location[1] += info.mWindowTop;
15285         }
15286     }
15287 
15288     /**
15289      * <p>Computes the coordinates of this view in its window. The argument
15290      * must be an array of two integers. After the method returns, the array
15291      * contains the x and y location in that order.</p>
15292      *
15293      * @param location an array of two integers in which to hold the coordinates
15294      */
15295     public void getLocationInWindow(int[] location) {
15296         if (location == null || location.length < 2) {
15297             throw new IllegalArgumentException("location must be an array of two integers");
15298         }
15299 
15300         if (mAttachInfo == null) {
15301             // When the view is not attached to a window, this method does not make sense
15302             location[0] = location[1] = 0;
15303             return;
15304         }
15305 
15306         float[] position = mAttachInfo.mTmpTransformLocation;
15307         position[0] = position[1] = 0.0f;
15308 
15309         if (!hasIdentityMatrix()) {
15310             getMatrix().mapPoints(position);
15311         }
15312 
15313         position[0] += mLeft;
15314         position[1] += mTop;
15315 
15316         ViewParent viewParent = mParent;
15317         while (viewParent instanceof View) {
15318             final View view = (View) viewParent;
15319 
15320             position[0] -= view.mScrollX;
15321             position[1] -= view.mScrollY;
15322 
15323             if (!view.hasIdentityMatrix()) {
15324                 view.getMatrix().mapPoints(position);
15325             }
15326 
15327             position[0] += view.mLeft;
15328             position[1] += view.mTop;
15329 
15330             viewParent = view.mParent;
15331          }
15332 
15333         if (viewParent instanceof ViewRootImpl) {
15334             // *cough*
15335             final ViewRootImpl vr = (ViewRootImpl) viewParent;
15336             position[1] -= vr.mCurScrollY;
15337         }
15338 
15339         location[0] = (int) (position[0] + 0.5f);
15340         location[1] = (int) (position[1] + 0.5f);
15341     }
15342 
15343     /**
15344      * {@hide}
15345      * @param id the id of the view to be found
15346      * @return the view of the specified id, null if cannot be found
15347      */
15348     protected View findViewTraversal(int id) {
15349         if (id == mID) {
15350             return this;
15351         }
15352         return null;
15353     }
15354 
15355     /**
15356      * {@hide}
15357      * @param tag the tag of the view to be found
15358      * @return the view of specified tag, null if cannot be found
15359      */
15360     protected View findViewWithTagTraversal(Object tag) {
15361         if (tag != null && tag.equals(mTag)) {
15362             return this;
15363         }
15364         return null;
15365     }
15366 
15367     /**
15368      * {@hide}
15369      * @param predicate The predicate to evaluate.
15370      * @param childToSkip If not null, ignores this child during the recursive traversal.
15371      * @return The first view that matches the predicate or null.
15372      */
15373     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
15374         if (predicate.apply(this)) {
15375             return this;
15376         }
15377         return null;
15378     }
15379 
15380     /**
15381      * Look for a child view with the given id.  If this view has the given
15382      * id, return this view.
15383      *
15384      * @param id The id to search for.
15385      * @return The view that has the given id in the hierarchy or null
15386      */
15387     public final View findViewById(int id) {
15388         if (id < 0) {
15389             return null;
15390         }
15391         return findViewTraversal(id);
15392     }
15393 
15394     /**
15395      * Finds a view by its unuque and stable accessibility id.
15396      *
15397      * @param accessibilityId The searched accessibility id.
15398      * @return The found view.
15399      */
15400     final View findViewByAccessibilityId(int accessibilityId) {
15401         if (accessibilityId < 0) {
15402             return null;
15403         }
15404         return findViewByAccessibilityIdTraversal(accessibilityId);
15405     }
15406 
15407     /**
15408      * Performs the traversal to find a view by its unuque and stable accessibility id.
15409      *
15410      * <strong>Note:</strong>This method does not stop at the root namespace
15411      * boundary since the user can touch the screen at an arbitrary location
15412      * potentially crossing the root namespace bounday which will send an
15413      * accessibility event to accessibility services and they should be able
15414      * to obtain the event source. Also accessibility ids are guaranteed to be
15415      * unique in the window.
15416      *
15417      * @param accessibilityId The accessibility id.
15418      * @return The found view.
15419      *
15420      * @hide
15421      */
15422     public View findViewByAccessibilityIdTraversal(int accessibilityId) {
15423         if (getAccessibilityViewId() == accessibilityId) {
15424             return this;
15425         }
15426         return null;
15427     }
15428 
15429     /**
15430      * Look for a child view with the given tag.  If this view has the given
15431      * tag, return this view.
15432      *
15433      * @param tag The tag to search for, using "tag.equals(getTag())".
15434      * @return The View that has the given tag in the hierarchy or null
15435      */
15436     public final View findViewWithTag(Object tag) {
15437         if (tag == null) {
15438             return null;
15439         }
15440         return findViewWithTagTraversal(tag);
15441     }
15442 
15443     /**
15444      * {@hide}
15445      * Look for a child view that matches the specified predicate.
15446      * If this view matches the predicate, return this view.
15447      *
15448      * @param predicate The predicate to evaluate.
15449      * @return The first view that matches the predicate or null.
15450      */
15451     public final View findViewByPredicate(Predicate<View> predicate) {
15452         return findViewByPredicateTraversal(predicate, null);
15453     }
15454 
15455     /**
15456      * {@hide}
15457      * Look for a child view that matches the specified predicate,
15458      * starting with the specified view and its descendents and then
15459      * recusively searching the ancestors and siblings of that view
15460      * until this view is reached.
15461      *
15462      * This method is useful in cases where the predicate does not match
15463      * a single unique view (perhaps multiple views use the same id)
15464      * and we are trying to find the view that is "closest" in scope to the
15465      * starting view.
15466      *
15467      * @param start The view to start from.
15468      * @param predicate The predicate to evaluate.
15469      * @return The first view that matches the predicate or null.
15470      */
15471     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
15472         View childToSkip = null;
15473         for (;;) {
15474             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
15475             if (view != null || start == this) {
15476                 return view;
15477             }
15478 
15479             ViewParent parent = start.getParent();
15480             if (parent == null || !(parent instanceof View)) {
15481                 return null;
15482             }
15483 
15484             childToSkip = start;
15485             start = (View) parent;
15486         }
15487     }
15488 
15489     /**
15490      * Sets the identifier for this view. The identifier does not have to be
15491      * unique in this view's hierarchy. The identifier should be a positive
15492      * number.
15493      *
15494      * @see #NO_ID
15495      * @see #getId()
15496      * @see #findViewById(int)
15497      *
15498      * @param id a number used to identify the view
15499      *
15500      * @attr ref android.R.styleable#View_id
15501      */
15502     public void setId(int id) {
15503         mID = id;
15504         if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
15505             mID = generateViewId();
15506         }
15507     }
15508 
15509     /**
15510      * {@hide}
15511      *
15512      * @param isRoot true if the view belongs to the root namespace, false
15513      *        otherwise
15514      */
15515     public void setIsRootNamespace(boolean isRoot) {
15516         if (isRoot) {
15517             mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
15518         } else {
15519             mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
15520         }
15521     }
15522 
15523     /**
15524      * {@hide}
15525      *
15526      * @return true if the view belongs to the root namespace, false otherwise
15527      */
15528     public boolean isRootNamespace() {
15529         return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
15530     }
15531 
15532     /**
15533      * Returns this view's identifier.
15534      *
15535      * @return a positive integer used to identify the view or {@link #NO_ID}
15536      *         if the view has no ID
15537      *
15538      * @see #setId(int)
15539      * @see #findViewById(int)
15540      * @attr ref android.R.styleable#View_id
15541      */
15542     @ViewDebug.CapturedViewProperty
15543     public int getId() {
15544         return mID;
15545     }
15546 
15547     /**
15548      * Returns this view's tag.
15549      *
15550      * @return the Object stored in this view as a tag
15551      *
15552      * @see #setTag(Object)
15553      * @see #getTag(int)
15554      */
15555     @ViewDebug.ExportedProperty
15556     public Object getTag() {
15557         return mTag;
15558     }
15559 
15560     /**
15561      * Sets the tag associated with this view. A tag can be used to mark
15562      * a view in its hierarchy and does not have to be unique within the
15563      * hierarchy. Tags can also be used to store data within a view without
15564      * resorting to another data structure.
15565      *
15566      * @param tag an Object to tag the view with
15567      *
15568      * @see #getTag()
15569      * @see #setTag(int, Object)
15570      */
15571     public void setTag(final Object tag) {
15572         mTag = tag;
15573     }
15574 
15575     /**
15576      * Returns the tag associated with this view and the specified key.
15577      *
15578      * @param key The key identifying the tag
15579      *
15580      * @return the Object stored in this view as a tag
15581      *
15582      * @see #setTag(int, Object)
15583      * @see #getTag()
15584      */
15585     public Object getTag(int key) {
15586         if (mKeyedTags != null) return mKeyedTags.get(key);
15587         return null;
15588     }
15589 
15590     /**
15591      * Sets a tag associated with this view and a key. A tag can be used
15592      * to mark a view in its hierarchy and does not have to be unique within
15593      * the hierarchy. Tags can also be used to store data within a view
15594      * without resorting to another data structure.
15595      *
15596      * The specified key should be an id declared in the resources of the
15597      * application to ensure it is unique (see the <a
15598      * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
15599      * Keys identified as belonging to
15600      * the Android framework or not associated with any package will cause
15601      * an {@link IllegalArgumentException} to be thrown.
15602      *
15603      * @param key The key identifying the tag
15604      * @param tag An Object to tag the view with
15605      *
15606      * @throws IllegalArgumentException If they specified key is not valid
15607      *
15608      * @see #setTag(Object)
15609      * @see #getTag(int)
15610      */
15611     public void setTag(int key, final Object tag) {
15612         // If the package id is 0x00 or 0x01, it's either an undefined package
15613         // or a framework id
15614         if ((key >>> 24) < 2) {
15615             throw new IllegalArgumentException("The key must be an application-specific "
15616                     + "resource id.");
15617         }
15618 
15619         setKeyedTag(key, tag);
15620     }
15621 
15622     /**
15623      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
15624      * framework id.
15625      *
15626      * @hide
15627      */
15628     public void setTagInternal(int key, Object tag) {
15629         if ((key >>> 24) != 0x1) {
15630             throw new IllegalArgumentException("The key must be a framework-specific "
15631                     + "resource id.");
15632         }
15633 
15634         setKeyedTag(key, tag);
15635     }
15636 
15637     private void setKeyedTag(int key, Object tag) {
15638         if (mKeyedTags == null) {
15639             mKeyedTags = new SparseArray<Object>();
15640         }
15641 
15642         mKeyedTags.put(key, tag);
15643     }
15644 
15645     /**
15646      * Prints information about this view in the log output, with the tag
15647      * {@link #VIEW_LOG_TAG}.
15648      *
15649      * @hide
15650      */
15651     public void debug() {
15652         debug(0);
15653     }
15654 
15655     /**
15656      * Prints information about this view in the log output, with the tag
15657      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
15658      * indentation defined by the <code>depth</code>.
15659      *
15660      * @param depth the indentation level
15661      *
15662      * @hide
15663      */
15664     protected void debug(int depth) {
15665         String output = debugIndent(depth - 1);
15666 
15667         output += "+ " + this;
15668         int id = getId();
15669         if (id != -1) {
15670             output += " (id=" + id + ")";
15671         }
15672         Object tag = getTag();
15673         if (tag != null) {
15674             output += " (tag=" + tag + ")";
15675         }
15676         Log.d(VIEW_LOG_TAG, output);
15677 
15678         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
15679             output = debugIndent(depth) + " FOCUSED";
15680             Log.d(VIEW_LOG_TAG, output);
15681         }
15682 
15683         output = debugIndent(depth);
15684         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
15685                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
15686                 + "} ";
15687         Log.d(VIEW_LOG_TAG, output);
15688 
15689         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
15690                 || mPaddingBottom != 0) {
15691             output = debugIndent(depth);
15692             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
15693                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
15694             Log.d(VIEW_LOG_TAG, output);
15695         }
15696 
15697         output = debugIndent(depth);
15698         output += "mMeasureWidth=" + mMeasuredWidth +
15699                 " mMeasureHeight=" + mMeasuredHeight;
15700         Log.d(VIEW_LOG_TAG, output);
15701 
15702         output = debugIndent(depth);
15703         if (mLayoutParams == null) {
15704             output += "BAD! no layout params";
15705         } else {
15706             output = mLayoutParams.debug(output);
15707         }
15708         Log.d(VIEW_LOG_TAG, output);
15709 
15710         output = debugIndent(depth);
15711         output += "flags={";
15712         output += View.printFlags(mViewFlags);
15713         output += "}";
15714         Log.d(VIEW_LOG_TAG, output);
15715 
15716         output = debugIndent(depth);
15717         output += "privateFlags={";
15718         output += View.printPrivateFlags(mPrivateFlags);
15719         output += "}";
15720         Log.d(VIEW_LOG_TAG, output);
15721     }
15722 
15723     /**
15724      * Creates a string of whitespaces used for indentation.
15725      *
15726      * @param depth the indentation level
15727      * @return a String containing (depth * 2 + 3) * 2 white spaces
15728      *
15729      * @hide
15730      */
15731     protected static String debugIndent(int depth) {
15732         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
15733         for (int i = 0; i < (depth * 2) + 3; i++) {
15734             spaces.append(' ').append(' ');
15735         }
15736         return spaces.toString();
15737     }
15738 
15739     /**
15740      * <p>Return the offset of the widget's text baseline from the widget's top
15741      * boundary. If this widget does not support baseline alignment, this
15742      * method returns -1. </p>
15743      *
15744      * @return the offset of the baseline within the widget's bounds or -1
15745      *         if baseline alignment is not supported
15746      */
15747     @ViewDebug.ExportedProperty(category = "layout")
15748     public int getBaseline() {
15749         return -1;
15750     }
15751 
15752     /**
15753      * Returns whether the view hierarchy is currently undergoing a layout pass. This
15754      * information is useful to avoid situations such as calling {@link #requestLayout()} during
15755      * a layout pass.
15756      *
15757      * @return whether the view hierarchy is currently undergoing a layout pass
15758      */
15759     public boolean isInLayout() {
15760         ViewRootImpl viewRoot = getViewRootImpl();
15761         return (viewRoot != null && viewRoot.isInLayout());
15762     }
15763 
15764     /**
15765      * Call this when something has changed which has invalidated the
15766      * layout of this view. This will schedule a layout pass of the view
15767      * tree. This should not be called while the view hierarchy is currently in a layout
15768      * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
15769      * end of the current layout pass (and then layout will run again) or after the current
15770      * frame is drawn and the next layout occurs.
15771      *
15772      * <p>Subclasses which override this method should call the superclass method to
15773      * handle possible request-during-layout errors correctly.</p>
15774      */
15775     public void requestLayout() {
15776         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
15777             // Only trigger request-during-layout logic if this is the view requesting it,
15778             // not the views in its parent hierarchy
15779             ViewRootImpl viewRoot = getViewRootImpl();
15780             if (viewRoot != null && viewRoot.isInLayout()) {
15781                 if (!viewRoot.requestLayoutDuringLayout(this)) {
15782                     return;
15783                 }
15784             }
15785             mAttachInfo.mViewRequestingLayout = this;
15786         }
15787 
15788         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
15789         mPrivateFlags |= PFLAG_INVALIDATED;
15790 
15791         if (mParent != null && !mParent.isLayoutRequested()) {
15792             mParent.requestLayout();
15793         }
15794         if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
15795             mAttachInfo.mViewRequestingLayout = null;
15796         }
15797     }
15798 
15799     /**
15800      * Forces this view to be laid out during the next layout pass.
15801      * This method does not call requestLayout() or forceLayout()
15802      * on the parent.
15803      */
15804     public void forceLayout() {
15805         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
15806         mPrivateFlags |= PFLAG_INVALIDATED;
15807     }
15808 
15809     /**
15810      * <p>
15811      * This is called to find out how big a view should be. The parent
15812      * supplies constraint information in the width and height parameters.
15813      * </p>
15814      *
15815      * <p>
15816      * The actual measurement work of a view is performed in
15817      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
15818      * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
15819      * </p>
15820      *
15821      *
15822      * @param widthMeasureSpec Horizontal space requirements as imposed by the
15823      *        parent
15824      * @param heightMeasureSpec Vertical space requirements as imposed by the
15825      *        parent
15826      *
15827      * @see #onMeasure(int, int)
15828      */
15829     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
15830         boolean optical = isLayoutModeOptical(this);
15831         if (optical != isLayoutModeOptical(mParent)) {
15832             Insets insets = getOpticalInsets();
15833             int oWidth  = insets.left + insets.right;
15834             int oHeight = insets.top  + insets.bottom;
15835             widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
15836             heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
15837         }
15838         if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
15839                 widthMeasureSpec != mOldWidthMeasureSpec ||
15840                 heightMeasureSpec != mOldHeightMeasureSpec) {
15841 
15842             // first clears the measured dimension flag
15843             mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
15844 
15845             resolveRtlPropertiesIfNeeded();
15846 
15847             // measure ourselves, this should set the measured dimension flag back
15848             onMeasure(widthMeasureSpec, heightMeasureSpec);
15849 
15850             // flag not set, setMeasuredDimension() was not invoked, we raise
15851             // an exception to warn the developer
15852             if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
15853                 throw new IllegalStateException("onMeasure() did not set the"
15854                         + " measured dimension by calling"
15855                         + " setMeasuredDimension()");
15856             }
15857 
15858             mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
15859         }
15860 
15861         mOldWidthMeasureSpec = widthMeasureSpec;
15862         mOldHeightMeasureSpec = heightMeasureSpec;
15863     }
15864 
15865     /**
15866      * <p>
15867      * Measure the view and its content to determine the measured width and the
15868      * measured height. This method is invoked by {@link #measure(int, int)} and
15869      * should be overriden by subclasses to provide accurate and efficient
15870      * measurement of their contents.
15871      * </p>
15872      *
15873      * <p>
15874      * <strong>CONTRACT:</strong> When overriding this method, you
15875      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
15876      * measured width and height of this view. Failure to do so will trigger an
15877      * <code>IllegalStateException</code>, thrown by
15878      * {@link #measure(int, int)}. Calling the superclass'
15879      * {@link #onMeasure(int, int)} is a valid use.
15880      * </p>
15881      *
15882      * <p>
15883      * The base class implementation of measure defaults to the background size,
15884      * unless a larger size is allowed by the MeasureSpec. Subclasses should
15885      * override {@link #onMeasure(int, int)} to provide better measurements of
15886      * their content.
15887      * </p>
15888      *
15889      * <p>
15890      * If this method is overridden, it is the subclass's responsibility to make
15891      * sure the measured height and width are at least the view's minimum height
15892      * and width ({@link #getSuggestedMinimumHeight()} and
15893      * {@link #getSuggestedMinimumWidth()}).
15894      * </p>
15895      *
15896      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
15897      *                         The requirements are encoded with
15898      *                         {@link android.view.View.MeasureSpec}.
15899      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
15900      *                         The requirements are encoded with
15901      *                         {@link android.view.View.MeasureSpec}.
15902      *
15903      * @see #getMeasuredWidth()
15904      * @see #getMeasuredHeight()
15905      * @see #setMeasuredDimension(int, int)
15906      * @see #getSuggestedMinimumHeight()
15907      * @see #getSuggestedMinimumWidth()
15908      * @see android.view.View.MeasureSpec#getMode(int)
15909      * @see android.view.View.MeasureSpec#getSize(int)
15910      */
15911     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
15912         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
15913                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
15914     }
15915 
15916     /**
15917      * <p>This method must be called by {@link #onMeasure(int, int)} to store the
15918      * measured width and measured height. Failing to do so will trigger an
15919      * exception at measurement time.</p>
15920      *
15921      * @param measuredWidth The measured width of this view.  May be a complex
15922      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15923      * {@link #MEASURED_STATE_TOO_SMALL}.
15924      * @param measuredHeight The measured height of this view.  May be a complex
15925      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15926      * {@link #MEASURED_STATE_TOO_SMALL}.
15927      */
15928     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
15929         boolean optical = isLayoutModeOptical(this);
15930         if (optical != isLayoutModeOptical(mParent)) {
15931             Insets insets = getOpticalInsets();
15932             int opticalWidth  = insets.left + insets.right;
15933             int opticalHeight = insets.top  + insets.bottom;
15934 
15935             measuredWidth  += optical ? opticalWidth  : -opticalWidth;
15936             measuredHeight += optical ? opticalHeight : -opticalHeight;
15937         }
15938         mMeasuredWidth = measuredWidth;
15939         mMeasuredHeight = measuredHeight;
15940 
15941         mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
15942     }
15943 
15944     /**
15945      * Merge two states as returned by {@link #getMeasuredState()}.
15946      * @param curState The current state as returned from a view or the result
15947      * of combining multiple views.
15948      * @param newState The new view state to combine.
15949      * @return Returns a new integer reflecting the combination of the two
15950      * states.
15951      */
15952     public static int combineMeasuredStates(int curState, int newState) {
15953         return curState | newState;
15954     }
15955 
15956     /**
15957      * Version of {@link #resolveSizeAndState(int, int, int)}
15958      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
15959      */
15960     public static int resolveSize(int size, int measureSpec) {
15961         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
15962     }
15963 
15964     /**
15965      * Utility to reconcile a desired size and state, with constraints imposed
15966      * by a MeasureSpec.  Will take the desired size, unless a different size
15967      * is imposed by the constraints.  The returned value is a compound integer,
15968      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
15969      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
15970      * size is smaller than the size the view wants to be.
15971      *
15972      * @param size How big the view wants to be
15973      * @param measureSpec Constraints imposed by the parent
15974      * @return Size information bit mask as defined by
15975      * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
15976      */
15977     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
15978         int result = size;
15979         int specMode = MeasureSpec.getMode(measureSpec);
15980         int specSize =  MeasureSpec.getSize(measureSpec);
15981         switch (specMode) {
15982         case MeasureSpec.UNSPECIFIED:
15983             result = size;
15984             break;
15985         case MeasureSpec.AT_MOST:
15986             if (specSize < size) {
15987                 result = specSize | MEASURED_STATE_TOO_SMALL;
15988             } else {
15989                 result = size;
15990             }
15991             break;
15992         case MeasureSpec.EXACTLY:
15993             result = specSize;
15994             break;
15995         }
15996         return result | (childMeasuredState&MEASURED_STATE_MASK);
15997     }
15998 
15999     /**
16000      * Utility to return a default size. Uses the supplied size if the
16001      * MeasureSpec imposed no constraints. Will get larger if allowed
16002      * by the MeasureSpec.
16003      *
16004      * @param size Default size for this view
16005      * @param measureSpec Constraints imposed by the parent
16006      * @return The size this view should be.
16007      */
16008     public static int getDefaultSize(int size, int measureSpec) {
16009         int result = size;
16010         int specMode = MeasureSpec.getMode(measureSpec);
16011         int specSize = MeasureSpec.getSize(measureSpec);
16012 
16013         switch (specMode) {
16014         case MeasureSpec.UNSPECIFIED:
16015             result = size;
16016             break;
16017         case MeasureSpec.AT_MOST:
16018         case MeasureSpec.EXACTLY:
16019             result = specSize;
16020             break;
16021         }
16022         return result;
16023     }
16024 
16025     /**
16026      * Returns the suggested minimum height that the view should use. This
16027      * returns the maximum of the view's minimum height
16028      * and the background's minimum height
16029      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
16030      * <p>
16031      * When being used in {@link #onMeasure(int, int)}, the caller should still
16032      * ensure the returned height is within the requirements of the parent.
16033      *
16034      * @return The suggested minimum height of the view.
16035      */
16036     protected int getSuggestedMinimumHeight() {
16037         return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
16038 
16039     }
16040 
16041     /**
16042      * Returns the suggested minimum width that the view should use. This
16043      * returns the maximum of the view's minimum width)
16044      * and the background's minimum width
16045      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
16046      * <p>
16047      * When being used in {@link #onMeasure(int, int)}, the caller should still
16048      * ensure the returned width is within the requirements of the parent.
16049      *
16050      * @return The suggested minimum width of the view.
16051      */
16052     protected int getSuggestedMinimumWidth() {
16053         return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
16054     }
16055 
16056     /**
16057      * Returns the minimum height of the view.
16058      *
16059      * @return the minimum height the view will try to be.
16060      *
16061      * @see #setMinimumHeight(int)
16062      *
16063      * @attr ref android.R.styleable#View_minHeight
16064      */
16065     public int getMinimumHeight() {
16066         return mMinHeight;
16067     }
16068 
16069     /**
16070      * Sets the minimum height of the view. It is not guaranteed the view will
16071      * be able to achieve this minimum height (for example, if its parent layout
16072      * constrains it with less available height).
16073      *
16074      * @param minHeight The minimum height the view will try to be.
16075      *
16076      * @see #getMinimumHeight()
16077      *
16078      * @attr ref android.R.styleable#View_minHeight
16079      */
16080     public void setMinimumHeight(int minHeight) {
16081         mMinHeight = minHeight;
16082         requestLayout();
16083     }
16084 
16085     /**
16086      * Returns the minimum width of the view.
16087      *
16088      * @return the minimum width the view will try to be.
16089      *
16090      * @see #setMinimumWidth(int)
16091      *
16092      * @attr ref android.R.styleable#View_minWidth
16093      */
16094     public int getMinimumWidth() {
16095         return mMinWidth;
16096     }
16097 
16098     /**
16099      * Sets the minimum width of the view. It is not guaranteed the view will
16100      * be able to achieve this minimum width (for example, if its parent layout
16101      * constrains it with less available width).
16102      *
16103      * @param minWidth The minimum width the view will try to be.
16104      *
16105      * @see #getMinimumWidth()
16106      *
16107      * @attr ref android.R.styleable#View_minWidth
16108      */
16109     public void setMinimumWidth(int minWidth) {
16110         mMinWidth = minWidth;
16111         requestLayout();
16112 
16113     }
16114 
16115     /**
16116      * Get the animation currently associated with this view.
16117      *
16118      * @return The animation that is currently playing or
16119      *         scheduled to play for this view.
16120      */
16121     public Animation getAnimation() {
16122         return mCurrentAnimation;
16123     }
16124 
16125     /**
16126      * Start the specified animation now.
16127      *
16128      * @param animation the animation to start now
16129      */
16130     public void startAnimation(Animation animation) {
16131         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
16132         setAnimation(animation);
16133         invalidateParentCaches();
16134         invalidate(true);
16135     }
16136 
16137     /**
16138      * Cancels any animations for this view.
16139      */
16140     public void clearAnimation() {
16141         if (mCurrentAnimation != null) {
16142             mCurrentAnimation.detach();
16143         }
16144         mCurrentAnimation = null;
16145         invalidateParentIfNeeded();
16146     }
16147 
16148     /**
16149      * Sets the next animation to play for this view.
16150      * If you want the animation to play immediately, use
16151      * {@link #startAnimation(android.view.animation.Animation)} instead.
16152      * This method provides allows fine-grained
16153      * control over the start time and invalidation, but you
16154      * must make sure that 1) the animation has a start time set, and
16155      * 2) the view's parent (which controls animations on its children)
16156      * will be invalidated when the animation is supposed to
16157      * start.
16158      *
16159      * @param animation The next animation, or null.
16160      */
16161     public void setAnimation(Animation animation) {
16162         mCurrentAnimation = animation;
16163 
16164         if (animation != null) {
16165             // If the screen is off assume the animation start time is now instead of
16166             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
16167             // would cause the animation to start when the screen turns back on
16168             if (mAttachInfo != null && !mAttachInfo.mScreenOn &&
16169                     animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
16170                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
16171             }
16172             animation.reset();
16173         }
16174     }
16175 
16176     /**
16177      * Invoked by a parent ViewGroup to notify the start of the animation
16178      * currently associated with this view. If you override this method,
16179      * always call super.onAnimationStart();
16180      *
16181      * @see #setAnimation(android.view.animation.Animation)
16182      * @see #getAnimation()
16183      */
16184     protected void onAnimationStart() {
16185         mPrivateFlags |= PFLAG_ANIMATION_STARTED;
16186     }
16187 
16188     /**
16189      * Invoked by a parent ViewGroup to notify the end of the animation
16190      * currently associated with this view. If you override this method,
16191      * always call super.onAnimationEnd();
16192      *
16193      * @see #setAnimation(android.view.animation.Animation)
16194      * @see #getAnimation()
16195      */
16196     protected void onAnimationEnd() {
16197         mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
16198     }
16199 
16200     /**
16201      * Invoked if there is a Transform that involves alpha. Subclass that can
16202      * draw themselves with the specified alpha should return true, and then
16203      * respect that alpha when their onDraw() is called. If this returns false
16204      * then the view may be redirected to draw into an offscreen buffer to
16205      * fulfill the request, which will look fine, but may be slower than if the
16206      * subclass handles it internally. The default implementation returns false.
16207      *
16208      * @param alpha The alpha (0..255) to apply to the view's drawing
16209      * @return true if the view can draw with the specified alpha.
16210      */
16211     protected boolean onSetAlpha(int alpha) {
16212         return false;
16213     }
16214 
16215     /**
16216      * This is used by the RootView to perform an optimization when
16217      * the view hierarchy contains one or several SurfaceView.
16218      * SurfaceView is always considered transparent, but its children are not,
16219      * therefore all View objects remove themselves from the global transparent
16220      * region (passed as a parameter to this function).
16221      *
16222      * @param region The transparent region for this ViewAncestor (window).
16223      *
16224      * @return Returns true if the effective visibility of the view at this
16225      * point is opaque, regardless of the transparent region; returns false
16226      * if it is possible for underlying windows to be seen behind the view.
16227      *
16228      * {@hide}
16229      */
16230     public boolean gatherTransparentRegion(Region region) {
16231         final AttachInfo attachInfo = mAttachInfo;
16232         if (region != null && attachInfo != null) {
16233             final int pflags = mPrivateFlags;
16234             if ((pflags & PFLAG_SKIP_DRAW) == 0) {
16235                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
16236                 // remove it from the transparent region.
16237                 final int[] location = attachInfo.mTransparentLocation;
16238                 getLocationInWindow(location);
16239                 region.op(location[0], location[1], location[0] + mRight - mLeft,
16240                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
16241             } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
16242                 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
16243                 // exists, so we remove the background drawable's non-transparent
16244                 // parts from this transparent region.
16245                 applyDrawableToTransparentRegion(mBackground, region);
16246             }
16247         }
16248         return true;
16249     }
16250 
16251     /**
16252      * Play a sound effect for this view.
16253      *
16254      * <p>The framework will play sound effects for some built in actions, such as
16255      * clicking, but you may wish to play these effects in your widget,
16256      * for instance, for internal navigation.
16257      *
16258      * <p>The sound effect will only be played if sound effects are enabled by the user, and
16259      * {@link #isSoundEffectsEnabled()} is true.
16260      *
16261      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
16262      */
16263     public void playSoundEffect(int soundConstant) {
16264         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
16265             return;
16266         }
16267         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
16268     }
16269 
16270     /**
16271      * BZZZTT!!1!
16272      *
16273      * <p>Provide haptic feedback to the user for this view.
16274      *
16275      * <p>The framework will provide haptic feedback for some built in actions,
16276      * such as long presses, but you may wish to provide feedback for your
16277      * own widget.
16278      *
16279      * <p>The feedback will only be performed if
16280      * {@link #isHapticFeedbackEnabled()} is true.
16281      *
16282      * @param feedbackConstant One of the constants defined in
16283      * {@link HapticFeedbackConstants}
16284      */
16285     public boolean performHapticFeedback(int feedbackConstant) {
16286         return performHapticFeedback(feedbackConstant, 0);
16287     }
16288 
16289     /**
16290      * BZZZTT!!1!
16291      *
16292      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
16293      *
16294      * @param feedbackConstant One of the constants defined in
16295      * {@link HapticFeedbackConstants}
16296      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
16297      */
16298     public boolean performHapticFeedback(int feedbackConstant, int flags) {
16299         if (mAttachInfo == null) {
16300             return false;
16301         }
16302         //noinspection SimplifiableIfStatement
16303         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
16304                 && !isHapticFeedbackEnabled()) {
16305             return false;
16306         }
16307         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
16308                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
16309     }
16310 
16311     /**
16312      * Request that the visibility of the status bar or other screen/window
16313      * decorations be changed.
16314      *
16315      * <p>This method is used to put the over device UI into temporary modes
16316      * where the user's attention is focused more on the application content,
16317      * by dimming or hiding surrounding system affordances.  This is typically
16318      * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
16319      * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
16320      * to be placed behind the action bar (and with these flags other system
16321      * affordances) so that smooth transitions between hiding and showing them
16322      * can be done.
16323      *
16324      * <p>Two representative examples of the use of system UI visibility is
16325      * implementing a content browsing application (like a magazine reader)
16326      * and a video playing application.
16327      *
16328      * <p>The first code shows a typical implementation of a View in a content
16329      * browsing application.  In this implementation, the application goes
16330      * into a content-oriented mode by hiding the status bar and action bar,
16331      * and putting the navigation elements into lights out mode.  The user can
16332      * then interact with content while in this mode.  Such an application should
16333      * provide an easy way for the user to toggle out of the mode (such as to
16334      * check information in the status bar or access notifications).  In the
16335      * implementation here, this is done simply by tapping on the content.
16336      *
16337      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
16338      *      content}
16339      *
16340      * <p>This second code sample shows a typical implementation of a View
16341      * in a video playing application.  In this situation, while the video is
16342      * playing the application would like to go into a complete full-screen mode,
16343      * to use as much of the display as possible for the video.  When in this state
16344      * the user can not interact with the application; the system intercepts
16345      * touching on the screen to pop the UI out of full screen mode.  See
16346      * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
16347      *
16348      * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
16349      *      content}
16350      *
16351      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
16352      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
16353      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
16354      * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
16355      */
16356     public void setSystemUiVisibility(int visibility) {
16357         if (visibility != mSystemUiVisibility) {
16358             mSystemUiVisibility = visibility;
16359             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
16360                 mParent.recomputeViewAttributes(this);
16361             }
16362         }
16363     }
16364 
16365     /**
16366      * Returns the last {@link #setSystemUiVisibility(int) that this view has requested.
16367      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
16368      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
16369      * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
16370      * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
16371      */
16372     public int getSystemUiVisibility() {
16373         return mSystemUiVisibility;
16374     }
16375 
16376     /**
16377      * Returns the current system UI visibility that is currently set for
16378      * the entire window.  This is the combination of the
16379      * {@link #setSystemUiVisibility(int)} values supplied by all of the
16380      * views in the window.
16381      */
16382     public int getWindowSystemUiVisibility() {
16383         return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
16384     }
16385 
16386     /**
16387      * Override to find out when the window's requested system UI visibility
16388      * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
16389      * This is different from the callbacks recieved through
16390      * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
16391      * in that this is only telling you about the local request of the window,
16392      * not the actual values applied by the system.
16393      */
16394     public void onWindowSystemUiVisibilityChanged(int visible) {
16395     }
16396 
16397     /**
16398      * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
16399      * the view hierarchy.
16400      */
16401     public void dispatchWindowSystemUiVisiblityChanged(int visible) {
16402         onWindowSystemUiVisibilityChanged(visible);
16403     }
16404 
16405     /**
16406      * Set a listener to receive callbacks when the visibility of the system bar changes.
16407      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
16408      */
16409     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
16410         getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
16411         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
16412             mParent.recomputeViewAttributes(this);
16413         }
16414     }
16415 
16416     /**
16417      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
16418      * the view hierarchy.
16419      */
16420     public void dispatchSystemUiVisibilityChanged(int visibility) {
16421         ListenerInfo li = mListenerInfo;
16422         if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
16423             li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
16424                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
16425         }
16426     }
16427 
16428     boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
16429         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
16430         if (val != mSystemUiVisibility) {
16431             setSystemUiVisibility(val);
16432             return true;
16433         }
16434         return false;
16435     }
16436 
16437     /** @hide */
16438     public void setDisabledSystemUiVisibility(int flags) {
16439         if (mAttachInfo != null) {
16440             if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
16441                 mAttachInfo.mDisabledSystemUiVisibility = flags;
16442                 if (mParent != null) {
16443                     mParent.recomputeViewAttributes(this);
16444                 }
16445             }
16446         }
16447     }
16448 
16449     /**
16450      * Creates an image that the system displays during the drag and drop
16451      * operation. This is called a &quot;drag shadow&quot;. The default implementation
16452      * for a DragShadowBuilder based on a View returns an image that has exactly the same
16453      * appearance as the given View. The default also positions the center of the drag shadow
16454      * directly under the touch point. If no View is provided (the constructor with no parameters
16455      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
16456      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
16457      * default is an invisible drag shadow.
16458      * <p>
16459      * You are not required to use the View you provide to the constructor as the basis of the
16460      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
16461      * anything you want as the drag shadow.
16462      * </p>
16463      * <p>
16464      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
16465      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
16466      *  size and position of the drag shadow. It uses this data to construct a
16467      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
16468      *  so that your application can draw the shadow image in the Canvas.
16469      * </p>
16470      *
16471      * <div class="special reference">
16472      * <h3>Developer Guides</h3>
16473      * <p>For a guide to implementing drag and drop features, read the
16474      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
16475      * </div>
16476      */
16477     public static class DragShadowBuilder {
16478         private final WeakReference<View> mView;
16479 
16480         /**
16481          * Constructs a shadow image builder based on a View. By default, the resulting drag
16482          * shadow will have the same appearance and dimensions as the View, with the touch point
16483          * over the center of the View.
16484          * @param view A View. Any View in scope can be used.
16485          */
16486         public DragShadowBuilder(View view) {
16487             mView = new WeakReference<View>(view);
16488         }
16489 
16490         /**
16491          * Construct a shadow builder object with no associated View.  This
16492          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
16493          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
16494          * to supply the drag shadow's dimensions and appearance without
16495          * reference to any View object. If they are not overridden, then the result is an
16496          * invisible drag shadow.
16497          */
16498         public DragShadowBuilder() {
16499             mView = new WeakReference<View>(null);
16500         }
16501 
16502         /**
16503          * Returns the View object that had been passed to the
16504          * {@link #View.DragShadowBuilder(View)}
16505          * constructor.  If that View parameter was {@code null} or if the
16506          * {@link #View.DragShadowBuilder()}
16507          * constructor was used to instantiate the builder object, this method will return
16508          * null.
16509          *
16510          * @return The View object associate with this builder object.
16511          */
16512         @SuppressWarnings({"JavadocReference"})
16513         final public View getView() {
16514             return mView.get();
16515         }
16516 
16517         /**
16518          * Provides the metrics for the shadow image. These include the dimensions of
16519          * the shadow image, and the point within that shadow that should
16520          * be centered under the touch location while dragging.
16521          * <p>
16522          * The default implementation sets the dimensions of the shadow to be the
16523          * same as the dimensions of the View itself and centers the shadow under
16524          * the touch point.
16525          * </p>
16526          *
16527          * @param shadowSize A {@link android.graphics.Point} containing the width and height
16528          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
16529          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
16530          * image.
16531          *
16532          * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
16533          * shadow image that should be underneath the touch point during the drag and drop
16534          * operation. Your application must set {@link android.graphics.Point#x} to the
16535          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
16536          */
16537         public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
16538             final View view = mView.get();
16539             if (view != null) {
16540                 shadowSize.set(view.getWidth(), view.getHeight());
16541                 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
16542             } else {
16543                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
16544             }
16545         }
16546 
16547         /**
16548          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
16549          * based on the dimensions it received from the
16550          * {@link #onProvideShadowMetrics(Point, Point)} callback.
16551          *
16552          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
16553          */
16554         public void onDrawShadow(Canvas canvas) {
16555             final View view = mView.get();
16556             if (view != null) {
16557                 view.draw(canvas);
16558             } else {
16559                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
16560             }
16561         }
16562     }
16563 
16564     /**
16565      * Starts a drag and drop operation. When your application calls this method, it passes a
16566      * {@link android.view.View.DragShadowBuilder} object to the system. The
16567      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
16568      * to get metrics for the drag shadow, and then calls the object's
16569      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
16570      * <p>
16571      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
16572      *  drag events to all the View objects in your application that are currently visible. It does
16573      *  this either by calling the View object's drag listener (an implementation of
16574      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
16575      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
16576      *  Both are passed a {@link android.view.DragEvent} object that has a
16577      *  {@link android.view.DragEvent#getAction()} value of
16578      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
16579      * </p>
16580      * <p>
16581      * Your application can invoke startDrag() on any attached View object. The View object does not
16582      * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
16583      * be related to the View the user selected for dragging.
16584      * </p>
16585      * @param data A {@link android.content.ClipData} object pointing to the data to be
16586      * transferred by the drag and drop operation.
16587      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
16588      * drag shadow.
16589      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
16590      * drop operation. This Object is put into every DragEvent object sent by the system during the
16591      * current drag.
16592      * <p>
16593      * myLocalState is a lightweight mechanism for the sending information from the dragged View
16594      * to the target Views. For example, it can contain flags that differentiate between a
16595      * a copy operation and a move operation.
16596      * </p>
16597      * @param flags Flags that control the drag and drop operation. No flags are currently defined,
16598      * so the parameter should be set to 0.
16599      * @return {@code true} if the method completes successfully, or
16600      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
16601      * do a drag, and so no drag operation is in progress.
16602      */
16603     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
16604             Object myLocalState, int flags) {
16605         if (ViewDebug.DEBUG_DRAG) {
16606             Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
16607         }
16608         boolean okay = false;
16609 
16610         Point shadowSize = new Point();
16611         Point shadowTouchPoint = new Point();
16612         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
16613 
16614         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
16615                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
16616             throw new IllegalStateException("Drag shadow dimensions must not be negative");
16617         }
16618 
16619         if (ViewDebug.DEBUG_DRAG) {
16620             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
16621                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
16622         }
16623         Surface surface = new Surface();
16624         try {
16625             IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
16626                     flags, shadowSize.x, shadowSize.y, surface);
16627             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
16628                     + " surface=" + surface);
16629             if (token != null) {
16630                 Canvas canvas = surface.lockCanvas(null);
16631                 try {
16632                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
16633                     shadowBuilder.onDrawShadow(canvas);
16634                 } finally {
16635                     surface.unlockCanvasAndPost(canvas);
16636                 }
16637 
16638                 final ViewRootImpl root = getViewRootImpl();
16639 
16640                 // Cache the local state object for delivery with DragEvents
16641                 root.setLocalDragState(myLocalState);
16642 
16643                 // repurpose 'shadowSize' for the last touch point
16644                 root.getLastTouchPoint(shadowSize);
16645 
16646                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
16647                         shadowSize.x, shadowSize.y,
16648                         shadowTouchPoint.x, shadowTouchPoint.y, data);
16649                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
16650 
16651                 // Off and running!  Release our local surface instance; the drag
16652                 // shadow surface is now managed by the system process.
16653                 surface.release();
16654             }
16655         } catch (Exception e) {
16656             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
16657             surface.destroy();
16658         }
16659 
16660         return okay;
16661     }
16662 
16663     /**
16664      * Handles drag events sent by the system following a call to
16665      * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
16666      *<p>
16667      * When the system calls this method, it passes a
16668      * {@link android.view.DragEvent} object. A call to
16669      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
16670      * in DragEvent. The method uses these to determine what is happening in the drag and drop
16671      * operation.
16672      * @param event The {@link android.view.DragEvent} sent by the system.
16673      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
16674      * in DragEvent, indicating the type of drag event represented by this object.
16675      * @return {@code true} if the method was successful, otherwise {@code false}.
16676      * <p>
16677      *  The method should return {@code true} in response to an action type of
16678      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
16679      *  operation.
16680      * </p>
16681      * <p>
16682      *  The method should also return {@code true} in response to an action type of
16683      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
16684      *  {@code false} if it didn't.
16685      * </p>
16686      */
16687     public boolean onDragEvent(DragEvent event) {
16688         return false;
16689     }
16690 
16691     /**
16692      * Detects if this View is enabled and has a drag event listener.
16693      * If both are true, then it calls the drag event listener with the
16694      * {@link android.view.DragEvent} it received. If the drag event listener returns
16695      * {@code true}, then dispatchDragEvent() returns {@code true}.
16696      * <p>
16697      * For all other cases, the method calls the
16698      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
16699      * method and returns its result.
16700      * </p>
16701      * <p>
16702      * This ensures that a drag event is always consumed, even if the View does not have a drag
16703      * event listener. However, if the View has a listener and the listener returns true, then
16704      * onDragEvent() is not called.
16705      * </p>
16706      */
16707     public boolean dispatchDragEvent(DragEvent event) {
16708         //noinspection SimplifiableIfStatement
16709         ListenerInfo li = mListenerInfo;
16710         if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
16711                 && li.mOnDragListener.onDrag(this, event)) {
16712             return true;
16713         }
16714         return onDragEvent(event);
16715     }
16716 
16717     boolean canAcceptDrag() {
16718         return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
16719     }
16720 
16721     /**
16722      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
16723      * it is ever exposed at all.
16724      * @hide
16725      */
16726     public void onCloseSystemDialogs(String reason) {
16727     }
16728 
16729     /**
16730      * Given a Drawable whose bounds have been set to draw into this view,
16731      * update a Region being computed for
16732      * {@link #gatherTransparentRegion(android.graphics.Region)} so
16733      * that any non-transparent parts of the Drawable are removed from the
16734      * given transparent region.
16735      *
16736      * @param dr The Drawable whose transparency is to be applied to the region.
16737      * @param region A Region holding the current transparency information,
16738      * where any parts of the region that are set are considered to be
16739      * transparent.  On return, this region will be modified to have the
16740      * transparency information reduced by the corresponding parts of the
16741      * Drawable that are not transparent.
16742      * {@hide}
16743      */
16744     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
16745         if (DBG) {
16746             Log.i("View", "Getting transparent region for: " + this);
16747         }
16748         final Region r = dr.getTransparentRegion();
16749         final Rect db = dr.getBounds();
16750         final AttachInfo attachInfo = mAttachInfo;
16751         if (r != null && attachInfo != null) {
16752             final int w = getRight()-getLeft();
16753             final int h = getBottom()-getTop();
16754             if (db.left > 0) {
16755                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
16756                 r.op(0, 0, db.left, h, Region.Op.UNION);
16757             }
16758             if (db.right < w) {
16759                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
16760                 r.op(db.right, 0, w, h, Region.Op.UNION);
16761             }
16762             if (db.top > 0) {
16763                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
16764                 r.op(0, 0, w, db.top, Region.Op.UNION);
16765             }
16766             if (db.bottom < h) {
16767                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
16768                 r.op(0, db.bottom, w, h, Region.Op.UNION);
16769             }
16770             final int[] location = attachInfo.mTransparentLocation;
16771             getLocationInWindow(location);
16772             r.translate(location[0], location[1]);
16773             region.op(r, Region.Op.INTERSECT);
16774         } else {
16775             region.op(db, Region.Op.DIFFERENCE);
16776         }
16777     }
16778 
16779     private void checkForLongClick(int delayOffset) {
16780         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
16781             mHasPerformedLongPress = false;
16782 
16783             if (mPendingCheckForLongPress == null) {
16784                 mPendingCheckForLongPress = new CheckForLongPress();
16785             }
16786             mPendingCheckForLongPress.rememberWindowAttachCount();
16787             postDelayed(mPendingCheckForLongPress,
16788                     ViewConfiguration.getLongPressTimeout() - delayOffset);
16789         }
16790     }
16791 
16792     /**
16793      * Inflate a view from an XML resource.  This convenience method wraps the {@link
16794      * LayoutInflater} class, which provides a full range of options for view inflation.
16795      *
16796      * @param context The Context object for your activity or application.
16797      * @param resource The resource ID to inflate
16798      * @param root A view group that will be the parent.  Used to properly inflate the
16799      * layout_* parameters.
16800      * @see LayoutInflater
16801      */
16802     public static View inflate(Context context, int resource, ViewGroup root) {
16803         LayoutInflater factory = LayoutInflater.from(context);
16804         return factory.inflate(resource, root);
16805     }
16806 
16807     /**
16808      * Scroll the view with standard behavior for scrolling beyond the normal
16809      * content boundaries. Views that call this method should override
16810      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
16811      * results of an over-scroll operation.
16812      *
16813      * Views can use this method to handle any touch or fling-based scrolling.
16814      *
16815      * @param deltaX Change in X in pixels
16816      * @param deltaY Change in Y in pixels
16817      * @param scrollX Current X scroll value in pixels before applying deltaX
16818      * @param scrollY Current Y scroll value in pixels before applying deltaY
16819      * @param scrollRangeX Maximum content scroll range along the X axis
16820      * @param scrollRangeY Maximum content scroll range along the Y axis
16821      * @param maxOverScrollX Number of pixels to overscroll by in either direction
16822      *          along the X axis.
16823      * @param maxOverScrollY Number of pixels to overscroll by in either direction
16824      *          along the Y axis.
16825      * @param isTouchEvent true if this scroll operation is the result of a touch event.
16826      * @return true if scrolling was clamped to an over-scroll boundary along either
16827      *          axis, false otherwise.
16828      */
16829     @SuppressWarnings({"UnusedParameters"})
16830     protected boolean overScrollBy(int deltaX, int deltaY,
16831             int scrollX, int scrollY,
16832             int scrollRangeX, int scrollRangeY,
16833             int maxOverScrollX, int maxOverScrollY,
16834             boolean isTouchEvent) {
16835         final int overScrollMode = mOverScrollMode;
16836         final boolean canScrollHorizontal =
16837                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
16838         final boolean canScrollVertical =
16839                 computeVerticalScrollRange() > computeVerticalScrollExtent();
16840         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
16841                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
16842         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
16843                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
16844 
16845         int newScrollX = scrollX + deltaX;
16846         if (!overScrollHorizontal) {
16847             maxOverScrollX = 0;
16848         }
16849 
16850         int newScrollY = scrollY + deltaY;
16851         if (!overScrollVertical) {
16852             maxOverScrollY = 0;
16853         }
16854 
16855         // Clamp values if at the limits and record
16856         final int left = -maxOverScrollX;
16857         final int right = maxOverScrollX + scrollRangeX;
16858         final int top = -maxOverScrollY;
16859         final int bottom = maxOverScrollY + scrollRangeY;
16860 
16861         boolean clampedX = false;
16862         if (newScrollX > right) {
16863             newScrollX = right;
16864             clampedX = true;
16865         } else if (newScrollX < left) {
16866             newScrollX = left;
16867             clampedX = true;
16868         }
16869 
16870         boolean clampedY = false;
16871         if (newScrollY > bottom) {
16872             newScrollY = bottom;
16873             clampedY = true;
16874         } else if (newScrollY < top) {
16875             newScrollY = top;
16876             clampedY = true;
16877         }
16878 
16879         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
16880 
16881         return clampedX || clampedY;
16882     }
16883 
16884     /**
16885      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
16886      * respond to the results of an over-scroll operation.
16887      *
16888      * @param scrollX New X scroll value in pixels
16889      * @param scrollY New Y scroll value in pixels
16890      * @param clampedX True if scrollX was clamped to an over-scroll boundary
16891      * @param clampedY True if scrollY was clamped to an over-scroll boundary
16892      */
16893     protected void onOverScrolled(int scrollX, int scrollY,
16894             boolean clampedX, boolean clampedY) {
16895         // Intentionally empty.
16896     }
16897 
16898     /**
16899      * Returns the over-scroll mode for this view. The result will be
16900      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16901      * (allow over-scrolling only if the view content is larger than the container),
16902      * or {@link #OVER_SCROLL_NEVER}.
16903      *
16904      * @return This view's over-scroll mode.
16905      */
16906     public int getOverScrollMode() {
16907         return mOverScrollMode;
16908     }
16909 
16910     /**
16911      * Set the over-scroll mode for this view. Valid over-scroll modes are
16912      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16913      * (allow over-scrolling only if the view content is larger than the container),
16914      * or {@link #OVER_SCROLL_NEVER}.
16915      *
16916      * Setting the over-scroll mode of a view will have an effect only if the
16917      * view is capable of scrolling.
16918      *
16919      * @param overScrollMode The new over-scroll mode for this view.
16920      */
16921     public void setOverScrollMode(int overScrollMode) {
16922         if (overScrollMode != OVER_SCROLL_ALWAYS &&
16923                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
16924                 overScrollMode != OVER_SCROLL_NEVER) {
16925             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
16926         }
16927         mOverScrollMode = overScrollMode;
16928     }
16929 
16930     /**
16931      * Gets a scale factor that determines the distance the view should scroll
16932      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
16933      * @return The vertical scroll scale factor.
16934      * @hide
16935      */
16936     protected float getVerticalScrollFactor() {
16937         if (mVerticalScrollFactor == 0) {
16938             TypedValue outValue = new TypedValue();
16939             if (!mContext.getTheme().resolveAttribute(
16940                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
16941                 throw new IllegalStateException(
16942                         "Expected theme to define listPreferredItemHeight.");
16943             }
16944             mVerticalScrollFactor = outValue.getDimension(
16945                     mContext.getResources().getDisplayMetrics());
16946         }
16947         return mVerticalScrollFactor;
16948     }
16949 
16950     /**
16951      * Gets a scale factor that determines the distance the view should scroll
16952      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
16953      * @return The horizontal scroll scale factor.
16954      * @hide
16955      */
16956     protected float getHorizontalScrollFactor() {
16957         // TODO: Should use something else.
16958         return getVerticalScrollFactor();
16959     }
16960 
16961     /**
16962      * Return the value specifying the text direction or policy that was set with
16963      * {@link #setTextDirection(int)}.
16964      *
16965      * @return the defined text direction. It can be one of:
16966      *
16967      * {@link #TEXT_DIRECTION_INHERIT},
16968      * {@link #TEXT_DIRECTION_FIRST_STRONG}
16969      * {@link #TEXT_DIRECTION_ANY_RTL},
16970      * {@link #TEXT_DIRECTION_LTR},
16971      * {@link #TEXT_DIRECTION_RTL},
16972      * {@link #TEXT_DIRECTION_LOCALE}
16973      *
16974      * @attr ref android.R.styleable#View_textDirection
16975      *
16976      * @hide
16977      */
16978     @ViewDebug.ExportedProperty(category = "text", mapping = {
16979             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
16980             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
16981             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
16982             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
16983             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
16984             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
16985     })
16986     public int getRawTextDirection() {
16987         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
16988     }
16989 
16990     /**
16991      * Set the text direction.
16992      *
16993      * @param textDirection the direction to set. Should be one of:
16994      *
16995      * {@link #TEXT_DIRECTION_INHERIT},
16996      * {@link #TEXT_DIRECTION_FIRST_STRONG}
16997      * {@link #TEXT_DIRECTION_ANY_RTL},
16998      * {@link #TEXT_DIRECTION_LTR},
16999      * {@link #TEXT_DIRECTION_RTL},
17000      * {@link #TEXT_DIRECTION_LOCALE}
17001      *
17002      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
17003      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
17004      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
17005      *
17006      * @attr ref android.R.styleable#View_textDirection
17007      */
17008     public void setTextDirection(int textDirection) {
17009         if (getRawTextDirection() != textDirection) {
17010             // Reset the current text direction and the resolved one
17011             mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
17012             resetResolvedTextDirection();
17013             // Set the new text direction
17014             mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
17015             // Do resolution
17016             resolveTextDirection();
17017             // Notify change
17018             onRtlPropertiesChanged(getLayoutDirection());
17019             // Refresh
17020             requestLayout();
17021             invalidate(true);
17022         }
17023     }
17024 
17025     /**
17026      * Return the resolved text direction.
17027      *
17028      * @return the resolved text direction. Returns one of:
17029      *
17030      * {@link #TEXT_DIRECTION_FIRST_STRONG}
17031      * {@link #TEXT_DIRECTION_ANY_RTL},
17032      * {@link #TEXT_DIRECTION_LTR},
17033      * {@link #TEXT_DIRECTION_RTL},
17034      * {@link #TEXT_DIRECTION_LOCALE}
17035      *
17036      * @attr ref android.R.styleable#View_textDirection
17037      */
17038     @ViewDebug.ExportedProperty(category = "text", mapping = {
17039             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
17040             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
17041             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
17042             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
17043             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
17044             @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
17045     })
17046     public int getTextDirection() {
17047         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
17048     }
17049 
17050     /**
17051      * Resolve the text direction.
17052      *
17053      * @return true if resolution has been done, false otherwise.
17054      *
17055      * @hide
17056      */
17057     public boolean resolveTextDirection() {
17058         // Reset any previous text direction resolution
17059         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
17060 
17061         if (hasRtlSupport()) {
17062             // Set resolved text direction flag depending on text direction flag
17063             final int textDirection = getRawTextDirection();
17064             switch(textDirection) {
17065                 case TEXT_DIRECTION_INHERIT:
17066                     if (!canResolveTextDirection()) {
17067                         // We cannot do the resolution if there is no parent, so use the default one
17068                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
17069                         // Resolution will need to happen again later
17070                         return false;
17071                     }
17072 
17073                     // Parent has not yet resolved, so we still return the default
17074                     if (!mParent.isTextDirectionResolved()) {
17075                         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
17076                         // Resolution will need to happen again later
17077                         return false;
17078                     }
17079 
17080                     // Set current resolved direction to the same value as the parent's one
17081                     final int parentResolvedDirection = mParent.getTextDirection();
17082                     switch (parentResolvedDirection) {
17083                         case TEXT_DIRECTION_FIRST_STRONG:
17084                         case TEXT_DIRECTION_ANY_RTL:
17085                         case TEXT_DIRECTION_LTR:
17086                         case TEXT_DIRECTION_RTL:
17087                         case TEXT_DIRECTION_LOCALE:
17088                             mPrivateFlags2 |=
17089                                     (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
17090                             break;
17091                         default:
17092                             // Default resolved direction is "first strong" heuristic
17093                             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
17094                     }
17095                     break;
17096                 case TEXT_DIRECTION_FIRST_STRONG:
17097                 case TEXT_DIRECTION_ANY_RTL:
17098                 case TEXT_DIRECTION_LTR:
17099                 case TEXT_DIRECTION_RTL:
17100                 case TEXT_DIRECTION_LOCALE:
17101                     // Resolved direction is the same as text direction
17102                     mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
17103                     break;
17104                 default:
17105                     // Default resolved direction is "first strong" heuristic
17106                     mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
17107             }
17108         } else {
17109             // Default resolved direction is "first strong" heuristic
17110             mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
17111         }
17112 
17113         // Set to resolved
17114         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
17115         return true;
17116     }
17117 
17118     /**
17119      * Check if text direction resolution can be done.
17120      *
17121      * @return true if text direction resolution can be done otherwise return false.
17122      *
17123      * @hide
17124      */
17125     public boolean canResolveTextDirection() {
17126         switch (getRawTextDirection()) {
17127             case TEXT_DIRECTION_INHERIT:
17128                 return (mParent != null) && mParent.canResolveTextDirection();
17129             default:
17130                 return true;
17131         }
17132     }
17133 
17134     /**
17135      * Reset resolved text direction. Text direction will be resolved during a call to
17136      * {@link #onMeasure(int, int)}.
17137      *
17138      * @hide
17139      */
17140     public void resetResolvedTextDirection() {
17141         // Reset any previous text direction resolution
17142         mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
17143         // Set to default value
17144         mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
17145     }
17146 
17147     /**
17148      * @return true if text direction is inherited.
17149      *
17150      * @hide
17151      */
17152     public boolean isTextDirectionInherited() {
17153         return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
17154     }
17155 
17156     /**
17157      * @return true if text direction is resolved.
17158      *
17159      * @hide
17160      */
17161     public boolean isTextDirectionResolved() {
17162         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
17163     }
17164 
17165     /**
17166      * Return the value specifying the text alignment or policy that was set with
17167      * {@link #setTextAlignment(int)}.
17168      *
17169      * @return the defined text alignment. It can be one of:
17170      *
17171      * {@link #TEXT_ALIGNMENT_INHERIT},
17172      * {@link #TEXT_ALIGNMENT_GRAVITY},
17173      * {@link #TEXT_ALIGNMENT_CENTER},
17174      * {@link #TEXT_ALIGNMENT_TEXT_START},
17175      * {@link #TEXT_ALIGNMENT_TEXT_END},
17176      * {@link #TEXT_ALIGNMENT_VIEW_START},
17177      * {@link #TEXT_ALIGNMENT_VIEW_END}
17178      *
17179      * @attr ref android.R.styleable#View_textAlignment
17180      *
17181      * @hide
17182      */
17183     @ViewDebug.ExportedProperty(category = "text", mapping = {
17184             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
17185             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
17186             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
17187             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
17188             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
17189             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
17190             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
17191     })
17192     public int getRawTextAlignment() {
17193         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
17194     }
17195 
17196     /**
17197      * Set the text alignment.
17198      *
17199      * @param textAlignment The text alignment to set. Should be one of
17200      *
17201      * {@link #TEXT_ALIGNMENT_INHERIT},
17202      * {@link #TEXT_ALIGNMENT_GRAVITY},
17203      * {@link #TEXT_ALIGNMENT_CENTER},
17204      * {@link #TEXT_ALIGNMENT_TEXT_START},
17205      * {@link #TEXT_ALIGNMENT_TEXT_END},
17206      * {@link #TEXT_ALIGNMENT_VIEW_START},
17207      * {@link #TEXT_ALIGNMENT_VIEW_END}
17208      *
17209      * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
17210      * proceeds up the parent chain of the view to get the value. If there is no parent, then it
17211      * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
17212      *
17213      * @attr ref android.R.styleable#View_textAlignment
17214      */
17215     public void setTextAlignment(int textAlignment) {
17216         if (textAlignment != getRawTextAlignment()) {
17217             // Reset the current and resolved text alignment
17218             mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
17219             resetResolvedTextAlignment();
17220             // Set the new text alignment
17221             mPrivateFlags2 |=
17222                     ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
17223             // Do resolution
17224             resolveTextAlignment();
17225             // Notify change
17226             onRtlPropertiesChanged(getLayoutDirection());
17227             // Refresh
17228             requestLayout();
17229             invalidate(true);
17230         }
17231     }
17232 
17233     /**
17234      * Return the resolved text alignment.
17235      *
17236      * @return the resolved text alignment. Returns one of:
17237      *
17238      * {@link #TEXT_ALIGNMENT_GRAVITY},
17239      * {@link #TEXT_ALIGNMENT_CENTER},
17240      * {@link #TEXT_ALIGNMENT_TEXT_START},
17241      * {@link #TEXT_ALIGNMENT_TEXT_END},
17242      * {@link #TEXT_ALIGNMENT_VIEW_START},
17243      * {@link #TEXT_ALIGNMENT_VIEW_END}
17244      *
17245      * @attr ref android.R.styleable#View_textAlignment
17246      */
17247     @ViewDebug.ExportedProperty(category = "text", mapping = {
17248             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
17249             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
17250             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
17251             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
17252             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
17253             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
17254             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
17255     })
17256     public int getTextAlignment() {
17257         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
17258                 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
17259     }
17260 
17261     /**
17262      * Resolve the text alignment.
17263      *
17264      * @return true if resolution has been done, false otherwise.
17265      *
17266      * @hide
17267      */
17268     public boolean resolveTextAlignment() {
17269         // Reset any previous text alignment resolution
17270         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
17271 
17272         if (hasRtlSupport()) {
17273             // Set resolved text alignment flag depending on text alignment flag
17274             final int textAlignment = getRawTextAlignment();
17275             switch (textAlignment) {
17276                 case TEXT_ALIGNMENT_INHERIT:
17277                     // Check if we can resolve the text alignment
17278                     if (!canResolveTextAlignment()) {
17279                         // We cannot do the resolution if there is no parent so use the default
17280                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17281                         // Resolution will need to happen again later
17282                         return false;
17283                     }
17284 
17285                     // Parent has not yet resolved, so we still return the default
17286                     if (!mParent.isTextAlignmentResolved()) {
17287                         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17288                         // Resolution will need to happen again later
17289                         return false;
17290                     }
17291 
17292                     final int parentResolvedTextAlignment = mParent.getTextAlignment();
17293                     switch (parentResolvedTextAlignment) {
17294                         case TEXT_ALIGNMENT_GRAVITY:
17295                         case TEXT_ALIGNMENT_TEXT_START:
17296                         case TEXT_ALIGNMENT_TEXT_END:
17297                         case TEXT_ALIGNMENT_CENTER:
17298                         case TEXT_ALIGNMENT_VIEW_START:
17299                         case TEXT_ALIGNMENT_VIEW_END:
17300                             // Resolved text alignment is the same as the parent resolved
17301                             // text alignment
17302                             mPrivateFlags2 |=
17303                                     (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
17304                             break;
17305                         default:
17306                             // Use default resolved text alignment
17307                             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17308                     }
17309                     break;
17310                 case TEXT_ALIGNMENT_GRAVITY:
17311                 case TEXT_ALIGNMENT_TEXT_START:
17312                 case TEXT_ALIGNMENT_TEXT_END:
17313                 case TEXT_ALIGNMENT_CENTER:
17314                 case TEXT_ALIGNMENT_VIEW_START:
17315                 case TEXT_ALIGNMENT_VIEW_END:
17316                     // Resolved text alignment is the same as text alignment
17317                     mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
17318                     break;
17319                 default:
17320                     // Use default resolved text alignment
17321                     mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17322             }
17323         } else {
17324             // Use default resolved text alignment
17325             mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17326         }
17327 
17328         // Set the resolved
17329         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
17330         return true;
17331     }
17332 
17333     /**
17334      * Check if text alignment resolution can be done.
17335      *
17336      * @return true if text alignment resolution can be done otherwise return false.
17337      *
17338      * @hide
17339      */
17340     public boolean canResolveTextAlignment() {
17341         switch (getRawTextAlignment()) {
17342             case TEXT_DIRECTION_INHERIT:
17343                 return (mParent != null) && mParent.canResolveTextAlignment();
17344             default:
17345                 return true;
17346         }
17347     }
17348 
17349     /**
17350      * Reset resolved text alignment. Text alignment will be resolved during a call to
17351      * {@link #onMeasure(int, int)}.
17352      *
17353      * @hide
17354      */
17355     public void resetResolvedTextAlignment() {
17356         // Reset any previous text alignment resolution
17357         mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
17358         // Set to default
17359         mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17360     }
17361 
17362     /**
17363      * @return true if text alignment is inherited.
17364      *
17365      * @hide
17366      */
17367     public boolean isTextAlignmentInherited() {
17368         return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
17369     }
17370 
17371     /**
17372      * @return true if text alignment is resolved.
17373      *
17374      * @hide
17375      */
17376     public boolean isTextAlignmentResolved() {
17377         return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
17378     }
17379 
17380     /**
17381      * Generate a value suitable for use in {@link #setId(int)}.
17382      * This value will not collide with ID values generated at build time by aapt for R.id.
17383      *
17384      * @return a generated ID value
17385      */
17386     public static int generateViewId() {
17387         for (;;) {
17388             final int result = sNextGeneratedId.get();
17389             // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
17390             int newValue = result + 1;
17391             if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
17392             if (sNextGeneratedId.compareAndSet(result, newValue)) {
17393                 return result;
17394             }
17395         }
17396     }
17397 
17398     //
17399     // Properties
17400     //
17401     /**
17402      * A Property wrapper around the <code>alpha</code> functionality handled by the
17403      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
17404      */
17405     public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
17406         @Override
17407         public void setValue(View object, float value) {
17408             object.setAlpha(value);
17409         }
17410 
17411         @Override
17412         public Float get(View object) {
17413             return object.getAlpha();
17414         }
17415     };
17416 
17417     /**
17418      * A Property wrapper around the <code>translationX</code> functionality handled by the
17419      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
17420      */
17421     public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
17422         @Override
17423         public void setValue(View object, float value) {
17424             object.setTranslationX(value);
17425         }
17426 
17427                 @Override
17428         public Float get(View object) {
17429             return object.getTranslationX();
17430         }
17431     };
17432 
17433     /**
17434      * A Property wrapper around the <code>translationY</code> functionality handled by the
17435      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
17436      */
17437     public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
17438         @Override
17439         public void setValue(View object, float value) {
17440             object.setTranslationY(value);
17441         }
17442 
17443         @Override
17444         public Float get(View object) {
17445             return object.getTranslationY();
17446         }
17447     };
17448 
17449     /**
17450      * A Property wrapper around the <code>x</code> functionality handled by the
17451      * {@link View#setX(float)} and {@link View#getX()} methods.
17452      */
17453     public static final Property<View, Float> X = new FloatProperty<View>("x") {
17454         @Override
17455         public void setValue(View object, float value) {
17456             object.setX(value);
17457         }
17458 
17459         @Override
17460         public Float get(View object) {
17461             return object.getX();
17462         }
17463     };
17464 
17465     /**
17466      * A Property wrapper around the <code>y</code> functionality handled by the
17467      * {@link View#setY(float)} and {@link View#getY()} methods.
17468      */
17469     public static final Property<View, Float> Y = new FloatProperty<View>("y") {
17470         @Override
17471         public void setValue(View object, float value) {
17472             object.setY(value);
17473         }
17474 
17475         @Override
17476         public Float get(View object) {
17477             return object.getY();
17478         }
17479     };
17480 
17481     /**
17482      * A Property wrapper around the <code>rotation</code> functionality handled by the
17483      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
17484      */
17485     public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
17486         @Override
17487         public void setValue(View object, float value) {
17488             object.setRotation(value);
17489         }
17490 
17491         @Override
17492         public Float get(View object) {
17493             return object.getRotation();
17494         }
17495     };
17496 
17497     /**
17498      * A Property wrapper around the <code>rotationX</code> functionality handled by the
17499      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
17500      */
17501     public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
17502         @Override
17503         public void setValue(View object, float value) {
17504             object.setRotationX(value);
17505         }
17506 
17507         @Override
17508         public Float get(View object) {
17509             return object.getRotationX();
17510         }
17511     };
17512 
17513     /**
17514      * A Property wrapper around the <code>rotationY</code> functionality handled by the
17515      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
17516      */
17517     public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
17518         @Override
17519         public void setValue(View object, float value) {
17520             object.setRotationY(value);
17521         }
17522 
17523         @Override
17524         public Float get(View object) {
17525             return object.getRotationY();
17526         }
17527     };
17528 
17529     /**
17530      * A Property wrapper around the <code>scaleX</code> functionality handled by the
17531      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
17532      */
17533     public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
17534         @Override
17535         public void setValue(View object, float value) {
17536             object.setScaleX(value);
17537         }
17538 
17539         @Override
17540         public Float get(View object) {
17541             return object.getScaleX();
17542         }
17543     };
17544 
17545     /**
17546      * A Property wrapper around the <code>scaleY</code> functionality handled by the
17547      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
17548      */
17549     public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
17550         @Override
17551         public void setValue(View object, float value) {
17552             object.setScaleY(value);
17553         }
17554 
17555         @Override
17556         public Float get(View object) {
17557             return object.getScaleY();
17558         }
17559     };
17560 
17561     /**
17562      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
17563      * Each MeasureSpec represents a requirement for either the width or the height.
17564      * A MeasureSpec is comprised of a size and a mode. There are three possible
17565      * modes:
17566      * <dl>
17567      * <dt>UNSPECIFIED</dt>
17568      * <dd>
17569      * The parent has not imposed any constraint on the child. It can be whatever size
17570      * it wants.
17571      * </dd>
17572      *
17573      * <dt>EXACTLY</dt>
17574      * <dd>
17575      * The parent has determined an exact size for the child. The child is going to be
17576      * given those bounds regardless of how big it wants to be.
17577      * </dd>
17578      *
17579      * <dt>AT_MOST</dt>
17580      * <dd>
17581      * The child can be as large as it wants up to the specified size.
17582      * </dd>
17583      * </dl>
17584      *
17585      * MeasureSpecs are implemented as ints to reduce object allocation. This class
17586      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
17587      */
17588     public static class MeasureSpec {
17589         private static final int MODE_SHIFT = 30;
17590         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
17591 
17592         /**
17593          * Measure specification mode: The parent has not imposed any constraint
17594          * on the child. It can be whatever size it wants.
17595          */
17596         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
17597 
17598         /**
17599          * Measure specification mode: The parent has determined an exact size
17600          * for the child. The child is going to be given those bounds regardless
17601          * of how big it wants to be.
17602          */
17603         public static final int EXACTLY     = 1 << MODE_SHIFT;
17604 
17605         /**
17606          * Measure specification mode: The child can be as large as it wants up
17607          * to the specified size.
17608          */
17609         public static final int AT_MOST     = 2 << MODE_SHIFT;
17610 
17611         /**
17612          * Creates a measure specification based on the supplied size and mode.
17613          *
17614          * The mode must always be one of the following:
17615          * <ul>
17616          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
17617          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
17618          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
17619          * </ul>
17620          *
17621          * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
17622          * implementation was such that the order of arguments did not matter
17623          * and overflow in either value could impact the resulting MeasureSpec.
17624          * {@link android.widget.RelativeLayout} was affected by this bug.
17625          * Apps targeting API levels greater than 17 will get the fixed, more strict
17626          * behavior.</p>
17627          *
17628          * @param size the size of the measure specification
17629          * @param mode the mode of the measure specification
17630          * @return the measure specification based on size and mode
17631          */
17632         public static int makeMeasureSpec(int size, int mode) {
17633             if (sUseBrokenMakeMeasureSpec) {
17634                 return size + mode;
17635             } else {
17636                 return (size & ~MODE_MASK) | (mode & MODE_MASK);
17637             }
17638         }
17639 
17640         /**
17641          * Extracts the mode from the supplied measure specification.
17642          *
17643          * @param measureSpec the measure specification to extract the mode from
17644          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
17645          *         {@link android.view.View.MeasureSpec#AT_MOST} or
17646          *         {@link android.view.View.MeasureSpec#EXACTLY}
17647          */
17648         public static int getMode(int measureSpec) {
17649             return (measureSpec & MODE_MASK);
17650         }
17651 
17652         /**
17653          * Extracts the size from the supplied measure specification.
17654          *
17655          * @param measureSpec the measure specification to extract the size from
17656          * @return the size in pixels defined in the supplied measure specification
17657          */
17658         public static int getSize(int measureSpec) {
17659             return (measureSpec & ~MODE_MASK);
17660         }
17661 
17662         static int adjust(int measureSpec, int delta) {
17663             return makeMeasureSpec(getSize(measureSpec + delta), getMode(measureSpec));
17664         }
17665 
17666         /**
17667          * Returns a String representation of the specified measure
17668          * specification.
17669          *
17670          * @param measureSpec the measure specification to convert to a String
17671          * @return a String with the following format: "MeasureSpec: MODE SIZE"
17672          */
17673         public static String toString(int measureSpec) {
17674             int mode = getMode(measureSpec);
17675             int size = getSize(measureSpec);
17676 
17677             StringBuilder sb = new StringBuilder("MeasureSpec: ");
17678 
17679             if (mode == UNSPECIFIED)
17680                 sb.append("UNSPECIFIED ");
17681             else if (mode == EXACTLY)
17682                 sb.append("EXACTLY ");
17683             else if (mode == AT_MOST)
17684                 sb.append("AT_MOST ");
17685             else
17686                 sb.append(mode).append(" ");
17687 
17688             sb.append(size);
17689             return sb.toString();
17690         }
17691     }
17692 
17693     class CheckForLongPress implements Runnable {
17694 
17695         private int mOriginalWindowAttachCount;
17696 
17697         public void run() {
17698             if (isPressed() && (mParent != null)
17699                     && mOriginalWindowAttachCount == mWindowAttachCount) {
17700                 if (performLongClick()) {
17701                     mHasPerformedLongPress = true;
17702                 }
17703             }
17704         }
17705 
17706         public void rememberWindowAttachCount() {
17707             mOriginalWindowAttachCount = mWindowAttachCount;
17708         }
17709     }
17710 
17711     private final class CheckForTap implements Runnable {
17712         public void run() {
17713             mPrivateFlags &= ~PFLAG_PREPRESSED;
17714             setPressed(true);
17715             checkForLongClick(ViewConfiguration.getTapTimeout());
17716         }
17717     }
17718 
17719     private final class PerformClick implements Runnable {
17720         public void run() {
17721             performClick();
17722         }
17723     }
17724 
17725     /** @hide */
17726     public void hackTurnOffWindowResizeAnim(boolean off) {
17727         mAttachInfo.mTurnOffWindowResizeAnim = off;
17728     }
17729 
17730     /**
17731      * This method returns a ViewPropertyAnimator object, which can be used to animate
17732      * specific properties on this View.
17733      *
17734      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
17735      */
17736     public ViewPropertyAnimator animate() {
17737         if (mAnimator == null) {
17738             mAnimator = new ViewPropertyAnimator(this);
17739         }
17740         return mAnimator;
17741     }
17742 
17743     /**
17744      * Interface definition for a callback to be invoked when a hardware key event is
17745      * dispatched to this view. The callback will be invoked before the key event is
17746      * given to the view. This is only useful for hardware keyboards; a software input
17747      * method has no obligation to trigger this listener.
17748      */
17749     public interface OnKeyListener {
17750         /**
17751          * Called when a hardware key is dispatched to a view. This allows listeners to
17752          * get a chance to respond before the target view.
17753          * <p>Key presses in software keyboards will generally NOT trigger this method,
17754          * although some may elect to do so in some situations. Do not assume a
17755          * software input method has to be key-based; even if it is, it may use key presses
17756          * in a different way than you expect, so there is no way to reliably catch soft
17757          * input key presses.
17758          *
17759          * @param v The view the key has been dispatched to.
17760          * @param keyCode The code for the physical key that was pressed
17761          * @param event The KeyEvent object containing full information about
17762          *        the event.
17763          * @return True if the listener has consumed the event, false otherwise.
17764          */
17765         boolean onKey(View v, int keyCode, KeyEvent event);
17766     }
17767 
17768     /**
17769      * Interface definition for a callback to be invoked when a touch event is
17770      * dispatched to this view. The callback will be invoked before the touch
17771      * event is given to the view.
17772      */
17773     public interface OnTouchListener {
17774         /**
17775          * Called when a touch event is dispatched to a view. This allows listeners to
17776          * get a chance to respond before the target view.
17777          *
17778          * @param v The view the touch event has been dispatched to.
17779          * @param event The MotionEvent object containing full information about
17780          *        the event.
17781          * @return True if the listener has consumed the event, false otherwise.
17782          */
17783         boolean onTouch(View v, MotionEvent event);
17784     }
17785 
17786     /**
17787      * Interface definition for a callback to be invoked when a hover event is
17788      * dispatched to this view. The callback will be invoked before the hover
17789      * event is given to the view.
17790      */
17791     public interface OnHoverListener {
17792         /**
17793          * Called when a hover event is dispatched to a view. This allows listeners to
17794          * get a chance to respond before the target view.
17795          *
17796          * @param v The view the hover event has been dispatched to.
17797          * @param event The MotionEvent object containing full information about
17798          *        the event.
17799          * @return True if the listener has consumed the event, false otherwise.
17800          */
17801         boolean onHover(View v, MotionEvent event);
17802     }
17803 
17804     /**
17805      * Interface definition for a callback to be invoked when a generic motion event is
17806      * dispatched to this view. The callback will be invoked before the generic motion
17807      * event is given to the view.
17808      */
17809     public interface OnGenericMotionListener {
17810         /**
17811          * Called when a generic motion event is dispatched to a view. This allows listeners to
17812          * get a chance to respond before the target view.
17813          *
17814          * @param v The view the generic motion event has been dispatched to.
17815          * @param event The MotionEvent object containing full information about
17816          *        the event.
17817          * @return True if the listener has consumed the event, false otherwise.
17818          */
17819         boolean onGenericMotion(View v, MotionEvent event);
17820     }
17821 
17822     /**
17823      * Interface definition for a callback to be invoked when a view has been clicked and held.
17824      */
17825     public interface OnLongClickListener {
17826         /**
17827          * Called when a view has been clicked and held.
17828          *
17829          * @param v The view that was clicked and held.
17830          *
17831          * @return true if the callback consumed the long click, false otherwise.
17832          */
17833         boolean onLongClick(View v);
17834     }
17835 
17836     /**
17837      * Interface definition for a callback to be invoked when a drag is being dispatched
17838      * to this view.  The callback will be invoked before the hosting view's own
17839      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
17840      * onDrag(event) behavior, it should return 'false' from this callback.
17841      *
17842      * <div class="special reference">
17843      * <h3>Developer Guides</h3>
17844      * <p>For a guide to implementing drag and drop features, read the
17845      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
17846      * </div>
17847      */
17848     public interface OnDragListener {
17849         /**
17850          * Called when a drag event is dispatched to a view. This allows listeners
17851          * to get a chance to override base View behavior.
17852          *
17853          * @param v The View that received the drag event.
17854          * @param event The {@link android.view.DragEvent} object for the drag event.
17855          * @return {@code true} if the drag event was handled successfully, or {@code false}
17856          * if the drag event was not handled. Note that {@code false} will trigger the View
17857          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
17858          */
17859         boolean onDrag(View v, DragEvent event);
17860     }
17861 
17862     /**
17863      * Interface definition for a callback to be invoked when the focus state of
17864      * a view changed.
17865      */
17866     public interface OnFocusChangeListener {
17867         /**
17868          * Called when the focus state of a view has changed.
17869          *
17870          * @param v The view whose state has changed.
17871          * @param hasFocus The new focus state of v.
17872          */
17873         void onFocusChange(View v, boolean hasFocus);
17874     }
17875 
17876     /**
17877      * Interface definition for a callback to be invoked when a view is clicked.
17878      */
17879     public interface OnClickListener {
17880         /**
17881          * Called when a view has been clicked.
17882          *
17883          * @param v The view that was clicked.
17884          */
17885         void onClick(View v);
17886     }
17887 
17888     /**
17889      * Interface definition for a callback to be invoked when the context menu
17890      * for this view is being built.
17891      */
17892     public interface OnCreateContextMenuListener {
17893         /**
17894          * Called when the context menu for this view is being built. It is not
17895          * safe to hold onto the menu after this method returns.
17896          *
17897          * @param menu The context menu that is being built
17898          * @param v The view for which the context menu is being built
17899          * @param menuInfo Extra information about the item for which the
17900          *            context menu should be shown. This information will vary
17901          *            depending on the class of v.
17902          */
17903         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
17904     }
17905 
17906     /**
17907      * Interface definition for a callback to be invoked when the status bar changes
17908      * visibility.  This reports <strong>global</strong> changes to the system UI
17909      * state, not what the application is requesting.
17910      *
17911      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
17912      */
17913     public interface OnSystemUiVisibilityChangeListener {
17914         /**
17915          * Called when the status bar changes visibility because of a call to
17916          * {@link View#setSystemUiVisibility(int)}.
17917          *
17918          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17919          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
17920          * This tells you the <strong>global</strong> state of these UI visibility
17921          * flags, not what your app is currently applying.
17922          */
17923         public void onSystemUiVisibilityChange(int visibility);
17924     }
17925 
17926     /**
17927      * Interface definition for a callback to be invoked when this view is attached
17928      * or detached from its window.
17929      */
17930     public interface OnAttachStateChangeListener {
17931         /**
17932          * Called when the view is attached to a window.
17933          * @param v The view that was attached
17934          */
17935         public void onViewAttachedToWindow(View v);
17936         /**
17937          * Called when the view is detached from a window.
17938          * @param v The view that was detached
17939          */
17940         public void onViewDetachedFromWindow(View v);
17941     }
17942 
17943     private final class UnsetPressedState implements Runnable {
17944         public void run() {
17945             setPressed(false);
17946         }
17947     }
17948 
17949     /**
17950      * Base class for derived classes that want to save and restore their own
17951      * state in {@link android.view.View#onSaveInstanceState()}.
17952      */
17953     public static class BaseSavedState extends AbsSavedState {
17954         /**
17955          * Constructor used when reading from a parcel. Reads the state of the superclass.
17956          *
17957          * @param source
17958          */
17959         public BaseSavedState(Parcel source) {
17960             super(source);
17961         }
17962 
17963         /**
17964          * Constructor called by derived classes when creating their SavedState objects
17965          *
17966          * @param superState The state of the superclass of this view
17967          */
17968         public BaseSavedState(Parcelable superState) {
17969             super(superState);
17970         }
17971 
17972         public static final Parcelable.Creator<BaseSavedState> CREATOR =
17973                 new Parcelable.Creator<BaseSavedState>() {
17974             public BaseSavedState createFromParcel(Parcel in) {
17975                 return new BaseSavedState(in);
17976             }
17977 
17978             public BaseSavedState[] newArray(int size) {
17979                 return new BaseSavedState[size];
17980             }
17981         };
17982     }
17983 
17984     /**
17985      * A set of information given to a view when it is attached to its parent
17986      * window.
17987      */
17988     static class AttachInfo {
17989         interface Callbacks {
17990             void playSoundEffect(int effectId);
17991             boolean performHapticFeedback(int effectId, boolean always);
17992         }
17993 
17994         /**
17995          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
17996          * to a Handler. This class contains the target (View) to invalidate and
17997          * the coordinates of the dirty rectangle.
17998          *
17999          * For performance purposes, this class also implements a pool of up to
18000          * POOL_LIMIT objects that get reused. This reduces memory allocations
18001          * whenever possible.
18002          */
18003         static class InvalidateInfo {
18004             private static final int POOL_LIMIT = 10;
18005 
18006             private static final SynchronizedPool<InvalidateInfo> sPool =
18007                     new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
18008 
18009             View target;
18010 
18011             int left;
18012             int top;
18013             int right;
18014             int bottom;
18015 
18016             public static InvalidateInfo obtain() {
18017                 InvalidateInfo instance = sPool.acquire();
18018                 return (instance != null) ? instance : new InvalidateInfo();
18019             }
18020 
18021             public void recycle() {
18022                 target = null;
18023                 sPool.release(this);
18024             }
18025         }
18026 
18027         final IWindowSession mSession;
18028 
18029         final IWindow mWindow;
18030 
18031         final IBinder mWindowToken;
18032 
18033         final Display mDisplay;
18034 
18035         final Callbacks mRootCallbacks;
18036 
18037         HardwareCanvas mHardwareCanvas;
18038 
18039         IWindowId mIWindowId;
18040         WindowId mWindowId;
18041 
18042         /**
18043          * The top view of the hierarchy.
18044          */
18045         View mRootView;
18046 
18047         IBinder mPanelParentWindowToken;
18048         Surface mSurface;
18049 
18050         boolean mHardwareAccelerated;
18051         boolean mHardwareAccelerationRequested;
18052         HardwareRenderer mHardwareRenderer;
18053 
18054         boolean mScreenOn;
18055 
18056         /**
18057          * Scale factor used by the compatibility mode
18058          */
18059         float mApplicationScale;
18060 
18061         /**
18062          * Indicates whether the application is in compatibility mode
18063          */
18064         boolean mScalingRequired;
18065 
18066         /**
18067          * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
18068          */
18069         boolean mTurnOffWindowResizeAnim;
18070 
18071         /**
18072          * Left position of this view's window
18073          */
18074         int mWindowLeft;
18075 
18076         /**
18077          * Top position of this view's window
18078          */
18079         int mWindowTop;
18080 
18081         /**
18082          * Indicates whether views need to use 32-bit drawing caches
18083          */
18084         boolean mUse32BitDrawingCache;
18085 
18086         /**
18087          * For windows that are full-screen but using insets to layout inside
18088          * of the screen areas, these are the current insets to appear inside
18089          * the overscan area of the display.
18090          */
18091         final Rect mOverscanInsets = new Rect();
18092 
18093         /**
18094          * For windows that are full-screen but using insets to layout inside
18095          * of the screen decorations, these are the current insets for the
18096          * content of the window.
18097          */
18098         final Rect mContentInsets = new Rect();
18099 
18100         /**
18101          * For windows that are full-screen but using insets to layout inside
18102          * of the screen decorations, these are the current insets for the
18103          * actual visible parts of the window.
18104          */
18105         final Rect mVisibleInsets = new Rect();
18106 
18107         /**
18108          * The internal insets given by this window.  This value is
18109          * supplied by the client (through
18110          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
18111          * be given to the window manager when changed to be used in laying
18112          * out windows behind it.
18113          */
18114         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
18115                 = new ViewTreeObserver.InternalInsetsInfo();
18116 
18117         /**
18118          * All views in the window's hierarchy that serve as scroll containers,
18119          * used to determine if the window can be resized or must be panned
18120          * to adjust for a soft input area.
18121          */
18122         final ArrayList<View> mScrollContainers = new ArrayList<View>();
18123 
18124         final KeyEvent.DispatcherState mKeyDispatchState
18125                 = new KeyEvent.DispatcherState();
18126 
18127         /**
18128          * Indicates whether the view's window currently has the focus.
18129          */
18130         boolean mHasWindowFocus;
18131 
18132         /**
18133          * The current visibility of the window.
18134          */
18135         int mWindowVisibility;
18136 
18137         /**
18138          * Indicates the time at which drawing started to occur.
18139          */
18140         long mDrawingTime;
18141 
18142         /**
18143          * Indicates whether or not ignoring the DIRTY_MASK flags.
18144          */
18145         boolean mIgnoreDirtyState;
18146 
18147         /**
18148          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
18149          * to avoid clearing that flag prematurely.
18150          */
18151         boolean mSetIgnoreDirtyState = false;
18152 
18153         /**
18154          * Indicates whether the view's window is currently in touch mode.
18155          */
18156         boolean mInTouchMode;
18157 
18158         /**
18159          * Indicates that ViewAncestor should trigger a global layout change
18160          * the next time it performs a traversal
18161          */
18162         boolean mRecomputeGlobalAttributes;
18163 
18164         /**
18165          * Always report new attributes at next traversal.
18166          */
18167         boolean mForceReportNewAttributes;
18168 
18169         /**
18170          * Set during a traveral if any views want to keep the screen on.
18171          */
18172         boolean mKeepScreenOn;
18173 
18174         /**
18175          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
18176          */
18177         int mSystemUiVisibility;
18178 
18179         /**
18180          * Hack to force certain system UI visibility flags to be cleared.
18181          */
18182         int mDisabledSystemUiVisibility;
18183 
18184         /**
18185          * Last global system UI visibility reported by the window manager.
18186          */
18187         int mGlobalSystemUiVisibility;
18188 
18189         /**
18190          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
18191          * attached.
18192          */
18193         boolean mHasSystemUiListeners;
18194 
18195         /**
18196          * Set if the window has requested to extend into the overscan region
18197          * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
18198          */
18199         boolean mOverscanRequested;
18200 
18201         /**
18202          * Set if the visibility of any views has changed.
18203          */
18204         boolean mViewVisibilityChanged;
18205 
18206         /**
18207          * Set to true if a view has been scrolled.
18208          */
18209         boolean mViewScrollChanged;
18210 
18211         /**
18212          * Global to the view hierarchy used as a temporary for dealing with
18213          * x/y points in the transparent region computations.
18214          */
18215         final int[] mTransparentLocation = new int[2];
18216 
18217         /**
18218          * Global to the view hierarchy used as a temporary for dealing with
18219          * x/y points in the ViewGroup.invalidateChild implementation.
18220          */
18221         final int[] mInvalidateChildLocation = new int[2];
18222 
18223 
18224         /**
18225          * Global to the view hierarchy used as a temporary for dealing with
18226          * x/y location when view is transformed.
18227          */
18228         final float[] mTmpTransformLocation = new float[2];
18229 
18230         /**
18231          * The view tree observer used to dispatch global events like
18232          * layout, pre-draw, touch mode change, etc.
18233          */
18234         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
18235 
18236         /**
18237          * A Canvas used by the view hierarchy to perform bitmap caching.
18238          */
18239         Canvas mCanvas;
18240 
18241         /**
18242          * The view root impl.
18243          */
18244         final ViewRootImpl mViewRootImpl;
18245 
18246         /**
18247          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
18248          * handler can be used to pump events in the UI events queue.
18249          */
18250         final Handler mHandler;
18251 
18252         /**
18253          * Temporary for use in computing invalidate rectangles while
18254          * calling up the hierarchy.
18255          */
18256         final Rect mTmpInvalRect = new Rect();
18257 
18258         /**
18259          * Temporary for use in computing hit areas with transformed views
18260          */
18261         final RectF mTmpTransformRect = new RectF();
18262 
18263         /**
18264          * Temporary for use in transforming invalidation rect
18265          */
18266         final Matrix mTmpMatrix = new Matrix();
18267 
18268         /**
18269          * Temporary for use in transforming invalidation rect
18270          */
18271         final Transformation mTmpTransformation = new Transformation();
18272 
18273         /**
18274          * Temporary list for use in collecting focusable descendents of a view.
18275          */
18276         final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
18277 
18278         /**
18279          * The id of the window for accessibility purposes.
18280          */
18281         int mAccessibilityWindowId = View.NO_ID;
18282 
18283         /**
18284          * Flags related to accessibility processing.
18285          *
18286          * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
18287          * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
18288          */
18289         int mAccessibilityFetchFlags;
18290 
18291         /**
18292          * The drawable for highlighting accessibility focus.
18293          */
18294         Drawable mAccessibilityFocusDrawable;
18295 
18296         /**
18297          * Show where the margins, bounds and layout bounds are for each view.
18298          */
18299         boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
18300 
18301         /**
18302          * Point used to compute visible regions.
18303          */
18304         final Point mPoint = new Point();
18305 
18306         /**
18307          * Used to track which View originated a requestLayout() call, used when
18308          * requestLayout() is called during layout.
18309          */
18310         View mViewRequestingLayout;
18311 
18312         /**
18313          * Creates a new set of attachment information with the specified
18314          * events handler and thread.
18315          *
18316          * @param handler the events handler the view must use
18317          */
18318         AttachInfo(IWindowSession session, IWindow window, Display display,
18319                 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
18320             mSession = session;
18321             mWindow = window;
18322             mWindowToken = window.asBinder();
18323             mDisplay = display;
18324             mViewRootImpl = viewRootImpl;
18325             mHandler = handler;
18326             mRootCallbacks = effectPlayer;
18327         }
18328     }
18329 
18330     /**
18331      * <p>ScrollabilityCache holds various fields used by a View when scrolling
18332      * is supported. This avoids keeping too many unused fields in most
18333      * instances of View.</p>
18334      */
18335     private static class ScrollabilityCache implements Runnable {
18336 
18337         /**
18338          * Scrollbars are not visible
18339          */
18340         public static final int OFF = 0;
18341 
18342         /**
18343          * Scrollbars are visible
18344          */
18345         public static final int ON = 1;
18346 
18347         /**
18348          * Scrollbars are fading away
18349          */
18350         public static final int FADING = 2;
18351 
18352         public boolean fadeScrollBars;
18353 
18354         public int fadingEdgeLength;
18355         public int scrollBarDefaultDelayBeforeFade;
18356         public int scrollBarFadeDuration;
18357 
18358         public int scrollBarSize;
18359         public ScrollBarDrawable scrollBar;
18360         public float[] interpolatorValues;
18361         public View host;
18362 
18363         public final Paint paint;
18364         public final Matrix matrix;
18365         public Shader shader;
18366 
18367         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
18368 
18369         private static final float[] OPAQUE = { 255 };
18370         private static final float[] TRANSPARENT = { 0.0f };
18371 
18372         /**
18373          * When fading should start. This time moves into the future every time
18374          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
18375          */
18376         public long fadeStartTime;
18377 
18378 
18379         /**
18380          * The current state of the scrollbars: ON, OFF, or FADING
18381          */
18382         public int state = OFF;
18383 
18384         private int mLastColor;
18385 
18386         public ScrollabilityCache(ViewConfiguration configuration, View host) {
18387             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
18388             scrollBarSize = configuration.getScaledScrollBarSize();
18389             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
18390             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
18391 
18392             paint = new Paint();
18393             matrix = new Matrix();
18394             // use use a height of 1, and then wack the matrix each time we
18395             // actually use it.
18396             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
18397             paint.setShader(shader);
18398             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
18399 
18400             this.host = host;
18401         }
18402 
18403         public void setFadeColor(int color) {
18404             if (color != mLastColor) {
18405                 mLastColor = color;
18406 
18407                 if (color != 0) {
18408                     shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
18409                             color & 0x00FFFFFF, Shader.TileMode.CLAMP);
18410                     paint.setShader(shader);
18411                     // Restore the default transfer mode (src_over)
18412                     paint.setXfermode(null);
18413                 } else {
18414                     shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
18415                     paint.setShader(shader);
18416                     paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
18417                 }
18418             }
18419         }
18420 
18421         public void run() {
18422             long now = AnimationUtils.currentAnimationTimeMillis();
18423             if (now >= fadeStartTime) {
18424 
18425                 // the animation fades the scrollbars out by changing
18426                 // the opacity (alpha) from fully opaque to fully
18427                 // transparent
18428                 int nextFrame = (int) now;
18429                 int framesCount = 0;
18430 
18431                 Interpolator interpolator = scrollBarInterpolator;
18432 
18433                 // Start opaque
18434                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
18435 
18436                 // End transparent
18437                 nextFrame += scrollBarFadeDuration;
18438                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
18439 
18440                 state = FADING;
18441 
18442                 // Kick off the fade animation
18443                 host.invalidate(true);
18444             }
18445         }
18446     }
18447 
18448     /**
18449      * Resuable callback for sending
18450      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
18451      */
18452     private class SendViewScrolledAccessibilityEvent implements Runnable {
18453         public volatile boolean mIsPending;
18454 
18455         public void run() {
18456             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
18457             mIsPending = false;
18458         }
18459     }
18460 
18461     /**
18462      * <p>
18463      * This class represents a delegate that can be registered in a {@link View}
18464      * to enhance accessibility support via composition rather via inheritance.
18465      * It is specifically targeted to widget developers that extend basic View
18466      * classes i.e. classes in package android.view, that would like their
18467      * applications to be backwards compatible.
18468      * </p>
18469      * <div class="special reference">
18470      * <h3>Developer Guides</h3>
18471      * <p>For more information about making applications accessible, read the
18472      * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
18473      * developer guide.</p>
18474      * </div>
18475      * <p>
18476      * A scenario in which a developer would like to use an accessibility delegate
18477      * is overriding a method introduced in a later API version then the minimal API
18478      * version supported by the application. For example, the method
18479      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
18480      * in API version 4 when the accessibility APIs were first introduced. If a
18481      * developer would like his application to run on API version 4 devices (assuming
18482      * all other APIs used by the application are version 4 or lower) and take advantage
18483      * of this method, instead of overriding the method which would break the application's
18484      * backwards compatibility, he can override the corresponding method in this
18485      * delegate and register the delegate in the target View if the API version of
18486      * the system is high enough i.e. the API version is same or higher to the API
18487      * version that introduced
18488      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
18489      * </p>
18490      * <p>
18491      * Here is an example implementation:
18492      * </p>
18493      * <code><pre><p>
18494      * if (Build.VERSION.SDK_INT >= 14) {
18495      *     // If the API version is equal of higher than the version in
18496      *     // which onInitializeAccessibilityNodeInfo was introduced we
18497      *     // register a delegate with a customized implementation.
18498      *     View view = findViewById(R.id.view_id);
18499      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
18500      *         public void onInitializeAccessibilityNodeInfo(View host,
18501      *                 AccessibilityNodeInfo info) {
18502      *             // Let the default implementation populate the info.
18503      *             super.onInitializeAccessibilityNodeInfo(host, info);
18504      *             // Set some other information.
18505      *             info.setEnabled(host.isEnabled());
18506      *         }
18507      *     });
18508      * }
18509      * </code></pre></p>
18510      * <p>
18511      * This delegate contains methods that correspond to the accessibility methods
18512      * in View. If a delegate has been specified the implementation in View hands
18513      * off handling to the corresponding method in this delegate. The default
18514      * implementation the delegate methods behaves exactly as the corresponding
18515      * method in View for the case of no accessibility delegate been set. Hence,
18516      * to customize the behavior of a View method, clients can override only the
18517      * corresponding delegate method without altering the behavior of the rest
18518      * accessibility related methods of the host view.
18519      * </p>
18520      */
18521     public static class AccessibilityDelegate {
18522 
18523         /**
18524          * Sends an accessibility event of the given type. If accessibility is not
18525          * enabled this method has no effect.
18526          * <p>
18527          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
18528          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
18529          * been set.
18530          * </p>
18531          *
18532          * @param host The View hosting the delegate.
18533          * @param eventType The type of the event to send.
18534          *
18535          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
18536          */
18537         public void sendAccessibilityEvent(View host, int eventType) {
18538             host.sendAccessibilityEventInternal(eventType);
18539         }
18540 
18541         /**
18542          * Performs the specified accessibility action on the view. For
18543          * possible accessibility actions look at {@link AccessibilityNodeInfo}.
18544          * <p>
18545          * The default implementation behaves as
18546          * {@link View#performAccessibilityAction(int, Bundle)
18547          *  View#performAccessibilityAction(int, Bundle)} for the case of
18548          *  no accessibility delegate been set.
18549          * </p>
18550          *
18551          * @param action The action to perform.
18552          * @return Whether the action was performed.
18553          *
18554          * @see View#performAccessibilityAction(int, Bundle)
18555          *      View#performAccessibilityAction(int, Bundle)
18556          */
18557         public boolean performAccessibilityAction(View host, int action, Bundle args) {
18558             return host.performAccessibilityActionInternal(action, args);
18559         }
18560 
18561         /**
18562          * Sends an accessibility event. This method behaves exactly as
18563          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
18564          * empty {@link AccessibilityEvent} and does not perform a check whether
18565          * accessibility is enabled.
18566          * <p>
18567          * The default implementation behaves as
18568          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
18569          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
18570          * the case of no accessibility delegate been set.
18571          * </p>
18572          *
18573          * @param host The View hosting the delegate.
18574          * @param event The event to send.
18575          *
18576          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
18577          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
18578          */
18579         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
18580             host.sendAccessibilityEventUncheckedInternal(event);
18581         }
18582 
18583         /**
18584          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
18585          * to its children for adding their text content to the event.
18586          * <p>
18587          * The default implementation behaves as
18588          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
18589          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
18590          * the case of no accessibility delegate been set.
18591          * </p>
18592          *
18593          * @param host The View hosting the delegate.
18594          * @param event The event.
18595          * @return True if the event population was completed.
18596          *
18597          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
18598          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
18599          */
18600         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
18601             return host.dispatchPopulateAccessibilityEventInternal(event);
18602         }
18603 
18604         /**
18605          * Gives a chance to the host View to populate the accessibility event with its
18606          * text content.
18607          * <p>
18608          * The default implementation behaves as
18609          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
18610          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
18611          * the case of no accessibility delegate been set.
18612          * </p>
18613          *
18614          * @param host The View hosting the delegate.
18615          * @param event The accessibility event which to populate.
18616          *
18617          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
18618          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
18619          */
18620         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
18621             host.onPopulateAccessibilityEventInternal(event);
18622         }
18623 
18624         /**
18625          * Initializes an {@link AccessibilityEvent} with information about the
18626          * the host View which is the event source.
18627          * <p>
18628          * The default implementation behaves as
18629          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
18630          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
18631          * the case of no accessibility delegate been set.
18632          * </p>
18633          *
18634          * @param host The View hosting the delegate.
18635          * @param event The event to initialize.
18636          *
18637          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
18638          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
18639          */
18640         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
18641             host.onInitializeAccessibilityEventInternal(event);
18642         }
18643 
18644         /**
18645          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
18646          * <p>
18647          * The default implementation behaves as
18648          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
18649          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
18650          * the case of no accessibility delegate been set.
18651          * </p>
18652          *
18653          * @param host The View hosting the delegate.
18654          * @param info The instance to initialize.
18655          *
18656          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
18657          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
18658          */
18659         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
18660             host.onInitializeAccessibilityNodeInfoInternal(info);
18661         }
18662 
18663         /**
18664          * Called when a child of the host View has requested sending an
18665          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
18666          * to augment the event.
18667          * <p>
18668          * The default implementation behaves as
18669          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
18670          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
18671          * the case of no accessibility delegate been set.
18672          * </p>
18673          *
18674          * @param host The View hosting the delegate.
18675          * @param child The child which requests sending the event.
18676          * @param event The event to be sent.
18677          * @return True if the event should be sent
18678          *
18679          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
18680          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
18681          */
18682         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
18683                 AccessibilityEvent event) {
18684             return host.onRequestSendAccessibilityEventInternal(child, event);
18685         }
18686 
18687         /**
18688          * Gets the provider for managing a virtual view hierarchy rooted at this View
18689          * and reported to {@link android.accessibilityservice.AccessibilityService}s
18690          * that explore the window content.
18691          * <p>
18692          * The default implementation behaves as
18693          * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
18694          * the case of no accessibility delegate been set.
18695          * </p>
18696          *
18697          * @return The provider.
18698          *
18699          * @see AccessibilityNodeProvider
18700          */
18701         public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
18702             return null;
18703         }
18704 
18705         /**
18706          * Returns an {@link AccessibilityNodeInfo} representing the host view from the
18707          * point of view of an {@link android.accessibilityservice.AccessibilityService}.
18708          * This method is responsible for obtaining an accessibility node info from a
18709          * pool of reusable instances and calling
18710          * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
18711          * view to initialize the former.
18712          * <p>
18713          * <strong>Note:</strong> The client is responsible for recycling the obtained
18714          * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
18715          * creation.
18716          * </p>
18717          * <p>
18718          * The default implementation behaves as
18719          * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
18720          * the case of no accessibility delegate been set.
18721          * </p>
18722          * @return A populated {@link AccessibilityNodeInfo}.
18723          *
18724          * @see AccessibilityNodeInfo
18725          *
18726          * @hide
18727          */
18728         public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
18729             return host.createAccessibilityNodeInfoInternal();
18730         }
18731     }
18732 
18733     private class MatchIdPredicate implements Predicate<View> {
18734         public int mId;
18735 
18736         @Override
18737         public boolean apply(View view) {
18738             return (view.mID == mId);
18739         }
18740     }
18741 
18742     private class MatchLabelForPredicate implements Predicate<View> {
18743         private int mLabeledId;
18744 
18745         @Override
18746         public boolean apply(View view) {
18747             return (view.mLabelForId == mLabeledId);
18748         }
18749     }
18750 
18751     /**
18752      * Dump all private flags in readable format, useful for documentation and
18753      * sanity checking.
18754      */
18755     private static void dumpFlags() {
18756         final HashMap<String, String> found = Maps.newHashMap();
18757         try {
18758             for (Field field : View.class.getDeclaredFields()) {
18759                 final int modifiers = field.getModifiers();
18760                 if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
18761                     if (field.getType().equals(int.class)) {
18762                         final int value = field.getInt(null);
18763                         dumpFlag(found, field.getName(), value);
18764                     } else if (field.getType().equals(int[].class)) {
18765                         final int[] values = (int[]) field.get(null);
18766                         for (int i = 0; i < values.length; i++) {
18767                             dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
18768                         }
18769                     }
18770                 }
18771             }
18772         } catch (IllegalAccessException e) {
18773             throw new RuntimeException(e);
18774         }
18775 
18776         final ArrayList<String> keys = Lists.newArrayList();
18777         keys.addAll(found.keySet());
18778         Collections.sort(keys);
18779         for (String key : keys) {
18780             Log.d(VIEW_LOG_TAG, found.get(key));
18781         }
18782     }
18783 
18784     private static void dumpFlag(HashMap<String, String> found, String name, int value) {
18785         // Sort flags by prefix, then by bits, always keeping unique keys
18786         final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
18787         final int prefix = name.indexOf('_');
18788         final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
18789         final String output = bits + " " + name;
18790         found.put(key, output);
18791     }
18792 }
18793