• 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.Interpolator;
28 import android.graphics.LinearGradient;
29 import android.graphics.Matrix;
30 import android.graphics.Paint;
31 import android.graphics.PixelFormat;
32 import android.graphics.Point;
33 import android.graphics.PorterDuff;
34 import android.graphics.PorterDuffXfermode;
35 import android.graphics.Rect;
36 import android.graphics.RectF;
37 import android.graphics.Region;
38 import android.graphics.Shader;
39 import android.graphics.drawable.ColorDrawable;
40 import android.graphics.drawable.Drawable;
41 import android.os.Handler;
42 import android.os.IBinder;
43 import android.os.Message;
44 import android.os.Parcel;
45 import android.os.Parcelable;
46 import android.os.RemoteException;
47 import android.os.SystemClock;
48 import android.text.TextUtils;
49 import android.util.AttributeSet;
50 import android.util.FloatProperty;
51 import android.util.LocaleUtil;
52 import android.util.Log;
53 import android.util.Pool;
54 import android.util.Poolable;
55 import android.util.PoolableManager;
56 import android.util.Pools;
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.accessibility.AccessibilityEvent;
62 import android.view.accessibility.AccessibilityEventSource;
63 import android.view.accessibility.AccessibilityManager;
64 import android.view.accessibility.AccessibilityNodeInfo;
65 import android.view.animation.Animation;
66 import android.view.animation.AnimationUtils;
67 import android.view.inputmethod.EditorInfo;
68 import android.view.inputmethod.InputConnection;
69 import android.view.inputmethod.InputMethodManager;
70 import android.widget.ScrollBarDrawable;
71 
72 import static android.os.Build.VERSION_CODES.*;
73 
74 import com.android.internal.R;
75 import com.android.internal.util.Predicate;
76 import com.android.internal.view.menu.MenuBuilder;
77 
78 import java.lang.ref.WeakReference;
79 import java.lang.reflect.InvocationTargetException;
80 import java.lang.reflect.Method;
81 import java.util.ArrayList;
82 import java.util.Arrays;
83 import java.util.Locale;
84 import java.util.concurrent.CopyOnWriteArrayList;
85 
86 /**
87  * <p>
88  * This class represents the basic building block for user interface components. A View
89  * occupies a rectangular area on the screen and is responsible for drawing and
90  * event handling. View is the base class for <em>widgets</em>, which are
91  * used to create interactive UI components (buttons, text fields, etc.). The
92  * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
93  * are invisible containers that hold other Views (or other ViewGroups) and define
94  * their layout properties.
95  * </p>
96  *
97  * <div class="special reference">
98  * <h3>Developer Guides</h3>
99  * <p>For information about using this class to develop your application's user interface,
100  * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
101  * </div>
102  *
103  * <a name="Using"></a>
104  * <h3>Using Views</h3>
105  * <p>
106  * All of the views in a window are arranged in a single tree. You can add views
107  * either from code or by specifying a tree of views in one or more XML layout
108  * files. There are many specialized subclasses of views that act as controls or
109  * are capable of displaying text, images, or other content.
110  * </p>
111  * <p>
112  * Once you have created a tree of views, there are typically a few types of
113  * common operations you may wish to perform:
114  * <ul>
115  * <li><strong>Set properties:</strong> for example setting the text of a
116  * {@link android.widget.TextView}. The available properties and the methods
117  * that set them will vary among the different subclasses of views. Note that
118  * properties that are known at build time can be set in the XML layout
119  * files.</li>
120  * <li><strong>Set focus:</strong> The framework will handled moving focus in
121  * response to user input. To force focus to a specific view, call
122  * {@link #requestFocus}.</li>
123  * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
124  * that will be notified when something interesting happens to the view. For
125  * example, all views will let you set a listener to be notified when the view
126  * gains or loses focus. You can register such a listener using
127  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
128  * Other view subclasses offer more specialized listeners. For example, a Button
129  * exposes a listener to notify clients when the button is clicked.</li>
130  * <li><strong>Set visibility:</strong> You can hide or show views using
131  * {@link #setVisibility(int)}.</li>
132  * </ul>
133  * </p>
134  * <p><em>
135  * Note: The Android framework is responsible for measuring, laying out and
136  * drawing views. You should not call methods that perform these actions on
137  * views yourself unless you are actually implementing a
138  * {@link android.view.ViewGroup}.
139  * </em></p>
140  *
141  * <a name="Lifecycle"></a>
142  * <h3>Implementing a Custom View</h3>
143  *
144  * <p>
145  * To implement a custom view, you will usually begin by providing overrides for
146  * some of the standard methods that the framework calls on all views. You do
147  * not need to override all of these methods. In fact, you can start by just
148  * overriding {@link #onDraw(android.graphics.Canvas)}.
149  * <table border="2" width="85%" align="center" cellpadding="5">
150  *     <thead>
151  *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
152  *     </thead>
153  *
154  *     <tbody>
155  *     <tr>
156  *         <td rowspan="2">Creation</td>
157  *         <td>Constructors</td>
158  *         <td>There is a form of the constructor that are called when the view
159  *         is created from code and a form that is called when the view is
160  *         inflated from a layout file. The second form should parse and apply
161  *         any attributes defined in the layout file.
162  *         </td>
163  *     </tr>
164  *     <tr>
165  *         <td><code>{@link #onFinishInflate()}</code></td>
166  *         <td>Called after a view and all of its children has been inflated
167  *         from XML.</td>
168  *     </tr>
169  *
170  *     <tr>
171  *         <td rowspan="3">Layout</td>
172  *         <td><code>{@link #onMeasure(int, int)}</code></td>
173  *         <td>Called to determine the size requirements for this view and all
174  *         of its children.
175  *         </td>
176  *     </tr>
177  *     <tr>
178  *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
179  *         <td>Called when this view should assign a size and position to all
180  *         of its children.
181  *         </td>
182  *     </tr>
183  *     <tr>
184  *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
185  *         <td>Called when the size of this view has changed.
186  *         </td>
187  *     </tr>
188  *
189  *     <tr>
190  *         <td>Drawing</td>
191  *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
192  *         <td>Called when the view should render its content.
193  *         </td>
194  *     </tr>
195  *
196  *     <tr>
197  *         <td rowspan="4">Event processing</td>
198  *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
199  *         <td>Called when a new key event occurs.
200  *         </td>
201  *     </tr>
202  *     <tr>
203  *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
204  *         <td>Called when a key up event occurs.
205  *         </td>
206  *     </tr>
207  *     <tr>
208  *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
209  *         <td>Called when a trackball motion event occurs.
210  *         </td>
211  *     </tr>
212  *     <tr>
213  *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
214  *         <td>Called when a touch screen motion event occurs.
215  *         </td>
216  *     </tr>
217  *
218  *     <tr>
219  *         <td rowspan="2">Focus</td>
220  *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
221  *         <td>Called when the view gains or loses focus.
222  *         </td>
223  *     </tr>
224  *
225  *     <tr>
226  *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
227  *         <td>Called when the window containing the view gains or loses focus.
228  *         </td>
229  *     </tr>
230  *
231  *     <tr>
232  *         <td rowspan="3">Attaching</td>
233  *         <td><code>{@link #onAttachedToWindow()}</code></td>
234  *         <td>Called when the view is attached to a window.
235  *         </td>
236  *     </tr>
237  *
238  *     <tr>
239  *         <td><code>{@link #onDetachedFromWindow}</code></td>
240  *         <td>Called when the view is detached from its window.
241  *         </td>
242  *     </tr>
243  *
244  *     <tr>
245  *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
246  *         <td>Called when the visibility of the window containing the view
247  *         has changed.
248  *         </td>
249  *     </tr>
250  *     </tbody>
251  *
252  * </table>
253  * </p>
254  *
255  * <a name="IDs"></a>
256  * <h3>IDs</h3>
257  * Views may have an integer id associated with them. These ids are typically
258  * assigned in the layout XML files, and are used to find specific views within
259  * the view tree. A common pattern is to:
260  * <ul>
261  * <li>Define a Button in the layout file and assign it a unique ID.
262  * <pre>
263  * &lt;Button
264  *     android:id="@+id/my_button"
265  *     android:layout_width="wrap_content"
266  *     android:layout_height="wrap_content"
267  *     android:text="@string/my_button_text"/&gt;
268  * </pre></li>
269  * <li>From the onCreate method of an Activity, find the Button
270  * <pre class="prettyprint">
271  *      Button myButton = (Button) findViewById(R.id.my_button);
272  * </pre></li>
273  * </ul>
274  * <p>
275  * View IDs need not be unique throughout the tree, but it is good practice to
276  * ensure that they are at least unique within the part of the tree you are
277  * searching.
278  * </p>
279  *
280  * <a name="Position"></a>
281  * <h3>Position</h3>
282  * <p>
283  * The geometry of a view is that of a rectangle. A view has a location,
284  * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
285  * two dimensions, expressed as a width and a height. The unit for location
286  * and dimensions is the pixel.
287  * </p>
288  *
289  * <p>
290  * It is possible to retrieve the location of a view by invoking the methods
291  * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
292  * coordinate of the rectangle representing the view. The latter returns the
293  * top, or Y, coordinate of the rectangle representing the view. These methods
294  * both return the location of the view relative to its parent. For instance,
295  * when getLeft() returns 20, that means the view is located 20 pixels to the
296  * right of the left edge of its direct parent.
297  * </p>
298  *
299  * <p>
300  * In addition, several convenience methods are offered to avoid unnecessary
301  * computations, namely {@link #getRight()} and {@link #getBottom()}.
302  * These methods return the coordinates of the right and bottom edges of the
303  * rectangle representing the view. For instance, calling {@link #getRight()}
304  * is similar to the following computation: <code>getLeft() + getWidth()</code>
305  * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
306  * </p>
307  *
308  * <a name="SizePaddingMargins"></a>
309  * <h3>Size, padding and margins</h3>
310  * <p>
311  * The size of a view is expressed with a width and a height. A view actually
312  * possess two pairs of width and height values.
313  * </p>
314  *
315  * <p>
316  * The first pair is known as <em>measured width</em> and
317  * <em>measured height</em>. These dimensions define how big a view wants to be
318  * within its parent (see <a href="#Layout">Layout</a> for more details.) The
319  * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
320  * and {@link #getMeasuredHeight()}.
321  * </p>
322  *
323  * <p>
324  * The second pair is simply known as <em>width</em> and <em>height</em>, or
325  * sometimes <em>drawing width</em> and <em>drawing height</em>. These
326  * dimensions define the actual size of the view on screen, at drawing time and
327  * after layout. These values may, but do not have to, be different from the
328  * measured width and height. The width and height can be obtained by calling
329  * {@link #getWidth()} and {@link #getHeight()}.
330  * </p>
331  *
332  * <p>
333  * To measure its dimensions, a view takes into account its padding. The padding
334  * is expressed in pixels for the left, top, right and bottom parts of the view.
335  * Padding can be used to offset the content of the view by a specific amount of
336  * pixels. For instance, a left padding of 2 will push the view's content by
337  * 2 pixels to the right of the left edge. Padding can be set using the
338  * {@link #setPadding(int, int, int, int)} method and queried by calling
339  * {@link #getPaddingLeft()}, {@link #getPaddingTop()},
340  * {@link #getPaddingRight()}, {@link #getPaddingBottom()}.
341  * </p>
342  *
343  * <p>
344  * Even though a view can define a padding, it does not provide any support for
345  * margins. However, view groups provide such a support. Refer to
346  * {@link android.view.ViewGroup} and
347  * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
348  * </p>
349  *
350  * <a name="Layout"></a>
351  * <h3>Layout</h3>
352  * <p>
353  * Layout is a two pass process: a measure pass and a layout pass. The measuring
354  * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
355  * of the view tree. Each view pushes dimension specifications down the tree
356  * during the recursion. At the end of the measure pass, every view has stored
357  * its measurements. The second pass happens in
358  * {@link #layout(int,int,int,int)} and is also top-down. During
359  * this pass each parent is responsible for positioning all of its children
360  * using the sizes computed in the measure pass.
361  * </p>
362  *
363  * <p>
364  * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
365  * {@link #getMeasuredHeight()} values must be set, along with those for all of
366  * that view's descendants. A view's measured width and measured height values
367  * must respect the constraints imposed by the view's parents. This guarantees
368  * that at the end of the measure pass, all parents accept all of their
369  * children's measurements. A parent view may call measure() more than once on
370  * its children. For example, the parent may measure each child once with
371  * unspecified dimensions to find out how big they want to be, then call
372  * measure() on them again with actual numbers if the sum of all the children's
373  * unconstrained sizes is too big or too small.
374  * </p>
375  *
376  * <p>
377  * The measure pass uses two classes to communicate dimensions. The
378  * {@link MeasureSpec} class is used by views to tell their parents how they
379  * want to be measured and positioned. The base LayoutParams class just
380  * describes how big the view wants to be for both width and height. For each
381  * dimension, it can specify one of:
382  * <ul>
383  * <li> an exact number
384  * <li>MATCH_PARENT, which means the view wants to be as big as its parent
385  * (minus padding)
386  * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
387  * enclose its content (plus padding).
388  * </ul>
389  * There are subclasses of LayoutParams for different subclasses of ViewGroup.
390  * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
391  * an X and Y value.
392  * </p>
393  *
394  * <p>
395  * MeasureSpecs are used to push requirements down the tree from parent to
396  * child. A MeasureSpec can be in one of three modes:
397  * <ul>
398  * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
399  * of a child view. For example, a LinearLayout may call measure() on its child
400  * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
401  * tall the child view wants to be given a width of 240 pixels.
402  * <li>EXACTLY: This is used by the parent to impose an exact size on the
403  * child. The child must use this size, and guarantee that all of its
404  * descendants will fit within this size.
405  * <li>AT_MOST: This is used by the parent to impose a maximum size on the
406  * child. The child must gurantee that it and all of its descendants will fit
407  * within this size.
408  * </ul>
409  * </p>
410  *
411  * <p>
412  * To intiate a layout, call {@link #requestLayout}. This method is typically
413  * called by a view on itself when it believes that is can no longer fit within
414  * its current bounds.
415  * </p>
416  *
417  * <a name="Drawing"></a>
418  * <h3>Drawing</h3>
419  * <p>
420  * Drawing is handled by walking the tree and rendering each view that
421  * intersects the invalid region. Because the tree is traversed in-order,
422  * this means that parents will draw before (i.e., behind) their children, with
423  * siblings drawn in the order they appear in the tree.
424  * If you set a background drawable for a View, then the View will draw it for you
425  * before calling back to its <code>onDraw()</code> method.
426  * </p>
427  *
428  * <p>
429  * Note that the framework will not draw views that are not in the invalid region.
430  * </p>
431  *
432  * <p>
433  * To force a view to draw, call {@link #invalidate()}.
434  * </p>
435  *
436  * <a name="EventHandlingThreading"></a>
437  * <h3>Event Handling and Threading</h3>
438  * <p>
439  * The basic cycle of a view is as follows:
440  * <ol>
441  * <li>An event comes in and is dispatched to the appropriate view. The view
442  * handles the event and notifies any listeners.</li>
443  * <li>If in the course of processing the event, the view's bounds may need
444  * to be changed, the view will call {@link #requestLayout()}.</li>
445  * <li>Similarly, if in the course of processing the event the view's appearance
446  * may need to be changed, the view will call {@link #invalidate()}.</li>
447  * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
448  * the framework will take care of measuring, laying out, and drawing the tree
449  * as appropriate.</li>
450  * </ol>
451  * </p>
452  *
453  * <p><em>Note: The entire view tree is single threaded. You must always be on
454  * the UI thread when calling any method on any view.</em>
455  * If you are doing work on other threads and want to update the state of a view
456  * from that thread, you should use a {@link Handler}.
457  * </p>
458  *
459  * <a name="FocusHandling"></a>
460  * <h3>Focus Handling</h3>
461  * <p>
462  * The framework will handle routine focus movement in response to user input.
463  * This includes changing the focus as views are removed or hidden, or as new
464  * views become available. Views indicate their willingness to take focus
465  * through the {@link #isFocusable} method. To change whether a view can take
466  * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
467  * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
468  * and can change this via {@link #setFocusableInTouchMode(boolean)}.
469  * </p>
470  * <p>
471  * Focus movement is based on an algorithm which finds the nearest neighbor in a
472  * given direction. In rare cases, the default algorithm may not match the
473  * intended behavior of the developer. In these situations, you can provide
474  * explicit overrides by using these XML attributes in the layout file:
475  * <pre>
476  * nextFocusDown
477  * nextFocusLeft
478  * nextFocusRight
479  * nextFocusUp
480  * </pre>
481  * </p>
482  *
483  *
484  * <p>
485  * To get a particular view to take focus, call {@link #requestFocus()}.
486  * </p>
487  *
488  * <a name="TouchMode"></a>
489  * <h3>Touch Mode</h3>
490  * <p>
491  * When a user is navigating a user interface via directional keys such as a D-pad, it is
492  * necessary to give focus to actionable items such as buttons so the user can see
493  * what will take input.  If the device has touch capabilities, however, and the user
494  * begins interacting with the interface by touching it, it is no longer necessary to
495  * always highlight, or give focus to, a particular view.  This motivates a mode
496  * for interaction named 'touch mode'.
497  * </p>
498  * <p>
499  * For a touch capable device, once the user touches the screen, the device
500  * will enter touch mode.  From this point onward, only views for which
501  * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
502  * Other views that are touchable, like buttons, will not take focus when touched; they will
503  * only fire the on click listeners.
504  * </p>
505  * <p>
506  * Any time a user hits a directional key, such as a D-pad direction, the view device will
507  * exit touch mode, and find a view to take focus, so that the user may resume interacting
508  * with the user interface without touching the screen again.
509  * </p>
510  * <p>
511  * The touch mode state is maintained across {@link android.app.Activity}s.  Call
512  * {@link #isInTouchMode} to see whether the device is currently in touch mode.
513  * </p>
514  *
515  * <a name="Scrolling"></a>
516  * <h3>Scrolling</h3>
517  * <p>
518  * The framework provides basic support for views that wish to internally
519  * scroll their content. This includes keeping track of the X and Y scroll
520  * offset as well as mechanisms for drawing scrollbars. See
521  * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
522  * {@link #awakenScrollBars()} for more details.
523  * </p>
524  *
525  * <a name="Tags"></a>
526  * <h3>Tags</h3>
527  * <p>
528  * Unlike IDs, tags are not used to identify views. Tags are essentially an
529  * extra piece of information that can be associated with a view. They are most
530  * often used as a convenience to store data related to views in the views
531  * themselves rather than by putting them in a separate structure.
532  * </p>
533  *
534  * <a name="Animation"></a>
535  * <h3>Animation</h3>
536  * <p>
537  * You can attach an {@link Animation} object to a view using
538  * {@link #setAnimation(Animation)} or
539  * {@link #startAnimation(Animation)}. The animation can alter the scale,
540  * rotation, translation and alpha of a view over time. If the animation is
541  * attached to a view that has children, the animation will affect the entire
542  * subtree rooted by that node. When an animation is started, the framework will
543  * take care of redrawing the appropriate views until the animation completes.
544  * </p>
545  * <p>
546  * Starting with Android 3.0, the preferred way of animating views is to use the
547  * {@link android.animation} package APIs.
548  * </p>
549  *
550  * <a name="Security"></a>
551  * <h3>Security</h3>
552  * <p>
553  * Sometimes it is essential that an application be able to verify that an action
554  * is being performed with the full knowledge and consent of the user, such as
555  * granting a permission request, making a purchase or clicking on an advertisement.
556  * Unfortunately, a malicious application could try to spoof the user into
557  * performing these actions, unaware, by concealing the intended purpose of the view.
558  * As a remedy, the framework offers a touch filtering mechanism that can be used to
559  * improve the security of views that provide access to sensitive functionality.
560  * </p><p>
561  * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
562  * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
563  * will discard touches that are received whenever the view's window is obscured by
564  * another visible window.  As a result, the view will not receive touches whenever a
565  * toast, dialog or other window appears above the view's window.
566  * </p><p>
567  * For more fine-grained control over security, consider overriding the
568  * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
569  * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
570  * </p>
571  *
572  * @attr ref android.R.styleable#View_alpha
573  * @attr ref android.R.styleable#View_background
574  * @attr ref android.R.styleable#View_clickable
575  * @attr ref android.R.styleable#View_contentDescription
576  * @attr ref android.R.styleable#View_drawingCacheQuality
577  * @attr ref android.R.styleable#View_duplicateParentState
578  * @attr ref android.R.styleable#View_id
579  * @attr ref android.R.styleable#View_requiresFadingEdge
580  * @attr ref android.R.styleable#View_fadingEdgeLength
581  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
582  * @attr ref android.R.styleable#View_fitsSystemWindows
583  * @attr ref android.R.styleable#View_isScrollContainer
584  * @attr ref android.R.styleable#View_focusable
585  * @attr ref android.R.styleable#View_focusableInTouchMode
586  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
587  * @attr ref android.R.styleable#View_keepScreenOn
588  * @attr ref android.R.styleable#View_layerType
589  * @attr ref android.R.styleable#View_longClickable
590  * @attr ref android.R.styleable#View_minHeight
591  * @attr ref android.R.styleable#View_minWidth
592  * @attr ref android.R.styleable#View_nextFocusDown
593  * @attr ref android.R.styleable#View_nextFocusLeft
594  * @attr ref android.R.styleable#View_nextFocusRight
595  * @attr ref android.R.styleable#View_nextFocusUp
596  * @attr ref android.R.styleable#View_onClick
597  * @attr ref android.R.styleable#View_padding
598  * @attr ref android.R.styleable#View_paddingBottom
599  * @attr ref android.R.styleable#View_paddingLeft
600  * @attr ref android.R.styleable#View_paddingRight
601  * @attr ref android.R.styleable#View_paddingTop
602  * @attr ref android.R.styleable#View_saveEnabled
603  * @attr ref android.R.styleable#View_rotation
604  * @attr ref android.R.styleable#View_rotationX
605  * @attr ref android.R.styleable#View_rotationY
606  * @attr ref android.R.styleable#View_scaleX
607  * @attr ref android.R.styleable#View_scaleY
608  * @attr ref android.R.styleable#View_scrollX
609  * @attr ref android.R.styleable#View_scrollY
610  * @attr ref android.R.styleable#View_scrollbarSize
611  * @attr ref android.R.styleable#View_scrollbarStyle
612  * @attr ref android.R.styleable#View_scrollbars
613  * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
614  * @attr ref android.R.styleable#View_scrollbarFadeDuration
615  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
616  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
617  * @attr ref android.R.styleable#View_scrollbarThumbVertical
618  * @attr ref android.R.styleable#View_scrollbarTrackVertical
619  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
620  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
621  * @attr ref android.R.styleable#View_soundEffectsEnabled
622  * @attr ref android.R.styleable#View_tag
623  * @attr ref android.R.styleable#View_transformPivotX
624  * @attr ref android.R.styleable#View_transformPivotY
625  * @attr ref android.R.styleable#View_translationX
626  * @attr ref android.R.styleable#View_translationY
627  * @attr ref android.R.styleable#View_visibility
628  *
629  * @see android.view.ViewGroup
630  */
631 public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Callback,
632         AccessibilityEventSource {
633     private static final boolean DBG = false;
634 
635     /**
636      * The logging tag used by this class with android.util.Log.
637      */
638     protected static final String VIEW_LOG_TAG = "View";
639 
640     /**
641      * Used to mark a View that has no ID.
642      */
643     public static final int NO_ID = -1;
644 
645     /**
646      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
647      * calling setFlags.
648      */
649     private static final int NOT_FOCUSABLE = 0x00000000;
650 
651     /**
652      * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
653      * setFlags.
654      */
655     private static final int FOCUSABLE = 0x00000001;
656 
657     /**
658      * Mask for use with setFlags indicating bits used for focus.
659      */
660     private static final int FOCUSABLE_MASK = 0x00000001;
661 
662     /**
663      * This view will adjust its padding to fit sytem windows (e.g. status bar)
664      */
665     private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
666 
667     /**
668      * This view is visible.
669      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
670      * android:visibility}.
671      */
672     public static final int VISIBLE = 0x00000000;
673 
674     /**
675      * This view is invisible, but it still takes up space for layout purposes.
676      * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
677      * android:visibility}.
678      */
679     public static final int INVISIBLE = 0x00000004;
680 
681     /**
682      * This view is invisible, and it doesn't take any space for layout
683      * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
684      * android:visibility}.
685      */
686     public static final int GONE = 0x00000008;
687 
688     /**
689      * Mask for use with setFlags indicating bits used for visibility.
690      * {@hide}
691      */
692     static final int VISIBILITY_MASK = 0x0000000C;
693 
694     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
695 
696     /**
697      * This view is enabled. Intrepretation varies by subclass.
698      * Use with ENABLED_MASK when calling setFlags.
699      * {@hide}
700      */
701     static final int ENABLED = 0x00000000;
702 
703     /**
704      * This view is disabled. Intrepretation varies by subclass.
705      * Use with ENABLED_MASK when calling setFlags.
706      * {@hide}
707      */
708     static final int DISABLED = 0x00000020;
709 
710    /**
711     * Mask for use with setFlags indicating bits used for indicating whether
712     * this view is enabled
713     * {@hide}
714     */
715     static final int ENABLED_MASK = 0x00000020;
716 
717     /**
718      * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
719      * called and further optimizations will be performed. It is okay to have
720      * this flag set and a background. Use with DRAW_MASK when calling setFlags.
721      * {@hide}
722      */
723     static final int WILL_NOT_DRAW = 0x00000080;
724 
725     /**
726      * Mask for use with setFlags indicating bits used for indicating whether
727      * this view is will draw
728      * {@hide}
729      */
730     static final int DRAW_MASK = 0x00000080;
731 
732     /**
733      * <p>This view doesn't show scrollbars.</p>
734      * {@hide}
735      */
736     static final int SCROLLBARS_NONE = 0x00000000;
737 
738     /**
739      * <p>This view shows horizontal scrollbars.</p>
740      * {@hide}
741      */
742     static final int SCROLLBARS_HORIZONTAL = 0x00000100;
743 
744     /**
745      * <p>This view shows vertical scrollbars.</p>
746      * {@hide}
747      */
748     static final int SCROLLBARS_VERTICAL = 0x00000200;
749 
750     /**
751      * <p>Mask for use with setFlags indicating bits used for indicating which
752      * scrollbars are enabled.</p>
753      * {@hide}
754      */
755     static final int SCROLLBARS_MASK = 0x00000300;
756 
757     /**
758      * Indicates that the view should filter touches when its window is obscured.
759      * Refer to the class comments for more information about this security feature.
760      * {@hide}
761      */
762     static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
763 
764     // note flag value 0x00000800 is now available for next flags...
765 
766     /**
767      * <p>This view doesn't show fading edges.</p>
768      * {@hide}
769      */
770     static final int FADING_EDGE_NONE = 0x00000000;
771 
772     /**
773      * <p>This view shows horizontal fading edges.</p>
774      * {@hide}
775      */
776     static final int FADING_EDGE_HORIZONTAL = 0x00001000;
777 
778     /**
779      * <p>This view shows vertical fading edges.</p>
780      * {@hide}
781      */
782     static final int FADING_EDGE_VERTICAL = 0x00002000;
783 
784     /**
785      * <p>Mask for use with setFlags indicating bits used for indicating which
786      * fading edges are enabled.</p>
787      * {@hide}
788      */
789     static final int FADING_EDGE_MASK = 0x00003000;
790 
791     /**
792      * <p>Indicates this view can be clicked. When clickable, a View reacts
793      * to clicks by notifying the OnClickListener.<p>
794      * {@hide}
795      */
796     static final int CLICKABLE = 0x00004000;
797 
798     /**
799      * <p>Indicates this view is caching its drawing into a bitmap.</p>
800      * {@hide}
801      */
802     static final int DRAWING_CACHE_ENABLED = 0x00008000;
803 
804     /**
805      * <p>Indicates that no icicle should be saved for this view.<p>
806      * {@hide}
807      */
808     static final int SAVE_DISABLED = 0x000010000;
809 
810     /**
811      * <p>Mask for use with setFlags indicating bits used for the saveEnabled
812      * property.</p>
813      * {@hide}
814      */
815     static final int SAVE_DISABLED_MASK = 0x000010000;
816 
817     /**
818      * <p>Indicates that no drawing cache should ever be created for this view.<p>
819      * {@hide}
820      */
821     static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
822 
823     /**
824      * <p>Indicates this view can take / keep focus when int touch mode.</p>
825      * {@hide}
826      */
827     static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
828 
829     /**
830      * <p>Enables low quality mode for the drawing cache.</p>
831      */
832     public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
833 
834     /**
835      * <p>Enables high quality mode for the drawing cache.</p>
836      */
837     public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
838 
839     /**
840      * <p>Enables automatic quality mode for the drawing cache.</p>
841      */
842     public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
843 
844     private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
845             DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
846     };
847 
848     /**
849      * <p>Mask for use with setFlags indicating bits used for the cache
850      * quality property.</p>
851      * {@hide}
852      */
853     static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
854 
855     /**
856      * <p>
857      * Indicates this view can be long clicked. When long clickable, a View
858      * reacts to long clicks by notifying the OnLongClickListener or showing a
859      * context menu.
860      * </p>
861      * {@hide}
862      */
863     static final int LONG_CLICKABLE = 0x00200000;
864 
865     /**
866      * <p>Indicates that this view gets its drawable states from its direct parent
867      * and ignores its original internal states.</p>
868      *
869      * @hide
870      */
871     static final int DUPLICATE_PARENT_STATE = 0x00400000;
872 
873     /**
874      * The scrollbar style to display the scrollbars inside the content area,
875      * without increasing the padding. The scrollbars will be overlaid with
876      * translucency on the view's content.
877      */
878     public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
879 
880     /**
881      * The scrollbar style to display the scrollbars inside the padded area,
882      * increasing the padding of the view. The scrollbars will not overlap the
883      * content area of the view.
884      */
885     public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
886 
887     /**
888      * The scrollbar style to display the scrollbars at the edge of the view,
889      * without increasing the padding. The scrollbars will be overlaid with
890      * translucency.
891      */
892     public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
893 
894     /**
895      * The scrollbar style to display the scrollbars at the edge of the view,
896      * increasing the padding of the view. The scrollbars will only overlap the
897      * background, if any.
898      */
899     public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
900 
901     /**
902      * Mask to check if the scrollbar style is overlay or inset.
903      * {@hide}
904      */
905     static final int SCROLLBARS_INSET_MASK = 0x01000000;
906 
907     /**
908      * Mask to check if the scrollbar style is inside or outside.
909      * {@hide}
910      */
911     static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
912 
913     /**
914      * Mask for scrollbar style.
915      * {@hide}
916      */
917     static final int SCROLLBARS_STYLE_MASK = 0x03000000;
918 
919     /**
920      * View flag indicating that the screen should remain on while the
921      * window containing this view is visible to the user.  This effectively
922      * takes care of automatically setting the WindowManager's
923      * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
924      */
925     public static final int KEEP_SCREEN_ON = 0x04000000;
926 
927     /**
928      * View flag indicating whether this view should have sound effects enabled
929      * for events such as clicking and touching.
930      */
931     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
932 
933     /**
934      * View flag indicating whether this view should have haptic feedback
935      * enabled for events such as long presses.
936      */
937     public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
938 
939     /**
940      * <p>Indicates that the view hierarchy should stop saving state when
941      * it reaches this view.  If state saving is initiated immediately at
942      * the view, it will be allowed.
943      * {@hide}
944      */
945     static final int PARENT_SAVE_DISABLED = 0x20000000;
946 
947     /**
948      * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
949      * {@hide}
950      */
951     static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
952 
953     /**
954      * Horizontal direction of this view is from Left to Right.
955      * Use with {@link #setLayoutDirection}.
956      * {@hide}
957      */
958     public static final int LAYOUT_DIRECTION_LTR = 0x00000000;
959 
960     /**
961      * Horizontal direction of this view is from Right to Left.
962      * Use with {@link #setLayoutDirection}.
963      * {@hide}
964      */
965     public static final int LAYOUT_DIRECTION_RTL = 0x40000000;
966 
967     /**
968      * Horizontal direction of this view is inherited from its parent.
969      * Use with {@link #setLayoutDirection}.
970      * {@hide}
971      */
972     public static final int LAYOUT_DIRECTION_INHERIT = 0x80000000;
973 
974     /**
975      * Horizontal direction of this view is from deduced from the default language
976      * script for the locale. Use with {@link #setLayoutDirection}.
977      * {@hide}
978      */
979     public static final int LAYOUT_DIRECTION_LOCALE = 0xC0000000;
980 
981     /**
982      * Mask for use with setFlags indicating bits used for horizontalDirection.
983      * {@hide}
984      */
985     static final int LAYOUT_DIRECTION_MASK = 0xC0000000;
986 
987     /*
988      * Array of horizontal direction flags for mapping attribute "horizontalDirection" to correct
989      * flag value.
990      * {@hide}
991      */
992     private static final int[] LAYOUT_DIRECTION_FLAGS = {LAYOUT_DIRECTION_LTR,
993         LAYOUT_DIRECTION_RTL, LAYOUT_DIRECTION_INHERIT, LAYOUT_DIRECTION_LOCALE};
994 
995     /**
996      * Default horizontalDirection.
997      * {@hide}
998      */
999     private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1000 
1001     /**
1002      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1003      * should add all focusable Views regardless if they are focusable in touch mode.
1004      */
1005     public static final int FOCUSABLES_ALL = 0x00000000;
1006 
1007     /**
1008      * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1009      * should add only Views focusable in touch mode.
1010      */
1011     public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1012 
1013     /**
1014      * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1015      * item.
1016      */
1017     public static final int FOCUS_BACKWARD = 0x00000001;
1018 
1019     /**
1020      * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1021      * item.
1022      */
1023     public static final int FOCUS_FORWARD = 0x00000002;
1024 
1025     /**
1026      * Use with {@link #focusSearch(int)}. Move focus to the left.
1027      */
1028     public static final int FOCUS_LEFT = 0x00000011;
1029 
1030     /**
1031      * Use with {@link #focusSearch(int)}. Move focus up.
1032      */
1033     public static final int FOCUS_UP = 0x00000021;
1034 
1035     /**
1036      * Use with {@link #focusSearch(int)}. Move focus to the right.
1037      */
1038     public static final int FOCUS_RIGHT = 0x00000042;
1039 
1040     /**
1041      * Use with {@link #focusSearch(int)}. Move focus down.
1042      */
1043     public static final int FOCUS_DOWN = 0x00000082;
1044 
1045     /**
1046      * Bits of {@link #getMeasuredWidthAndState()} and
1047      * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1048      */
1049     public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1050 
1051     /**
1052      * Bits of {@link #getMeasuredWidthAndState()} and
1053      * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1054      */
1055     public static final int MEASURED_STATE_MASK = 0xff000000;
1056 
1057     /**
1058      * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1059      * for functions that combine both width and height into a single int,
1060      * such as {@link #getMeasuredState()} and the childState argument of
1061      * {@link #resolveSizeAndState(int, int, int)}.
1062      */
1063     public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1064 
1065     /**
1066      * Bit of {@link #getMeasuredWidthAndState()} and
1067      * {@link #getMeasuredWidthAndState()} that indicates the measured size
1068      * is smaller that the space the view would like to have.
1069      */
1070     public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1071 
1072     /**
1073      * Base View state sets
1074      */
1075     // Singles
1076     /**
1077      * Indicates the view has no states set. States are used with
1078      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1079      * view depending on its state.
1080      *
1081      * @see android.graphics.drawable.Drawable
1082      * @see #getDrawableState()
1083      */
1084     protected static final int[] EMPTY_STATE_SET;
1085     /**
1086      * Indicates the view is enabled. States are used with
1087      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1088      * view depending on its state.
1089      *
1090      * @see android.graphics.drawable.Drawable
1091      * @see #getDrawableState()
1092      */
1093     protected static final int[] ENABLED_STATE_SET;
1094     /**
1095      * Indicates the view is focused. States are used with
1096      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1097      * view depending on its state.
1098      *
1099      * @see android.graphics.drawable.Drawable
1100      * @see #getDrawableState()
1101      */
1102     protected static final int[] FOCUSED_STATE_SET;
1103     /**
1104      * Indicates the view is selected. States are used with
1105      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1106      * view depending on its state.
1107      *
1108      * @see android.graphics.drawable.Drawable
1109      * @see #getDrawableState()
1110      */
1111     protected static final int[] SELECTED_STATE_SET;
1112     /**
1113      * Indicates the view is pressed. States are used with
1114      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1115      * view depending on its state.
1116      *
1117      * @see android.graphics.drawable.Drawable
1118      * @see #getDrawableState()
1119      * @hide
1120      */
1121     protected static final int[] PRESSED_STATE_SET;
1122     /**
1123      * Indicates the view's window has focus. States are used with
1124      * {@link android.graphics.drawable.Drawable} to change the drawing of the
1125      * view depending on its state.
1126      *
1127      * @see android.graphics.drawable.Drawable
1128      * @see #getDrawableState()
1129      */
1130     protected static final int[] WINDOW_FOCUSED_STATE_SET;
1131     // Doubles
1132     /**
1133      * Indicates the view is enabled and has the focus.
1134      *
1135      * @see #ENABLED_STATE_SET
1136      * @see #FOCUSED_STATE_SET
1137      */
1138     protected static final int[] ENABLED_FOCUSED_STATE_SET;
1139     /**
1140      * Indicates the view is enabled and selected.
1141      *
1142      * @see #ENABLED_STATE_SET
1143      * @see #SELECTED_STATE_SET
1144      */
1145     protected static final int[] ENABLED_SELECTED_STATE_SET;
1146     /**
1147      * Indicates the view is enabled and that its window has focus.
1148      *
1149      * @see #ENABLED_STATE_SET
1150      * @see #WINDOW_FOCUSED_STATE_SET
1151      */
1152     protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1153     /**
1154      * Indicates the view is focused and selected.
1155      *
1156      * @see #FOCUSED_STATE_SET
1157      * @see #SELECTED_STATE_SET
1158      */
1159     protected static final int[] FOCUSED_SELECTED_STATE_SET;
1160     /**
1161      * Indicates the view has the focus and that its window has the focus.
1162      *
1163      * @see #FOCUSED_STATE_SET
1164      * @see #WINDOW_FOCUSED_STATE_SET
1165      */
1166     protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1167     /**
1168      * Indicates the view is selected and that its window has the focus.
1169      *
1170      * @see #SELECTED_STATE_SET
1171      * @see #WINDOW_FOCUSED_STATE_SET
1172      */
1173     protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1174     // Triples
1175     /**
1176      * Indicates the view is enabled, focused and selected.
1177      *
1178      * @see #ENABLED_STATE_SET
1179      * @see #FOCUSED_STATE_SET
1180      * @see #SELECTED_STATE_SET
1181      */
1182     protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1183     /**
1184      * Indicates the view is enabled, focused and its window has the focus.
1185      *
1186      * @see #ENABLED_STATE_SET
1187      * @see #FOCUSED_STATE_SET
1188      * @see #WINDOW_FOCUSED_STATE_SET
1189      */
1190     protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1191     /**
1192      * Indicates the view is enabled, selected and its window has the focus.
1193      *
1194      * @see #ENABLED_STATE_SET
1195      * @see #SELECTED_STATE_SET
1196      * @see #WINDOW_FOCUSED_STATE_SET
1197      */
1198     protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1199     /**
1200      * Indicates the view is focused, selected and its window has the focus.
1201      *
1202      * @see #FOCUSED_STATE_SET
1203      * @see #SELECTED_STATE_SET
1204      * @see #WINDOW_FOCUSED_STATE_SET
1205      */
1206     protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1207     /**
1208      * Indicates the view is enabled, focused, selected and its window
1209      * has the focus.
1210      *
1211      * @see #ENABLED_STATE_SET
1212      * @see #FOCUSED_STATE_SET
1213      * @see #SELECTED_STATE_SET
1214      * @see #WINDOW_FOCUSED_STATE_SET
1215      */
1216     protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1217     /**
1218      * Indicates the view is pressed and its window has the focus.
1219      *
1220      * @see #PRESSED_STATE_SET
1221      * @see #WINDOW_FOCUSED_STATE_SET
1222      */
1223     protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1224     /**
1225      * Indicates the view is pressed and selected.
1226      *
1227      * @see #PRESSED_STATE_SET
1228      * @see #SELECTED_STATE_SET
1229      */
1230     protected static final int[] PRESSED_SELECTED_STATE_SET;
1231     /**
1232      * Indicates the view is pressed, selected and its window has the focus.
1233      *
1234      * @see #PRESSED_STATE_SET
1235      * @see #SELECTED_STATE_SET
1236      * @see #WINDOW_FOCUSED_STATE_SET
1237      */
1238     protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1239     /**
1240      * Indicates the view is pressed and focused.
1241      *
1242      * @see #PRESSED_STATE_SET
1243      * @see #FOCUSED_STATE_SET
1244      */
1245     protected static final int[] PRESSED_FOCUSED_STATE_SET;
1246     /**
1247      * Indicates the view is pressed, focused and its window has the focus.
1248      *
1249      * @see #PRESSED_STATE_SET
1250      * @see #FOCUSED_STATE_SET
1251      * @see #WINDOW_FOCUSED_STATE_SET
1252      */
1253     protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1254     /**
1255      * Indicates the view is pressed, focused and selected.
1256      *
1257      * @see #PRESSED_STATE_SET
1258      * @see #SELECTED_STATE_SET
1259      * @see #FOCUSED_STATE_SET
1260      */
1261     protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1262     /**
1263      * Indicates the view is pressed, focused, selected and its window has the focus.
1264      *
1265      * @see #PRESSED_STATE_SET
1266      * @see #FOCUSED_STATE_SET
1267      * @see #SELECTED_STATE_SET
1268      * @see #WINDOW_FOCUSED_STATE_SET
1269      */
1270     protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1271     /**
1272      * Indicates the view is pressed and enabled.
1273      *
1274      * @see #PRESSED_STATE_SET
1275      * @see #ENABLED_STATE_SET
1276      */
1277     protected static final int[] PRESSED_ENABLED_STATE_SET;
1278     /**
1279      * Indicates the view is pressed, enabled and its window has the focus.
1280      *
1281      * @see #PRESSED_STATE_SET
1282      * @see #ENABLED_STATE_SET
1283      * @see #WINDOW_FOCUSED_STATE_SET
1284      */
1285     protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1286     /**
1287      * Indicates the view is pressed, enabled and selected.
1288      *
1289      * @see #PRESSED_STATE_SET
1290      * @see #ENABLED_STATE_SET
1291      * @see #SELECTED_STATE_SET
1292      */
1293     protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1294     /**
1295      * Indicates the view is pressed, enabled, selected and its window has the
1296      * focus.
1297      *
1298      * @see #PRESSED_STATE_SET
1299      * @see #ENABLED_STATE_SET
1300      * @see #SELECTED_STATE_SET
1301      * @see #WINDOW_FOCUSED_STATE_SET
1302      */
1303     protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1304     /**
1305      * Indicates the view is pressed, enabled and focused.
1306      *
1307      * @see #PRESSED_STATE_SET
1308      * @see #ENABLED_STATE_SET
1309      * @see #FOCUSED_STATE_SET
1310      */
1311     protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1312     /**
1313      * Indicates the view is pressed, enabled, focused and its window has the
1314      * focus.
1315      *
1316      * @see #PRESSED_STATE_SET
1317      * @see #ENABLED_STATE_SET
1318      * @see #FOCUSED_STATE_SET
1319      * @see #WINDOW_FOCUSED_STATE_SET
1320      */
1321     protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1322     /**
1323      * Indicates the view is pressed, enabled, focused and selected.
1324      *
1325      * @see #PRESSED_STATE_SET
1326      * @see #ENABLED_STATE_SET
1327      * @see #SELECTED_STATE_SET
1328      * @see #FOCUSED_STATE_SET
1329      */
1330     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1331     /**
1332      * Indicates the view is pressed, enabled, focused, selected and its window
1333      * has the focus.
1334      *
1335      * @see #PRESSED_STATE_SET
1336      * @see #ENABLED_STATE_SET
1337      * @see #SELECTED_STATE_SET
1338      * @see #FOCUSED_STATE_SET
1339      * @see #WINDOW_FOCUSED_STATE_SET
1340      */
1341     protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1342 
1343     /**
1344      * The order here is very important to {@link #getDrawableState()}
1345      */
1346     private static final int[][] VIEW_STATE_SETS;
1347 
1348     static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1349     static final int VIEW_STATE_SELECTED = 1 << 1;
1350     static final int VIEW_STATE_FOCUSED = 1 << 2;
1351     static final int VIEW_STATE_ENABLED = 1 << 3;
1352     static final int VIEW_STATE_PRESSED = 1 << 4;
1353     static final int VIEW_STATE_ACTIVATED = 1 << 5;
1354     static final int VIEW_STATE_ACCELERATED = 1 << 6;
1355     static final int VIEW_STATE_HOVERED = 1 << 7;
1356     static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1357     static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
1358 
1359     static final int[] VIEW_STATE_IDS = new int[] {
1360         R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
1361         R.attr.state_selected,          VIEW_STATE_SELECTED,
1362         R.attr.state_focused,           VIEW_STATE_FOCUSED,
1363         R.attr.state_enabled,           VIEW_STATE_ENABLED,
1364         R.attr.state_pressed,           VIEW_STATE_PRESSED,
1365         R.attr.state_activated,         VIEW_STATE_ACTIVATED,
1366         R.attr.state_accelerated,       VIEW_STATE_ACCELERATED,
1367         R.attr.state_hovered,           VIEW_STATE_HOVERED,
1368         R.attr.state_drag_can_accept,   VIEW_STATE_DRAG_CAN_ACCEPT,
1369         R.attr.state_drag_hovered,      VIEW_STATE_DRAG_HOVERED,
1370     };
1371 
1372     static {
1373         if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1374             throw new IllegalStateException(
1375                     "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1376         }
1377         int[] orderedIds = new int[VIEW_STATE_IDS.length];
1378         for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
1379             int viewState = R.styleable.ViewDrawableStates[i];
1380             for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
1381                 if (VIEW_STATE_IDS[j] == viewState) {
1382                     orderedIds[i * 2] = viewState;
1383                     orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
1384                 }
1385             }
1386         }
1387         final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1388         VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1389         for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
1390             int numBits = Integer.bitCount(i);
1391             int[] set = new int[numBits];
1392             int pos = 0;
1393             for (int j = 0; j < orderedIds.length; j += 2) {
1394                 if ((i & orderedIds[j+1]) != 0) {
1395                     set[pos++] = orderedIds[j];
1396                 }
1397             }
1398             VIEW_STATE_SETS[i] = set;
1399         }
1400 
1401         EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1402         WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1403         SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1404         SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1405                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1406         FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1407         FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1408                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1409         FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1410                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1411         FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1412                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1413                 | VIEW_STATE_FOCUSED];
1414         ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1415         ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1416                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1417         ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1418                 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1419         ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1420                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1421                 | VIEW_STATE_ENABLED];
1422         ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1423                 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1424         ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1425                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1426                 | VIEW_STATE_ENABLED];
1427         ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1428                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1429                 | VIEW_STATE_ENABLED];
1430         ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1431                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1432                 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1433 
1434         PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1435         PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1436                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1437         PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1438                 VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1439         PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1440                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1441                 | VIEW_STATE_PRESSED];
1442         PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1443                 VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1444         PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1445                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1446                 | VIEW_STATE_PRESSED];
1447         PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1448                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1449                 | VIEW_STATE_PRESSED];
1450         PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1451                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1452                 | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1453         PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1454                 VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1455         PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1456                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1457                 | VIEW_STATE_PRESSED];
1458         PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1459                 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1460                 | VIEW_STATE_PRESSED];
1461         PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1462                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1463                 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1464         PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1465                 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1466                 | VIEW_STATE_PRESSED];
1467         PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1468                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1469                 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1470         PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1471                 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1472                 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1473         PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1474                 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1475                 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1476                 | VIEW_STATE_PRESSED];
1477     }
1478 
1479     /**
1480      * Accessibility event types that are dispatched for text population.
1481      */
1482     private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1483             AccessibilityEvent.TYPE_VIEW_CLICKED
1484             | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1485             | AccessibilityEvent.TYPE_VIEW_SELECTED
1486             | AccessibilityEvent.TYPE_VIEW_FOCUSED
1487             | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1488             | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1489             | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1490             | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED;
1491 
1492     /**
1493      * Temporary Rect currently for use in setBackground().  This will probably
1494      * be extended in the future to hold our own class with more than just
1495      * a Rect. :)
1496      */
1497     static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1498 
1499     /**
1500      * Map used to store views' tags.
1501      */
1502     private SparseArray<Object> mKeyedTags;
1503 
1504     /**
1505      * The next available accessiiblity id.
1506      */
1507     private static int sNextAccessibilityViewId;
1508 
1509     /**
1510      * The animation currently associated with this view.
1511      * @hide
1512      */
1513     protected Animation mCurrentAnimation = null;
1514 
1515     /**
1516      * Width as measured during measure pass.
1517      * {@hide}
1518      */
1519     @ViewDebug.ExportedProperty(category = "measurement")
1520     int mMeasuredWidth;
1521 
1522     /**
1523      * Height as measured during measure pass.
1524      * {@hide}
1525      */
1526     @ViewDebug.ExportedProperty(category = "measurement")
1527     int mMeasuredHeight;
1528 
1529     /**
1530      * Flag to indicate that this view was marked INVALIDATED, or had its display list
1531      * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1532      * its display list. This flag, used only when hw accelerated, allows us to clear the
1533      * flag while retaining this information until it's needed (at getDisplayList() time and
1534      * in drawChild(), when we decide to draw a view's children's display lists into our own).
1535      *
1536      * {@hide}
1537      */
1538     boolean mRecreateDisplayList = false;
1539 
1540     /**
1541      * The view's identifier.
1542      * {@hide}
1543      *
1544      * @see #setId(int)
1545      * @see #getId()
1546      */
1547     @ViewDebug.ExportedProperty(resolveId = true)
1548     int mID = NO_ID;
1549 
1550     /**
1551      * The stable ID of this view for accessibility porposes.
1552      */
1553     int mAccessibilityViewId = NO_ID;
1554 
1555     /**
1556      * The view's tag.
1557      * {@hide}
1558      *
1559      * @see #setTag(Object)
1560      * @see #getTag()
1561      */
1562     protected Object mTag;
1563 
1564     // for mPrivateFlags:
1565     /** {@hide} */
1566     static final int WANTS_FOCUS                    = 0x00000001;
1567     /** {@hide} */
1568     static final int FOCUSED                        = 0x00000002;
1569     /** {@hide} */
1570     static final int SELECTED                       = 0x00000004;
1571     /** {@hide} */
1572     static final int IS_ROOT_NAMESPACE              = 0x00000008;
1573     /** {@hide} */
1574     static final int HAS_BOUNDS                     = 0x00000010;
1575     /** {@hide} */
1576     static final int DRAWN                          = 0x00000020;
1577     /**
1578      * When this flag is set, this view is running an animation on behalf of its
1579      * children and should therefore not cancel invalidate requests, even if they
1580      * lie outside of this view's bounds.
1581      *
1582      * {@hide}
1583      */
1584     static final int DRAW_ANIMATION                 = 0x00000040;
1585     /** {@hide} */
1586     static final int SKIP_DRAW                      = 0x00000080;
1587     /** {@hide} */
1588     static final int ONLY_DRAWS_BACKGROUND          = 0x00000100;
1589     /** {@hide} */
1590     static final int REQUEST_TRANSPARENT_REGIONS    = 0x00000200;
1591     /** {@hide} */
1592     static final int DRAWABLE_STATE_DIRTY           = 0x00000400;
1593     /** {@hide} */
1594     static final int MEASURED_DIMENSION_SET         = 0x00000800;
1595     /** {@hide} */
1596     static final int FORCE_LAYOUT                   = 0x00001000;
1597     /** {@hide} */
1598     static final int LAYOUT_REQUIRED                = 0x00002000;
1599 
1600     private static final int PRESSED                = 0x00004000;
1601 
1602     /** {@hide} */
1603     static final int DRAWING_CACHE_VALID            = 0x00008000;
1604     /**
1605      * Flag used to indicate that this view should be drawn once more (and only once
1606      * more) after its animation has completed.
1607      * {@hide}
1608      */
1609     static final int ANIMATION_STARTED              = 0x00010000;
1610 
1611     private static final int SAVE_STATE_CALLED      = 0x00020000;
1612 
1613     /**
1614      * Indicates that the View returned true when onSetAlpha() was called and that
1615      * the alpha must be restored.
1616      * {@hide}
1617      */
1618     static final int ALPHA_SET                      = 0x00040000;
1619 
1620     /**
1621      * Set by {@link #setScrollContainer(boolean)}.
1622      */
1623     static final int SCROLL_CONTAINER               = 0x00080000;
1624 
1625     /**
1626      * Set by {@link #setScrollContainer(boolean)}.
1627      */
1628     static final int SCROLL_CONTAINER_ADDED         = 0x00100000;
1629 
1630     /**
1631      * View flag indicating whether this view was invalidated (fully or partially.)
1632      *
1633      * @hide
1634      */
1635     static final int DIRTY                          = 0x00200000;
1636 
1637     /**
1638      * View flag indicating whether this view was invalidated by an opaque
1639      * invalidate request.
1640      *
1641      * @hide
1642      */
1643     static final int DIRTY_OPAQUE                   = 0x00400000;
1644 
1645     /**
1646      * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
1647      *
1648      * @hide
1649      */
1650     static final int DIRTY_MASK                     = 0x00600000;
1651 
1652     /**
1653      * Indicates whether the background is opaque.
1654      *
1655      * @hide
1656      */
1657     static final int OPAQUE_BACKGROUND              = 0x00800000;
1658 
1659     /**
1660      * Indicates whether the scrollbars are opaque.
1661      *
1662      * @hide
1663      */
1664     static final int OPAQUE_SCROLLBARS              = 0x01000000;
1665 
1666     /**
1667      * Indicates whether the view is opaque.
1668      *
1669      * @hide
1670      */
1671     static final int OPAQUE_MASK                    = 0x01800000;
1672 
1673     /**
1674      * Indicates a prepressed state;
1675      * the short time between ACTION_DOWN and recognizing
1676      * a 'real' press. Prepressed is used to recognize quick taps
1677      * even when they are shorter than ViewConfiguration.getTapTimeout().
1678      *
1679      * @hide
1680      */
1681     private static final int PREPRESSED             = 0x02000000;
1682 
1683     /**
1684      * Indicates whether the view is temporarily detached.
1685      *
1686      * @hide
1687      */
1688     static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
1689 
1690     /**
1691      * Indicates that we should awaken scroll bars once attached
1692      *
1693      * @hide
1694      */
1695     private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1696 
1697     /**
1698      * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1699      * @hide
1700      */
1701     private static final int HOVERED              = 0x10000000;
1702 
1703     /**
1704      * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
1705      * for transform operations
1706      *
1707      * @hide
1708      */
1709     private static final int PIVOT_EXPLICITLY_SET = 0x20000000;
1710 
1711     /** {@hide} */
1712     static final int ACTIVATED                    = 0x40000000;
1713 
1714     /**
1715      * Indicates that this view was specifically invalidated, not just dirtied because some
1716      * child view was invalidated. The flag is used to determine when we need to recreate
1717      * a view's display list (as opposed to just returning a reference to its existing
1718      * display list).
1719      *
1720      * @hide
1721      */
1722     static final int INVALIDATED                  = 0x80000000;
1723 
1724     /* Masks for mPrivateFlags2 */
1725 
1726     /**
1727      * Indicates that this view has reported that it can accept the current drag's content.
1728      * Cleared when the drag operation concludes.
1729      * @hide
1730      */
1731     static final int DRAG_CAN_ACCEPT              = 0x00000001;
1732 
1733     /**
1734      * Indicates that this view is currently directly under the drag location in a
1735      * drag-and-drop operation involving content that it can accept.  Cleared when
1736      * the drag exits the view, or when the drag operation concludes.
1737      * @hide
1738      */
1739     static final int DRAG_HOVERED                 = 0x00000002;
1740 
1741     /**
1742      * Indicates whether the view layout direction has been resolved and drawn to the
1743      * right-to-left direction.
1744      *
1745      * @hide
1746      */
1747     static final int LAYOUT_DIRECTION_RESOLVED_RTL = 0x00000004;
1748 
1749     /**
1750      * Indicates whether the view layout direction has been resolved.
1751      *
1752      * @hide
1753      */
1754     static final int LAYOUT_DIRECTION_RESOLVED = 0x00000008;
1755 
1756 
1757     /* End of masks for mPrivateFlags2 */
1758 
1759     static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
1760 
1761     /**
1762      * Always allow a user to over-scroll this view, provided it is a
1763      * view that can scroll.
1764      *
1765      * @see #getOverScrollMode()
1766      * @see #setOverScrollMode(int)
1767      */
1768     public static final int OVER_SCROLL_ALWAYS = 0;
1769 
1770     /**
1771      * Allow a user to over-scroll this view only if the content is large
1772      * enough to meaningfully scroll, provided it is a view that can scroll.
1773      *
1774      * @see #getOverScrollMode()
1775      * @see #setOverScrollMode(int)
1776      */
1777     public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
1778 
1779     /**
1780      * Never allow a user to over-scroll this view.
1781      *
1782      * @see #getOverScrollMode()
1783      * @see #setOverScrollMode(int)
1784      */
1785     public static final int OVER_SCROLL_NEVER = 2;
1786 
1787     /**
1788      * View has requested the system UI (status bar) to be visible (the default).
1789      *
1790      * @see #setSystemUiVisibility(int)
1791      */
1792     public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
1793 
1794     /**
1795      * View has requested the system UI to enter an unobtrusive "low profile" mode.
1796      *
1797      * This is for use in games, book readers, video players, or any other "immersive" application
1798      * where the usual system chrome is deemed too distracting.
1799      *
1800      * In low profile mode, the status bar and/or navigation icons may dim.
1801      *
1802      * @see #setSystemUiVisibility(int)
1803      */
1804     public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
1805 
1806     /**
1807      * View has requested that the system navigation be temporarily hidden.
1808      *
1809      * This is an even less obtrusive state than that called for by
1810      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
1811      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
1812      * those to disappear. This is useful (in conjunction with the
1813      * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
1814      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
1815      * window flags) for displaying content using every last pixel on the display.
1816      *
1817      * There is a limitation: because navigation controls are so important, the least user
1818      * interaction will cause them to reappear immediately.
1819      *
1820      * @see #setSystemUiVisibility(int)
1821      */
1822     public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
1823 
1824     /**
1825      * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
1826      */
1827     public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
1828 
1829     /**
1830      * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
1831      */
1832     public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
1833 
1834     /**
1835      * @hide
1836      *
1837      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1838      * out of the public fields to keep the undefined bits out of the developer's way.
1839      *
1840      * Flag to make the status bar not expandable.  Unless you also
1841      * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
1842      */
1843     public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
1844 
1845     /**
1846      * @hide
1847      *
1848      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1849      * out of the public fields to keep the undefined bits out of the developer's way.
1850      *
1851      * Flag to hide notification icons and scrolling ticker text.
1852      */
1853     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
1854 
1855     /**
1856      * @hide
1857      *
1858      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1859      * out of the public fields to keep the undefined bits out of the developer's way.
1860      *
1861      * Flag to disable incoming notification alerts.  This will not block
1862      * icons, but it will block sound, vibrating and other visual or aural notifications.
1863      */
1864     public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
1865 
1866     /**
1867      * @hide
1868      *
1869      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1870      * out of the public fields to keep the undefined bits out of the developer's way.
1871      *
1872      * Flag to hide only the scrolling ticker.  Note that
1873      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
1874      * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
1875      */
1876     public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
1877 
1878     /**
1879      * @hide
1880      *
1881      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1882      * out of the public fields to keep the undefined bits out of the developer's way.
1883      *
1884      * Flag to hide the center system info area.
1885      */
1886     public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
1887 
1888     /**
1889      * @hide
1890      *
1891      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1892      * out of the public fields to keep the undefined bits out of the developer's way.
1893      *
1894      * Flag to hide only the home button.  Don't use this
1895      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
1896      */
1897     public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
1898 
1899     /**
1900      * @hide
1901      *
1902      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1903      * out of the public fields to keep the undefined bits out of the developer's way.
1904      *
1905      * Flag to hide only the back button. Don't use this
1906      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
1907      */
1908     public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
1909 
1910     /**
1911      * @hide
1912      *
1913      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1914      * out of the public fields to keep the undefined bits out of the developer's way.
1915      *
1916      * Flag to hide only the clock.  You might use this if your activity has
1917      * its own clock making the status bar's clock redundant.
1918      */
1919     public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
1920 
1921     /**
1922      * @hide
1923      *
1924      * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1925      * out of the public fields to keep the undefined bits out of the developer's way.
1926      *
1927      * Flag to hide only the recent apps button. Don't use this
1928      * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
1929      */
1930     public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
1931 
1932     /**
1933      * @hide
1934      *
1935      * NOTE: This flag may only be used in subtreeSystemUiVisibility, etc. etc.
1936      *
1937      * This hides HOME and RECENT and is provided for compatibility with interim implementations.
1938      */
1939     @Deprecated
1940     public static final int STATUS_BAR_DISABLE_NAVIGATION =
1941             STATUS_BAR_DISABLE_HOME | STATUS_BAR_DISABLE_RECENT;
1942 
1943     /**
1944      * @hide
1945      */
1946     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
1947 
1948     /**
1949      * These are the system UI flags that can be cleared by events outside
1950      * of an application.  Currently this is just the ability to tap on the
1951      * screen while hiding the navigation bar to have it return.
1952      * @hide
1953      */
1954     public static final int SYSTEM_UI_CLEARABLE_FLAGS =
1955             SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
1956 
1957     /**
1958      * Find views that render the specified text.
1959      *
1960      * @see #findViewsWithText(ArrayList, CharSequence, int)
1961      */
1962     public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
1963 
1964     /**
1965      * Find find views that contain the specified content description.
1966      *
1967      * @see #findViewsWithText(ArrayList, CharSequence, int)
1968      */
1969     public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
1970 
1971     /**
1972      * Controls the over-scroll mode for this view.
1973      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
1974      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
1975      * and {@link #OVER_SCROLL_NEVER}.
1976      */
1977     private int mOverScrollMode;
1978 
1979     /**
1980      * The parent this view is attached to.
1981      * {@hide}
1982      *
1983      * @see #getParent()
1984      */
1985     protected ViewParent mParent;
1986 
1987     /**
1988      * {@hide}
1989      */
1990     AttachInfo mAttachInfo;
1991 
1992     /**
1993      * {@hide}
1994      */
1995     @ViewDebug.ExportedProperty(flagMapping = {
1996         @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
1997                 name = "FORCE_LAYOUT"),
1998         @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
1999                 name = "LAYOUT_REQUIRED"),
2000         @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
2001             name = "DRAWING_CACHE_INVALID", outputIf = false),
2002         @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
2003         @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
2004         @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2005         @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
2006     })
2007     int mPrivateFlags;
2008     int mPrivateFlags2;
2009 
2010     /**
2011      * This view's request for the visibility of the status bar.
2012      * @hide
2013      */
2014     @ViewDebug.ExportedProperty(flagMapping = {
2015         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2016                                 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2017                                 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2018         @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2019                                 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2020                                 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2021         @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2022                                 equals = SYSTEM_UI_FLAG_VISIBLE,
2023                                 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2024     })
2025     int mSystemUiVisibility;
2026 
2027     /**
2028      * Count of how many windows this view has been attached to.
2029      */
2030     int mWindowAttachCount;
2031 
2032     /**
2033      * The layout parameters associated with this view and used by the parent
2034      * {@link android.view.ViewGroup} to determine how this view should be
2035      * laid out.
2036      * {@hide}
2037      */
2038     protected ViewGroup.LayoutParams mLayoutParams;
2039 
2040     /**
2041      * The view flags hold various views states.
2042      * {@hide}
2043      */
2044     @ViewDebug.ExportedProperty
2045     int mViewFlags;
2046 
2047     static class TransformationInfo {
2048         /**
2049          * The transform matrix for the View. This transform is calculated internally
2050          * based on the rotation, scaleX, and scaleY properties. The identity matrix
2051          * is used by default. Do *not* use this variable directly; instead call
2052          * getMatrix(), which will automatically recalculate the matrix if necessary
2053          * to get the correct matrix based on the latest rotation and scale properties.
2054          */
2055         private final Matrix mMatrix = new Matrix();
2056 
2057         /**
2058          * The transform matrix for the View. This transform is calculated internally
2059          * based on the rotation, scaleX, and scaleY properties. The identity matrix
2060          * is used by default. Do *not* use this variable directly; instead call
2061          * getInverseMatrix(), which will automatically recalculate the matrix if necessary
2062          * to get the correct matrix based on the latest rotation and scale properties.
2063          */
2064         private Matrix mInverseMatrix;
2065 
2066         /**
2067          * An internal variable that tracks whether we need to recalculate the
2068          * transform matrix, based on whether the rotation or scaleX/Y properties
2069          * have changed since the matrix was last calculated.
2070          */
2071         boolean mMatrixDirty = false;
2072 
2073         /**
2074          * An internal variable that tracks whether we need to recalculate the
2075          * transform matrix, based on whether the rotation or scaleX/Y properties
2076          * have changed since the matrix was last calculated.
2077          */
2078         private boolean mInverseMatrixDirty = true;
2079 
2080         /**
2081          * A variable that tracks whether we need to recalculate the
2082          * transform matrix, based on whether the rotation or scaleX/Y properties
2083          * have changed since the matrix was last calculated. This variable
2084          * is only valid after a call to updateMatrix() or to a function that
2085          * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
2086          */
2087         private boolean mMatrixIsIdentity = true;
2088 
2089         /**
2090          * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
2091          */
2092         private Camera mCamera = null;
2093 
2094         /**
2095          * This matrix is used when computing the matrix for 3D rotations.
2096          */
2097         private Matrix matrix3D = null;
2098 
2099         /**
2100          * These prev values are used to recalculate a centered pivot point when necessary. The
2101          * pivot point is only used in matrix operations (when rotation, scale, or translation are
2102          * set), so thes values are only used then as well.
2103          */
2104         private int mPrevWidth = -1;
2105         private int mPrevHeight = -1;
2106 
2107         /**
2108          * The degrees rotation around the vertical axis through the pivot point.
2109          */
2110         @ViewDebug.ExportedProperty
2111         float mRotationY = 0f;
2112 
2113         /**
2114          * The degrees rotation around the horizontal axis through the pivot point.
2115          */
2116         @ViewDebug.ExportedProperty
2117         float mRotationX = 0f;
2118 
2119         /**
2120          * The degrees rotation around the pivot point.
2121          */
2122         @ViewDebug.ExportedProperty
2123         float mRotation = 0f;
2124 
2125         /**
2126          * The amount of translation of the object away from its left property (post-layout).
2127          */
2128         @ViewDebug.ExportedProperty
2129         float mTranslationX = 0f;
2130 
2131         /**
2132          * The amount of translation of the object away from its top property (post-layout).
2133          */
2134         @ViewDebug.ExportedProperty
2135         float mTranslationY = 0f;
2136 
2137         /**
2138          * The amount of scale in the x direction around the pivot point. A
2139          * value of 1 means no scaling is applied.
2140          */
2141         @ViewDebug.ExportedProperty
2142         float mScaleX = 1f;
2143 
2144         /**
2145          * The amount of scale in the y direction around the pivot point. A
2146          * value of 1 means no scaling is applied.
2147          */
2148         @ViewDebug.ExportedProperty
2149         float mScaleY = 1f;
2150 
2151         /**
2152          * The amount of scale in the x direction around the pivot point. A
2153          * value of 1 means no scaling is applied.
2154          */
2155         @ViewDebug.ExportedProperty
2156         float mPivotX = 0f;
2157 
2158         /**
2159          * The amount of scale in the y direction around the pivot point. A
2160          * value of 1 means no scaling is applied.
2161          */
2162         @ViewDebug.ExportedProperty
2163         float mPivotY = 0f;
2164 
2165         /**
2166          * The opacity of the View. This is a value from 0 to 1, where 0 means
2167          * completely transparent and 1 means completely opaque.
2168          */
2169         @ViewDebug.ExportedProperty
2170         float mAlpha = 1f;
2171     }
2172 
2173     TransformationInfo mTransformationInfo;
2174 
2175     private boolean mLastIsOpaque;
2176 
2177     /**
2178      * Convenience value to check for float values that are close enough to zero to be considered
2179      * zero.
2180      */
2181     private static final float NONZERO_EPSILON = .001f;
2182 
2183     /**
2184      * The distance in pixels from the left edge of this view's parent
2185      * to the left edge of this view.
2186      * {@hide}
2187      */
2188     @ViewDebug.ExportedProperty(category = "layout")
2189     protected int mLeft;
2190     /**
2191      * The distance in pixels from the left edge of this view's parent
2192      * to the right edge of this view.
2193      * {@hide}
2194      */
2195     @ViewDebug.ExportedProperty(category = "layout")
2196     protected int mRight;
2197     /**
2198      * The distance in pixels from the top edge of this view's parent
2199      * to the top edge of this view.
2200      * {@hide}
2201      */
2202     @ViewDebug.ExportedProperty(category = "layout")
2203     protected int mTop;
2204     /**
2205      * The distance in pixels from the top edge of this view's parent
2206      * to the bottom edge of this view.
2207      * {@hide}
2208      */
2209     @ViewDebug.ExportedProperty(category = "layout")
2210     protected int mBottom;
2211 
2212     /**
2213      * The offset, in pixels, by which the content of this view is scrolled
2214      * horizontally.
2215      * {@hide}
2216      */
2217     @ViewDebug.ExportedProperty(category = "scrolling")
2218     protected int mScrollX;
2219     /**
2220      * The offset, in pixels, by which the content of this view is scrolled
2221      * vertically.
2222      * {@hide}
2223      */
2224     @ViewDebug.ExportedProperty(category = "scrolling")
2225     protected int mScrollY;
2226 
2227     /**
2228      * The left padding in pixels, that is the distance in pixels between the
2229      * left edge of this view and the left edge of its content.
2230      * {@hide}
2231      */
2232     @ViewDebug.ExportedProperty(category = "padding")
2233     protected int mPaddingLeft;
2234     /**
2235      * The right padding in pixels, that is the distance in pixels between the
2236      * right edge of this view and the right edge of its content.
2237      * {@hide}
2238      */
2239     @ViewDebug.ExportedProperty(category = "padding")
2240     protected int mPaddingRight;
2241     /**
2242      * The top padding in pixels, that is the distance in pixels between the
2243      * top edge of this view and the top edge of its content.
2244      * {@hide}
2245      */
2246     @ViewDebug.ExportedProperty(category = "padding")
2247     protected int mPaddingTop;
2248     /**
2249      * The bottom padding in pixels, that is the distance in pixels between the
2250      * bottom edge of this view and the bottom edge of its content.
2251      * {@hide}
2252      */
2253     @ViewDebug.ExportedProperty(category = "padding")
2254     protected int mPaddingBottom;
2255 
2256     /**
2257      * Briefly describes the view and is primarily used for accessibility support.
2258      */
2259     private CharSequence mContentDescription;
2260 
2261     /**
2262      * Cache the paddingRight set by the user to append to the scrollbar's size.
2263      *
2264      * @hide
2265      */
2266     @ViewDebug.ExportedProperty(category = "padding")
2267     protected int mUserPaddingRight;
2268 
2269     /**
2270      * Cache the paddingBottom set by the user to append to the scrollbar's size.
2271      *
2272      * @hide
2273      */
2274     @ViewDebug.ExportedProperty(category = "padding")
2275     protected int mUserPaddingBottom;
2276 
2277     /**
2278      * Cache the paddingLeft set by the user to append to the scrollbar's size.
2279      *
2280      * @hide
2281      */
2282     @ViewDebug.ExportedProperty(category = "padding")
2283     protected int mUserPaddingLeft;
2284 
2285     /**
2286      * Cache if the user padding is relative.
2287      *
2288      */
2289     @ViewDebug.ExportedProperty(category = "padding")
2290     boolean mUserPaddingRelative;
2291 
2292     /**
2293      * Cache the paddingStart set by the user to append to the scrollbar's size.
2294      *
2295      */
2296     @ViewDebug.ExportedProperty(category = "padding")
2297     int mUserPaddingStart;
2298 
2299     /**
2300      * Cache the paddingEnd set by the user to append to the scrollbar's size.
2301      *
2302      */
2303     @ViewDebug.ExportedProperty(category = "padding")
2304     int mUserPaddingEnd;
2305 
2306     /**
2307      * @hide
2308      */
2309     int mOldWidthMeasureSpec = Integer.MIN_VALUE;
2310     /**
2311      * @hide
2312      */
2313     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
2314 
2315     private Drawable mBGDrawable;
2316 
2317     private int mBackgroundResource;
2318     private boolean mBackgroundSizeChanged;
2319 
2320     /**
2321      * Listener used to dispatch focus change events.
2322      * This field should be made private, so it is hidden from the SDK.
2323      * {@hide}
2324      */
2325     protected OnFocusChangeListener mOnFocusChangeListener;
2326 
2327     /**
2328      * Listeners for layout change events.
2329      */
2330     private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
2331 
2332     /**
2333      * Listeners for attach events.
2334      */
2335     private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
2336 
2337     /**
2338      * Listener used to dispatch click events.
2339      * This field should be made private, so it is hidden from the SDK.
2340      * {@hide}
2341      */
2342     protected OnClickListener mOnClickListener;
2343 
2344     /**
2345      * Listener used to dispatch long click events.
2346      * This field should be made private, so it is hidden from the SDK.
2347      * {@hide}
2348      */
2349     protected OnLongClickListener mOnLongClickListener;
2350 
2351     /**
2352      * Listener used to build the context menu.
2353      * This field should be made private, so it is hidden from the SDK.
2354      * {@hide}
2355      */
2356     protected OnCreateContextMenuListener mOnCreateContextMenuListener;
2357 
2358     private OnKeyListener mOnKeyListener;
2359 
2360     private OnTouchListener mOnTouchListener;
2361 
2362     private OnHoverListener mOnHoverListener;
2363 
2364     private OnGenericMotionListener mOnGenericMotionListener;
2365 
2366     private OnDragListener mOnDragListener;
2367 
2368     private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
2369 
2370     /**
2371      * The application environment this view lives in.
2372      * This field should be made private, so it is hidden from the SDK.
2373      * {@hide}
2374      */
2375     protected Context mContext;
2376 
2377     private final Resources mResources;
2378 
2379     private ScrollabilityCache mScrollCache;
2380 
2381     private int[] mDrawableState = null;
2382 
2383     /**
2384      * Set to true when drawing cache is enabled and cannot be created.
2385      *
2386      * @hide
2387      */
2388     public boolean mCachingFailed;
2389 
2390     private Bitmap mDrawingCache;
2391     private Bitmap mUnscaledDrawingCache;
2392     private HardwareLayer mHardwareLayer;
2393     DisplayList mDisplayList;
2394 
2395     /**
2396      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
2397      * the user may specify which view to go to next.
2398      */
2399     private int mNextFocusLeftId = View.NO_ID;
2400 
2401     /**
2402      * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
2403      * the user may specify which view to go to next.
2404      */
2405     private int mNextFocusRightId = View.NO_ID;
2406 
2407     /**
2408      * When this view has focus and the next focus is {@link #FOCUS_UP},
2409      * the user may specify which view to go to next.
2410      */
2411     private int mNextFocusUpId = View.NO_ID;
2412 
2413     /**
2414      * When this view has focus and the next focus is {@link #FOCUS_DOWN},
2415      * the user may specify which view to go to next.
2416      */
2417     private int mNextFocusDownId = View.NO_ID;
2418 
2419     /**
2420      * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
2421      * the user may specify which view to go to next.
2422      */
2423     int mNextFocusForwardId = View.NO_ID;
2424 
2425     private CheckForLongPress mPendingCheckForLongPress;
2426     private CheckForTap mPendingCheckForTap = null;
2427     private PerformClick mPerformClick;
2428     private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
2429 
2430     private UnsetPressedState mUnsetPressedState;
2431 
2432     /**
2433      * Whether the long press's action has been invoked.  The tap's action is invoked on the
2434      * up event while a long press is invoked as soon as the long press duration is reached, so
2435      * a long press could be performed before the tap is checked, in which case the tap's action
2436      * should not be invoked.
2437      */
2438     private boolean mHasPerformedLongPress;
2439 
2440     /**
2441      * The minimum height of the view. We'll try our best to have the height
2442      * of this view to at least this amount.
2443      */
2444     @ViewDebug.ExportedProperty(category = "measurement")
2445     private int mMinHeight;
2446 
2447     /**
2448      * The minimum width of the view. We'll try our best to have the width
2449      * of this view to at least this amount.
2450      */
2451     @ViewDebug.ExportedProperty(category = "measurement")
2452     private int mMinWidth;
2453 
2454     /**
2455      * The delegate to handle touch events that are physically in this view
2456      * but should be handled by another view.
2457      */
2458     private TouchDelegate mTouchDelegate = null;
2459 
2460     /**
2461      * Solid color to use as a background when creating the drawing cache. Enables
2462      * the cache to use 16 bit bitmaps instead of 32 bit.
2463      */
2464     private int mDrawingCacheBackgroundColor = 0;
2465 
2466     /**
2467      * Special tree observer used when mAttachInfo is null.
2468      */
2469     private ViewTreeObserver mFloatingTreeObserver;
2470 
2471     /**
2472      * Cache the touch slop from the context that created the view.
2473      */
2474     private int mTouchSlop;
2475 
2476     /**
2477      * Object that handles automatic animation of view properties.
2478      */
2479     private ViewPropertyAnimator mAnimator = null;
2480 
2481     /**
2482      * Flag indicating that a drag can cross window boundaries.  When
2483      * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
2484      * with this flag set, all visible applications will be able to participate
2485      * in the drag operation and receive the dragged content.
2486      *
2487      * @hide
2488      */
2489     public static final int DRAG_FLAG_GLOBAL = 1;
2490 
2491     /**
2492      * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
2493      */
2494     private float mVerticalScrollFactor;
2495 
2496     /**
2497      * Position of the vertical scroll bar.
2498      */
2499     private int mVerticalScrollbarPosition;
2500 
2501     /**
2502      * Position the scroll bar at the default position as determined by the system.
2503      */
2504     public static final int SCROLLBAR_POSITION_DEFAULT = 0;
2505 
2506     /**
2507      * Position the scroll bar along the left edge.
2508      */
2509     public static final int SCROLLBAR_POSITION_LEFT = 1;
2510 
2511     /**
2512      * Position the scroll bar along the right edge.
2513      */
2514     public static final int SCROLLBAR_POSITION_RIGHT = 2;
2515 
2516     /**
2517      * Indicates that the view does not have a layer.
2518      *
2519      * @see #getLayerType()
2520      * @see #setLayerType(int, android.graphics.Paint)
2521      * @see #LAYER_TYPE_SOFTWARE
2522      * @see #LAYER_TYPE_HARDWARE
2523      */
2524     public static final int LAYER_TYPE_NONE = 0;
2525 
2526     /**
2527      * <p>Indicates that the view has a software layer. A software layer is backed
2528      * by a bitmap and causes the view to be rendered using Android's software
2529      * rendering pipeline, even if hardware acceleration is enabled.</p>
2530      *
2531      * <p>Software layers have various usages:</p>
2532      * <p>When the application is not using hardware acceleration, a software layer
2533      * is useful to apply a specific color filter and/or blending mode and/or
2534      * translucency to a view and all its children.</p>
2535      * <p>When the application is using hardware acceleration, a software layer
2536      * is useful to render drawing primitives not supported by the hardware
2537      * accelerated pipeline. It can also be used to cache a complex view tree
2538      * into a texture and reduce the complexity of drawing operations. For instance,
2539      * when animating a complex view tree with a translation, a software layer can
2540      * be used to render the view tree only once.</p>
2541      * <p>Software layers should be avoided when the affected view tree updates
2542      * often. Every update will require to re-render the software layer, which can
2543      * potentially be slow (particularly when hardware acceleration is turned on
2544      * since the layer will have to be uploaded into a hardware texture after every
2545      * update.)</p>
2546      *
2547      * @see #getLayerType()
2548      * @see #setLayerType(int, android.graphics.Paint)
2549      * @see #LAYER_TYPE_NONE
2550      * @see #LAYER_TYPE_HARDWARE
2551      */
2552     public static final int LAYER_TYPE_SOFTWARE = 1;
2553 
2554     /**
2555      * <p>Indicates that the view has a hardware layer. A hardware layer is backed
2556      * by a hardware specific texture (generally Frame Buffer Objects or FBO on
2557      * OpenGL hardware) and causes the view to be rendered using Android's hardware
2558      * rendering pipeline, but only if hardware acceleration is turned on for the
2559      * view hierarchy. When hardware acceleration is turned off, hardware layers
2560      * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
2561      *
2562      * <p>A hardware layer is useful to apply a specific color filter and/or
2563      * blending mode and/or translucency to a view and all its children.</p>
2564      * <p>A hardware layer can be used to cache a complex view tree into a
2565      * texture and reduce the complexity of drawing operations. For instance,
2566      * when animating a complex view tree with a translation, a hardware layer can
2567      * be used to render the view tree only once.</p>
2568      * <p>A hardware layer can also be used to increase the rendering quality when
2569      * rotation transformations are applied on a view. It can also be used to
2570      * prevent potential clipping issues when applying 3D transforms on a view.</p>
2571      *
2572      * @see #getLayerType()
2573      * @see #setLayerType(int, android.graphics.Paint)
2574      * @see #LAYER_TYPE_NONE
2575      * @see #LAYER_TYPE_SOFTWARE
2576      */
2577     public static final int LAYER_TYPE_HARDWARE = 2;
2578 
2579     @ViewDebug.ExportedProperty(category = "drawing", mapping = {
2580             @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
2581             @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
2582             @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
2583     })
2584     int mLayerType = LAYER_TYPE_NONE;
2585     Paint mLayerPaint;
2586     Rect mLocalDirtyRect;
2587 
2588     /**
2589      * Set to true when the view is sending hover accessibility events because it
2590      * is the innermost hovered view.
2591      */
2592     private boolean mSendingHoverAccessibilityEvents;
2593 
2594     /**
2595      * Delegate for injecting accessiblity functionality.
2596      */
2597     AccessibilityDelegate mAccessibilityDelegate;
2598 
2599     /**
2600      * Text direction is inherited thru {@link ViewGroup}
2601      * @hide
2602      */
2603     public static final int TEXT_DIRECTION_INHERIT = 0;
2604 
2605     /**
2606      * Text direction is using "first strong algorithm". The first strong directional character
2607      * determines the paragraph direction. If there is no strong directional character, the
2608      * paragraph direction is the view's resolved ayout direction.
2609      *
2610      * @hide
2611      */
2612     public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2613 
2614     /**
2615      * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2616      * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2617      * If there are neither, the paragraph direction is the view's resolved layout direction.
2618      *
2619      * @hide
2620      */
2621     public static final int TEXT_DIRECTION_ANY_RTL = 2;
2622 
2623     /**
2624      * Text direction is forced to LTR.
2625      *
2626      * @hide
2627      */
2628     public static final int TEXT_DIRECTION_LTR = 3;
2629 
2630     /**
2631      * Text direction is forced to RTL.
2632      *
2633      * @hide
2634      */
2635     public static final int TEXT_DIRECTION_RTL = 4;
2636 
2637     /**
2638      * Default text direction is inherited
2639      *
2640      * @hide
2641      */
2642     protected static int DEFAULT_TEXT_DIRECTION = TEXT_DIRECTION_INHERIT;
2643 
2644     /**
2645      * The text direction that has been defined by {@link #setTextDirection(int)}.
2646      *
2647      * {@hide}
2648      */
2649     @ViewDebug.ExportedProperty(category = "text", mapping = {
2650             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
2651             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
2652             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
2653             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
2654             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
2655     })
2656     private int mTextDirection = DEFAULT_TEXT_DIRECTION;
2657 
2658     /**
2659      * The resolved text direction.  This needs resolution if the value is
2660      * TEXT_DIRECTION_INHERIT.  The resolution matches mTextDirection if that is
2661      * not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds up the parent
2662      * chain of the view.
2663      *
2664      * {@hide}
2665      */
2666     @ViewDebug.ExportedProperty(category = "text", mapping = {
2667             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
2668             @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
2669             @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
2670             @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
2671             @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
2672     })
2673     private int mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
2674 
2675     /**
2676      * Consistency verifier for debugging purposes.
2677      * @hide
2678      */
2679     protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
2680             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
2681                     new InputEventConsistencyVerifier(this, 0) : null;
2682 
2683     /**
2684      * Simple constructor to use when creating a view from code.
2685      *
2686      * @param context The Context the view is running in, through which it can
2687      *        access the current theme, resources, etc.
2688      */
View(Context context)2689     public View(Context context) {
2690         mContext = context;
2691         mResources = context != null ? context.getResources() : null;
2692         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | LAYOUT_DIRECTION_INHERIT;
2693         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
2694         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
2695         mUserPaddingStart = -1;
2696         mUserPaddingEnd = -1;
2697         mUserPaddingRelative = false;
2698     }
2699 
2700     /**
2701      * Constructor that is called when inflating a view from XML. This is called
2702      * when a view is being constructed from an XML file, supplying attributes
2703      * that were specified in the XML file. This version uses a default style of
2704      * 0, so the only attribute values applied are those in the Context's Theme
2705      * and the given AttributeSet.
2706      *
2707      * <p>
2708      * The method onFinishInflate() will be called after all children have been
2709      * added.
2710      *
2711      * @param context The Context the view is running in, through which it can
2712      *        access the current theme, resources, etc.
2713      * @param attrs The attributes of the XML tag that is inflating the view.
2714      * @see #View(Context, AttributeSet, int)
2715      */
View(Context context, AttributeSet attrs)2716     public View(Context context, AttributeSet attrs) {
2717         this(context, attrs, 0);
2718     }
2719 
2720     /**
2721      * Perform inflation from XML and apply a class-specific base style. This
2722      * constructor of View allows subclasses to use their own base style when
2723      * they are inflating. For example, a Button class's constructor would call
2724      * this version of the super class constructor and supply
2725      * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
2726      * the theme's button style to modify all of the base view attributes (in
2727      * particular its background) as well as the Button class's attributes.
2728      *
2729      * @param context The Context the view is running in, through which it can
2730      *        access the current theme, resources, etc.
2731      * @param attrs The attributes of the XML tag that is inflating the view.
2732      * @param defStyle The default style to apply to this view. If 0, no style
2733      *        will be applied (beyond what is included in the theme). This may
2734      *        either be an attribute resource, whose value will be retrieved
2735      *        from the current theme, or an explicit style resource.
2736      * @see #View(Context, AttributeSet)
2737      */
View(Context context, AttributeSet attrs, int defStyle)2738     public View(Context context, AttributeSet attrs, int defStyle) {
2739         this(context);
2740 
2741         TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
2742                 defStyle, 0);
2743 
2744         Drawable background = null;
2745 
2746         int leftPadding = -1;
2747         int topPadding = -1;
2748         int rightPadding = -1;
2749         int bottomPadding = -1;
2750         int startPadding = -1;
2751         int endPadding = -1;
2752 
2753         int padding = -1;
2754 
2755         int viewFlagValues = 0;
2756         int viewFlagMasks = 0;
2757 
2758         boolean setScrollContainer = false;
2759 
2760         int x = 0;
2761         int y = 0;
2762 
2763         float tx = 0;
2764         float ty = 0;
2765         float rotation = 0;
2766         float rotationX = 0;
2767         float rotationY = 0;
2768         float sx = 1f;
2769         float sy = 1f;
2770         boolean transformSet = false;
2771 
2772         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
2773 
2774         int overScrollMode = mOverScrollMode;
2775         final int N = a.getIndexCount();
2776         for (int i = 0; i < N; i++) {
2777             int attr = a.getIndex(i);
2778             switch (attr) {
2779                 case com.android.internal.R.styleable.View_background:
2780                     background = a.getDrawable(attr);
2781                     break;
2782                 case com.android.internal.R.styleable.View_padding:
2783                     padding = a.getDimensionPixelSize(attr, -1);
2784                     break;
2785                  case com.android.internal.R.styleable.View_paddingLeft:
2786                     leftPadding = a.getDimensionPixelSize(attr, -1);
2787                     break;
2788                 case com.android.internal.R.styleable.View_paddingTop:
2789                     topPadding = a.getDimensionPixelSize(attr, -1);
2790                     break;
2791                 case com.android.internal.R.styleable.View_paddingRight:
2792                     rightPadding = a.getDimensionPixelSize(attr, -1);
2793                     break;
2794                 case com.android.internal.R.styleable.View_paddingBottom:
2795                     bottomPadding = a.getDimensionPixelSize(attr, -1);
2796                     break;
2797                 case com.android.internal.R.styleable.View_paddingStart:
2798                     startPadding = a.getDimensionPixelSize(attr, -1);
2799                     break;
2800                 case com.android.internal.R.styleable.View_paddingEnd:
2801                     endPadding = a.getDimensionPixelSize(attr, -1);
2802                     break;
2803                 case com.android.internal.R.styleable.View_scrollX:
2804                     x = a.getDimensionPixelOffset(attr, 0);
2805                     break;
2806                 case com.android.internal.R.styleable.View_scrollY:
2807                     y = a.getDimensionPixelOffset(attr, 0);
2808                     break;
2809                 case com.android.internal.R.styleable.View_alpha:
2810                     setAlpha(a.getFloat(attr, 1f));
2811                     break;
2812                 case com.android.internal.R.styleable.View_transformPivotX:
2813                     setPivotX(a.getDimensionPixelOffset(attr, 0));
2814                     break;
2815                 case com.android.internal.R.styleable.View_transformPivotY:
2816                     setPivotY(a.getDimensionPixelOffset(attr, 0));
2817                     break;
2818                 case com.android.internal.R.styleable.View_translationX:
2819                     tx = a.getDimensionPixelOffset(attr, 0);
2820                     transformSet = true;
2821                     break;
2822                 case com.android.internal.R.styleable.View_translationY:
2823                     ty = a.getDimensionPixelOffset(attr, 0);
2824                     transformSet = true;
2825                     break;
2826                 case com.android.internal.R.styleable.View_rotation:
2827                     rotation = a.getFloat(attr, 0);
2828                     transformSet = true;
2829                     break;
2830                 case com.android.internal.R.styleable.View_rotationX:
2831                     rotationX = a.getFloat(attr, 0);
2832                     transformSet = true;
2833                     break;
2834                 case com.android.internal.R.styleable.View_rotationY:
2835                     rotationY = a.getFloat(attr, 0);
2836                     transformSet = true;
2837                     break;
2838                 case com.android.internal.R.styleable.View_scaleX:
2839                     sx = a.getFloat(attr, 1f);
2840                     transformSet = true;
2841                     break;
2842                 case com.android.internal.R.styleable.View_scaleY:
2843                     sy = a.getFloat(attr, 1f);
2844                     transformSet = true;
2845                     break;
2846                 case com.android.internal.R.styleable.View_id:
2847                     mID = a.getResourceId(attr, NO_ID);
2848                     break;
2849                 case com.android.internal.R.styleable.View_tag:
2850                     mTag = a.getText(attr);
2851                     break;
2852                 case com.android.internal.R.styleable.View_fitsSystemWindows:
2853                     if (a.getBoolean(attr, false)) {
2854                         viewFlagValues |= FITS_SYSTEM_WINDOWS;
2855                         viewFlagMasks |= FITS_SYSTEM_WINDOWS;
2856                     }
2857                     break;
2858                 case com.android.internal.R.styleable.View_focusable:
2859                     if (a.getBoolean(attr, false)) {
2860                         viewFlagValues |= FOCUSABLE;
2861                         viewFlagMasks |= FOCUSABLE_MASK;
2862                     }
2863                     break;
2864                 case com.android.internal.R.styleable.View_focusableInTouchMode:
2865                     if (a.getBoolean(attr, false)) {
2866                         viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
2867                         viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
2868                     }
2869                     break;
2870                 case com.android.internal.R.styleable.View_clickable:
2871                     if (a.getBoolean(attr, false)) {
2872                         viewFlagValues |= CLICKABLE;
2873                         viewFlagMasks |= CLICKABLE;
2874                     }
2875                     break;
2876                 case com.android.internal.R.styleable.View_longClickable:
2877                     if (a.getBoolean(attr, false)) {
2878                         viewFlagValues |= LONG_CLICKABLE;
2879                         viewFlagMasks |= LONG_CLICKABLE;
2880                     }
2881                     break;
2882                 case com.android.internal.R.styleable.View_saveEnabled:
2883                     if (!a.getBoolean(attr, true)) {
2884                         viewFlagValues |= SAVE_DISABLED;
2885                         viewFlagMasks |= SAVE_DISABLED_MASK;
2886                     }
2887                     break;
2888                 case com.android.internal.R.styleable.View_duplicateParentState:
2889                     if (a.getBoolean(attr, false)) {
2890                         viewFlagValues |= DUPLICATE_PARENT_STATE;
2891                         viewFlagMasks |= DUPLICATE_PARENT_STATE;
2892                     }
2893                     break;
2894                 case com.android.internal.R.styleable.View_visibility:
2895                     final int visibility = a.getInt(attr, 0);
2896                     if (visibility != 0) {
2897                         viewFlagValues |= VISIBILITY_FLAGS[visibility];
2898                         viewFlagMasks |= VISIBILITY_MASK;
2899                     }
2900                     break;
2901                 case com.android.internal.R.styleable.View_layoutDirection:
2902                     // Clear any HORIZONTAL_DIRECTION flag already set
2903                     viewFlagValues &= ~LAYOUT_DIRECTION_MASK;
2904                     // Set the HORIZONTAL_DIRECTION flags depending on the value of the attribute
2905                     final int layoutDirection = a.getInt(attr, -1);
2906                     if (layoutDirection != -1) {
2907                         viewFlagValues |= LAYOUT_DIRECTION_FLAGS[layoutDirection];
2908                     } else {
2909                         // Set to default (LAYOUT_DIRECTION_INHERIT)
2910                         viewFlagValues |= LAYOUT_DIRECTION_DEFAULT;
2911                     }
2912                     viewFlagMasks |= LAYOUT_DIRECTION_MASK;
2913                     break;
2914                 case com.android.internal.R.styleable.View_drawingCacheQuality:
2915                     final int cacheQuality = a.getInt(attr, 0);
2916                     if (cacheQuality != 0) {
2917                         viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
2918                         viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
2919                     }
2920                     break;
2921                 case com.android.internal.R.styleable.View_contentDescription:
2922                     mContentDescription = a.getString(attr);
2923                     break;
2924                 case com.android.internal.R.styleable.View_soundEffectsEnabled:
2925                     if (!a.getBoolean(attr, true)) {
2926                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
2927                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
2928                     }
2929                     break;
2930                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
2931                     if (!a.getBoolean(attr, true)) {
2932                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
2933                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
2934                     }
2935                     break;
2936                 case R.styleable.View_scrollbars:
2937                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
2938                     if (scrollbars != SCROLLBARS_NONE) {
2939                         viewFlagValues |= scrollbars;
2940                         viewFlagMasks |= SCROLLBARS_MASK;
2941                         initializeScrollbars(a);
2942                     }
2943                     break;
2944                 //noinspection deprecation
2945                 case R.styleable.View_fadingEdge:
2946                     if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) {
2947                         // Ignore the attribute starting with ICS
2948                         break;
2949                     }
2950                     // With builds < ICS, fall through and apply fading edges
2951                 case R.styleable.View_requiresFadingEdge:
2952                     final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
2953                     if (fadingEdge != FADING_EDGE_NONE) {
2954                         viewFlagValues |= fadingEdge;
2955                         viewFlagMasks |= FADING_EDGE_MASK;
2956                         initializeFadingEdge(a);
2957                     }
2958                     break;
2959                 case R.styleable.View_scrollbarStyle:
2960                     scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
2961                     if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
2962                         viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
2963                         viewFlagMasks |= SCROLLBARS_STYLE_MASK;
2964                     }
2965                     break;
2966                 case R.styleable.View_isScrollContainer:
2967                     setScrollContainer = true;
2968                     if (a.getBoolean(attr, false)) {
2969                         setScrollContainer(true);
2970                     }
2971                     break;
2972                 case com.android.internal.R.styleable.View_keepScreenOn:
2973                     if (a.getBoolean(attr, false)) {
2974                         viewFlagValues |= KEEP_SCREEN_ON;
2975                         viewFlagMasks |= KEEP_SCREEN_ON;
2976                     }
2977                     break;
2978                 case R.styleable.View_filterTouchesWhenObscured:
2979                     if (a.getBoolean(attr, false)) {
2980                         viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
2981                         viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
2982                     }
2983                     break;
2984                 case R.styleable.View_nextFocusLeft:
2985                     mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
2986                     break;
2987                 case R.styleable.View_nextFocusRight:
2988                     mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
2989                     break;
2990                 case R.styleable.View_nextFocusUp:
2991                     mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
2992                     break;
2993                 case R.styleable.View_nextFocusDown:
2994                     mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
2995                     break;
2996                 case R.styleable.View_nextFocusForward:
2997                     mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
2998                     break;
2999                 case R.styleable.View_minWidth:
3000                     mMinWidth = a.getDimensionPixelSize(attr, 0);
3001                     break;
3002                 case R.styleable.View_minHeight:
3003                     mMinHeight = a.getDimensionPixelSize(attr, 0);
3004                     break;
3005                 case R.styleable.View_onClick:
3006                     if (context.isRestricted()) {
3007                         throw new IllegalStateException("The android:onClick attribute cannot "
3008                                 + "be used within a restricted context");
3009                     }
3010 
3011                     final String handlerName = a.getString(attr);
3012                     if (handlerName != null) {
3013                         setOnClickListener(new OnClickListener() {
3014                             private Method mHandler;
3015 
3016                             public void onClick(View v) {
3017                                 if (mHandler == null) {
3018                                     try {
3019                                         mHandler = getContext().getClass().getMethod(handlerName,
3020                                                 View.class);
3021                                     } catch (NoSuchMethodException e) {
3022                                         int id = getId();
3023                                         String idText = id == NO_ID ? "" : " with id '"
3024                                                 + getContext().getResources().getResourceEntryName(
3025                                                     id) + "'";
3026                                         throw new IllegalStateException("Could not find a method " +
3027                                                 handlerName + "(View) in the activity "
3028                                                 + getContext().getClass() + " for onClick handler"
3029                                                 + " on view " + View.this.getClass() + idText, e);
3030                                     }
3031                                 }
3032 
3033                                 try {
3034                                     mHandler.invoke(getContext(), View.this);
3035                                 } catch (IllegalAccessException e) {
3036                                     throw new IllegalStateException("Could not execute non "
3037                                             + "public method of the activity", e);
3038                                 } catch (InvocationTargetException e) {
3039                                     throw new IllegalStateException("Could not execute "
3040                                             + "method of the activity", e);
3041                                 }
3042                             }
3043                         });
3044                     }
3045                     break;
3046                 case R.styleable.View_overScrollMode:
3047                     overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3048                     break;
3049                 case R.styleable.View_verticalScrollbarPosition:
3050                     mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3051                     break;
3052                 case R.styleable.View_layerType:
3053                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3054                     break;
3055                 case R.styleable.View_textDirection:
3056                     mTextDirection = a.getInt(attr, DEFAULT_TEXT_DIRECTION);
3057                     break;
3058             }
3059         }
3060 
3061         a.recycle();
3062 
3063         setOverScrollMode(overScrollMode);
3064 
3065         if (background != null) {
3066             setBackgroundDrawable(background);
3067         }
3068 
3069         mUserPaddingRelative = (startPadding >= 0 || endPadding >= 0);
3070 
3071         // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved
3072         // layout direction). Those cached values will be used later during padding resolution.
3073         mUserPaddingStart = startPadding;
3074         mUserPaddingEnd = endPadding;
3075 
3076         if (padding >= 0) {
3077             leftPadding = padding;
3078             topPadding = padding;
3079             rightPadding = padding;
3080             bottomPadding = padding;
3081         }
3082 
3083         // If the user specified the padding (either with android:padding or
3084         // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
3085         // use the default padding or the padding from the background drawable
3086         // (stored at this point in mPadding*)
3087         setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
3088                 topPadding >= 0 ? topPadding : mPaddingTop,
3089                 rightPadding >= 0 ? rightPadding : mPaddingRight,
3090                 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
3091 
3092         if (viewFlagMasks != 0) {
3093             setFlags(viewFlagValues, viewFlagMasks);
3094         }
3095 
3096         // Needs to be called after mViewFlags is set
3097         if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3098             recomputePadding();
3099         }
3100 
3101         if (x != 0 || y != 0) {
3102             scrollTo(x, y);
3103         }
3104 
3105         if (transformSet) {
3106             setTranslationX(tx);
3107             setTranslationY(ty);
3108             setRotation(rotation);
3109             setRotationX(rotationX);
3110             setRotationY(rotationY);
3111             setScaleX(sx);
3112             setScaleY(sy);
3113         }
3114 
3115         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
3116             setScrollContainer(true);
3117         }
3118 
3119         computeOpaqueFlags();
3120     }
3121 
3122     /**
3123      * Non-public constructor for use in testing
3124      */
View()3125     View() {
3126         mResources = null;
3127     }
3128 
3129     /**
3130      * <p>
3131      * Initializes the fading edges from a given set of styled attributes. This
3132      * method should be called by subclasses that need fading edges and when an
3133      * instance of these subclasses is created programmatically rather than
3134      * being inflated from XML. This method is automatically called when the XML
3135      * is inflated.
3136      * </p>
3137      *
3138      * @param a the styled attributes set to initialize the fading edges from
3139      */
initializeFadingEdge(TypedArray a)3140     protected void initializeFadingEdge(TypedArray a) {
3141         initScrollCache();
3142 
3143         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
3144                 R.styleable.View_fadingEdgeLength,
3145                 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
3146     }
3147 
3148     /**
3149      * Returns the size of the vertical faded edges used to indicate that more
3150      * content in this view is visible.
3151      *
3152      * @return The size in pixels of the vertical faded edge or 0 if vertical
3153      *         faded edges are not enabled for this view.
3154      * @attr ref android.R.styleable#View_fadingEdgeLength
3155      */
getVerticalFadingEdgeLength()3156     public int getVerticalFadingEdgeLength() {
3157         if (isVerticalFadingEdgeEnabled()) {
3158             ScrollabilityCache cache = mScrollCache;
3159             if (cache != null) {
3160                 return cache.fadingEdgeLength;
3161             }
3162         }
3163         return 0;
3164     }
3165 
3166     /**
3167      * Set the size of the faded edge used to indicate that more content in this
3168      * view is available.  Will not change whether the fading edge is enabled; use
3169      * {@link #setVerticalFadingEdgeEnabled(boolean)} or
3170      * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
3171      * for the vertical or horizontal fading edges.
3172      *
3173      * @param length The size in pixels of the faded edge used to indicate that more
3174      *        content in this view is visible.
3175      */
setFadingEdgeLength(int length)3176     public void setFadingEdgeLength(int length) {
3177         initScrollCache();
3178         mScrollCache.fadingEdgeLength = length;
3179     }
3180 
3181     /**
3182      * Returns the size of the horizontal faded edges used to indicate that more
3183      * content in this view is visible.
3184      *
3185      * @return The size in pixels of the horizontal faded edge or 0 if horizontal
3186      *         faded edges are not enabled for this view.
3187      * @attr ref android.R.styleable#View_fadingEdgeLength
3188      */
getHorizontalFadingEdgeLength()3189     public int getHorizontalFadingEdgeLength() {
3190         if (isHorizontalFadingEdgeEnabled()) {
3191             ScrollabilityCache cache = mScrollCache;
3192             if (cache != null) {
3193                 return cache.fadingEdgeLength;
3194             }
3195         }
3196         return 0;
3197     }
3198 
3199     /**
3200      * Returns the width of the vertical scrollbar.
3201      *
3202      * @return The width in pixels of the vertical scrollbar or 0 if there
3203      *         is no vertical scrollbar.
3204      */
getVerticalScrollbarWidth()3205     public int getVerticalScrollbarWidth() {
3206         ScrollabilityCache cache = mScrollCache;
3207         if (cache != null) {
3208             ScrollBarDrawable scrollBar = cache.scrollBar;
3209             if (scrollBar != null) {
3210                 int size = scrollBar.getSize(true);
3211                 if (size <= 0) {
3212                     size = cache.scrollBarSize;
3213                 }
3214                 return size;
3215             }
3216             return 0;
3217         }
3218         return 0;
3219     }
3220 
3221     /**
3222      * Returns the height of the horizontal scrollbar.
3223      *
3224      * @return The height in pixels of the horizontal scrollbar or 0 if
3225      *         there is no horizontal scrollbar.
3226      */
getHorizontalScrollbarHeight()3227     protected int getHorizontalScrollbarHeight() {
3228         ScrollabilityCache cache = mScrollCache;
3229         if (cache != null) {
3230             ScrollBarDrawable scrollBar = cache.scrollBar;
3231             if (scrollBar != null) {
3232                 int size = scrollBar.getSize(false);
3233                 if (size <= 0) {
3234                     size = cache.scrollBarSize;
3235                 }
3236                 return size;
3237             }
3238             return 0;
3239         }
3240         return 0;
3241     }
3242 
3243     /**
3244      * <p>
3245      * Initializes the scrollbars from a given set of styled attributes. This
3246      * method should be called by subclasses that need scrollbars and when an
3247      * instance of these subclasses is created programmatically rather than
3248      * being inflated from XML. This method is automatically called when the XML
3249      * is inflated.
3250      * </p>
3251      *
3252      * @param a the styled attributes set to initialize the scrollbars from
3253      */
initializeScrollbars(TypedArray a)3254     protected void initializeScrollbars(TypedArray a) {
3255         initScrollCache();
3256 
3257         final ScrollabilityCache scrollabilityCache = mScrollCache;
3258 
3259         if (scrollabilityCache.scrollBar == null) {
3260             scrollabilityCache.scrollBar = new ScrollBarDrawable();
3261         }
3262 
3263         final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
3264 
3265         if (!fadeScrollbars) {
3266             scrollabilityCache.state = ScrollabilityCache.ON;
3267         }
3268         scrollabilityCache.fadeScrollBars = fadeScrollbars;
3269 
3270 
3271         scrollabilityCache.scrollBarFadeDuration = a.getInt(
3272                 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
3273                         .getScrollBarFadeDuration());
3274         scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
3275                 R.styleable.View_scrollbarDefaultDelayBeforeFade,
3276                 ViewConfiguration.getScrollDefaultDelay());
3277 
3278 
3279         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
3280                 com.android.internal.R.styleable.View_scrollbarSize,
3281                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
3282 
3283         Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
3284         scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
3285 
3286         Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
3287         if (thumb != null) {
3288             scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
3289         }
3290 
3291         boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
3292                 false);
3293         if (alwaysDraw) {
3294             scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
3295         }
3296 
3297         track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
3298         scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
3299 
3300         thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
3301         if (thumb != null) {
3302             scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
3303         }
3304 
3305         alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
3306                 false);
3307         if (alwaysDraw) {
3308             scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
3309         }
3310 
3311         // Re-apply user/background padding so that scrollbar(s) get added
3312         resolvePadding();
3313     }
3314 
3315     /**
3316      * <p>
3317      * Initalizes the scrollability cache if necessary.
3318      * </p>
3319      */
initScrollCache()3320     private void initScrollCache() {
3321         if (mScrollCache == null) {
3322             mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
3323         }
3324     }
3325 
3326     /**
3327      * Set the position of the vertical scroll bar. Should be one of
3328      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
3329      * {@link #SCROLLBAR_POSITION_RIGHT}.
3330      *
3331      * @param position Where the vertical scroll bar should be positioned.
3332      */
setVerticalScrollbarPosition(int position)3333     public void setVerticalScrollbarPosition(int position) {
3334         if (mVerticalScrollbarPosition != position) {
3335             mVerticalScrollbarPosition = position;
3336             computeOpaqueFlags();
3337             resolvePadding();
3338         }
3339     }
3340 
3341     /**
3342      * @return The position where the vertical scroll bar will show, if applicable.
3343      * @see #setVerticalScrollbarPosition(int)
3344      */
getVerticalScrollbarPosition()3345     public int getVerticalScrollbarPosition() {
3346         return mVerticalScrollbarPosition;
3347     }
3348 
3349     /**
3350      * Register a callback to be invoked when focus of this view changed.
3351      *
3352      * @param l The callback that will run.
3353      */
setOnFocusChangeListener(OnFocusChangeListener l)3354     public void setOnFocusChangeListener(OnFocusChangeListener l) {
3355         mOnFocusChangeListener = l;
3356     }
3357 
3358     /**
3359      * Add a listener that will be called when the bounds of the view change due to
3360      * layout processing.
3361      *
3362      * @param listener The listener that will be called when layout bounds change.
3363      */
addOnLayoutChangeListener(OnLayoutChangeListener listener)3364     public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
3365         if (mOnLayoutChangeListeners == null) {
3366             mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
3367         }
3368         if (!mOnLayoutChangeListeners.contains(listener)) {
3369             mOnLayoutChangeListeners.add(listener);
3370         }
3371     }
3372 
3373     /**
3374      * Remove a listener for layout changes.
3375      *
3376      * @param listener The listener for layout bounds change.
3377      */
removeOnLayoutChangeListener(OnLayoutChangeListener listener)3378     public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
3379         if (mOnLayoutChangeListeners == null) {
3380             return;
3381         }
3382         mOnLayoutChangeListeners.remove(listener);
3383     }
3384 
3385     /**
3386      * Add a listener for attach state changes.
3387      *
3388      * This listener will be called whenever this view is attached or detached
3389      * from a window. Remove the listener using
3390      * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
3391      *
3392      * @param listener Listener to attach
3393      * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
3394      */
addOnAttachStateChangeListener(OnAttachStateChangeListener listener)3395     public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
3396         if (mOnAttachStateChangeListeners == null) {
3397             mOnAttachStateChangeListeners = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
3398         }
3399         mOnAttachStateChangeListeners.add(listener);
3400     }
3401 
3402     /**
3403      * Remove a listener for attach state changes. The listener will receive no further
3404      * notification of window attach/detach events.
3405      *
3406      * @param listener Listener to remove
3407      * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
3408      */
removeOnAttachStateChangeListener(OnAttachStateChangeListener listener)3409     public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
3410         if (mOnAttachStateChangeListeners == null) {
3411             return;
3412         }
3413         mOnAttachStateChangeListeners.remove(listener);
3414     }
3415 
3416     /**
3417      * Returns the focus-change callback registered for this view.
3418      *
3419      * @return The callback, or null if one is not registered.
3420      */
getOnFocusChangeListener()3421     public OnFocusChangeListener getOnFocusChangeListener() {
3422         return mOnFocusChangeListener;
3423     }
3424 
3425     /**
3426      * Register a callback to be invoked when this view is clicked. If this view is not
3427      * clickable, it becomes clickable.
3428      *
3429      * @param l The callback that will run
3430      *
3431      * @see #setClickable(boolean)
3432      */
setOnClickListener(OnClickListener l)3433     public void setOnClickListener(OnClickListener l) {
3434         if (!isClickable()) {
3435             setClickable(true);
3436         }
3437         mOnClickListener = l;
3438     }
3439 
3440     /**
3441      * Register a callback to be invoked when this view is clicked and held. If this view is not
3442      * long clickable, it becomes long clickable.
3443      *
3444      * @param l The callback that will run
3445      *
3446      * @see #setLongClickable(boolean)
3447      */
setOnLongClickListener(OnLongClickListener l)3448     public void setOnLongClickListener(OnLongClickListener l) {
3449         if (!isLongClickable()) {
3450             setLongClickable(true);
3451         }
3452         mOnLongClickListener = l;
3453     }
3454 
3455     /**
3456      * Register a callback to be invoked when the context menu for this view is
3457      * being built. If this view is not long clickable, it becomes long clickable.
3458      *
3459      * @param l The callback that will run
3460      *
3461      */
setOnCreateContextMenuListener(OnCreateContextMenuListener l)3462     public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
3463         if (!isLongClickable()) {
3464             setLongClickable(true);
3465         }
3466         mOnCreateContextMenuListener = l;
3467     }
3468 
3469     /**
3470      * Call this view's OnClickListener, if it is defined.
3471      *
3472      * @return True there was an assigned OnClickListener that was called, false
3473      *         otherwise is returned.
3474      */
performClick()3475     public boolean performClick() {
3476         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
3477 
3478         if (mOnClickListener != null) {
3479             playSoundEffect(SoundEffectConstants.CLICK);
3480             mOnClickListener.onClick(this);
3481             return true;
3482         }
3483 
3484         return false;
3485     }
3486 
3487     /**
3488      * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
3489      * OnLongClickListener did not consume the event.
3490      *
3491      * @return True if one of the above receivers consumed the event, false otherwise.
3492      */
performLongClick()3493     public boolean performLongClick() {
3494         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
3495 
3496         boolean handled = false;
3497         if (mOnLongClickListener != null) {
3498             handled = mOnLongClickListener.onLongClick(View.this);
3499         }
3500         if (!handled) {
3501             handled = showContextMenu();
3502         }
3503         if (handled) {
3504             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
3505         }
3506         return handled;
3507     }
3508 
3509     /**
3510      * Performs button-related actions during a touch down event.
3511      *
3512      * @param event The event.
3513      * @return True if the down was consumed.
3514      *
3515      * @hide
3516      */
performButtonActionOnTouchDown(MotionEvent event)3517     protected boolean performButtonActionOnTouchDown(MotionEvent event) {
3518         if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
3519             if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
3520                 return true;
3521             }
3522         }
3523         return false;
3524     }
3525 
3526     /**
3527      * Bring up the context menu for this view.
3528      *
3529      * @return Whether a context menu was displayed.
3530      */
showContextMenu()3531     public boolean showContextMenu() {
3532         return getParent().showContextMenuForChild(this);
3533     }
3534 
3535     /**
3536      * Bring up the context menu for this view, referring to the item under the specified point.
3537      *
3538      * @param x The referenced x coordinate.
3539      * @param y The referenced y coordinate.
3540      * @param metaState The keyboard modifiers that were pressed.
3541      * @return Whether a context menu was displayed.
3542      *
3543      * @hide
3544      */
showContextMenu(float x, float y, int metaState)3545     public boolean showContextMenu(float x, float y, int metaState) {
3546         return showContextMenu();
3547     }
3548 
3549     /**
3550      * Start an action mode.
3551      *
3552      * @param callback Callback that will control the lifecycle of the action mode
3553      * @return The new action mode if it is started, null otherwise
3554      *
3555      * @see ActionMode
3556      */
startActionMode(ActionMode.Callback callback)3557     public ActionMode startActionMode(ActionMode.Callback callback) {
3558         return getParent().startActionModeForChild(this, callback);
3559     }
3560 
3561     /**
3562      * Register a callback to be invoked when a key is pressed in this view.
3563      * @param l the key listener to attach to this view
3564      */
setOnKeyListener(OnKeyListener l)3565     public void setOnKeyListener(OnKeyListener l) {
3566         mOnKeyListener = l;
3567     }
3568 
3569     /**
3570      * Register a callback to be invoked when a touch event is sent to this view.
3571      * @param l the touch listener to attach to this view
3572      */
setOnTouchListener(OnTouchListener l)3573     public void setOnTouchListener(OnTouchListener l) {
3574         mOnTouchListener = l;
3575     }
3576 
3577     /**
3578      * Register a callback to be invoked when a generic motion event is sent to this view.
3579      * @param l the generic motion listener to attach to this view
3580      */
setOnGenericMotionListener(OnGenericMotionListener l)3581     public void setOnGenericMotionListener(OnGenericMotionListener l) {
3582         mOnGenericMotionListener = l;
3583     }
3584 
3585     /**
3586      * Register a callback to be invoked when a hover event is sent to this view.
3587      * @param l the hover listener to attach to this view
3588      */
setOnHoverListener(OnHoverListener l)3589     public void setOnHoverListener(OnHoverListener l) {
3590         mOnHoverListener = l;
3591     }
3592 
3593     /**
3594      * Register a drag event listener callback object for this View. The parameter is
3595      * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
3596      * View, the system calls the
3597      * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
3598      * @param l An implementation of {@link android.view.View.OnDragListener}.
3599      */
setOnDragListener(OnDragListener l)3600     public void setOnDragListener(OnDragListener l) {
3601         mOnDragListener = l;
3602     }
3603 
3604     /**
3605      * Give this view focus. This will cause
3606      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
3607      *
3608      * Note: this does not check whether this {@link View} should get focus, it just
3609      * gives it focus no matter what.  It should only be called internally by framework
3610      * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
3611      *
3612      * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
3613      *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
3614      *        focus moved when requestFocus() is called. It may not always
3615      *        apply, in which case use the default View.FOCUS_DOWN.
3616      * @param previouslyFocusedRect The rectangle of the view that had focus
3617      *        prior in this View's coordinate system.
3618      */
handleFocusGainInternal(int direction, Rect previouslyFocusedRect)3619     void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
3620         if (DBG) {
3621             System.out.println(this + " requestFocus()");
3622         }
3623 
3624         if ((mPrivateFlags & FOCUSED) == 0) {
3625             mPrivateFlags |= FOCUSED;
3626 
3627             if (mParent != null) {
3628                 mParent.requestChildFocus(this, this);
3629             }
3630 
3631             onFocusChanged(true, direction, previouslyFocusedRect);
3632             refreshDrawableState();
3633         }
3634     }
3635 
3636     /**
3637      * Request that a rectangle of this view be visible on the screen,
3638      * scrolling if necessary just enough.
3639      *
3640      * <p>A View should call this if it maintains some notion of which part
3641      * of its content is interesting.  For example, a text editing view
3642      * should call this when its cursor moves.
3643      *
3644      * @param rectangle The rectangle.
3645      * @return Whether any parent scrolled.
3646      */
requestRectangleOnScreen(Rect rectangle)3647     public boolean requestRectangleOnScreen(Rect rectangle) {
3648         return requestRectangleOnScreen(rectangle, false);
3649     }
3650 
3651     /**
3652      * Request that a rectangle of this view be visible on the screen,
3653      * scrolling if necessary just enough.
3654      *
3655      * <p>A View should call this if it maintains some notion of which part
3656      * of its content is interesting.  For example, a text editing view
3657      * should call this when its cursor moves.
3658      *
3659      * <p>When <code>immediate</code> is set to true, scrolling will not be
3660      * animated.
3661      *
3662      * @param rectangle The rectangle.
3663      * @param immediate True to forbid animated scrolling, false otherwise
3664      * @return Whether any parent scrolled.
3665      */
requestRectangleOnScreen(Rect rectangle, boolean immediate)3666     public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
3667         View child = this;
3668         ViewParent parent = mParent;
3669         boolean scrolled = false;
3670         while (parent != null) {
3671             scrolled |= parent.requestChildRectangleOnScreen(child,
3672                     rectangle, immediate);
3673 
3674             // offset rect so next call has the rectangle in the
3675             // coordinate system of its direct child.
3676             rectangle.offset(child.getLeft(), child.getTop());
3677             rectangle.offset(-child.getScrollX(), -child.getScrollY());
3678 
3679             if (!(parent instanceof View)) {
3680                 break;
3681             }
3682 
3683             child = (View) parent;
3684             parent = child.getParent();
3685         }
3686         return scrolled;
3687     }
3688 
3689     /**
3690      * Called when this view wants to give up focus. This will cause
3691      * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
3692      */
clearFocus()3693     public void clearFocus() {
3694         if (DBG) {
3695             System.out.println(this + " clearFocus()");
3696         }
3697 
3698         if ((mPrivateFlags & FOCUSED) != 0) {
3699             mPrivateFlags &= ~FOCUSED;
3700 
3701             if (mParent != null) {
3702                 mParent.clearChildFocus(this);
3703             }
3704 
3705             onFocusChanged(false, 0, null);
3706             refreshDrawableState();
3707         }
3708     }
3709 
3710     /**
3711      * Called to clear the focus of a view that is about to be removed.
3712      * Doesn't call clearChildFocus, which prevents this view from taking
3713      * focus again before it has been removed from the parent
3714      */
clearFocusForRemoval()3715     void clearFocusForRemoval() {
3716         if ((mPrivateFlags & FOCUSED) != 0) {
3717             mPrivateFlags &= ~FOCUSED;
3718 
3719             onFocusChanged(false, 0, null);
3720             refreshDrawableState();
3721         }
3722     }
3723 
3724     /**
3725      * Called internally by the view system when a new view is getting focus.
3726      * This is what clears the old focus.
3727      */
unFocus()3728     void unFocus() {
3729         if (DBG) {
3730             System.out.println(this + " unFocus()");
3731         }
3732 
3733         if ((mPrivateFlags & FOCUSED) != 0) {
3734             mPrivateFlags &= ~FOCUSED;
3735 
3736             onFocusChanged(false, 0, null);
3737             refreshDrawableState();
3738         }
3739     }
3740 
3741     /**
3742      * Returns true if this view has focus iteself, or is the ancestor of the
3743      * view that has focus.
3744      *
3745      * @return True if this view has or contains focus, false otherwise.
3746      */
3747     @ViewDebug.ExportedProperty(category = "focus")
hasFocus()3748     public boolean hasFocus() {
3749         return (mPrivateFlags & FOCUSED) != 0;
3750     }
3751 
3752     /**
3753      * Returns true if this view is focusable or if it contains a reachable View
3754      * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
3755      * is a View whose parents do not block descendants focus.
3756      *
3757      * Only {@link #VISIBLE} views are considered focusable.
3758      *
3759      * @return True if the view is focusable or if the view contains a focusable
3760      *         View, false otherwise.
3761      *
3762      * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
3763      */
hasFocusable()3764     public boolean hasFocusable() {
3765         return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
3766     }
3767 
3768     /**
3769      * Called by the view system when the focus state of this view changes.
3770      * When the focus change event is caused by directional navigation, direction
3771      * and previouslyFocusedRect provide insight into where the focus is coming from.
3772      * When overriding, be sure to call up through to the super class so that
3773      * the standard focus handling will occur.
3774      *
3775      * @param gainFocus True if the View has focus; false otherwise.
3776      * @param direction The direction focus has moved when requestFocus()
3777      *                  is called to give this view focus. Values are
3778      *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
3779      *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
3780      *                  It may not always apply, in which case use the default.
3781      * @param previouslyFocusedRect The rectangle, in this view's coordinate
3782      *        system, of the previously focused view.  If applicable, this will be
3783      *        passed in as finer grained information about where the focus is coming
3784      *        from (in addition to direction).  Will be <code>null</code> otherwise.
3785      */
onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect)3786     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
3787         if (gainFocus) {
3788             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
3789         }
3790 
3791         InputMethodManager imm = InputMethodManager.peekInstance();
3792         if (!gainFocus) {
3793             if (isPressed()) {
3794                 setPressed(false);
3795             }
3796             if (imm != null && mAttachInfo != null
3797                     && mAttachInfo.mHasWindowFocus) {
3798                 imm.focusOut(this);
3799             }
3800             onFocusLost();
3801         } else if (imm != null && mAttachInfo != null
3802                 && mAttachInfo.mHasWindowFocus) {
3803             imm.focusIn(this);
3804         }
3805 
3806         invalidate(true);
3807         if (mOnFocusChangeListener != null) {
3808             mOnFocusChangeListener.onFocusChange(this, gainFocus);
3809         }
3810 
3811         if (mAttachInfo != null) {
3812             mAttachInfo.mKeyDispatchState.reset(this);
3813         }
3814     }
3815 
3816     /**
3817      * Sends an accessibility event of the given type. If accessiiblity is
3818      * not enabled this method has no effect. The default implementation calls
3819      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
3820      * to populate information about the event source (this View), then calls
3821      * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
3822      * populate the text content of the event source including its descendants,
3823      * and last calls
3824      * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
3825      * on its parent to resuest sending of the event to interested parties.
3826      * <p>
3827      * If an {@link AccessibilityDelegate} has been specified via calling
3828      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3829      * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
3830      * responsible for handling this call.
3831      * </p>
3832      *
3833      * @param eventType The type of the event to send, as defined by several types from
3834      * {@link android.view.accessibility.AccessibilityEvent}, such as
3835      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
3836      * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
3837      *
3838      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
3839      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
3840      * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
3841      * @see AccessibilityDelegate
3842      */
sendAccessibilityEvent(int eventType)3843     public void sendAccessibilityEvent(int eventType) {
3844         if (mAccessibilityDelegate != null) {
3845             mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
3846         } else {
3847             sendAccessibilityEventInternal(eventType);
3848         }
3849     }
3850 
3851     /**
3852      * @see #sendAccessibilityEvent(int)
3853      *
3854      * Note: Called from the default {@link AccessibilityDelegate}.
3855      */
sendAccessibilityEventInternal(int eventType)3856     void sendAccessibilityEventInternal(int eventType) {
3857         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
3858             sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
3859         }
3860     }
3861 
3862     /**
3863      * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
3864      * takes as an argument an empty {@link AccessibilityEvent} and does not
3865      * perform a check whether accessibility is enabled.
3866      * <p>
3867      * If an {@link AccessibilityDelegate} has been specified via calling
3868      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3869      * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
3870      * is responsible for handling this call.
3871      * </p>
3872      *
3873      * @param event The event to send.
3874      *
3875      * @see #sendAccessibilityEvent(int)
3876      */
sendAccessibilityEventUnchecked(AccessibilityEvent event)3877     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
3878         if (mAccessibilityDelegate != null) {
3879            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
3880         } else {
3881             sendAccessibilityEventUncheckedInternal(event);
3882         }
3883     }
3884 
3885     /**
3886      * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
3887      *
3888      * Note: Called from the default {@link AccessibilityDelegate}.
3889      */
sendAccessibilityEventUncheckedInternal(AccessibilityEvent event)3890     void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
3891         if (!isShown()) {
3892             return;
3893         }
3894         onInitializeAccessibilityEvent(event);
3895         // Only a subset of accessibility events populates text content.
3896         if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
3897             dispatchPopulateAccessibilityEvent(event);
3898         }
3899         // In the beginning we called #isShown(), so we know that getParent() is not null.
3900         getParent().requestSendAccessibilityEvent(this, event);
3901     }
3902 
3903     /**
3904      * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
3905      * to its children for adding their text content to the event. Note that the
3906      * event text is populated in a separate dispatch path since we add to the
3907      * event not only the text of the source but also the text of all its descendants.
3908      * A typical implementation will call
3909      * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
3910      * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
3911      * on each child. Override this method if custom population of the event text
3912      * content is required.
3913      * <p>
3914      * If an {@link AccessibilityDelegate} has been specified via calling
3915      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3916      * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
3917      * is responsible for handling this call.
3918      * </p>
3919      * <p>
3920      * <em>Note:</em> Accessibility events of certain types are not dispatched for
3921      * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
3922      * </p>
3923      *
3924      * @param event The event.
3925      *
3926      * @return True if the event population was completed.
3927      */
dispatchPopulateAccessibilityEvent(AccessibilityEvent event)3928     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
3929         if (mAccessibilityDelegate != null) {
3930             return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
3931         } else {
3932             return dispatchPopulateAccessibilityEventInternal(event);
3933         }
3934     }
3935 
3936     /**
3937      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
3938      *
3939      * Note: Called from the default {@link AccessibilityDelegate}.
3940      */
dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event)3941     boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
3942         onPopulateAccessibilityEvent(event);
3943         return false;
3944     }
3945 
3946     /**
3947      * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
3948      * giving a chance to this View to populate the accessibility event with its
3949      * text content. While this method is free to modify event
3950      * attributes other than text content, doing so should normally be performed in
3951      * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
3952      * <p>
3953      * Example: Adding formatted date string to an accessibility event in addition
3954      *          to the text added by the super implementation:
3955      * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
3956      *     super.onPopulateAccessibilityEvent(event);
3957      *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
3958      *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
3959      *         mCurrentDate.getTimeInMillis(), flags);
3960      *     event.getText().add(selectedDateUtterance);
3961      * }</pre>
3962      * <p>
3963      * If an {@link AccessibilityDelegate} has been specified via calling
3964      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3965      * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
3966      * is responsible for handling this call.
3967      * </p>
3968      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
3969      * information to the event, in case the default implementation has basic information to add.
3970      * </p>
3971      *
3972      * @param event The accessibility event which to populate.
3973      *
3974      * @see #sendAccessibilityEvent(int)
3975      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
3976      */
onPopulateAccessibilityEvent(AccessibilityEvent event)3977     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
3978         if (mAccessibilityDelegate != null) {
3979             mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
3980         } else {
3981             onPopulateAccessibilityEventInternal(event);
3982         }
3983     }
3984 
3985     /**
3986      * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
3987      *
3988      * Note: Called from the default {@link AccessibilityDelegate}.
3989      */
onPopulateAccessibilityEventInternal(AccessibilityEvent event)3990     void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
3991 
3992     }
3993 
3994     /**
3995      * Initializes an {@link AccessibilityEvent} with information about
3996      * this View which is the event source. In other words, the source of
3997      * an accessibility event is the view whose state change triggered firing
3998      * the event.
3999      * <p>
4000      * Example: Setting the password property of an event in addition
4001      *          to properties set by the super implementation:
4002      * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4003      *     super.onInitializeAccessibilityEvent(event);
4004      *     event.setPassword(true);
4005      * }</pre>
4006      * <p>
4007      * If an {@link AccessibilityDelegate} has been specified via calling
4008      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4009      * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
4010      * is responsible for handling this call.
4011      * </p>
4012      * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4013      * information to the event, in case the default implementation has basic information to add.
4014      * </p>
4015      * @param event The event to initialize.
4016      *
4017      * @see #sendAccessibilityEvent(int)
4018      * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4019      */
onInitializeAccessibilityEvent(AccessibilityEvent event)4020     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4021         if (mAccessibilityDelegate != null) {
4022             mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
4023         } else {
4024             onInitializeAccessibilityEventInternal(event);
4025         }
4026     }
4027 
4028     /**
4029      * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4030      *
4031      * Note: Called from the default {@link AccessibilityDelegate}.
4032      */
onInitializeAccessibilityEventInternal(AccessibilityEvent event)4033     void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
4034         event.setSource(this);
4035         event.setClassName(getClass().getName());
4036         event.setPackageName(getContext().getPackageName());
4037         event.setEnabled(isEnabled());
4038         event.setContentDescription(mContentDescription);
4039 
4040         if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
4041             ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
4042             getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
4043                     FOCUSABLES_ALL);
4044             event.setItemCount(focusablesTempList.size());
4045             event.setCurrentItemIndex(focusablesTempList.indexOf(this));
4046             focusablesTempList.clear();
4047         }
4048     }
4049 
4050     /**
4051      * Returns an {@link AccessibilityNodeInfo} representing this view from the
4052      * point of view of an {@link android.accessibilityservice.AccessibilityService}.
4053      * This method is responsible for obtaining an accessibility node info from a
4054      * pool of reusable instances and calling
4055      * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
4056      * initialize the former.
4057      * <p>
4058      * Note: The client is responsible for recycling the obtained instance by calling
4059      *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
4060      * </p>
4061      * @return A populated {@link AccessibilityNodeInfo}.
4062      *
4063      * @see AccessibilityNodeInfo
4064      */
createAccessibilityNodeInfo()4065     public AccessibilityNodeInfo createAccessibilityNodeInfo() {
4066         AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
4067         onInitializeAccessibilityNodeInfo(info);
4068         return info;
4069     }
4070 
4071     /**
4072      * Initializes an {@link AccessibilityNodeInfo} with information about this view.
4073      * The base implementation sets:
4074      * <ul>
4075      *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
4076      *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
4077      *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
4078      *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
4079      *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
4080      *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
4081      *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
4082      *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
4083      *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
4084      *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
4085      *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
4086      *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
4087      * </ul>
4088      * <p>
4089      * Subclasses should override this method, call the super implementation,
4090      * and set additional attributes.
4091      * </p>
4092      * <p>
4093      * If an {@link AccessibilityDelegate} has been specified via calling
4094      * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4095      * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
4096      * is responsible for handling this call.
4097      * </p>
4098      *
4099      * @param info The instance to initialize.
4100      */
onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info)4101     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
4102         if (mAccessibilityDelegate != null) {
4103             mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
4104         } else {
4105             onInitializeAccessibilityNodeInfoInternal(info);
4106         }
4107     }
4108 
4109     /**
4110      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
4111      *
4112      * Note: Called from the default {@link AccessibilityDelegate}.
4113      */
onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info)4114     void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
4115         Rect bounds = mAttachInfo.mTmpInvalRect;
4116         getDrawingRect(bounds);
4117         info.setBoundsInParent(bounds);
4118 
4119         int[] locationOnScreen = mAttachInfo.mInvalidateChildLocation;
4120         getLocationOnScreen(locationOnScreen);
4121         bounds.offsetTo(0, 0);
4122         bounds.offset(locationOnScreen[0], locationOnScreen[1]);
4123         info.setBoundsInScreen(bounds);
4124 
4125         ViewParent parent = getParent();
4126         if (parent instanceof View) {
4127             View parentView = (View) parent;
4128             info.setParent(parentView);
4129         }
4130 
4131         info.setPackageName(mContext.getPackageName());
4132         info.setClassName(getClass().getName());
4133         info.setContentDescription(getContentDescription());
4134 
4135         info.setEnabled(isEnabled());
4136         info.setClickable(isClickable());
4137         info.setFocusable(isFocusable());
4138         info.setFocused(isFocused());
4139         info.setSelected(isSelected());
4140         info.setLongClickable(isLongClickable());
4141 
4142         // TODO: These make sense only if we are in an AdapterView but all
4143         // views can be selected. Maybe from accessiiblity perspective
4144         // we should report as selectable view in an AdapterView.
4145         info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
4146         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
4147 
4148         if (isFocusable()) {
4149             if (isFocused()) {
4150                 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
4151             } else {
4152                 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
4153             }
4154         }
4155     }
4156 
4157     /**
4158      * Sets a delegate for implementing accessibility support via compositon as
4159      * opposed to inheritance. The delegate's primary use is for implementing
4160      * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
4161      *
4162      * @param delegate The delegate instance.
4163      *
4164      * @see AccessibilityDelegate
4165      */
setAccessibilityDelegate(AccessibilityDelegate delegate)4166     public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
4167         mAccessibilityDelegate = delegate;
4168     }
4169 
4170     /**
4171      * Gets the unique identifier of this view on the screen for accessibility purposes.
4172      * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
4173      *
4174      * @return The view accessibility id.
4175      *
4176      * @hide
4177      */
getAccessibilityViewId()4178     public int getAccessibilityViewId() {
4179         if (mAccessibilityViewId == NO_ID) {
4180             mAccessibilityViewId = sNextAccessibilityViewId++;
4181         }
4182         return mAccessibilityViewId;
4183     }
4184 
4185     /**
4186      * Gets the unique identifier of the window in which this View reseides.
4187      *
4188      * @return The window accessibility id.
4189      *
4190      * @hide
4191      */
getAccessibilityWindowId()4192     public int getAccessibilityWindowId() {
4193         return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
4194     }
4195 
4196     /**
4197      * Gets the {@link View} description. It briefly describes the view and is
4198      * primarily used for accessibility support. Set this property to enable
4199      * better accessibility support for your application. This is especially
4200      * true for views that do not have textual representation (For example,
4201      * ImageButton).
4202      *
4203      * @return The content descriptiopn.
4204      *
4205      * @attr ref android.R.styleable#View_contentDescription
4206      */
getContentDescription()4207     public CharSequence getContentDescription() {
4208         return mContentDescription;
4209     }
4210 
4211     /**
4212      * Sets the {@link View} description. It briefly describes the view and is
4213      * primarily used for accessibility support. Set this property to enable
4214      * better accessibility support for your application. This is especially
4215      * true for views that do not have textual representation (For example,
4216      * ImageButton).
4217      *
4218      * @param contentDescription The content description.
4219      *
4220      * @attr ref android.R.styleable#View_contentDescription
4221      */
setContentDescription(CharSequence contentDescription)4222     public void setContentDescription(CharSequence contentDescription) {
4223         mContentDescription = contentDescription;
4224     }
4225 
4226     /**
4227      * Invoked whenever this view loses focus, either by losing window focus or by losing
4228      * focus within its window. This method can be used to clear any state tied to the
4229      * focus. For instance, if a button is held pressed with the trackball and the window
4230      * loses focus, this method can be used to cancel the press.
4231      *
4232      * Subclasses of View overriding this method should always call super.onFocusLost().
4233      *
4234      * @see #onFocusChanged(boolean, int, android.graphics.Rect)
4235      * @see #onWindowFocusChanged(boolean)
4236      *
4237      * @hide pending API council approval
4238      */
onFocusLost()4239     protected void onFocusLost() {
4240         resetPressedState();
4241     }
4242 
resetPressedState()4243     private void resetPressedState() {
4244         if ((mViewFlags & ENABLED_MASK) == DISABLED) {
4245             return;
4246         }
4247 
4248         if (isPressed()) {
4249             setPressed(false);
4250 
4251             if (!mHasPerformedLongPress) {
4252                 removeLongPressCallback();
4253             }
4254         }
4255     }
4256 
4257     /**
4258      * Returns true if this view has focus
4259      *
4260      * @return True if this view has focus, false otherwise.
4261      */
4262     @ViewDebug.ExportedProperty(category = "focus")
isFocused()4263     public boolean isFocused() {
4264         return (mPrivateFlags & FOCUSED) != 0;
4265     }
4266 
4267     /**
4268      * Find the view in the hierarchy rooted at this view that currently has
4269      * focus.
4270      *
4271      * @return The view that currently has focus, or null if no focused view can
4272      *         be found.
4273      */
findFocus()4274     public View findFocus() {
4275         return (mPrivateFlags & FOCUSED) != 0 ? this : null;
4276     }
4277 
4278     /**
4279      * Change whether this view is one of the set of scrollable containers in
4280      * its window.  This will be used to determine whether the window can
4281      * resize or must pan when a soft input area is open -- scrollable
4282      * containers allow the window to use resize mode since the container
4283      * will appropriately shrink.
4284      */
setScrollContainer(boolean isScrollContainer)4285     public void setScrollContainer(boolean isScrollContainer) {
4286         if (isScrollContainer) {
4287             if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
4288                 mAttachInfo.mScrollContainers.add(this);
4289                 mPrivateFlags |= SCROLL_CONTAINER_ADDED;
4290             }
4291             mPrivateFlags |= SCROLL_CONTAINER;
4292         } else {
4293             if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
4294                 mAttachInfo.mScrollContainers.remove(this);
4295             }
4296             mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
4297         }
4298     }
4299 
4300     /**
4301      * Returns the quality of the drawing cache.
4302      *
4303      * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
4304      *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
4305      *
4306      * @see #setDrawingCacheQuality(int)
4307      * @see #setDrawingCacheEnabled(boolean)
4308      * @see #isDrawingCacheEnabled()
4309      *
4310      * @attr ref android.R.styleable#View_drawingCacheQuality
4311      */
getDrawingCacheQuality()4312     public int getDrawingCacheQuality() {
4313         return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
4314     }
4315 
4316     /**
4317      * Set the drawing cache quality of this view. This value is used only when the
4318      * drawing cache is enabled
4319      *
4320      * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
4321      *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
4322      *
4323      * @see #getDrawingCacheQuality()
4324      * @see #setDrawingCacheEnabled(boolean)
4325      * @see #isDrawingCacheEnabled()
4326      *
4327      * @attr ref android.R.styleable#View_drawingCacheQuality
4328      */
setDrawingCacheQuality(int quality)4329     public void setDrawingCacheQuality(int quality) {
4330         setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
4331     }
4332 
4333     /**
4334      * Returns whether the screen should remain on, corresponding to the current
4335      * value of {@link #KEEP_SCREEN_ON}.
4336      *
4337      * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
4338      *
4339      * @see #setKeepScreenOn(boolean)
4340      *
4341      * @attr ref android.R.styleable#View_keepScreenOn
4342      */
getKeepScreenOn()4343     public boolean getKeepScreenOn() {
4344         return (mViewFlags & KEEP_SCREEN_ON) != 0;
4345     }
4346 
4347     /**
4348      * Controls whether the screen should remain on, modifying the
4349      * value of {@link #KEEP_SCREEN_ON}.
4350      *
4351      * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
4352      *
4353      * @see #getKeepScreenOn()
4354      *
4355      * @attr ref android.R.styleable#View_keepScreenOn
4356      */
setKeepScreenOn(boolean keepScreenOn)4357     public void setKeepScreenOn(boolean keepScreenOn) {
4358         setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
4359     }
4360 
4361     /**
4362      * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
4363      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4364      *
4365      * @attr ref android.R.styleable#View_nextFocusLeft
4366      */
getNextFocusLeftId()4367     public int getNextFocusLeftId() {
4368         return mNextFocusLeftId;
4369     }
4370 
4371     /**
4372      * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
4373      * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
4374      * decide automatically.
4375      *
4376      * @attr ref android.R.styleable#View_nextFocusLeft
4377      */
setNextFocusLeftId(int nextFocusLeftId)4378     public void setNextFocusLeftId(int nextFocusLeftId) {
4379         mNextFocusLeftId = nextFocusLeftId;
4380     }
4381 
4382     /**
4383      * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
4384      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4385      *
4386      * @attr ref android.R.styleable#View_nextFocusRight
4387      */
getNextFocusRightId()4388     public int getNextFocusRightId() {
4389         return mNextFocusRightId;
4390     }
4391 
4392     /**
4393      * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
4394      * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
4395      * decide automatically.
4396      *
4397      * @attr ref android.R.styleable#View_nextFocusRight
4398      */
setNextFocusRightId(int nextFocusRightId)4399     public void setNextFocusRightId(int nextFocusRightId) {
4400         mNextFocusRightId = nextFocusRightId;
4401     }
4402 
4403     /**
4404      * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
4405      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4406      *
4407      * @attr ref android.R.styleable#View_nextFocusUp
4408      */
getNextFocusUpId()4409     public int getNextFocusUpId() {
4410         return mNextFocusUpId;
4411     }
4412 
4413     /**
4414      * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
4415      * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
4416      * decide automatically.
4417      *
4418      * @attr ref android.R.styleable#View_nextFocusUp
4419      */
setNextFocusUpId(int nextFocusUpId)4420     public void setNextFocusUpId(int nextFocusUpId) {
4421         mNextFocusUpId = nextFocusUpId;
4422     }
4423 
4424     /**
4425      * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
4426      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4427      *
4428      * @attr ref android.R.styleable#View_nextFocusDown
4429      */
getNextFocusDownId()4430     public int getNextFocusDownId() {
4431         return mNextFocusDownId;
4432     }
4433 
4434     /**
4435      * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
4436      * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
4437      * decide automatically.
4438      *
4439      * @attr ref android.R.styleable#View_nextFocusDown
4440      */
setNextFocusDownId(int nextFocusDownId)4441     public void setNextFocusDownId(int nextFocusDownId) {
4442         mNextFocusDownId = nextFocusDownId;
4443     }
4444 
4445     /**
4446      * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
4447      * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4448      *
4449      * @attr ref android.R.styleable#View_nextFocusForward
4450      */
getNextFocusForwardId()4451     public int getNextFocusForwardId() {
4452         return mNextFocusForwardId;
4453     }
4454 
4455     /**
4456      * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
4457      * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
4458      * decide automatically.
4459      *
4460      * @attr ref android.R.styleable#View_nextFocusForward
4461      */
setNextFocusForwardId(int nextFocusForwardId)4462     public void setNextFocusForwardId(int nextFocusForwardId) {
4463         mNextFocusForwardId = nextFocusForwardId;
4464     }
4465 
4466     /**
4467      * Returns the visibility of this view and all of its ancestors
4468      *
4469      * @return True if this view and all of its ancestors are {@link #VISIBLE}
4470      */
isShown()4471     public boolean isShown() {
4472         View current = this;
4473         //noinspection ConstantConditions
4474         do {
4475             if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
4476                 return false;
4477             }
4478             ViewParent parent = current.mParent;
4479             if (parent == null) {
4480                 return false; // We are not attached to the view root
4481             }
4482             if (!(parent instanceof View)) {
4483                 return true;
4484             }
4485             current = (View) parent;
4486         } while (current != null);
4487 
4488         return false;
4489     }
4490 
4491     /**
4492      * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag
4493      * is set
4494      *
4495      * @param insets Insets for system windows
4496      *
4497      * @return True if this view applied the insets, false otherwise
4498      */
fitSystemWindows(Rect insets)4499     protected boolean fitSystemWindows(Rect insets) {
4500         if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
4501             mPaddingLeft = insets.left;
4502             mPaddingTop = insets.top;
4503             mPaddingRight = insets.right;
4504             mPaddingBottom = insets.bottom;
4505             requestLayout();
4506             return true;
4507         }
4508         return false;
4509     }
4510 
4511     /**
4512      * Set whether or not this view should account for system screen decorations
4513      * such as the status bar and inset its content. This allows this view to be
4514      * positioned in absolute screen coordinates and remain visible to the user.
4515      *
4516      * <p>This should only be used by top-level window decor views.
4517      *
4518      * @param fitSystemWindows true to inset content for system screen decorations, false for
4519      *                         default behavior.
4520      *
4521      * @attr ref android.R.styleable#View_fitsSystemWindows
4522      */
setFitsSystemWindows(boolean fitSystemWindows)4523     public void setFitsSystemWindows(boolean fitSystemWindows) {
4524         setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
4525     }
4526 
4527     /**
4528      * Check for the FITS_SYSTEM_WINDOWS flag. If this method returns true, this view
4529      * will account for system screen decorations such as the status bar and inset its
4530      * content. This allows the view to be positioned in absolute screen coordinates
4531      * and remain visible to the user.
4532      *
4533      * @return true if this view will adjust its content bounds for system screen decorations.
4534      *
4535      * @attr ref android.R.styleable#View_fitsSystemWindows
4536      */
fitsSystemWindows()4537     public boolean fitsSystemWindows() {
4538         return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
4539     }
4540 
4541     /**
4542      * Returns the visibility status for this view.
4543      *
4544      * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
4545      * @attr ref android.R.styleable#View_visibility
4546      */
4547     @ViewDebug.ExportedProperty(mapping = {
4548         @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
4549         @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
4550         @ViewDebug.IntToString(from = GONE,      to = "GONE")
4551     })
getVisibility()4552     public int getVisibility() {
4553         return mViewFlags & VISIBILITY_MASK;
4554     }
4555 
4556     /**
4557      * Set the enabled state of this view.
4558      *
4559      * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
4560      * @attr ref android.R.styleable#View_visibility
4561      */
4562     @RemotableViewMethod
setVisibility(int visibility)4563     public void setVisibility(int visibility) {
4564         setFlags(visibility, VISIBILITY_MASK);
4565         if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
4566     }
4567 
4568     /**
4569      * Returns the enabled status for this view. The interpretation of the
4570      * enabled state varies by subclass.
4571      *
4572      * @return True if this view is enabled, false otherwise.
4573      */
4574     @ViewDebug.ExportedProperty
isEnabled()4575     public boolean isEnabled() {
4576         return (mViewFlags & ENABLED_MASK) == ENABLED;
4577     }
4578 
4579     /**
4580      * Set the enabled state of this view. The interpretation of the enabled
4581      * state varies by subclass.
4582      *
4583      * @param enabled True if this view is enabled, false otherwise.
4584      */
4585     @RemotableViewMethod
setEnabled(boolean enabled)4586     public void setEnabled(boolean enabled) {
4587         if (enabled == isEnabled()) return;
4588 
4589         setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
4590 
4591         /*
4592          * The View most likely has to change its appearance, so refresh
4593          * the drawable state.
4594          */
4595         refreshDrawableState();
4596 
4597         // Invalidate too, since the default behavior for views is to be
4598         // be drawn at 50% alpha rather than to change the drawable.
4599         invalidate(true);
4600     }
4601 
4602     /**
4603      * Set whether this view can receive the focus.
4604      *
4605      * Setting this to false will also ensure that this view is not focusable
4606      * in touch mode.
4607      *
4608      * @param focusable If true, this view can receive the focus.
4609      *
4610      * @see #setFocusableInTouchMode(boolean)
4611      * @attr ref android.R.styleable#View_focusable
4612      */
setFocusable(boolean focusable)4613     public void setFocusable(boolean focusable) {
4614         if (!focusable) {
4615             setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
4616         }
4617         setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
4618     }
4619 
4620     /**
4621      * Set whether this view can receive focus while in touch mode.
4622      *
4623      * Setting this to true will also ensure that this view is focusable.
4624      *
4625      * @param focusableInTouchMode If true, this view can receive the focus while
4626      *   in touch mode.
4627      *
4628      * @see #setFocusable(boolean)
4629      * @attr ref android.R.styleable#View_focusableInTouchMode
4630      */
setFocusableInTouchMode(boolean focusableInTouchMode)4631     public void setFocusableInTouchMode(boolean focusableInTouchMode) {
4632         // Focusable in touch mode should always be set before the focusable flag
4633         // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
4634         // which, in touch mode, will not successfully request focus on this view
4635         // because the focusable in touch mode flag is not set
4636         setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
4637         if (focusableInTouchMode) {
4638             setFlags(FOCUSABLE, FOCUSABLE_MASK);
4639         }
4640     }
4641 
4642     /**
4643      * Set whether this view should have sound effects enabled for events such as
4644      * clicking and touching.
4645      *
4646      * <p>You may wish to disable sound effects for a view if you already play sounds,
4647      * for instance, a dial key that plays dtmf tones.
4648      *
4649      * @param soundEffectsEnabled whether sound effects are enabled for this view.
4650      * @see #isSoundEffectsEnabled()
4651      * @see #playSoundEffect(int)
4652      * @attr ref android.R.styleable#View_soundEffectsEnabled
4653      */
setSoundEffectsEnabled(boolean soundEffectsEnabled)4654     public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
4655         setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
4656     }
4657 
4658     /**
4659      * @return whether this view should have sound effects enabled for events such as
4660      *     clicking and touching.
4661      *
4662      * @see #setSoundEffectsEnabled(boolean)
4663      * @see #playSoundEffect(int)
4664      * @attr ref android.R.styleable#View_soundEffectsEnabled
4665      */
4666     @ViewDebug.ExportedProperty
isSoundEffectsEnabled()4667     public boolean isSoundEffectsEnabled() {
4668         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
4669     }
4670 
4671     /**
4672      * Set whether this view should have haptic feedback for events such as
4673      * long presses.
4674      *
4675      * <p>You may wish to disable haptic feedback if your view already controls
4676      * its own haptic feedback.
4677      *
4678      * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
4679      * @see #isHapticFeedbackEnabled()
4680      * @see #performHapticFeedback(int)
4681      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
4682      */
setHapticFeedbackEnabled(boolean hapticFeedbackEnabled)4683     public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
4684         setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
4685     }
4686 
4687     /**
4688      * @return whether this view should have haptic feedback enabled for events
4689      * long presses.
4690      *
4691      * @see #setHapticFeedbackEnabled(boolean)
4692      * @see #performHapticFeedback(int)
4693      * @attr ref android.R.styleable#View_hapticFeedbackEnabled
4694      */
4695     @ViewDebug.ExportedProperty
isHapticFeedbackEnabled()4696     public boolean isHapticFeedbackEnabled() {
4697         return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
4698     }
4699 
4700     /**
4701      * Returns the layout direction for this view.
4702      *
4703      * @return One of {@link #LAYOUT_DIRECTION_LTR},
4704      *   {@link #LAYOUT_DIRECTION_RTL},
4705      *   {@link #LAYOUT_DIRECTION_INHERIT} or
4706      *   {@link #LAYOUT_DIRECTION_LOCALE}.
4707      * @attr ref android.R.styleable#View_layoutDirection
4708      *
4709      * @hide
4710      */
4711     @ViewDebug.ExportedProperty(category = "layout", mapping = {
4712         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
4713         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
4714         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
4715         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
4716     })
getLayoutDirection()4717     public int getLayoutDirection() {
4718         return mViewFlags & LAYOUT_DIRECTION_MASK;
4719     }
4720 
4721     /**
4722      * Set the layout direction for this view. This will propagate a reset of layout direction
4723      * resolution to the view's children and resolve layout direction for this view.
4724      *
4725      * @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR},
4726      *   {@link #LAYOUT_DIRECTION_RTL},
4727      *   {@link #LAYOUT_DIRECTION_INHERIT} or
4728      *   {@link #LAYOUT_DIRECTION_LOCALE}.
4729      *
4730      * @attr ref android.R.styleable#View_layoutDirection
4731      *
4732      * @hide
4733      */
4734     @RemotableViewMethod
setLayoutDirection(int layoutDirection)4735     public void setLayoutDirection(int layoutDirection) {
4736         if (getLayoutDirection() != layoutDirection) {
4737             resetResolvedLayoutDirection();
4738             // Setting the flag will also request a layout.
4739             setFlags(layoutDirection, LAYOUT_DIRECTION_MASK);
4740         }
4741     }
4742 
4743     /**
4744      * Returns the resolved layout direction for this view.
4745      *
4746      * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
4747      * {@link #LAYOUT_DIRECTION_LTR} id the layout direction is not RTL.
4748      *
4749      * @hide
4750      */
4751     @ViewDebug.ExportedProperty(category = "layout", mapping = {
4752         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "RESOLVED_DIRECTION_LTR"),
4753         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RESOLVED_DIRECTION_RTL")
4754     })
getResolvedLayoutDirection()4755     public int getResolvedLayoutDirection() {
4756         resolveLayoutDirectionIfNeeded();
4757         return ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED_RTL) == LAYOUT_DIRECTION_RESOLVED_RTL) ?
4758                 LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
4759     }
4760 
4761     /**
4762      * <p>Indicates whether or not this view's layout is right-to-left. This is resolved from
4763      * layout attribute and/or the inherited value from the parent.</p>
4764      *
4765      * @return true if the layout is right-to-left.
4766      *
4767      * @hide
4768      */
4769     @ViewDebug.ExportedProperty(category = "layout")
isLayoutRtl()4770     public boolean isLayoutRtl() {
4771         return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
4772     }
4773 
4774     /**
4775      * If this view doesn't do any drawing on its own, set this flag to
4776      * allow further optimizations. By default, this flag is not set on
4777      * View, but could be set on some View subclasses such as ViewGroup.
4778      *
4779      * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
4780      * you should clear this flag.
4781      *
4782      * @param willNotDraw whether or not this View draw on its own
4783      */
setWillNotDraw(boolean willNotDraw)4784     public void setWillNotDraw(boolean willNotDraw) {
4785         setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
4786     }
4787 
4788     /**
4789      * Returns whether or not this View draws on its own.
4790      *
4791      * @return true if this view has nothing to draw, false otherwise
4792      */
4793     @ViewDebug.ExportedProperty(category = "drawing")
willNotDraw()4794     public boolean willNotDraw() {
4795         return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
4796     }
4797 
4798     /**
4799      * When a View's drawing cache is enabled, drawing is redirected to an
4800      * offscreen bitmap. Some views, like an ImageView, must be able to
4801      * bypass this mechanism if they already draw a single bitmap, to avoid
4802      * unnecessary usage of the memory.
4803      *
4804      * @param willNotCacheDrawing true if this view does not cache its
4805      *        drawing, false otherwise
4806      */
setWillNotCacheDrawing(boolean willNotCacheDrawing)4807     public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
4808         setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
4809     }
4810 
4811     /**
4812      * Returns whether or not this View can cache its drawing or not.
4813      *
4814      * @return true if this view does not cache its drawing, false otherwise
4815      */
4816     @ViewDebug.ExportedProperty(category = "drawing")
willNotCacheDrawing()4817     public boolean willNotCacheDrawing() {
4818         return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
4819     }
4820 
4821     /**
4822      * Indicates whether this view reacts to click events or not.
4823      *
4824      * @return true if the view is clickable, false otherwise
4825      *
4826      * @see #setClickable(boolean)
4827      * @attr ref android.R.styleable#View_clickable
4828      */
4829     @ViewDebug.ExportedProperty
isClickable()4830     public boolean isClickable() {
4831         return (mViewFlags & CLICKABLE) == CLICKABLE;
4832     }
4833 
4834     /**
4835      * Enables or disables click events for this view. When a view
4836      * is clickable it will change its state to "pressed" on every click.
4837      * Subclasses should set the view clickable to visually react to
4838      * user's clicks.
4839      *
4840      * @param clickable true to make the view clickable, false otherwise
4841      *
4842      * @see #isClickable()
4843      * @attr ref android.R.styleable#View_clickable
4844      */
setClickable(boolean clickable)4845     public void setClickable(boolean clickable) {
4846         setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
4847     }
4848 
4849     /**
4850      * Indicates whether this view reacts to long click events or not.
4851      *
4852      * @return true if the view is long clickable, false otherwise
4853      *
4854      * @see #setLongClickable(boolean)
4855      * @attr ref android.R.styleable#View_longClickable
4856      */
isLongClickable()4857     public boolean isLongClickable() {
4858         return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
4859     }
4860 
4861     /**
4862      * Enables or disables long click events for this view. When a view is long
4863      * clickable it reacts to the user holding down the button for a longer
4864      * duration than a tap. This event can either launch the listener or a
4865      * context menu.
4866      *
4867      * @param longClickable true to make the view long clickable, false otherwise
4868      * @see #isLongClickable()
4869      * @attr ref android.R.styleable#View_longClickable
4870      */
setLongClickable(boolean longClickable)4871     public void setLongClickable(boolean longClickable) {
4872         setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
4873     }
4874 
4875     /**
4876      * Sets the pressed state for this view.
4877      *
4878      * @see #isClickable()
4879      * @see #setClickable(boolean)
4880      *
4881      * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
4882      *        the View's internal state from a previously set "pressed" state.
4883      */
setPressed(boolean pressed)4884     public void setPressed(boolean pressed) {
4885         if (pressed) {
4886             mPrivateFlags |= PRESSED;
4887         } else {
4888             mPrivateFlags &= ~PRESSED;
4889         }
4890         refreshDrawableState();
4891         dispatchSetPressed(pressed);
4892     }
4893 
4894     /**
4895      * Dispatch setPressed to all of this View's children.
4896      *
4897      * @see #setPressed(boolean)
4898      *
4899      * @param pressed The new pressed state
4900      */
dispatchSetPressed(boolean pressed)4901     protected void dispatchSetPressed(boolean pressed) {
4902     }
4903 
4904     /**
4905      * Indicates whether the view is currently in pressed state. Unless
4906      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
4907      * the pressed state.
4908      *
4909      * @see #setPressed(boolean)
4910      * @see #isClickable()
4911      * @see #setClickable(boolean)
4912      *
4913      * @return true if the view is currently pressed, false otherwise
4914      */
isPressed()4915     public boolean isPressed() {
4916         return (mPrivateFlags & PRESSED) == PRESSED;
4917     }
4918 
4919     /**
4920      * Indicates whether this view will save its state (that is,
4921      * whether its {@link #onSaveInstanceState} method will be called).
4922      *
4923      * @return Returns true if the view state saving is enabled, else false.
4924      *
4925      * @see #setSaveEnabled(boolean)
4926      * @attr ref android.R.styleable#View_saveEnabled
4927      */
isSaveEnabled()4928     public boolean isSaveEnabled() {
4929         return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
4930     }
4931 
4932     /**
4933      * Controls whether the saving of this view's state is
4934      * enabled (that is, whether its {@link #onSaveInstanceState} method
4935      * will be called).  Note that even if freezing is enabled, the
4936      * view still must have an id assigned to it (via {@link #setId(int)})
4937      * for its state to be saved.  This flag can only disable the
4938      * saving of this view; any child views may still have their state saved.
4939      *
4940      * @param enabled Set to false to <em>disable</em> state saving, or true
4941      * (the default) to allow it.
4942      *
4943      * @see #isSaveEnabled()
4944      * @see #setId(int)
4945      * @see #onSaveInstanceState()
4946      * @attr ref android.R.styleable#View_saveEnabled
4947      */
setSaveEnabled(boolean enabled)4948     public void setSaveEnabled(boolean enabled) {
4949         setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
4950     }
4951 
4952     /**
4953      * Gets whether the framework should discard touches when the view's
4954      * window is obscured by another visible window.
4955      * Refer to the {@link View} security documentation for more details.
4956      *
4957      * @return True if touch filtering is enabled.
4958      *
4959      * @see #setFilterTouchesWhenObscured(boolean)
4960      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
4961      */
4962     @ViewDebug.ExportedProperty
getFilterTouchesWhenObscured()4963     public boolean getFilterTouchesWhenObscured() {
4964         return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
4965     }
4966 
4967     /**
4968      * Sets whether the framework should discard touches when the view's
4969      * window is obscured by another visible window.
4970      * Refer to the {@link View} security documentation for more details.
4971      *
4972      * @param enabled True if touch filtering should be enabled.
4973      *
4974      * @see #getFilterTouchesWhenObscured
4975      * @attr ref android.R.styleable#View_filterTouchesWhenObscured
4976      */
setFilterTouchesWhenObscured(boolean enabled)4977     public void setFilterTouchesWhenObscured(boolean enabled) {
4978         setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
4979                 FILTER_TOUCHES_WHEN_OBSCURED);
4980     }
4981 
4982     /**
4983      * Indicates whether the entire hierarchy under this view will save its
4984      * state when a state saving traversal occurs from its parent.  The default
4985      * is true; if false, these views will not be saved unless
4986      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
4987      *
4988      * @return Returns true if the view state saving from parent is enabled, else false.
4989      *
4990      * @see #setSaveFromParentEnabled(boolean)
4991      */
isSaveFromParentEnabled()4992     public boolean isSaveFromParentEnabled() {
4993         return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
4994     }
4995 
4996     /**
4997      * Controls whether the entire hierarchy under this view will save its
4998      * state when a state saving traversal occurs from its parent.  The default
4999      * is true; if false, these views will not be saved unless
5000      * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
5001      *
5002      * @param enabled Set to false to <em>disable</em> state saving, or true
5003      * (the default) to allow it.
5004      *
5005      * @see #isSaveFromParentEnabled()
5006      * @see #setId(int)
5007      * @see #onSaveInstanceState()
5008      */
setSaveFromParentEnabled(boolean enabled)5009     public void setSaveFromParentEnabled(boolean enabled) {
5010         setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
5011     }
5012 
5013 
5014     /**
5015      * Returns whether this View is able to take focus.
5016      *
5017      * @return True if this view can take focus, or false otherwise.
5018      * @attr ref android.R.styleable#View_focusable
5019      */
5020     @ViewDebug.ExportedProperty(category = "focus")
isFocusable()5021     public final boolean isFocusable() {
5022         return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
5023     }
5024 
5025     /**
5026      * When a view is focusable, it may not want to take focus when in touch mode.
5027      * For example, a button would like focus when the user is navigating via a D-pad
5028      * so that the user can click on it, but once the user starts touching the screen,
5029      * the button shouldn't take focus
5030      * @return Whether the view is focusable in touch mode.
5031      * @attr ref android.R.styleable#View_focusableInTouchMode
5032      */
5033     @ViewDebug.ExportedProperty
isFocusableInTouchMode()5034     public final boolean isFocusableInTouchMode() {
5035         return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
5036     }
5037 
5038     /**
5039      * Find the nearest view in the specified direction that can take focus.
5040      * This does not actually give focus to that view.
5041      *
5042      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5043      *
5044      * @return The nearest focusable in the specified direction, or null if none
5045      *         can be found.
5046      */
focusSearch(int direction)5047     public View focusSearch(int direction) {
5048         if (mParent != null) {
5049             return mParent.focusSearch(this, direction);
5050         } else {
5051             return null;
5052         }
5053     }
5054 
5055     /**
5056      * This method is the last chance for the focused view and its ancestors to
5057      * respond to an arrow key. This is called when the focused view did not
5058      * consume the key internally, nor could the view system find a new view in
5059      * the requested direction to give focus to.
5060      *
5061      * @param focused The currently focused view.
5062      * @param direction The direction focus wants to move. One of FOCUS_UP,
5063      *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
5064      * @return True if the this view consumed this unhandled move.
5065      */
dispatchUnhandledMove(View focused, int direction)5066     public boolean dispatchUnhandledMove(View focused, int direction) {
5067         return false;
5068     }
5069 
5070     /**
5071      * If a user manually specified the next view id for a particular direction,
5072      * use the root to look up the view.
5073      * @param root The root view of the hierarchy containing this view.
5074      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
5075      * or FOCUS_BACKWARD.
5076      * @return The user specified next view, or null if there is none.
5077      */
findUserSetNextFocus(View root, int direction)5078     View findUserSetNextFocus(View root, int direction) {
5079         switch (direction) {
5080             case FOCUS_LEFT:
5081                 if (mNextFocusLeftId == View.NO_ID) return null;
5082                 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
5083             case FOCUS_RIGHT:
5084                 if (mNextFocusRightId == View.NO_ID) return null;
5085                 return findViewInsideOutShouldExist(root, mNextFocusRightId);
5086             case FOCUS_UP:
5087                 if (mNextFocusUpId == View.NO_ID) return null;
5088                 return findViewInsideOutShouldExist(root, mNextFocusUpId);
5089             case FOCUS_DOWN:
5090                 if (mNextFocusDownId == View.NO_ID) return null;
5091                 return findViewInsideOutShouldExist(root, mNextFocusDownId);
5092             case FOCUS_FORWARD:
5093                 if (mNextFocusForwardId == View.NO_ID) return null;
5094                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
5095             case FOCUS_BACKWARD: {
5096                 final int id = mID;
5097                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
5098                     @Override
5099                     public boolean apply(View t) {
5100                         return t.mNextFocusForwardId == id;
5101                     }
5102                 });
5103             }
5104         }
5105         return null;
5106     }
5107 
5108     private View findViewInsideOutShouldExist(View root, final int childViewId) {
5109         View result = root.findViewByPredicateInsideOut(this, new Predicate<View>() {
5110             @Override
5111             public boolean apply(View t) {
5112                 return t.mID == childViewId;
5113             }
5114         });
5115 
5116         if (result == null) {
5117             Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
5118                     + "by user for id " + childViewId);
5119         }
5120         return result;
5121     }
5122 
5123     /**
5124      * Find and return all focusable views that are descendants of this view,
5125      * possibly including this view if it is focusable itself.
5126      *
5127      * @param direction The direction of the focus
5128      * @return A list of focusable views
5129      */
5130     public ArrayList<View> getFocusables(int direction) {
5131         ArrayList<View> result = new ArrayList<View>(24);
5132         addFocusables(result, direction);
5133         return result;
5134     }
5135 
5136     /**
5137      * Add any focusable views that are descendants of this view (possibly
5138      * including this view if it is focusable itself) to views.  If we are in touch mode,
5139      * only add views that are also focusable in touch mode.
5140      *
5141      * @param views Focusable views found so far
5142      * @param direction The direction of the focus
5143      */
5144     public void addFocusables(ArrayList<View> views, int direction) {
5145         addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
5146     }
5147 
5148     /**
5149      * Adds any focusable views that are descendants of this view (possibly
5150      * including this view if it is focusable itself) to views. This method
5151      * adds all focusable views regardless if we are in touch mode or
5152      * only views focusable in touch mode if we are in touch mode depending on
5153      * the focusable mode paramater.
5154      *
5155      * @param views Focusable views found so far or null if all we are interested is
5156      *        the number of focusables.
5157      * @param direction The direction of the focus.
5158      * @param focusableMode The type of focusables to be added.
5159      *
5160      * @see #FOCUSABLES_ALL
5161      * @see #FOCUSABLES_TOUCH_MODE
5162      */
5163     public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
5164         if (!isFocusable()) {
5165             return;
5166         }
5167 
5168         if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE &&
5169                 isInTouchMode() && !isFocusableInTouchMode()) {
5170             return;
5171         }
5172 
5173         if (views != null) {
5174             views.add(this);
5175         }
5176     }
5177 
5178     /**
5179      * Finds the Views that contain given text. The containment is case insensitive.
5180      * The search is performed by either the text that the View renders or the content
5181      * description that describes the view for accessibility purposes and the view does
5182      * not render or both. Clients can specify how the search is to be performed via
5183      * passing the {@link #FIND_VIEWS_WITH_TEXT} and
5184      * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
5185      *
5186      * @param outViews The output list of matching Views.
5187      * @param searched The text to match against.
5188      *
5189      * @see #FIND_VIEWS_WITH_TEXT
5190      * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
5191      * @see #setContentDescription(CharSequence)
5192      */
5193     public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
5194         if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0 && !TextUtils.isEmpty(searched)
5195                 && !TextUtils.isEmpty(mContentDescription)) {
5196             String searchedLowerCase = searched.toString().toLowerCase();
5197             String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
5198             if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
5199                 outViews.add(this);
5200             }
5201         }
5202     }
5203 
5204     /**
5205      * Find and return all touchable views that are descendants of this view,
5206      * possibly including this view if it is touchable itself.
5207      *
5208      * @return A list of touchable views
5209      */
5210     public ArrayList<View> getTouchables() {
5211         ArrayList<View> result = new ArrayList<View>();
5212         addTouchables(result);
5213         return result;
5214     }
5215 
5216     /**
5217      * Add any touchable views that are descendants of this view (possibly
5218      * including this view if it is touchable itself) to views.
5219      *
5220      * @param views Touchable views found so far
5221      */
5222     public void addTouchables(ArrayList<View> views) {
5223         final int viewFlags = mViewFlags;
5224 
5225         if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
5226                 && (viewFlags & ENABLED_MASK) == ENABLED) {
5227             views.add(this);
5228         }
5229     }
5230 
5231     /**
5232      * Call this to try to give focus to a specific view or to one of its
5233      * descendants.
5234      *
5235      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
5236      * false), or if it is focusable and it is not focusable in touch mode
5237      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
5238      *
5239      * See also {@link #focusSearch(int)}, which is what you call to say that you
5240      * have focus, and you want your parent to look for the next one.
5241      *
5242      * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
5243      * {@link #FOCUS_DOWN} and <code>null</code>.
5244      *
5245      * @return Whether this view or one of its descendants actually took focus.
5246      */
5247     public final boolean requestFocus() {
5248         return requestFocus(View.FOCUS_DOWN);
5249     }
5250 
5251 
5252     /**
5253      * Call this to try to give focus to a specific view or to one of its
5254      * descendants and give it a hint about what direction focus is heading.
5255      *
5256      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
5257      * false), or if it is focusable and it is not focusable in touch mode
5258      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
5259      *
5260      * See also {@link #focusSearch(int)}, which is what you call to say that you
5261      * have focus, and you want your parent to look for the next one.
5262      *
5263      * This is equivalent to calling {@link #requestFocus(int, Rect)} with
5264      * <code>null</code> set for the previously focused rectangle.
5265      *
5266      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5267      * @return Whether this view or one of its descendants actually took focus.
5268      */
5269     public final boolean requestFocus(int direction) {
5270         return requestFocus(direction, null);
5271     }
5272 
5273     /**
5274      * Call this to try to give focus to a specific view or to one of its descendants
5275      * and give it hints about the direction and a specific rectangle that the focus
5276      * is coming from.  The rectangle can help give larger views a finer grained hint
5277      * about where focus is coming from, and therefore, where to show selection, or
5278      * forward focus change internally.
5279      *
5280      * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
5281      * false), or if it is focusable and it is not focusable in touch mode
5282      * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
5283      *
5284      * A View will not take focus if it is not visible.
5285      *
5286      * A View will not take focus if one of its parents has
5287      * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
5288      * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
5289      *
5290      * See also {@link #focusSearch(int)}, which is what you call to say that you
5291      * have focus, and you want your parent to look for the next one.
5292      *
5293      * You may wish to override this method if your custom {@link View} has an internal
5294      * {@link View} that it wishes to forward the request to.
5295      *
5296      * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5297      * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
5298      *        to give a finer grained hint about where focus is coming from.  May be null
5299      *        if there is no hint.
5300      * @return Whether this view or one of its descendants actually took focus.
5301      */
5302     public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
5303         // need to be focusable
5304         if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
5305                 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
5306             return false;
5307         }
5308 
5309         // need to be focusable in touch mode if in touch mode
5310         if (isInTouchMode() &&
5311             (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
5312                return false;
5313         }
5314 
5315         // need to not have any parents blocking us
5316         if (hasAncestorThatBlocksDescendantFocus()) {
5317             return false;
5318         }
5319 
5320         handleFocusGainInternal(direction, previouslyFocusedRect);
5321         return true;
5322     }
5323 
5324     /** Gets the ViewAncestor, or null if not attached. */
5325     /*package*/ ViewRootImpl getViewRootImpl() {
5326         View root = getRootView();
5327         return root != null ? (ViewRootImpl)root.getParent() : null;
5328     }
5329 
5330     /**
5331      * Call this to try to give focus to a specific view or to one of its descendants. This is a
5332      * special variant of {@link #requestFocus() } that will allow views that are not focuable in
5333      * touch mode to request focus when they are touched.
5334      *
5335      * @return Whether this view or one of its descendants actually took focus.
5336      *
5337      * @see #isInTouchMode()
5338      *
5339      */
5340     public final boolean requestFocusFromTouch() {
5341         // Leave touch mode if we need to
5342         if (isInTouchMode()) {
5343             ViewRootImpl viewRoot = getViewRootImpl();
5344             if (viewRoot != null) {
5345                 viewRoot.ensureTouchMode(false);
5346             }
5347         }
5348         return requestFocus(View.FOCUS_DOWN);
5349     }
5350 
5351     /**
5352      * @return Whether any ancestor of this view blocks descendant focus.
5353      */
5354     private boolean hasAncestorThatBlocksDescendantFocus() {
5355         ViewParent ancestor = mParent;
5356         while (ancestor instanceof ViewGroup) {
5357             final ViewGroup vgAncestor = (ViewGroup) ancestor;
5358             if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
5359                 return true;
5360             } else {
5361                 ancestor = vgAncestor.getParent();
5362             }
5363         }
5364         return false;
5365     }
5366 
5367     /**
5368      * @hide
5369      */
5370     public void dispatchStartTemporaryDetach() {
5371         onStartTemporaryDetach();
5372     }
5373 
5374     /**
5375      * This is called when a container is going to temporarily detach a child, with
5376      * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
5377      * It will either be followed by {@link #onFinishTemporaryDetach()} or
5378      * {@link #onDetachedFromWindow()} when the container is done.
5379      */
5380     public void onStartTemporaryDetach() {
5381         removeUnsetPressCallback();
5382         mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
5383     }
5384 
5385     /**
5386      * @hide
5387      */
5388     public void dispatchFinishTemporaryDetach() {
5389         onFinishTemporaryDetach();
5390     }
5391 
5392     /**
5393      * Called after {@link #onStartTemporaryDetach} when the container is done
5394      * changing the view.
5395      */
5396     public void onFinishTemporaryDetach() {
5397     }
5398 
5399     /**
5400      * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
5401      * for this view's window.  Returns null if the view is not currently attached
5402      * to the window.  Normally you will not need to use this directly, but
5403      * just use the standard high-level event callbacks like
5404      * {@link #onKeyDown(int, KeyEvent)}.
5405      */
5406     public KeyEvent.DispatcherState getKeyDispatcherState() {
5407         return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
5408     }
5409 
5410     /**
5411      * Dispatch a key event before it is processed by any input method
5412      * associated with the view hierarchy.  This can be used to intercept
5413      * key events in special situations before the IME consumes them; a
5414      * typical example would be handling the BACK key to update the application's
5415      * UI instead of allowing the IME to see it and close itself.
5416      *
5417      * @param event The key event to be dispatched.
5418      * @return True if the event was handled, false otherwise.
5419      */
5420     public boolean dispatchKeyEventPreIme(KeyEvent event) {
5421         return onKeyPreIme(event.getKeyCode(), event);
5422     }
5423 
5424     /**
5425      * Dispatch a key event to the next view on the focus path. This path runs
5426      * from the top of the view tree down to the currently focused view. If this
5427      * view has focus, it will dispatch to itself. Otherwise it will dispatch
5428      * the next node down the focus path. This method also fires any key
5429      * listeners.
5430      *
5431      * @param event The key event to be dispatched.
5432      * @return True if the event was handled, false otherwise.
5433      */
5434     public boolean dispatchKeyEvent(KeyEvent event) {
5435         if (mInputEventConsistencyVerifier != null) {
5436             mInputEventConsistencyVerifier.onKeyEvent(event, 0);
5437         }
5438 
5439         // Give any attached key listener a first crack at the event.
5440         //noinspection SimplifiableIfStatement
5441         if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
5442                 && mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
5443             return true;
5444         }
5445 
5446         if (event.dispatch(this, mAttachInfo != null
5447                 ? mAttachInfo.mKeyDispatchState : null, this)) {
5448             return true;
5449         }
5450 
5451         if (mInputEventConsistencyVerifier != null) {
5452             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5453         }
5454         return false;
5455     }
5456 
5457     /**
5458      * Dispatches a key shortcut event.
5459      *
5460      * @param event The key event to be dispatched.
5461      * @return True if the event was handled by the view, false otherwise.
5462      */
5463     public boolean dispatchKeyShortcutEvent(KeyEvent event) {
5464         return onKeyShortcut(event.getKeyCode(), event);
5465     }
5466 
5467     /**
5468      * Pass the touch screen motion event down to the target view, or this
5469      * view if it is the target.
5470      *
5471      * @param event The motion event to be dispatched.
5472      * @return True if the event was handled by the view, false otherwise.
5473      */
5474     public boolean dispatchTouchEvent(MotionEvent event) {
5475         if (mInputEventConsistencyVerifier != null) {
5476             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
5477         }
5478 
5479         if (onFilterTouchEventForSecurity(event)) {
5480             //noinspection SimplifiableIfStatement
5481             if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
5482                     mOnTouchListener.onTouch(this, event)) {
5483                 return true;
5484             }
5485 
5486             if (onTouchEvent(event)) {
5487                 return true;
5488             }
5489         }
5490 
5491         if (mInputEventConsistencyVerifier != null) {
5492             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5493         }
5494         return false;
5495     }
5496 
5497     /**
5498      * Filter the touch event to apply security policies.
5499      *
5500      * @param event The motion event to be filtered.
5501      * @return True if the event should be dispatched, false if the event should be dropped.
5502      *
5503      * @see #getFilterTouchesWhenObscured
5504      */
5505     public boolean onFilterTouchEventForSecurity(MotionEvent event) {
5506         //noinspection RedundantIfStatement
5507         if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
5508                 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
5509             // Window is obscured, drop this touch.
5510             return false;
5511         }
5512         return true;
5513     }
5514 
5515     /**
5516      * Pass a trackball motion event down to the focused view.
5517      *
5518      * @param event The motion event to be dispatched.
5519      * @return True if the event was handled by the view, false otherwise.
5520      */
5521     public boolean dispatchTrackballEvent(MotionEvent event) {
5522         if (mInputEventConsistencyVerifier != null) {
5523             mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
5524         }
5525 
5526         return onTrackballEvent(event);
5527     }
5528 
5529     /**
5530      * Dispatch a generic motion event.
5531      * <p>
5532      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
5533      * are delivered to the view under the pointer.  All other generic motion events are
5534      * delivered to the focused view.  Hover events are handled specially and are delivered
5535      * to {@link #onHoverEvent(MotionEvent)}.
5536      * </p>
5537      *
5538      * @param event The motion event to be dispatched.
5539      * @return True if the event was handled by the view, false otherwise.
5540      */
5541     public boolean dispatchGenericMotionEvent(MotionEvent event) {
5542         if (mInputEventConsistencyVerifier != null) {
5543             mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
5544         }
5545 
5546         final int source = event.getSource();
5547         if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
5548             final int action = event.getAction();
5549             if (action == MotionEvent.ACTION_HOVER_ENTER
5550                     || action == MotionEvent.ACTION_HOVER_MOVE
5551                     || action == MotionEvent.ACTION_HOVER_EXIT) {
5552                 if (dispatchHoverEvent(event)) {
5553                     return true;
5554                 }
5555             } else if (dispatchGenericPointerEvent(event)) {
5556                 return true;
5557             }
5558         } else if (dispatchGenericFocusedEvent(event)) {
5559             return true;
5560         }
5561 
5562         if (dispatchGenericMotionEventInternal(event)) {
5563             return true;
5564         }
5565 
5566         if (mInputEventConsistencyVerifier != null) {
5567             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5568         }
5569         return false;
5570     }
5571 
5572     private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
5573         //noinspection SimplifiableIfStatement
5574         if (mOnGenericMotionListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
5575                 && mOnGenericMotionListener.onGenericMotion(this, event)) {
5576             return true;
5577         }
5578 
5579         if (onGenericMotionEvent(event)) {
5580             return true;
5581         }
5582 
5583         if (mInputEventConsistencyVerifier != null) {
5584             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5585         }
5586         return false;
5587     }
5588 
5589     /**
5590      * Dispatch a hover event.
5591      * <p>
5592      * Do not call this method directly.
5593      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
5594      * </p>
5595      *
5596      * @param event The motion event to be dispatched.
5597      * @return True if the event was handled by the view, false otherwise.
5598      */
5599     protected boolean dispatchHoverEvent(MotionEvent event) {
5600         //noinspection SimplifiableIfStatement
5601         if (mOnHoverListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
5602                 && mOnHoverListener.onHover(this, event)) {
5603             return true;
5604         }
5605 
5606         return onHoverEvent(event);
5607     }
5608 
5609     /**
5610      * Returns true if the view has a child to which it has recently sent
5611      * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
5612      * it does not have a hovered child, then it must be the innermost hovered view.
5613      * @hide
5614      */
5615     protected boolean hasHoveredChild() {
5616         return false;
5617     }
5618 
5619     /**
5620      * Dispatch a generic motion event to the view under the first pointer.
5621      * <p>
5622      * Do not call this method directly.
5623      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
5624      * </p>
5625      *
5626      * @param event The motion event to be dispatched.
5627      * @return True if the event was handled by the view, false otherwise.
5628      */
5629     protected boolean dispatchGenericPointerEvent(MotionEvent event) {
5630         return false;
5631     }
5632 
5633     /**
5634      * Dispatch a generic motion event to the currently focused view.
5635      * <p>
5636      * Do not call this method directly.
5637      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
5638      * </p>
5639      *
5640      * @param event The motion event to be dispatched.
5641      * @return True if the event was handled by the view, false otherwise.
5642      */
5643     protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
5644         return false;
5645     }
5646 
5647     /**
5648      * Dispatch a pointer event.
5649      * <p>
5650      * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
5651      * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
5652      * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
5653      * and should not be expected to handle other pointing device features.
5654      * </p>
5655      *
5656      * @param event The motion event to be dispatched.
5657      * @return True if the event was handled by the view, false otherwise.
5658      * @hide
5659      */
5660     public final boolean dispatchPointerEvent(MotionEvent event) {
5661         if (event.isTouchEvent()) {
5662             return dispatchTouchEvent(event);
5663         } else {
5664             return dispatchGenericMotionEvent(event);
5665         }
5666     }
5667 
5668     /**
5669      * Called when the window containing this view gains or loses window focus.
5670      * ViewGroups should override to route to their children.
5671      *
5672      * @param hasFocus True if the window containing this view now has focus,
5673      *        false otherwise.
5674      */
5675     public void dispatchWindowFocusChanged(boolean hasFocus) {
5676         onWindowFocusChanged(hasFocus);
5677     }
5678 
5679     /**
5680      * Called when the window containing this view gains or loses focus.  Note
5681      * that this is separate from view focus: to receive key events, both
5682      * your view and its window must have focus.  If a window is displayed
5683      * on top of yours that takes input focus, then your own window will lose
5684      * focus but the view focus will remain unchanged.
5685      *
5686      * @param hasWindowFocus True if the window containing this view now has
5687      *        focus, false otherwise.
5688      */
5689     public void onWindowFocusChanged(boolean hasWindowFocus) {
5690         InputMethodManager imm = InputMethodManager.peekInstance();
5691         if (!hasWindowFocus) {
5692             if (isPressed()) {
5693                 setPressed(false);
5694             }
5695             if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
5696                 imm.focusOut(this);
5697             }
5698             removeLongPressCallback();
5699             removeTapCallback();
5700             onFocusLost();
5701         } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
5702             imm.focusIn(this);
5703         }
5704         refreshDrawableState();
5705     }
5706 
5707     /**
5708      * Returns true if this view is in a window that currently has window focus.
5709      * Note that this is not the same as the view itself having focus.
5710      *
5711      * @return True if this view is in a window that currently has window focus.
5712      */
5713     public boolean hasWindowFocus() {
5714         return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
5715     }
5716 
5717     /**
5718      * Dispatch a view visibility change down the view hierarchy.
5719      * ViewGroups should override to route to their children.
5720      * @param changedView The view whose visibility changed. Could be 'this' or
5721      * an ancestor view.
5722      * @param visibility The new visibility of changedView: {@link #VISIBLE},
5723      * {@link #INVISIBLE} or {@link #GONE}.
5724      */
5725     protected void dispatchVisibilityChanged(View changedView, int visibility) {
5726         onVisibilityChanged(changedView, visibility);
5727     }
5728 
5729     /**
5730      * Called when the visibility of the view or an ancestor of the view is changed.
5731      * @param changedView The view whose visibility changed. Could be 'this' or
5732      * an ancestor view.
5733      * @param visibility The new visibility of changedView: {@link #VISIBLE},
5734      * {@link #INVISIBLE} or {@link #GONE}.
5735      */
5736     protected void onVisibilityChanged(View changedView, int visibility) {
5737         if (visibility == VISIBLE) {
5738             if (mAttachInfo != null) {
5739                 initialAwakenScrollBars();
5740             } else {
5741                 mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
5742             }
5743         }
5744     }
5745 
5746     /**
5747      * Dispatch a hint about whether this view is displayed. For instance, when
5748      * a View moves out of the screen, it might receives a display hint indicating
5749      * the view is not displayed. Applications should not <em>rely</em> on this hint
5750      * as there is no guarantee that they will receive one.
5751      *
5752      * @param hint A hint about whether or not this view is displayed:
5753      * {@link #VISIBLE} or {@link #INVISIBLE}.
5754      */
5755     public void dispatchDisplayHint(int hint) {
5756         onDisplayHint(hint);
5757     }
5758 
5759     /**
5760      * Gives this view a hint about whether is displayed or not. For instance, when
5761      * a View moves out of the screen, it might receives a display hint indicating
5762      * the view is not displayed. Applications should not <em>rely</em> on this hint
5763      * as there is no guarantee that they will receive one.
5764      *
5765      * @param hint A hint about whether or not this view is displayed:
5766      * {@link #VISIBLE} or {@link #INVISIBLE}.
5767      */
5768     protected void onDisplayHint(int hint) {
5769     }
5770 
5771     /**
5772      * Dispatch a window visibility change down the view hierarchy.
5773      * ViewGroups should override to route to their children.
5774      *
5775      * @param visibility The new visibility of the window.
5776      *
5777      * @see #onWindowVisibilityChanged(int)
5778      */
5779     public void dispatchWindowVisibilityChanged(int visibility) {
5780         onWindowVisibilityChanged(visibility);
5781     }
5782 
5783     /**
5784      * Called when the window containing has change its visibility
5785      * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
5786      * that this tells you whether or not your window is being made visible
5787      * to the window manager; this does <em>not</em> tell you whether or not
5788      * your window is obscured by other windows on the screen, even if it
5789      * is itself visible.
5790      *
5791      * @param visibility The new visibility of the window.
5792      */
5793     protected void onWindowVisibilityChanged(int visibility) {
5794         if (visibility == VISIBLE) {
5795             initialAwakenScrollBars();
5796         }
5797     }
5798 
5799     /**
5800      * Returns the current visibility of the window this view is attached to
5801      * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
5802      *
5803      * @return Returns the current visibility of the view's window.
5804      */
5805     public int getWindowVisibility() {
5806         return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
5807     }
5808 
5809     /**
5810      * Retrieve the overall visible display size in which the window this view is
5811      * attached to has been positioned in.  This takes into account screen
5812      * decorations above the window, for both cases where the window itself
5813      * is being position inside of them or the window is being placed under
5814      * then and covered insets are used for the window to position its content
5815      * inside.  In effect, this tells you the available area where content can
5816      * be placed and remain visible to users.
5817      *
5818      * <p>This function requires an IPC back to the window manager to retrieve
5819      * the requested information, so should not be used in performance critical
5820      * code like drawing.
5821      *
5822      * @param outRect Filled in with the visible display frame.  If the view
5823      * is not attached to a window, this is simply the raw display size.
5824      */
5825     public void getWindowVisibleDisplayFrame(Rect outRect) {
5826         if (mAttachInfo != null) {
5827             try {
5828                 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
5829             } catch (RemoteException e) {
5830                 return;
5831             }
5832             // XXX This is really broken, and probably all needs to be done
5833             // in the window manager, and we need to know more about whether
5834             // we want the area behind or in front of the IME.
5835             final Rect insets = mAttachInfo.mVisibleInsets;
5836             outRect.left += insets.left;
5837             outRect.top += insets.top;
5838             outRect.right -= insets.right;
5839             outRect.bottom -= insets.bottom;
5840             return;
5841         }
5842         Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
5843         d.getRectSize(outRect);
5844     }
5845 
5846     /**
5847      * Dispatch a notification about a resource configuration change down
5848      * the view hierarchy.
5849      * ViewGroups should override to route to their children.
5850      *
5851      * @param newConfig The new resource configuration.
5852      *
5853      * @see #onConfigurationChanged(android.content.res.Configuration)
5854      */
5855     public void dispatchConfigurationChanged(Configuration newConfig) {
5856         onConfigurationChanged(newConfig);
5857     }
5858 
5859     /**
5860      * Called when the current configuration of the resources being used
5861      * by the application have changed.  You can use this to decide when
5862      * to reload resources that can changed based on orientation and other
5863      * configuration characterstics.  You only need to use this if you are
5864      * not relying on the normal {@link android.app.Activity} mechanism of
5865      * recreating the activity instance upon a configuration change.
5866      *
5867      * @param newConfig The new resource configuration.
5868      */
5869     protected void onConfigurationChanged(Configuration newConfig) {
5870     }
5871 
5872     /**
5873      * Private function to aggregate all per-view attributes in to the view
5874      * root.
5875      */
5876     void dispatchCollectViewAttributes(int visibility) {
5877         performCollectViewAttributes(visibility);
5878     }
5879 
5880     void performCollectViewAttributes(int visibility) {
5881         if ((visibility & VISIBILITY_MASK) == VISIBLE && mAttachInfo != null) {
5882             if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
5883                 mAttachInfo.mKeepScreenOn = true;
5884             }
5885             mAttachInfo.mSystemUiVisibility |= mSystemUiVisibility;
5886             if (mOnSystemUiVisibilityChangeListener != null) {
5887                 mAttachInfo.mHasSystemUiListeners = true;
5888             }
5889         }
5890     }
5891 
5892     void needGlobalAttributesUpdate(boolean force) {
5893         final AttachInfo ai = mAttachInfo;
5894         if (ai != null) {
5895             if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
5896                     || ai.mHasSystemUiListeners) {
5897                 ai.mRecomputeGlobalAttributes = true;
5898             }
5899         }
5900     }
5901 
5902     /**
5903      * Returns whether the device is currently in touch mode.  Touch mode is entered
5904      * once the user begins interacting with the device by touch, and affects various
5905      * things like whether focus is always visible to the user.
5906      *
5907      * @return Whether the device is in touch mode.
5908      */
5909     @ViewDebug.ExportedProperty
5910     public boolean isInTouchMode() {
5911         if (mAttachInfo != null) {
5912             return mAttachInfo.mInTouchMode;
5913         } else {
5914             return ViewRootImpl.isInTouchMode();
5915         }
5916     }
5917 
5918     /**
5919      * Returns the context the view is running in, through which it can
5920      * access the current theme, resources, etc.
5921      *
5922      * @return The view's Context.
5923      */
5924     @ViewDebug.CapturedViewProperty
5925     public final Context getContext() {
5926         return mContext;
5927     }
5928 
5929     /**
5930      * Handle a key event before it is processed by any input method
5931      * associated with the view hierarchy.  This can be used to intercept
5932      * key events in special situations before the IME consumes them; a
5933      * typical example would be handling the BACK key to update the application's
5934      * UI instead of allowing the IME to see it and close itself.
5935      *
5936      * @param keyCode The value in event.getKeyCode().
5937      * @param event Description of the key event.
5938      * @return If you handled the event, return true. If you want to allow the
5939      *         event to be handled by the next receiver, return false.
5940      */
5941     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
5942         return false;
5943     }
5944 
5945     /**
5946      * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
5947      * KeyEvent.Callback.onKeyDown()}: perform press of the view
5948      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
5949      * is released, if the view is enabled and clickable.
5950      *
5951      * @param keyCode A key code that represents the button pressed, from
5952      *                {@link android.view.KeyEvent}.
5953      * @param event   The KeyEvent object that defines the button action.
5954      */
5955     public boolean onKeyDown(int keyCode, KeyEvent event) {
5956         boolean result = false;
5957 
5958         switch (keyCode) {
5959             case KeyEvent.KEYCODE_DPAD_CENTER:
5960             case KeyEvent.KEYCODE_ENTER: {
5961                 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
5962                     return true;
5963                 }
5964                 // Long clickable items don't necessarily have to be clickable
5965                 if (((mViewFlags & CLICKABLE) == CLICKABLE ||
5966                         (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
5967                         (event.getRepeatCount() == 0)) {
5968                     setPressed(true);
5969                     checkForLongClick(0);
5970                     return true;
5971                 }
5972                 break;
5973             }
5974         }
5975         return result;
5976     }
5977 
5978     /**
5979      * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
5980      * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
5981      * the event).
5982      */
5983     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
5984         return false;
5985     }
5986 
5987     /**
5988      * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
5989      * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
5990      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
5991      * {@link KeyEvent#KEYCODE_ENTER} is released.
5992      *
5993      * @param keyCode A key code that represents the button pressed, from
5994      *                {@link android.view.KeyEvent}.
5995      * @param event   The KeyEvent object that defines the button action.
5996      */
5997     public boolean onKeyUp(int keyCode, KeyEvent event) {
5998         boolean result = false;
5999 
6000         switch (keyCode) {
6001             case KeyEvent.KEYCODE_DPAD_CENTER:
6002             case KeyEvent.KEYCODE_ENTER: {
6003                 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6004                     return true;
6005                 }
6006                 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
6007                     setPressed(false);
6008 
6009                     if (!mHasPerformedLongPress) {
6010                         // This is a tap, so remove the longpress check
6011                         removeLongPressCallback();
6012 
6013                         result = performClick();
6014                     }
6015                 }
6016                 break;
6017             }
6018         }
6019         return result;
6020     }
6021 
6022     /**
6023      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
6024      * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
6025      * the event).
6026      *
6027      * @param keyCode     A key code that represents the button pressed, from
6028      *                    {@link android.view.KeyEvent}.
6029      * @param repeatCount The number of times the action was made.
6030      * @param event       The KeyEvent object that defines the button action.
6031      */
6032     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
6033         return false;
6034     }
6035 
6036     /**
6037      * Called on the focused view when a key shortcut event is not handled.
6038      * Override this method to implement local key shortcuts for the View.
6039      * Key shortcuts can also be implemented by setting the
6040      * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
6041      *
6042      * @param keyCode The value in event.getKeyCode().
6043      * @param event Description of the key event.
6044      * @return If you handled the event, return true. If you want to allow the
6045      *         event to be handled by the next receiver, return false.
6046      */
6047     public boolean onKeyShortcut(int keyCode, KeyEvent event) {
6048         return false;
6049     }
6050 
6051     /**
6052      * Check whether the called view is a text editor, in which case it
6053      * would make sense to automatically display a soft input window for
6054      * it.  Subclasses should override this if they implement
6055      * {@link #onCreateInputConnection(EditorInfo)} to return true if
6056      * a call on that method would return a non-null InputConnection, and
6057      * they are really a first-class editor that the user would normally
6058      * start typing on when the go into a window containing your view.
6059      *
6060      * <p>The default implementation always returns false.  This does
6061      * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
6062      * will not be called or the user can not otherwise perform edits on your
6063      * view; it is just a hint to the system that this is not the primary
6064      * purpose of this view.
6065      *
6066      * @return Returns true if this view is a text editor, else false.
6067      */
6068     public boolean onCheckIsTextEditor() {
6069         return false;
6070     }
6071 
6072     /**
6073      * Create a new InputConnection for an InputMethod to interact
6074      * with the view.  The default implementation returns null, since it doesn't
6075      * support input methods.  You can override this to implement such support.
6076      * This is only needed for views that take focus and text input.
6077      *
6078      * <p>When implementing this, you probably also want to implement
6079      * {@link #onCheckIsTextEditor()} to indicate you will return a
6080      * non-null InputConnection.
6081      *
6082      * @param outAttrs Fill in with attribute information about the connection.
6083      */
6084     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
6085         return null;
6086     }
6087 
6088     /**
6089      * Called by the {@link android.view.inputmethod.InputMethodManager}
6090      * when a view who is not the current
6091      * input connection target is trying to make a call on the manager.  The
6092      * default implementation returns false; you can override this to return
6093      * true for certain views if you are performing InputConnection proxying
6094      * to them.
6095      * @param view The View that is making the InputMethodManager call.
6096      * @return Return true to allow the call, false to reject.
6097      */
6098     public boolean checkInputConnectionProxy(View view) {
6099         return false;
6100     }
6101 
6102     /**
6103      * Show the context menu for this view. It is not safe to hold on to the
6104      * menu after returning from this method.
6105      *
6106      * You should normally not overload this method. Overload
6107      * {@link #onCreateContextMenu(ContextMenu)} or define an
6108      * {@link OnCreateContextMenuListener} to add items to the context menu.
6109      *
6110      * @param menu The context menu to populate
6111      */
6112     public void createContextMenu(ContextMenu menu) {
6113         ContextMenuInfo menuInfo = getContextMenuInfo();
6114 
6115         // Sets the current menu info so all items added to menu will have
6116         // my extra info set.
6117         ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
6118 
6119         onCreateContextMenu(menu);
6120         if (mOnCreateContextMenuListener != null) {
6121             mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
6122         }
6123 
6124         // Clear the extra information so subsequent items that aren't mine don't
6125         // have my extra info.
6126         ((MenuBuilder)menu).setCurrentMenuInfo(null);
6127 
6128         if (mParent != null) {
6129             mParent.createContextMenu(menu);
6130         }
6131     }
6132 
6133     /**
6134      * Views should implement this if they have extra information to associate
6135      * with the context menu. The return result is supplied as a parameter to
6136      * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
6137      * callback.
6138      *
6139      * @return Extra information about the item for which the context menu
6140      *         should be shown. This information will vary across different
6141      *         subclasses of View.
6142      */
6143     protected ContextMenuInfo getContextMenuInfo() {
6144         return null;
6145     }
6146 
6147     /**
6148      * Views should implement this if the view itself is going to add items to
6149      * the context menu.
6150      *
6151      * @param menu the context menu to populate
6152      */
6153     protected void onCreateContextMenu(ContextMenu menu) {
6154     }
6155 
6156     /**
6157      * Implement this method to handle trackball motion events.  The
6158      * <em>relative</em> movement of the trackball since the last event
6159      * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
6160      * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
6161      * that a movement of 1 corresponds to the user pressing one DPAD key (so
6162      * they will often be fractional values, representing the more fine-grained
6163      * movement information available from a trackball).
6164      *
6165      * @param event The motion event.
6166      * @return True if the event was handled, false otherwise.
6167      */
6168     public boolean onTrackballEvent(MotionEvent event) {
6169         return false;
6170     }
6171 
6172     /**
6173      * Implement this method to handle generic motion events.
6174      * <p>
6175      * Generic motion events describe joystick movements, mouse hovers, track pad
6176      * touches, scroll wheel movements and other input events.  The
6177      * {@link MotionEvent#getSource() source} of the motion event specifies
6178      * the class of input that was received.  Implementations of this method
6179      * must examine the bits in the source before processing the event.
6180      * The following code example shows how this is done.
6181      * </p><p>
6182      * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
6183      * are delivered to the view under the pointer.  All other generic motion events are
6184      * delivered to the focused view.
6185      * </p>
6186      * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
6187      *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
6188      *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
6189      *             // process the joystick movement...
6190      *             return true;
6191      *         }
6192      *     }
6193      *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_POINTER) != 0) {
6194      *         switch (event.getAction()) {
6195      *             case MotionEvent.ACTION_HOVER_MOVE:
6196      *                 // process the mouse hover movement...
6197      *                 return true;
6198      *             case MotionEvent.ACTION_SCROLL:
6199      *                 // process the scroll wheel movement...
6200      *                 return true;
6201      *         }
6202      *     }
6203      *     return super.onGenericMotionEvent(event);
6204      * }</pre>
6205      *
6206      * @param event The generic motion event being processed.
6207      * @return True if the event was handled, false otherwise.
6208      */
6209     public boolean onGenericMotionEvent(MotionEvent event) {
6210         return false;
6211     }
6212 
6213     /**
6214      * Implement this method to handle hover events.
6215      * <p>
6216      * This method is called whenever a pointer is hovering into, over, or out of the
6217      * bounds of a view and the view is not currently being touched.
6218      * Hover events are represented as pointer events with action
6219      * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
6220      * or {@link MotionEvent#ACTION_HOVER_EXIT}.
6221      * </p>
6222      * <ul>
6223      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
6224      * when the pointer enters the bounds of the view.</li>
6225      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
6226      * when the pointer has already entered the bounds of the view and has moved.</li>
6227      * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
6228      * when the pointer has exited the bounds of the view or when the pointer is
6229      * about to go down due to a button click, tap, or similar user action that
6230      * causes the view to be touched.</li>
6231      * </ul>
6232      * <p>
6233      * The view should implement this method to return true to indicate that it is
6234      * handling the hover event, such as by changing its drawable state.
6235      * </p><p>
6236      * The default implementation calls {@link #setHovered} to update the hovered state
6237      * of the view when a hover enter or hover exit event is received, if the view
6238      * is enabled and is clickable.  The default implementation also sends hover
6239      * accessibility events.
6240      * </p>
6241      *
6242      * @param event The motion event that describes the hover.
6243      * @return True if the view handled the hover event.
6244      *
6245      * @see #isHovered
6246      * @see #setHovered
6247      * @see #onHoverChanged
6248      */
6249     public boolean onHoverEvent(MotionEvent event) {
6250         // The root view may receive hover (or touch) events that are outside the bounds of
6251         // the window.  This code ensures that we only send accessibility events for
6252         // hovers that are actually within the bounds of the root view.
6253         final int action = event.getAction();
6254         if (!mSendingHoverAccessibilityEvents) {
6255             if ((action == MotionEvent.ACTION_HOVER_ENTER
6256                     || action == MotionEvent.ACTION_HOVER_MOVE)
6257                     && !hasHoveredChild()
6258                     && pointInView(event.getX(), event.getY())) {
6259                 mSendingHoverAccessibilityEvents = true;
6260                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
6261             }
6262         } else {
6263             if (action == MotionEvent.ACTION_HOVER_EXIT
6264                     || (action == MotionEvent.ACTION_HOVER_MOVE
6265                             && !pointInView(event.getX(), event.getY()))) {
6266                 mSendingHoverAccessibilityEvents = false;
6267                 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
6268             }
6269         }
6270 
6271         if (isHoverable()) {
6272             switch (action) {
6273                 case MotionEvent.ACTION_HOVER_ENTER:
6274                     setHovered(true);
6275                     break;
6276                 case MotionEvent.ACTION_HOVER_EXIT:
6277                     setHovered(false);
6278                     break;
6279             }
6280 
6281             // Dispatch the event to onGenericMotionEvent before returning true.
6282             // This is to provide compatibility with existing applications that
6283             // handled HOVER_MOVE events in onGenericMotionEvent and that would
6284             // break because of the new default handling for hoverable views
6285             // in onHoverEvent.
6286             // Note that onGenericMotionEvent will be called by default when
6287             // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
6288             dispatchGenericMotionEventInternal(event);
6289             return true;
6290         }
6291         return false;
6292     }
6293 
6294     /**
6295      * Returns true if the view should handle {@link #onHoverEvent}
6296      * by calling {@link #setHovered} to change its hovered state.
6297      *
6298      * @return True if the view is hoverable.
6299      */
6300     private boolean isHoverable() {
6301         final int viewFlags = mViewFlags;
6302         //noinspection SimplifiableIfStatement
6303         if ((viewFlags & ENABLED_MASK) == DISABLED) {
6304             return false;
6305         }
6306 
6307         return (viewFlags & CLICKABLE) == CLICKABLE
6308                 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
6309     }
6310 
6311     /**
6312      * Returns true if the view is currently hovered.
6313      *
6314      * @return True if the view is currently hovered.
6315      *
6316      * @see #setHovered
6317      * @see #onHoverChanged
6318      */
6319     @ViewDebug.ExportedProperty
6320     public boolean isHovered() {
6321         return (mPrivateFlags & HOVERED) != 0;
6322     }
6323 
6324     /**
6325      * Sets whether the view is currently hovered.
6326      * <p>
6327      * Calling this method also changes the drawable state of the view.  This
6328      * enables the view to react to hover by using different drawable resources
6329      * to change its appearance.
6330      * </p><p>
6331      * The {@link #onHoverChanged} method is called when the hovered state changes.
6332      * </p>
6333      *
6334      * @param hovered True if the view is hovered.
6335      *
6336      * @see #isHovered
6337      * @see #onHoverChanged
6338      */
6339     public void setHovered(boolean hovered) {
6340         if (hovered) {
6341             if ((mPrivateFlags & HOVERED) == 0) {
6342                 mPrivateFlags |= HOVERED;
6343                 refreshDrawableState();
6344                 onHoverChanged(true);
6345             }
6346         } else {
6347             if ((mPrivateFlags & HOVERED) != 0) {
6348                 mPrivateFlags &= ~HOVERED;
6349                 refreshDrawableState();
6350                 onHoverChanged(false);
6351             }
6352         }
6353     }
6354 
6355     /**
6356      * Implement this method to handle hover state changes.
6357      * <p>
6358      * This method is called whenever the hover state changes as a result of a
6359      * call to {@link #setHovered}.
6360      * </p>
6361      *
6362      * @param hovered The current hover state, as returned by {@link #isHovered}.
6363      *
6364      * @see #isHovered
6365      * @see #setHovered
6366      */
6367     public void onHoverChanged(boolean hovered) {
6368     }
6369 
6370     /**
6371      * Implement this method to handle touch screen motion events.
6372      *
6373      * @param event The motion event.
6374      * @return True if the event was handled, false otherwise.
6375      */
6376     public boolean onTouchEvent(MotionEvent event) {
6377         final int viewFlags = mViewFlags;
6378 
6379         if ((viewFlags & ENABLED_MASK) == DISABLED) {
6380             if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PRESSED) != 0) {
6381                 mPrivateFlags &= ~PRESSED;
6382                 refreshDrawableState();
6383             }
6384             // A disabled view that is clickable still consumes the touch
6385             // events, it just doesn't respond to them.
6386             return (((viewFlags & CLICKABLE) == CLICKABLE ||
6387                     (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
6388         }
6389 
6390         if (mTouchDelegate != null) {
6391             if (mTouchDelegate.onTouchEvent(event)) {
6392                 return true;
6393             }
6394         }
6395 
6396         if (((viewFlags & CLICKABLE) == CLICKABLE ||
6397                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
6398             switch (event.getAction()) {
6399                 case MotionEvent.ACTION_UP:
6400                     boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
6401                     if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
6402                         // take focus if we don't have it already and we should in
6403                         // touch mode.
6404                         boolean focusTaken = false;
6405                         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
6406                             focusTaken = requestFocus();
6407                         }
6408 
6409                         if (prepressed) {
6410                             // The button is being released before we actually
6411                             // showed it as pressed.  Make it show the pressed
6412                             // state now (before scheduling the click) to ensure
6413                             // the user sees it.
6414                             mPrivateFlags |= PRESSED;
6415                             refreshDrawableState();
6416                        }
6417 
6418                         if (!mHasPerformedLongPress) {
6419                             // This is a tap, so remove the longpress check
6420                             removeLongPressCallback();
6421 
6422                             // Only perform take click actions if we were in the pressed state
6423                             if (!focusTaken) {
6424                                 // Use a Runnable and post this rather than calling
6425                                 // performClick directly. This lets other visual state
6426                                 // of the view update before click actions start.
6427                                 if (mPerformClick == null) {
6428                                     mPerformClick = new PerformClick();
6429                                 }
6430                                 if (!post(mPerformClick)) {
6431                                     performClick();
6432                                 }
6433                             }
6434                         }
6435 
6436                         if (mUnsetPressedState == null) {
6437                             mUnsetPressedState = new UnsetPressedState();
6438                         }
6439 
6440                         if (prepressed) {
6441                             postDelayed(mUnsetPressedState,
6442                                     ViewConfiguration.getPressedStateDuration());
6443                         } else if (!post(mUnsetPressedState)) {
6444                             // If the post failed, unpress right now
6445                             mUnsetPressedState.run();
6446                         }
6447                         removeTapCallback();
6448                     }
6449                     break;
6450 
6451                 case MotionEvent.ACTION_DOWN:
6452                     mHasPerformedLongPress = false;
6453 
6454                     if (performButtonActionOnTouchDown(event)) {
6455                         break;
6456                     }
6457 
6458                     // Walk up the hierarchy to determine if we're inside a scrolling container.
6459                     boolean isInScrollingContainer = isInScrollingContainer();
6460 
6461                     // For views inside a scrolling container, delay the pressed feedback for
6462                     // a short period in case this is a scroll.
6463                     if (isInScrollingContainer) {
6464                         mPrivateFlags |= PREPRESSED;
6465                         if (mPendingCheckForTap == null) {
6466                             mPendingCheckForTap = new CheckForTap();
6467                         }
6468                         postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
6469                     } else {
6470                         // Not inside a scrolling container, so show the feedback right away
6471                         mPrivateFlags |= PRESSED;
6472                         refreshDrawableState();
6473                         checkForLongClick(0);
6474                     }
6475                     break;
6476 
6477                 case MotionEvent.ACTION_CANCEL:
6478                     mPrivateFlags &= ~PRESSED;
6479                     refreshDrawableState();
6480                     removeTapCallback();
6481                     break;
6482 
6483                 case MotionEvent.ACTION_MOVE:
6484                     final int x = (int) event.getX();
6485                     final int y = (int) event.getY();
6486 
6487                     // Be lenient about moving outside of buttons
6488                     if (!pointInView(x, y, mTouchSlop)) {
6489                         // Outside button
6490                         removeTapCallback();
6491                         if ((mPrivateFlags & PRESSED) != 0) {
6492                             // Remove any future long press/tap checks
6493                             removeLongPressCallback();
6494 
6495                             // Need to switch from pressed to not pressed
6496                             mPrivateFlags &= ~PRESSED;
6497                             refreshDrawableState();
6498                         }
6499                     }
6500                     break;
6501             }
6502             return true;
6503         }
6504 
6505         return false;
6506     }
6507 
6508     /**
6509      * @hide
6510      */
6511     public boolean isInScrollingContainer() {
6512         ViewParent p = getParent();
6513         while (p != null && p instanceof ViewGroup) {
6514             if (((ViewGroup) p).shouldDelayChildPressedState()) {
6515                 return true;
6516             }
6517             p = p.getParent();
6518         }
6519         return false;
6520     }
6521 
6522     /**
6523      * Remove the longpress detection timer.
6524      */
6525     private void removeLongPressCallback() {
6526         if (mPendingCheckForLongPress != null) {
6527           removeCallbacks(mPendingCheckForLongPress);
6528         }
6529     }
6530 
6531     /**
6532      * Remove the pending click action
6533      */
6534     private void removePerformClickCallback() {
6535         if (mPerformClick != null) {
6536             removeCallbacks(mPerformClick);
6537         }
6538     }
6539 
6540     /**
6541      * Remove the prepress detection timer.
6542      */
6543     private void removeUnsetPressCallback() {
6544         if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
6545             setPressed(false);
6546             removeCallbacks(mUnsetPressedState);
6547         }
6548     }
6549 
6550     /**
6551      * Remove the tap detection timer.
6552      */
6553     private void removeTapCallback() {
6554         if (mPendingCheckForTap != null) {
6555             mPrivateFlags &= ~PREPRESSED;
6556             removeCallbacks(mPendingCheckForTap);
6557         }
6558     }
6559 
6560     /**
6561      * Cancels a pending long press.  Your subclass can use this if you
6562      * want the context menu to come up if the user presses and holds
6563      * at the same place, but you don't want it to come up if they press
6564      * and then move around enough to cause scrolling.
6565      */
6566     public void cancelLongPress() {
6567         removeLongPressCallback();
6568 
6569         /*
6570          * The prepressed state handled by the tap callback is a display
6571          * construct, but the tap callback will post a long press callback
6572          * less its own timeout. Remove it here.
6573          */
6574         removeTapCallback();
6575     }
6576 
6577     /**
6578      * Remove the pending callback for sending a
6579      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
6580      */
6581     private void removeSendViewScrolledAccessibilityEventCallback() {
6582         if (mSendViewScrolledAccessibilityEvent != null) {
6583             removeCallbacks(mSendViewScrolledAccessibilityEvent);
6584         }
6585     }
6586 
6587     /**
6588      * Sets the TouchDelegate for this View.
6589      */
6590     public void setTouchDelegate(TouchDelegate delegate) {
6591         mTouchDelegate = delegate;
6592     }
6593 
6594     /**
6595      * Gets the TouchDelegate for this View.
6596      */
6597     public TouchDelegate getTouchDelegate() {
6598         return mTouchDelegate;
6599     }
6600 
6601     /**
6602      * Set flags controlling behavior of this view.
6603      *
6604      * @param flags Constant indicating the value which should be set
6605      * @param mask Constant indicating the bit range that should be changed
6606      */
6607     void setFlags(int flags, int mask) {
6608         int old = mViewFlags;
6609         mViewFlags = (mViewFlags & ~mask) | (flags & mask);
6610 
6611         int changed = mViewFlags ^ old;
6612         if (changed == 0) {
6613             return;
6614         }
6615         int privateFlags = mPrivateFlags;
6616 
6617         /* Check if the FOCUSABLE bit has changed */
6618         if (((changed & FOCUSABLE_MASK) != 0) &&
6619                 ((privateFlags & HAS_BOUNDS) !=0)) {
6620             if (((old & FOCUSABLE_MASK) == FOCUSABLE)
6621                     && ((privateFlags & FOCUSED) != 0)) {
6622                 /* Give up focus if we are no longer focusable */
6623                 clearFocus();
6624             } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
6625                     && ((privateFlags & FOCUSED) == 0)) {
6626                 /*
6627                  * Tell the view system that we are now available to take focus
6628                  * if no one else already has it.
6629                  */
6630                 if (mParent != null) mParent.focusableViewAvailable(this);
6631             }
6632         }
6633 
6634         if ((flags & VISIBILITY_MASK) == VISIBLE) {
6635             if ((changed & VISIBILITY_MASK) != 0) {
6636                 /*
6637                  * If this view is becoming visible, invalidate it in case it changed while
6638                  * it was not visible. Marking it drawn ensures that the invalidation will
6639                  * go through.
6640                  */
6641                 mPrivateFlags |= DRAWN;
6642                 invalidate(true);
6643 
6644                 needGlobalAttributesUpdate(true);
6645 
6646                 // a view becoming visible is worth notifying the parent
6647                 // about in case nothing has focus.  even if this specific view
6648                 // isn't focusable, it may contain something that is, so let
6649                 // the root view try to give this focus if nothing else does.
6650                 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
6651                     mParent.focusableViewAvailable(this);
6652                 }
6653             }
6654         }
6655 
6656         /* Check if the GONE bit has changed */
6657         if ((changed & GONE) != 0) {
6658             needGlobalAttributesUpdate(false);
6659             requestLayout();
6660 
6661             if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
6662                 if (hasFocus()) clearFocus();
6663                 destroyDrawingCache();
6664                 if (mParent instanceof View) {
6665                     // GONE views noop invalidation, so invalidate the parent
6666                     ((View) mParent).invalidate(true);
6667                 }
6668                 // Mark the view drawn to ensure that it gets invalidated properly the next
6669                 // time it is visible and gets invalidated
6670                 mPrivateFlags |= DRAWN;
6671             }
6672             if (mAttachInfo != null) {
6673                 mAttachInfo.mViewVisibilityChanged = true;
6674             }
6675         }
6676 
6677         /* Check if the VISIBLE bit has changed */
6678         if ((changed & INVISIBLE) != 0) {
6679             needGlobalAttributesUpdate(false);
6680             /*
6681              * If this view is becoming invisible, set the DRAWN flag so that
6682              * the next invalidate() will not be skipped.
6683              */
6684             mPrivateFlags |= DRAWN;
6685 
6686             if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
6687                 // root view becoming invisible shouldn't clear focus
6688                 if (getRootView() != this) {
6689                     clearFocus();
6690                 }
6691             }
6692             if (mAttachInfo != null) {
6693                 mAttachInfo.mViewVisibilityChanged = true;
6694             }
6695         }
6696 
6697         if ((changed & VISIBILITY_MASK) != 0) {
6698             if (mParent instanceof ViewGroup) {
6699                 ((ViewGroup) mParent).onChildVisibilityChanged(this, (flags & VISIBILITY_MASK));
6700                 ((View) mParent).invalidate(true);
6701             } else if (mParent != null) {
6702                 mParent.invalidateChild(this, null);
6703             }
6704             dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
6705         }
6706 
6707         if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
6708             destroyDrawingCache();
6709         }
6710 
6711         if ((changed & DRAWING_CACHE_ENABLED) != 0) {
6712             destroyDrawingCache();
6713             mPrivateFlags &= ~DRAWING_CACHE_VALID;
6714             invalidateParentCaches();
6715         }
6716 
6717         if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
6718             destroyDrawingCache();
6719             mPrivateFlags &= ~DRAWING_CACHE_VALID;
6720         }
6721 
6722         if ((changed & DRAW_MASK) != 0) {
6723             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
6724                 if (mBGDrawable != null) {
6725                     mPrivateFlags &= ~SKIP_DRAW;
6726                     mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
6727                 } else {
6728                     mPrivateFlags |= SKIP_DRAW;
6729                 }
6730             } else {
6731                 mPrivateFlags &= ~SKIP_DRAW;
6732             }
6733             requestLayout();
6734             invalidate(true);
6735         }
6736 
6737         if ((changed & KEEP_SCREEN_ON) != 0) {
6738             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
6739                 mParent.recomputeViewAttributes(this);
6740             }
6741         }
6742 
6743         if ((changed & LAYOUT_DIRECTION_MASK) != 0) {
6744             requestLayout();
6745         }
6746     }
6747 
6748     /**
6749      * Change the view's z order in the tree, so it's on top of other sibling
6750      * views
6751      */
6752     public void bringToFront() {
6753         if (mParent != null) {
6754             mParent.bringChildToFront(this);
6755         }
6756     }
6757 
6758     /**
6759      * This is called in response to an internal scroll in this view (i.e., the
6760      * view scrolled its own contents). This is typically as a result of
6761      * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
6762      * called.
6763      *
6764      * @param l Current horizontal scroll origin.
6765      * @param t Current vertical scroll origin.
6766      * @param oldl Previous horizontal scroll origin.
6767      * @param oldt Previous vertical scroll origin.
6768      */
6769     protected void onScrollChanged(int l, int t, int oldl, int oldt) {
6770         if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6771             postSendViewScrolledAccessibilityEventCallback();
6772         }
6773 
6774         mBackgroundSizeChanged = true;
6775 
6776         final AttachInfo ai = mAttachInfo;
6777         if (ai != null) {
6778             ai.mViewScrollChanged = true;
6779         }
6780     }
6781 
6782     /**
6783      * Interface definition for a callback to be invoked when the layout bounds of a view
6784      * changes due to layout processing.
6785      */
6786     public interface OnLayoutChangeListener {
6787         /**
6788          * Called when the focus state of a view has changed.
6789          *
6790          * @param v The view whose state has changed.
6791          * @param left The new value of the view's left property.
6792          * @param top The new value of the view's top property.
6793          * @param right The new value of the view's right property.
6794          * @param bottom The new value of the view's bottom property.
6795          * @param oldLeft The previous value of the view's left property.
6796          * @param oldTop The previous value of the view's top property.
6797          * @param oldRight The previous value of the view's right property.
6798          * @param oldBottom The previous value of the view's bottom property.
6799          */
6800         void onLayoutChange(View v, int left, int top, int right, int bottom,
6801             int oldLeft, int oldTop, int oldRight, int oldBottom);
6802     }
6803 
6804     /**
6805      * This is called during layout when the size of this view has changed. If
6806      * you were just added to the view hierarchy, you're called with the old
6807      * values of 0.
6808      *
6809      * @param w Current width of this view.
6810      * @param h Current height of this view.
6811      * @param oldw Old width of this view.
6812      * @param oldh Old height of this view.
6813      */
6814     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
6815     }
6816 
6817     /**
6818      * Called by draw to draw the child views. This may be overridden
6819      * by derived classes to gain control just before its children are drawn
6820      * (but after its own view has been drawn).
6821      * @param canvas the canvas on which to draw the view
6822      */
6823     protected void dispatchDraw(Canvas canvas) {
6824     }
6825 
6826     /**
6827      * Gets the parent of this view. Note that the parent is a
6828      * ViewParent and not necessarily a View.
6829      *
6830      * @return Parent of this view.
6831      */
6832     public final ViewParent getParent() {
6833         return mParent;
6834     }
6835 
6836     /**
6837      * Set the horizontal scrolled position of your view. This will cause a call to
6838      * {@link #onScrollChanged(int, int, int, int)} and the view will be
6839      * invalidated.
6840      * @param value the x position to scroll to
6841      */
6842     public void setScrollX(int value) {
6843         scrollTo(value, mScrollY);
6844     }
6845 
6846     /**
6847      * Set the vertical scrolled position of your view. This will cause a call to
6848      * {@link #onScrollChanged(int, int, int, int)} and the view will be
6849      * invalidated.
6850      * @param value the y position to scroll to
6851      */
6852     public void setScrollY(int value) {
6853         scrollTo(mScrollX, value);
6854     }
6855 
6856     /**
6857      * Return the scrolled left position of this view. This is the left edge of
6858      * the displayed part of your view. You do not need to draw any pixels
6859      * farther left, since those are outside of the frame of your view on
6860      * screen.
6861      *
6862      * @return The left edge of the displayed part of your view, in pixels.
6863      */
6864     public final int getScrollX() {
6865         return mScrollX;
6866     }
6867 
6868     /**
6869      * Return the scrolled top position of this view. This is the top edge of
6870      * the displayed part of your view. You do not need to draw any pixels above
6871      * it, since those are outside of the frame of your view on screen.
6872      *
6873      * @return The top edge of the displayed part of your view, in pixels.
6874      */
6875     public final int getScrollY() {
6876         return mScrollY;
6877     }
6878 
6879     /**
6880      * Return the width of the your view.
6881      *
6882      * @return The width of your view, in pixels.
6883      */
6884     @ViewDebug.ExportedProperty(category = "layout")
6885     public final int getWidth() {
6886         return mRight - mLeft;
6887     }
6888 
6889     /**
6890      * Return the height of your view.
6891      *
6892      * @return The height of your view, in pixels.
6893      */
6894     @ViewDebug.ExportedProperty(category = "layout")
6895     public final int getHeight() {
6896         return mBottom - mTop;
6897     }
6898 
6899     /**
6900      * Return the visible drawing bounds of your view. Fills in the output
6901      * rectangle with the values from getScrollX(), getScrollY(),
6902      * getWidth(), and getHeight().
6903      *
6904      * @param outRect The (scrolled) drawing bounds of the view.
6905      */
6906     public void getDrawingRect(Rect outRect) {
6907         outRect.left = mScrollX;
6908         outRect.top = mScrollY;
6909         outRect.right = mScrollX + (mRight - mLeft);
6910         outRect.bottom = mScrollY + (mBottom - mTop);
6911     }
6912 
6913     /**
6914      * Like {@link #getMeasuredWidthAndState()}, but only returns the
6915      * raw width component (that is the result is masked by
6916      * {@link #MEASURED_SIZE_MASK}).
6917      *
6918      * @return The raw measured width of this view.
6919      */
6920     public final int getMeasuredWidth() {
6921         return mMeasuredWidth & MEASURED_SIZE_MASK;
6922     }
6923 
6924     /**
6925      * Return the full width measurement information for this view as computed
6926      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
6927      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
6928      * This should be used during measurement and layout calculations only. Use
6929      * {@link #getWidth()} to see how wide a view is after layout.
6930      *
6931      * @return The measured width of this view as a bit mask.
6932      */
6933     public final int getMeasuredWidthAndState() {
6934         return mMeasuredWidth;
6935     }
6936 
6937     /**
6938      * Like {@link #getMeasuredHeightAndState()}, but only returns the
6939      * raw width component (that is the result is masked by
6940      * {@link #MEASURED_SIZE_MASK}).
6941      *
6942      * @return The raw measured height of this view.
6943      */
6944     public final int getMeasuredHeight() {
6945         return mMeasuredHeight & MEASURED_SIZE_MASK;
6946     }
6947 
6948     /**
6949      * Return the full height measurement information for this view as computed
6950      * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
6951      * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
6952      * This should be used during measurement and layout calculations only. Use
6953      * {@link #getHeight()} to see how wide a view is after layout.
6954      *
6955      * @return The measured width of this view as a bit mask.
6956      */
6957     public final int getMeasuredHeightAndState() {
6958         return mMeasuredHeight;
6959     }
6960 
6961     /**
6962      * Return only the state bits of {@link #getMeasuredWidthAndState()}
6963      * and {@link #getMeasuredHeightAndState()}, combined into one integer.
6964      * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
6965      * and the height component is at the shifted bits
6966      * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
6967      */
6968     public final int getMeasuredState() {
6969         return (mMeasuredWidth&MEASURED_STATE_MASK)
6970                 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
6971                         & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
6972     }
6973 
6974     /**
6975      * The transform matrix of this view, which is calculated based on the current
6976      * roation, scale, and pivot properties.
6977      *
6978      * @see #getRotation()
6979      * @see #getScaleX()
6980      * @see #getScaleY()
6981      * @see #getPivotX()
6982      * @see #getPivotY()
6983      * @return The current transform matrix for the view
6984      */
6985     public Matrix getMatrix() {
6986         if (mTransformationInfo != null) {
6987             updateMatrix();
6988             return mTransformationInfo.mMatrix;
6989         }
6990         return Matrix.IDENTITY_MATRIX;
6991     }
6992 
6993     /**
6994      * Utility function to determine if the value is far enough away from zero to be
6995      * considered non-zero.
6996      * @param value A floating point value to check for zero-ness
6997      * @return whether the passed-in value is far enough away from zero to be considered non-zero
6998      */
6999     private static boolean nonzero(float value) {
7000         return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
7001     }
7002 
7003     /**
7004      * Returns true if the transform matrix is the identity matrix.
7005      * Recomputes the matrix if necessary.
7006      *
7007      * @return True if the transform matrix is the identity matrix, false otherwise.
7008      */
7009     final boolean hasIdentityMatrix() {
7010         if (mTransformationInfo != null) {
7011             updateMatrix();
7012             return mTransformationInfo.mMatrixIsIdentity;
7013         }
7014         return true;
7015     }
7016 
7017     void ensureTransformationInfo() {
7018         if (mTransformationInfo == null) {
7019             mTransformationInfo = new TransformationInfo();
7020         }
7021     }
7022 
7023     /**
7024      * Recomputes the transform matrix if necessary.
7025      */
7026     private void updateMatrix() {
7027         final TransformationInfo info = mTransformationInfo;
7028         if (info == null) {
7029             return;
7030         }
7031         if (info.mMatrixDirty) {
7032             // transform-related properties have changed since the last time someone
7033             // asked for the matrix; recalculate it with the current values
7034 
7035             // Figure out if we need to update the pivot point
7036             if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7037                 if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
7038                     info.mPrevWidth = mRight - mLeft;
7039                     info.mPrevHeight = mBottom - mTop;
7040                     info.mPivotX = info.mPrevWidth / 2f;
7041                     info.mPivotY = info.mPrevHeight / 2f;
7042                 }
7043             }
7044             info.mMatrix.reset();
7045             if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
7046                 info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
7047                 info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
7048                 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
7049             } else {
7050                 if (info.mCamera == null) {
7051                     info.mCamera = new Camera();
7052                     info.matrix3D = new Matrix();
7053                 }
7054                 info.mCamera.save();
7055                 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
7056                 info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
7057                 info.mCamera.getMatrix(info.matrix3D);
7058                 info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
7059                 info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
7060                         info.mPivotY + info.mTranslationY);
7061                 info.mMatrix.postConcat(info.matrix3D);
7062                 info.mCamera.restore();
7063             }
7064             info.mMatrixDirty = false;
7065             info.mMatrixIsIdentity = info.mMatrix.isIdentity();
7066             info.mInverseMatrixDirty = true;
7067         }
7068     }
7069 
7070     /**
7071      * Utility method to retrieve the inverse of the current mMatrix property.
7072      * We cache the matrix to avoid recalculating it when transform properties
7073      * have not changed.
7074      *
7075      * @return The inverse of the current matrix of this view.
7076      */
7077     final Matrix getInverseMatrix() {
7078         final TransformationInfo info = mTransformationInfo;
7079         if (info != null) {
7080             updateMatrix();
7081             if (info.mInverseMatrixDirty) {
7082                 if (info.mInverseMatrix == null) {
7083                     info.mInverseMatrix = new Matrix();
7084                 }
7085                 info.mMatrix.invert(info.mInverseMatrix);
7086                 info.mInverseMatrixDirty = false;
7087             }
7088             return info.mInverseMatrix;
7089         }
7090         return Matrix.IDENTITY_MATRIX;
7091     }
7092 
7093     /**
7094      * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
7095      * views are drawn) from the camera to this view. The camera's distance
7096      * affects 3D transformations, for instance rotations around the X and Y
7097      * axis. If the rotationX or rotationY properties are changed and this view is
7098      * large (more than half the size of the screen), it is recommended to always
7099      * use a camera distance that's greater than the height (X axis rotation) or
7100      * the width (Y axis rotation) of this view.</p>
7101      *
7102      * <p>The distance of the camera from the view plane can have an affect on the
7103      * perspective distortion of the view when it is rotated around the x or y axis.
7104      * For example, a large distance will result in a large viewing angle, and there
7105      * will not be much perspective distortion of the view as it rotates. A short
7106      * distance may cause much more perspective distortion upon rotation, and can
7107      * also result in some drawing artifacts if the rotated view ends up partially
7108      * behind the camera (which is why the recommendation is to use a distance at
7109      * least as far as the size of the view, if the view is to be rotated.)</p>
7110      *
7111      * <p>The distance is expressed in "depth pixels." The default distance depends
7112      * on the screen density. For instance, on a medium density display, the
7113      * default distance is 1280. On a high density display, the default distance
7114      * is 1920.</p>
7115      *
7116      * <p>If you want to specify a distance that leads to visually consistent
7117      * results across various densities, use the following formula:</p>
7118      * <pre>
7119      * float scale = context.getResources().getDisplayMetrics().density;
7120      * view.setCameraDistance(distance * scale);
7121      * </pre>
7122      *
7123      * <p>The density scale factor of a high density display is 1.5,
7124      * and 1920 = 1280 * 1.5.</p>
7125      *
7126      * @param distance The distance in "depth pixels", if negative the opposite
7127      *        value is used
7128      *
7129      * @see #setRotationX(float)
7130      * @see #setRotationY(float)
7131      */
7132     public void setCameraDistance(float distance) {
7133         invalidateParentCaches();
7134         invalidate(false);
7135 
7136         ensureTransformationInfo();
7137         final float dpi = mResources.getDisplayMetrics().densityDpi;
7138         final TransformationInfo info = mTransformationInfo;
7139         if (info.mCamera == null) {
7140             info.mCamera = new Camera();
7141             info.matrix3D = new Matrix();
7142         }
7143 
7144         info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
7145         info.mMatrixDirty = true;
7146 
7147         invalidate(false);
7148     }
7149 
7150     /**
7151      * The degrees that the view is rotated around the pivot point.
7152      *
7153      * @see #setRotation(float)
7154      * @see #getPivotX()
7155      * @see #getPivotY()
7156      *
7157      * @return The degrees of rotation.
7158      */
7159     public float getRotation() {
7160         return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
7161     }
7162 
7163     /**
7164      * Sets the degrees that the view is rotated around the pivot point. Increasing values
7165      * result in clockwise rotation.
7166      *
7167      * @param rotation The degrees of rotation.
7168      *
7169      * @see #getRotation()
7170      * @see #getPivotX()
7171      * @see #getPivotY()
7172      * @see #setRotationX(float)
7173      * @see #setRotationY(float)
7174      *
7175      * @attr ref android.R.styleable#View_rotation
7176      */
7177     public void setRotation(float rotation) {
7178         ensureTransformationInfo();
7179         final TransformationInfo info = mTransformationInfo;
7180         if (info.mRotation != rotation) {
7181             invalidateParentCaches();
7182             // Double-invalidation is necessary to capture view's old and new areas
7183             invalidate(false);
7184             info.mRotation = rotation;
7185             info.mMatrixDirty = true;
7186             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7187             invalidate(false);
7188         }
7189     }
7190 
7191     /**
7192      * The degrees that the view is rotated around the vertical axis through the pivot point.
7193      *
7194      * @see #getPivotX()
7195      * @see #getPivotY()
7196      * @see #setRotationY(float)
7197      *
7198      * @return The degrees of Y rotation.
7199      */
7200     public float getRotationY() {
7201         return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
7202     }
7203 
7204     /**
7205      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
7206      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
7207      * down the y axis.
7208      *
7209      * When rotating large views, it is recommended to adjust the camera distance
7210      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
7211      *
7212      * @param rotationY The degrees of Y rotation.
7213      *
7214      * @see #getRotationY()
7215      * @see #getPivotX()
7216      * @see #getPivotY()
7217      * @see #setRotation(float)
7218      * @see #setRotationX(float)
7219      * @see #setCameraDistance(float)
7220      *
7221      * @attr ref android.R.styleable#View_rotationY
7222      */
7223     public void setRotationY(float rotationY) {
7224         ensureTransformationInfo();
7225         final TransformationInfo info = mTransformationInfo;
7226         if (info.mRotationY != rotationY) {
7227             invalidateParentCaches();
7228             // Double-invalidation is necessary to capture view's old and new areas
7229             invalidate(false);
7230             info.mRotationY = rotationY;
7231             info.mMatrixDirty = true;
7232             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7233             invalidate(false);
7234         }
7235     }
7236 
7237     /**
7238      * The degrees that the view is rotated around the horizontal axis through the pivot point.
7239      *
7240      * @see #getPivotX()
7241      * @see #getPivotY()
7242      * @see #setRotationX(float)
7243      *
7244      * @return The degrees of X rotation.
7245      */
7246     public float getRotationX() {
7247         return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
7248     }
7249 
7250     /**
7251      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
7252      * Increasing values result in clockwise rotation from the viewpoint of looking down the
7253      * x axis.
7254      *
7255      * When rotating large views, it is recommended to adjust the camera distance
7256      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
7257      *
7258      * @param rotationX The degrees of X rotation.
7259      *
7260      * @see #getRotationX()
7261      * @see #getPivotX()
7262      * @see #getPivotY()
7263      * @see #setRotation(float)
7264      * @see #setRotationY(float)
7265      * @see #setCameraDistance(float)
7266      *
7267      * @attr ref android.R.styleable#View_rotationX
7268      */
7269     public void setRotationX(float rotationX) {
7270         ensureTransformationInfo();
7271         final TransformationInfo info = mTransformationInfo;
7272         if (info.mRotationX != rotationX) {
7273             invalidateParentCaches();
7274             // Double-invalidation is necessary to capture view's old and new areas
7275             invalidate(false);
7276             info.mRotationX = rotationX;
7277             info.mMatrixDirty = true;
7278             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7279             invalidate(false);
7280         }
7281     }
7282 
7283     /**
7284      * The amount that the view is scaled in x around the pivot point, as a proportion of
7285      * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
7286      *
7287      * <p>By default, this is 1.0f.
7288      *
7289      * @see #getPivotX()
7290      * @see #getPivotY()
7291      * @return The scaling factor.
7292      */
7293     public float getScaleX() {
7294         return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
7295     }
7296 
7297     /**
7298      * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
7299      * the view's unscaled width. A value of 1 means that no scaling is applied.
7300      *
7301      * @param scaleX The scaling factor.
7302      * @see #getPivotX()
7303      * @see #getPivotY()
7304      *
7305      * @attr ref android.R.styleable#View_scaleX
7306      */
7307     public void setScaleX(float scaleX) {
7308         ensureTransformationInfo();
7309         final TransformationInfo info = mTransformationInfo;
7310         if (info.mScaleX != scaleX) {
7311             invalidateParentCaches();
7312             // Double-invalidation is necessary to capture view's old and new areas
7313             invalidate(false);
7314             info.mScaleX = scaleX;
7315             info.mMatrixDirty = true;
7316             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7317             invalidate(false);
7318         }
7319     }
7320 
7321     /**
7322      * The amount that the view is scaled in y around the pivot point, as a proportion of
7323      * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
7324      *
7325      * <p>By default, this is 1.0f.
7326      *
7327      * @see #getPivotX()
7328      * @see #getPivotY()
7329      * @return The scaling factor.
7330      */
7331     public float getScaleY() {
7332         return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
7333     }
7334 
7335     /**
7336      * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
7337      * the view's unscaled width. A value of 1 means that no scaling is applied.
7338      *
7339      * @param scaleY The scaling factor.
7340      * @see #getPivotX()
7341      * @see #getPivotY()
7342      *
7343      * @attr ref android.R.styleable#View_scaleY
7344      */
7345     public void setScaleY(float scaleY) {
7346         ensureTransformationInfo();
7347         final TransformationInfo info = mTransformationInfo;
7348         if (info.mScaleY != scaleY) {
7349             invalidateParentCaches();
7350             // Double-invalidation is necessary to capture view's old and new areas
7351             invalidate(false);
7352             info.mScaleY = scaleY;
7353             info.mMatrixDirty = true;
7354             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7355             invalidate(false);
7356         }
7357     }
7358 
7359     /**
7360      * The x location of the point around which the view is {@link #setRotation(float) rotated}
7361      * and {@link #setScaleX(float) scaled}.
7362      *
7363      * @see #getRotation()
7364      * @see #getScaleX()
7365      * @see #getScaleY()
7366      * @see #getPivotY()
7367      * @return The x location of the pivot point.
7368      */
7369     public float getPivotX() {
7370         return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
7371     }
7372 
7373     /**
7374      * Sets the x location of the point around which the view is
7375      * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
7376      * By default, the pivot point is centered on the object.
7377      * Setting this property disables this behavior and causes the view to use only the
7378      * explicitly set pivotX and pivotY values.
7379      *
7380      * @param pivotX The x location of the pivot point.
7381      * @see #getRotation()
7382      * @see #getScaleX()
7383      * @see #getScaleY()
7384      * @see #getPivotY()
7385      *
7386      * @attr ref android.R.styleable#View_transformPivotX
7387      */
7388     public void setPivotX(float pivotX) {
7389         ensureTransformationInfo();
7390         mPrivateFlags |= PIVOT_EXPLICITLY_SET;
7391         final TransformationInfo info = mTransformationInfo;
7392         if (info.mPivotX != pivotX) {
7393             invalidateParentCaches();
7394             // Double-invalidation is necessary to capture view's old and new areas
7395             invalidate(false);
7396             info.mPivotX = pivotX;
7397             info.mMatrixDirty = true;
7398             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7399             invalidate(false);
7400         }
7401     }
7402 
7403     /**
7404      * The y location of the point around which the view is {@link #setRotation(float) rotated}
7405      * and {@link #setScaleY(float) scaled}.
7406      *
7407      * @see #getRotation()
7408      * @see #getScaleX()
7409      * @see #getScaleY()
7410      * @see #getPivotY()
7411      * @return The y location of the pivot point.
7412      */
7413     public float getPivotY() {
7414         return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
7415     }
7416 
7417     /**
7418      * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
7419      * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
7420      * Setting this property disables this behavior and causes the view to use only the
7421      * explicitly set pivotX and pivotY values.
7422      *
7423      * @param pivotY The y location of the pivot point.
7424      * @see #getRotation()
7425      * @see #getScaleX()
7426      * @see #getScaleY()
7427      * @see #getPivotY()
7428      *
7429      * @attr ref android.R.styleable#View_transformPivotY
7430      */
7431     public void setPivotY(float pivotY) {
7432         ensureTransformationInfo();
7433         mPrivateFlags |= PIVOT_EXPLICITLY_SET;
7434         final TransformationInfo info = mTransformationInfo;
7435         if (info.mPivotY != pivotY) {
7436             invalidateParentCaches();
7437             // Double-invalidation is necessary to capture view's old and new areas
7438             invalidate(false);
7439             info.mPivotY = pivotY;
7440             info.mMatrixDirty = true;
7441             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7442             invalidate(false);
7443         }
7444     }
7445 
7446     /**
7447      * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
7448      * completely transparent and 1 means the view is completely opaque.
7449      *
7450      * <p>By default this is 1.0f.
7451      * @return The opacity of the view.
7452      */
7453     public float getAlpha() {
7454         return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
7455     }
7456 
7457     /**
7458      * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
7459      * completely transparent and 1 means the view is completely opaque.</p>
7460      *
7461      * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
7462      * responsible for applying the opacity itself. Otherwise, calling this method is
7463      * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
7464      * setting a hardware layer.</p>
7465      *
7466      * @param alpha The opacity of the view.
7467      *
7468      * @see #setLayerType(int, android.graphics.Paint)
7469      *
7470      * @attr ref android.R.styleable#View_alpha
7471      */
7472     public void setAlpha(float alpha) {
7473         ensureTransformationInfo();
7474         mTransformationInfo.mAlpha = alpha;
7475         invalidateParentCaches();
7476         if (onSetAlpha((int) (alpha * 255))) {
7477             mPrivateFlags |= ALPHA_SET;
7478             // subclass is handling alpha - don't optimize rendering cache invalidation
7479             invalidate(true);
7480         } else {
7481             mPrivateFlags &= ~ALPHA_SET;
7482             invalidate(false);
7483         }
7484     }
7485 
7486     /**
7487      * Faster version of setAlpha() which performs the same steps except there are
7488      * no calls to invalidate(). The caller of this function should perform proper invalidation
7489      * on the parent and this object. The return value indicates whether the subclass handles
7490      * alpha (the return value for onSetAlpha()).
7491      *
7492      * @param alpha The new value for the alpha property
7493      * @return true if the View subclass handles alpha (the return value for onSetAlpha())
7494      */
7495     boolean setAlphaNoInvalidation(float alpha) {
7496         ensureTransformationInfo();
7497         mTransformationInfo.mAlpha = alpha;
7498         boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
7499         if (subclassHandlesAlpha) {
7500             mPrivateFlags |= ALPHA_SET;
7501         } else {
7502             mPrivateFlags &= ~ALPHA_SET;
7503         }
7504         return subclassHandlesAlpha;
7505     }
7506 
7507     /**
7508      * Top position of this view relative to its parent.
7509      *
7510      * @return The top of this view, in pixels.
7511      */
7512     @ViewDebug.CapturedViewProperty
7513     public final int getTop() {
7514         return mTop;
7515     }
7516 
7517     /**
7518      * Sets the top position of this view relative to its parent. This method is meant to be called
7519      * by the layout system and should not generally be called otherwise, because the property
7520      * may be changed at any time by the layout.
7521      *
7522      * @param top The top of this view, in pixels.
7523      */
7524     public final void setTop(int top) {
7525         if (top != mTop) {
7526             updateMatrix();
7527             final boolean matrixIsIdentity = mTransformationInfo == null
7528                     || mTransformationInfo.mMatrixIsIdentity;
7529             if (matrixIsIdentity) {
7530                 if (mAttachInfo != null) {
7531                     int minTop;
7532                     int yLoc;
7533                     if (top < mTop) {
7534                         minTop = top;
7535                         yLoc = top - mTop;
7536                     } else {
7537                         minTop = mTop;
7538                         yLoc = 0;
7539                     }
7540                     invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
7541                 }
7542             } else {
7543                 // Double-invalidation is necessary to capture view's old and new areas
7544                 invalidate(true);
7545             }
7546 
7547             int width = mRight - mLeft;
7548             int oldHeight = mBottom - mTop;
7549 
7550             mTop = top;
7551 
7552             onSizeChanged(width, mBottom - mTop, width, oldHeight);
7553 
7554             if (!matrixIsIdentity) {
7555                 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7556                     // A change in dimension means an auto-centered pivot point changes, too
7557                     mTransformationInfo.mMatrixDirty = true;
7558                 }
7559                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7560                 invalidate(true);
7561             }
7562             mBackgroundSizeChanged = true;
7563             invalidateParentIfNeeded();
7564         }
7565     }
7566 
7567     /**
7568      * Bottom position of this view relative to its parent.
7569      *
7570      * @return The bottom of this view, in pixels.
7571      */
7572     @ViewDebug.CapturedViewProperty
7573     public final int getBottom() {
7574         return mBottom;
7575     }
7576 
7577     /**
7578      * True if this view has changed since the last time being drawn.
7579      *
7580      * @return The dirty state of this view.
7581      */
7582     public boolean isDirty() {
7583         return (mPrivateFlags & DIRTY_MASK) != 0;
7584     }
7585 
7586     /**
7587      * Sets the bottom position of this view relative to its parent. This method is meant to be
7588      * called by the layout system and should not generally be called otherwise, because the
7589      * property may be changed at any time by the layout.
7590      *
7591      * @param bottom The bottom of this view, in pixels.
7592      */
7593     public final void setBottom(int bottom) {
7594         if (bottom != mBottom) {
7595             updateMatrix();
7596             final boolean matrixIsIdentity = mTransformationInfo == null
7597                     || mTransformationInfo.mMatrixIsIdentity;
7598             if (matrixIsIdentity) {
7599                 if (mAttachInfo != null) {
7600                     int maxBottom;
7601                     if (bottom < mBottom) {
7602                         maxBottom = mBottom;
7603                     } else {
7604                         maxBottom = bottom;
7605                     }
7606                     invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
7607                 }
7608             } else {
7609                 // Double-invalidation is necessary to capture view's old and new areas
7610                 invalidate(true);
7611             }
7612 
7613             int width = mRight - mLeft;
7614             int oldHeight = mBottom - mTop;
7615 
7616             mBottom = bottom;
7617 
7618             onSizeChanged(width, mBottom - mTop, width, oldHeight);
7619 
7620             if (!matrixIsIdentity) {
7621                 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7622                     // A change in dimension means an auto-centered pivot point changes, too
7623                     mTransformationInfo.mMatrixDirty = true;
7624                 }
7625                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7626                 invalidate(true);
7627             }
7628             mBackgroundSizeChanged = true;
7629             invalidateParentIfNeeded();
7630         }
7631     }
7632 
7633     /**
7634      * Left position of this view relative to its parent.
7635      *
7636      * @return The left edge of this view, in pixels.
7637      */
7638     @ViewDebug.CapturedViewProperty
7639     public final int getLeft() {
7640         return mLeft;
7641     }
7642 
7643     /**
7644      * Sets the left position of this view relative to its parent. This method is meant to be called
7645      * by the layout system and should not generally be called otherwise, because the property
7646      * may be changed at any time by the layout.
7647      *
7648      * @param left The bottom of this view, in pixels.
7649      */
7650     public final void setLeft(int left) {
7651         if (left != mLeft) {
7652             updateMatrix();
7653             final boolean matrixIsIdentity = mTransformationInfo == null
7654                     || mTransformationInfo.mMatrixIsIdentity;
7655             if (matrixIsIdentity) {
7656                 if (mAttachInfo != null) {
7657                     int minLeft;
7658                     int xLoc;
7659                     if (left < mLeft) {
7660                         minLeft = left;
7661                         xLoc = left - mLeft;
7662                     } else {
7663                         minLeft = mLeft;
7664                         xLoc = 0;
7665                     }
7666                     invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
7667                 }
7668             } else {
7669                 // Double-invalidation is necessary to capture view's old and new areas
7670                 invalidate(true);
7671             }
7672 
7673             int oldWidth = mRight - mLeft;
7674             int height = mBottom - mTop;
7675 
7676             mLeft = left;
7677 
7678             onSizeChanged(mRight - mLeft, height, oldWidth, height);
7679 
7680             if (!matrixIsIdentity) {
7681                 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7682                     // A change in dimension means an auto-centered pivot point changes, too
7683                     mTransformationInfo.mMatrixDirty = true;
7684                 }
7685                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7686                 invalidate(true);
7687             }
7688             mBackgroundSizeChanged = true;
7689             invalidateParentIfNeeded();
7690         }
7691     }
7692 
7693     /**
7694      * Right position of this view relative to its parent.
7695      *
7696      * @return The right edge of this view, in pixels.
7697      */
7698     @ViewDebug.CapturedViewProperty
7699     public final int getRight() {
7700         return mRight;
7701     }
7702 
7703     /**
7704      * Sets the right position of this view relative to its parent. This method is meant to be called
7705      * by the layout system and should not generally be called otherwise, because the property
7706      * may be changed at any time by the layout.
7707      *
7708      * @param right The bottom of this view, in pixels.
7709      */
7710     public final void setRight(int right) {
7711         if (right != mRight) {
7712             updateMatrix();
7713             final boolean matrixIsIdentity = mTransformationInfo == null
7714                     || mTransformationInfo.mMatrixIsIdentity;
7715             if (matrixIsIdentity) {
7716                 if (mAttachInfo != null) {
7717                     int maxRight;
7718                     if (right < mRight) {
7719                         maxRight = mRight;
7720                     } else {
7721                         maxRight = right;
7722                     }
7723                     invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
7724                 }
7725             } else {
7726                 // Double-invalidation is necessary to capture view's old and new areas
7727                 invalidate(true);
7728             }
7729 
7730             int oldWidth = mRight - mLeft;
7731             int height = mBottom - mTop;
7732 
7733             mRight = right;
7734 
7735             onSizeChanged(mRight - mLeft, height, oldWidth, height);
7736 
7737             if (!matrixIsIdentity) {
7738                 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7739                     // A change in dimension means an auto-centered pivot point changes, too
7740                     mTransformationInfo.mMatrixDirty = true;
7741                 }
7742                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7743                 invalidate(true);
7744             }
7745             mBackgroundSizeChanged = true;
7746             invalidateParentIfNeeded();
7747         }
7748     }
7749 
7750     /**
7751      * The visual x position of this view, in pixels. This is equivalent to the
7752      * {@link #setTranslationX(float) translationX} property plus the current
7753      * {@link #getLeft() left} property.
7754      *
7755      * @return The visual x position of this view, in pixels.
7756      */
7757     public float getX() {
7758         return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
7759     }
7760 
7761     /**
7762      * Sets the visual x position of this view, in pixels. This is equivalent to setting the
7763      * {@link #setTranslationX(float) translationX} property to be the difference between
7764      * the x value passed in and the current {@link #getLeft() left} property.
7765      *
7766      * @param x The visual x position of this view, in pixels.
7767      */
7768     public void setX(float x) {
7769         setTranslationX(x - mLeft);
7770     }
7771 
7772     /**
7773      * The visual y position of this view, in pixels. This is equivalent to the
7774      * {@link #setTranslationY(float) translationY} property plus the current
7775      * {@link #getTop() top} property.
7776      *
7777      * @return The visual y position of this view, in pixels.
7778      */
7779     public float getY() {
7780         return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
7781     }
7782 
7783     /**
7784      * Sets the visual y position of this view, in pixels. This is equivalent to setting the
7785      * {@link #setTranslationY(float) translationY} property to be the difference between
7786      * the y value passed in and the current {@link #getTop() top} property.
7787      *
7788      * @param y The visual y position of this view, in pixels.
7789      */
7790     public void setY(float y) {
7791         setTranslationY(y - mTop);
7792     }
7793 
7794 
7795     /**
7796      * The horizontal location of this view relative to its {@link #getLeft() left} position.
7797      * This position is post-layout, in addition to wherever the object's
7798      * layout placed it.
7799      *
7800      * @return The horizontal position of this view relative to its left position, in pixels.
7801      */
7802     public float getTranslationX() {
7803         return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
7804     }
7805 
7806     /**
7807      * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
7808      * This effectively positions the object post-layout, in addition to wherever the object's
7809      * layout placed it.
7810      *
7811      * @param translationX The horizontal position of this view relative to its left position,
7812      * in pixels.
7813      *
7814      * @attr ref android.R.styleable#View_translationX
7815      */
7816     public void setTranslationX(float translationX) {
7817         ensureTransformationInfo();
7818         final TransformationInfo info = mTransformationInfo;
7819         if (info.mTranslationX != translationX) {
7820             invalidateParentCaches();
7821             // Double-invalidation is necessary to capture view's old and new areas
7822             invalidate(false);
7823             info.mTranslationX = translationX;
7824             info.mMatrixDirty = true;
7825             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7826             invalidate(false);
7827         }
7828     }
7829 
7830     /**
7831      * The horizontal location of this view relative to its {@link #getTop() top} position.
7832      * This position is post-layout, in addition to wherever the object's
7833      * layout placed it.
7834      *
7835      * @return The vertical position of this view relative to its top position,
7836      * in pixels.
7837      */
7838     public float getTranslationY() {
7839         return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
7840     }
7841 
7842     /**
7843      * Sets the vertical location of this view relative to its {@link #getTop() top} position.
7844      * This effectively positions the object post-layout, in addition to wherever the object's
7845      * layout placed it.
7846      *
7847      * @param translationY The vertical position of this view relative to its top position,
7848      * in pixels.
7849      *
7850      * @attr ref android.R.styleable#View_translationY
7851      */
7852     public void setTranslationY(float translationY) {
7853         ensureTransformationInfo();
7854         final TransformationInfo info = mTransformationInfo;
7855         if (info.mTranslationY != translationY) {
7856             invalidateParentCaches();
7857             // Double-invalidation is necessary to capture view's old and new areas
7858             invalidate(false);
7859             info.mTranslationY = translationY;
7860             info.mMatrixDirty = true;
7861             mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7862             invalidate(false);
7863         }
7864     }
7865 
7866     /**
7867      * @hide
7868      */
7869     public void setFastTranslationX(float x) {
7870         ensureTransformationInfo();
7871         final TransformationInfo info = mTransformationInfo;
7872         info.mTranslationX = x;
7873         info.mMatrixDirty = true;
7874     }
7875 
7876     /**
7877      * @hide
7878      */
7879     public void setFastTranslationY(float y) {
7880         ensureTransformationInfo();
7881         final TransformationInfo info = mTransformationInfo;
7882         info.mTranslationY = y;
7883         info.mMatrixDirty = true;
7884     }
7885 
7886     /**
7887      * @hide
7888      */
7889     public void setFastX(float x) {
7890         ensureTransformationInfo();
7891         final TransformationInfo info = mTransformationInfo;
7892         info.mTranslationX = x - mLeft;
7893         info.mMatrixDirty = true;
7894     }
7895 
7896     /**
7897      * @hide
7898      */
7899     public void setFastY(float y) {
7900         ensureTransformationInfo();
7901         final TransformationInfo info = mTransformationInfo;
7902         info.mTranslationY = y - mTop;
7903         info.mMatrixDirty = true;
7904     }
7905 
7906     /**
7907      * @hide
7908      */
7909     public void setFastScaleX(float x) {
7910         ensureTransformationInfo();
7911         final TransformationInfo info = mTransformationInfo;
7912         info.mScaleX = x;
7913         info.mMatrixDirty = true;
7914     }
7915 
7916     /**
7917      * @hide
7918      */
7919     public void setFastScaleY(float y) {
7920         ensureTransformationInfo();
7921         final TransformationInfo info = mTransformationInfo;
7922         info.mScaleY = y;
7923         info.mMatrixDirty = true;
7924     }
7925 
7926     /**
7927      * @hide
7928      */
7929     public void setFastAlpha(float alpha) {
7930         ensureTransformationInfo();
7931         mTransformationInfo.mAlpha = alpha;
7932     }
7933 
7934     /**
7935      * @hide
7936      */
7937     public void setFastRotationY(float y) {
7938         ensureTransformationInfo();
7939         final TransformationInfo info = mTransformationInfo;
7940         info.mRotationY = y;
7941         info.mMatrixDirty = true;
7942     }
7943 
7944     /**
7945      * Hit rectangle in parent's coordinates
7946      *
7947      * @param outRect The hit rectangle of the view.
7948      */
7949     public void getHitRect(Rect outRect) {
7950         updateMatrix();
7951         final TransformationInfo info = mTransformationInfo;
7952         if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
7953             outRect.set(mLeft, mTop, mRight, mBottom);
7954         } else {
7955             final RectF tmpRect = mAttachInfo.mTmpTransformRect;
7956             tmpRect.set(-info.mPivotX, -info.mPivotY,
7957                     getWidth() - info.mPivotX, getHeight() - info.mPivotY);
7958             info.mMatrix.mapRect(tmpRect);
7959             outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
7960                     (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
7961         }
7962     }
7963 
7964     /**
7965      * Determines whether the given point, in local coordinates is inside the view.
7966      */
7967     /*package*/ final boolean pointInView(float localX, float localY) {
7968         return localX >= 0 && localX < (mRight - mLeft)
7969                 && localY >= 0 && localY < (mBottom - mTop);
7970     }
7971 
7972     /**
7973      * Utility method to determine whether the given point, in local coordinates,
7974      * is inside the view, where the area of the view is expanded by the slop factor.
7975      * This method is called while processing touch-move events to determine if the event
7976      * is still within the view.
7977      */
7978     private boolean pointInView(float localX, float localY, float slop) {
7979         return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
7980                 localY < ((mBottom - mTop) + slop);
7981     }
7982 
7983     /**
7984      * When a view has focus and the user navigates away from it, the next view is searched for
7985      * starting from the rectangle filled in by this method.
7986      *
7987      * By default, the rectange is the {@link #getDrawingRect(android.graphics.Rect)})
7988      * of the view.  However, if your view maintains some idea of internal selection,
7989      * such as a cursor, or a selected row or column, you should override this method and
7990      * fill in a more specific rectangle.
7991      *
7992      * @param r The rectangle to fill in, in this view's coordinates.
7993      */
7994     public void getFocusedRect(Rect r) {
7995         getDrawingRect(r);
7996     }
7997 
7998     /**
7999      * If some part of this view is not clipped by any of its parents, then
8000      * return that area in r in global (root) coordinates. To convert r to local
8001      * coordinates, offset it by -globalOffset (e.g. r.offset(-globalOffset.x,
8002      * -globalOffset.y)) If the view is completely clipped or translated out,
8003      * return false.
8004      *
8005      * @param r If true is returned, r holds the global coordinates of the
8006      *        visible portion of this view.
8007      * @param globalOffset If true is returned, globalOffset holds the dx,dy
8008      *        between this view and its root. globalOffet may be null.
8009      * @return true if r is non-empty (i.e. part of the view is visible at the
8010      *         root level.
8011      */
8012     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
8013         int width = mRight - mLeft;
8014         int height = mBottom - mTop;
8015         if (width > 0 && height > 0) {
8016             r.set(0, 0, width, height);
8017             if (globalOffset != null) {
8018                 globalOffset.set(-mScrollX, -mScrollY);
8019             }
8020             return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
8021         }
8022         return false;
8023     }
8024 
8025     public final boolean getGlobalVisibleRect(Rect r) {
8026         return getGlobalVisibleRect(r, null);
8027     }
8028 
8029     public final boolean getLocalVisibleRect(Rect r) {
8030         Point offset = new Point();
8031         if (getGlobalVisibleRect(r, offset)) {
8032             r.offset(-offset.x, -offset.y); // make r local
8033             return true;
8034         }
8035         return false;
8036     }
8037 
8038     /**
8039      * Offset this view's vertical location by the specified number of pixels.
8040      *
8041      * @param offset the number of pixels to offset the view by
8042      */
8043     public void offsetTopAndBottom(int offset) {
8044         if (offset != 0) {
8045             updateMatrix();
8046             final boolean matrixIsIdentity = mTransformationInfo == null
8047                     || mTransformationInfo.mMatrixIsIdentity;
8048             if (matrixIsIdentity) {
8049                 final ViewParent p = mParent;
8050                 if (p != null && mAttachInfo != null) {
8051                     final Rect r = mAttachInfo.mTmpInvalRect;
8052                     int minTop;
8053                     int maxBottom;
8054                     int yLoc;
8055                     if (offset < 0) {
8056                         minTop = mTop + offset;
8057                         maxBottom = mBottom;
8058                         yLoc = offset;
8059                     } else {
8060                         minTop = mTop;
8061                         maxBottom = mBottom + offset;
8062                         yLoc = 0;
8063                     }
8064                     r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
8065                     p.invalidateChild(this, r);
8066                 }
8067             } else {
8068                 invalidate(false);
8069             }
8070 
8071             mTop += offset;
8072             mBottom += offset;
8073 
8074             if (!matrixIsIdentity) {
8075                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
8076                 invalidate(false);
8077             }
8078             invalidateParentIfNeeded();
8079         }
8080     }
8081 
8082     /**
8083      * Offset this view's horizontal location by the specified amount of pixels.
8084      *
8085      * @param offset the numer of pixels to offset the view by
8086      */
8087     public void offsetLeftAndRight(int offset) {
8088         if (offset != 0) {
8089             updateMatrix();
8090             final boolean matrixIsIdentity = mTransformationInfo == null
8091                     || mTransformationInfo.mMatrixIsIdentity;
8092             if (matrixIsIdentity) {
8093                 final ViewParent p = mParent;
8094                 if (p != null && mAttachInfo != null) {
8095                     final Rect r = mAttachInfo.mTmpInvalRect;
8096                     int minLeft;
8097                     int maxRight;
8098                     if (offset < 0) {
8099                         minLeft = mLeft + offset;
8100                         maxRight = mRight;
8101                     } else {
8102                         minLeft = mLeft;
8103                         maxRight = mRight + offset;
8104                     }
8105                     r.set(0, 0, maxRight - minLeft, mBottom - mTop);
8106                     p.invalidateChild(this, r);
8107                 }
8108             } else {
8109                 invalidate(false);
8110             }
8111 
8112             mLeft += offset;
8113             mRight += offset;
8114 
8115             if (!matrixIsIdentity) {
8116                 mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
8117                 invalidate(false);
8118             }
8119             invalidateParentIfNeeded();
8120         }
8121     }
8122 
8123     /**
8124      * Get the LayoutParams associated with this view. All views should have
8125      * layout parameters. These supply parameters to the <i>parent</i> of this
8126      * view specifying how it should be arranged. There are many subclasses of
8127      * ViewGroup.LayoutParams, and these correspond to the different subclasses
8128      * of ViewGroup that are responsible for arranging their children.
8129      *
8130      * This method may return null if this View is not attached to a parent
8131      * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
8132      * was not invoked successfully. When a View is attached to a parent
8133      * ViewGroup, this method must not return null.
8134      *
8135      * @return The LayoutParams associated with this view, or null if no
8136      *         parameters have been set yet
8137      */
8138     @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
8139     public ViewGroup.LayoutParams getLayoutParams() {
8140         return mLayoutParams;
8141     }
8142 
8143     /**
8144      * Set the layout parameters associated with this view. These supply
8145      * parameters to the <i>parent</i> of this view specifying how it should be
8146      * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
8147      * correspond to the different subclasses of ViewGroup that are responsible
8148      * for arranging their children.
8149      *
8150      * @param params The layout parameters for this view, cannot be null
8151      */
8152     public void setLayoutParams(ViewGroup.LayoutParams params) {
8153         if (params == null) {
8154             throw new NullPointerException("Layout parameters cannot be null");
8155         }
8156         mLayoutParams = params;
8157         requestLayout();
8158     }
8159 
8160     /**
8161      * Set the scrolled position of your view. This will cause a call to
8162      * {@link #onScrollChanged(int, int, int, int)} and the view will be
8163      * invalidated.
8164      * @param x the x position to scroll to
8165      * @param y the y position to scroll to
8166      */
8167     public void scrollTo(int x, int y) {
8168         if (mScrollX != x || mScrollY != y) {
8169             int oldX = mScrollX;
8170             int oldY = mScrollY;
8171             mScrollX = x;
8172             mScrollY = y;
8173             invalidateParentCaches();
8174             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
8175             if (!awakenScrollBars()) {
8176                 invalidate(true);
8177             }
8178         }
8179     }
8180 
8181     /**
8182      * Move the scrolled position of your view. This will cause a call to
8183      * {@link #onScrollChanged(int, int, int, int)} and the view will be
8184      * invalidated.
8185      * @param x the amount of pixels to scroll by horizontally
8186      * @param y the amount of pixels to scroll by vertically
8187      */
8188     public void scrollBy(int x, int y) {
8189         scrollTo(mScrollX + x, mScrollY + y);
8190     }
8191 
8192     /**
8193      * <p>Trigger the scrollbars to draw. When invoked this method starts an
8194      * animation to fade the scrollbars out after a default delay. If a subclass
8195      * provides animated scrolling, the start delay should equal the duration
8196      * of the scrolling animation.</p>
8197      *
8198      * <p>The animation starts only if at least one of the scrollbars is
8199      * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
8200      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
8201      * this method returns true, and false otherwise. If the animation is
8202      * started, this method calls {@link #invalidate()}; in that case the
8203      * caller should not call {@link #invalidate()}.</p>
8204      *
8205      * <p>This method should be invoked every time a subclass directly updates
8206      * the scroll parameters.</p>
8207      *
8208      * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
8209      * and {@link #scrollTo(int, int)}.</p>
8210      *
8211      * @return true if the animation is played, false otherwise
8212      *
8213      * @see #awakenScrollBars(int)
8214      * @see #scrollBy(int, int)
8215      * @see #scrollTo(int, int)
8216      * @see #isHorizontalScrollBarEnabled()
8217      * @see #isVerticalScrollBarEnabled()
8218      * @see #setHorizontalScrollBarEnabled(boolean)
8219      * @see #setVerticalScrollBarEnabled(boolean)
8220      */
8221     protected boolean awakenScrollBars() {
8222         return mScrollCache != null &&
8223                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
8224     }
8225 
8226     /**
8227      * Trigger the scrollbars to draw.
8228      * This method differs from awakenScrollBars() only in its default duration.
8229      * initialAwakenScrollBars() will show the scroll bars for longer than
8230      * usual to give the user more of a chance to notice them.
8231      *
8232      * @return true if the animation is played, false otherwise.
8233      */
8234     private boolean initialAwakenScrollBars() {
8235         return mScrollCache != null &&
8236                 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
8237     }
8238 
8239     /**
8240      * <p>
8241      * Trigger the scrollbars to draw. When invoked this method starts an
8242      * animation to fade the scrollbars out after a fixed delay. If a subclass
8243      * provides animated scrolling, the start delay should equal the duration of
8244      * the scrolling animation.
8245      * </p>
8246      *
8247      * <p>
8248      * The animation starts only if at least one of the scrollbars is enabled,
8249      * as specified by {@link #isHorizontalScrollBarEnabled()} and
8250      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
8251      * this method returns true, and false otherwise. If the animation is
8252      * started, this method calls {@link #invalidate()}; in that case the caller
8253      * should not call {@link #invalidate()}.
8254      * </p>
8255      *
8256      * <p>
8257      * This method should be invoked everytime a subclass directly updates the
8258      * scroll parameters.
8259      * </p>
8260      *
8261      * @param startDelay the delay, in milliseconds, after which the animation
8262      *        should start; when the delay is 0, the animation starts
8263      *        immediately
8264      * @return true if the animation is played, false otherwise
8265      *
8266      * @see #scrollBy(int, int)
8267      * @see #scrollTo(int, int)
8268      * @see #isHorizontalScrollBarEnabled()
8269      * @see #isVerticalScrollBarEnabled()
8270      * @see #setHorizontalScrollBarEnabled(boolean)
8271      * @see #setVerticalScrollBarEnabled(boolean)
8272      */
8273     protected boolean awakenScrollBars(int startDelay) {
8274         return awakenScrollBars(startDelay, true);
8275     }
8276 
8277     /**
8278      * <p>
8279      * Trigger the scrollbars to draw. When invoked this method starts an
8280      * animation to fade the scrollbars out after a fixed delay. If a subclass
8281      * provides animated scrolling, the start delay should equal the duration of
8282      * the scrolling animation.
8283      * </p>
8284      *
8285      * <p>
8286      * The animation starts only if at least one of the scrollbars is enabled,
8287      * as specified by {@link #isHorizontalScrollBarEnabled()} and
8288      * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
8289      * this method returns true, and false otherwise. If the animation is
8290      * started, this method calls {@link #invalidate()} if the invalidate parameter
8291      * is set to true; in that case the caller
8292      * should not call {@link #invalidate()}.
8293      * </p>
8294      *
8295      * <p>
8296      * This method should be invoked everytime a subclass directly updates the
8297      * scroll parameters.
8298      * </p>
8299      *
8300      * @param startDelay the delay, in milliseconds, after which the animation
8301      *        should start; when the delay is 0, the animation starts
8302      *        immediately
8303      *
8304      * @param invalidate Wheter this method should call invalidate
8305      *
8306      * @return true if the animation is played, false otherwise
8307      *
8308      * @see #scrollBy(int, int)
8309      * @see #scrollTo(int, int)
8310      * @see #isHorizontalScrollBarEnabled()
8311      * @see #isVerticalScrollBarEnabled()
8312      * @see #setHorizontalScrollBarEnabled(boolean)
8313      * @see #setVerticalScrollBarEnabled(boolean)
8314      */
8315     protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
8316         final ScrollabilityCache scrollCache = mScrollCache;
8317 
8318         if (scrollCache == null || !scrollCache.fadeScrollBars) {
8319             return false;
8320         }
8321 
8322         if (scrollCache.scrollBar == null) {
8323             scrollCache.scrollBar = new ScrollBarDrawable();
8324         }
8325 
8326         if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
8327 
8328             if (invalidate) {
8329                 // Invalidate to show the scrollbars
8330                 invalidate(true);
8331             }
8332 
8333             if (scrollCache.state == ScrollabilityCache.OFF) {
8334                 // FIXME: this is copied from WindowManagerService.
8335                 // We should get this value from the system when it
8336                 // is possible to do so.
8337                 final int KEY_REPEAT_FIRST_DELAY = 750;
8338                 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
8339             }
8340 
8341             // Tell mScrollCache when we should start fading. This may
8342             // extend the fade start time if one was already scheduled
8343             long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
8344             scrollCache.fadeStartTime = fadeStartTime;
8345             scrollCache.state = ScrollabilityCache.ON;
8346 
8347             // Schedule our fader to run, unscheduling any old ones first
8348             if (mAttachInfo != null) {
8349                 mAttachInfo.mHandler.removeCallbacks(scrollCache);
8350                 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
8351             }
8352 
8353             return true;
8354         }
8355 
8356         return false;
8357     }
8358 
8359     /**
8360      * Do not invalidate views which are not visible and which are not running an animation. They
8361      * will not get drawn and they should not set dirty flags as if they will be drawn
8362      */
8363     private boolean skipInvalidate() {
8364         return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
8365                 (!(mParent instanceof ViewGroup) ||
8366                         !((ViewGroup) mParent).isViewTransitioning(this));
8367     }
8368     /**
8369      * Mark the area defined by dirty as needing to be drawn. If the view is
8370      * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
8371      * in the future. This must be called from a UI thread. To call from a non-UI
8372      * thread, call {@link #postInvalidate()}.
8373      *
8374      * WARNING: This method is destructive to dirty.
8375      * @param dirty the rectangle representing the bounds of the dirty region
8376      */
8377     public void invalidate(Rect dirty) {
8378         if (ViewDebug.TRACE_HIERARCHY) {
8379             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
8380         }
8381 
8382         if (skipInvalidate()) {
8383             return;
8384         }
8385         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8386                 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
8387                 (mPrivateFlags & INVALIDATED) != INVALIDATED) {
8388             mPrivateFlags &= ~DRAWING_CACHE_VALID;
8389             mPrivateFlags |= INVALIDATED;
8390             mPrivateFlags |= DIRTY;
8391             final ViewParent p = mParent;
8392             final AttachInfo ai = mAttachInfo;
8393             //noinspection PointlessBooleanExpression,ConstantConditions
8394             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
8395                 if (p != null && ai != null && ai.mHardwareAccelerated) {
8396                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy
8397                     // with a null dirty rect, which tells the ViewAncestor to redraw everything
8398                     p.invalidateChild(this, null);
8399                     return;
8400                 }
8401             }
8402             if (p != null && ai != null) {
8403                 final int scrollX = mScrollX;
8404                 final int scrollY = mScrollY;
8405                 final Rect r = ai.mTmpInvalRect;
8406                 r.set(dirty.left - scrollX, dirty.top - scrollY,
8407                         dirty.right - scrollX, dirty.bottom - scrollY);
8408                 mParent.invalidateChild(this, r);
8409             }
8410         }
8411     }
8412 
8413     /**
8414      * Mark the area defined by the rect (l,t,r,b) as needing to be drawn.
8415      * The coordinates of the dirty rect are relative to the view.
8416      * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
8417      * will be called at some point in the future. This must be called from
8418      * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
8419      * @param l the left position of the dirty region
8420      * @param t the top position of the dirty region
8421      * @param r the right position of the dirty region
8422      * @param b the bottom position of the dirty region
8423      */
8424     public void invalidate(int l, int t, int r, int b) {
8425         if (ViewDebug.TRACE_HIERARCHY) {
8426             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
8427         }
8428 
8429         if (skipInvalidate()) {
8430             return;
8431         }
8432         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8433                 (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
8434                 (mPrivateFlags & INVALIDATED) != INVALIDATED) {
8435             mPrivateFlags &= ~DRAWING_CACHE_VALID;
8436             mPrivateFlags |= INVALIDATED;
8437             mPrivateFlags |= DIRTY;
8438             final ViewParent p = mParent;
8439             final AttachInfo ai = mAttachInfo;
8440             //noinspection PointlessBooleanExpression,ConstantConditions
8441             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
8442                 if (p != null && ai != null && ai.mHardwareAccelerated) {
8443                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy
8444                     // with a null dirty rect, which tells the ViewAncestor to redraw everything
8445                     p.invalidateChild(this, null);
8446                     return;
8447                 }
8448             }
8449             if (p != null && ai != null && l < r && t < b) {
8450                 final int scrollX = mScrollX;
8451                 final int scrollY = mScrollY;
8452                 final Rect tmpr = ai.mTmpInvalRect;
8453                 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
8454                 p.invalidateChild(this, tmpr);
8455             }
8456         }
8457     }
8458 
8459     /**
8460      * Invalidate the whole view. If the view is visible,
8461      * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
8462      * the future. This must be called from a UI thread. To call from a non-UI thread,
8463      * call {@link #postInvalidate()}.
8464      */
8465     public void invalidate() {
8466         invalidate(true);
8467     }
8468 
8469     /**
8470      * This is where the invalidate() work actually happens. A full invalidate()
8471      * causes the drawing cache to be invalidated, but this function can be called with
8472      * invalidateCache set to false to skip that invalidation step for cases that do not
8473      * need it (for example, a component that remains at the same dimensions with the same
8474      * content).
8475      *
8476      * @param invalidateCache Whether the drawing cache for this view should be invalidated as
8477      * well. This is usually true for a full invalidate, but may be set to false if the
8478      * View's contents or dimensions have not changed.
8479      */
8480     void invalidate(boolean invalidateCache) {
8481         if (ViewDebug.TRACE_HIERARCHY) {
8482             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
8483         }
8484 
8485         if (skipInvalidate()) {
8486             return;
8487         }
8488         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8489                 (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||
8490                 (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) {
8491             mLastIsOpaque = isOpaque();
8492             mPrivateFlags &= ~DRAWN;
8493             mPrivateFlags |= DIRTY;
8494             if (invalidateCache) {
8495                 mPrivateFlags |= INVALIDATED;
8496                 mPrivateFlags &= ~DRAWING_CACHE_VALID;
8497             }
8498             final AttachInfo ai = mAttachInfo;
8499             final ViewParent p = mParent;
8500             //noinspection PointlessBooleanExpression,ConstantConditions
8501             if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
8502                 if (p != null && ai != null && ai.mHardwareAccelerated) {
8503                     // fast-track for GL-enabled applications; just invalidate the whole hierarchy
8504                     // with a null dirty rect, which tells the ViewAncestor to redraw everything
8505                     p.invalidateChild(this, null);
8506                     return;
8507                 }
8508             }
8509 
8510             if (p != null && ai != null) {
8511                 final Rect r = ai.mTmpInvalRect;
8512                 r.set(0, 0, mRight - mLeft, mBottom - mTop);
8513                 // Don't call invalidate -- we don't want to internally scroll
8514                 // our own bounds
8515                 p.invalidateChild(this, r);
8516             }
8517         }
8518     }
8519 
8520     /**
8521      * @hide
8522      */
8523     public void fastInvalidate() {
8524         if (skipInvalidate()) {
8525             return;
8526         }
8527         if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8528             (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
8529             (mPrivateFlags & INVALIDATED) != INVALIDATED) {
8530             if (mParent instanceof View) {
8531                 ((View) mParent).mPrivateFlags |= INVALIDATED;
8532             }
8533             mPrivateFlags &= ~DRAWN;
8534             mPrivateFlags |= DIRTY;
8535             mPrivateFlags |= INVALIDATED;
8536             mPrivateFlags &= ~DRAWING_CACHE_VALID;
8537             if (mParent != null && mAttachInfo != null) {
8538                 if (mAttachInfo.mHardwareAccelerated) {
8539                     mParent.invalidateChild(this, null);
8540                 } else {
8541                     final Rect r = mAttachInfo.mTmpInvalRect;
8542                     r.set(0, 0, mRight - mLeft, mBottom - mTop);
8543                     // Don't call invalidate -- we don't want to internally scroll
8544                     // our own bounds
8545                     mParent.invalidateChild(this, r);
8546                 }
8547             }
8548         }
8549     }
8550 
8551     /**
8552      * Used to indicate that the parent of this view should clear its caches. This functionality
8553      * is used to force the parent to rebuild its display list (when hardware-accelerated),
8554      * which is necessary when various parent-managed properties of the view change, such as
8555      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
8556      * clears the parent caches and does not causes an invalidate event.
8557      *
8558      * @hide
8559      */
8560     protected void invalidateParentCaches() {
8561         if (mParent instanceof View) {
8562             ((View) mParent).mPrivateFlags |= INVALIDATED;
8563         }
8564     }
8565 
8566     /**
8567      * Used to indicate that the parent of this view should be invalidated. This functionality
8568      * is used to force the parent to rebuild its display list (when hardware-accelerated),
8569      * which is necessary when various parent-managed properties of the view change, such as
8570      * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
8571      * an invalidation event to the parent.
8572      *
8573      * @hide
8574      */
8575     protected void invalidateParentIfNeeded() {
8576         if (isHardwareAccelerated() && mParent instanceof View) {
8577             ((View) mParent).invalidate(true);
8578         }
8579     }
8580 
8581     /**
8582      * Indicates whether this View is opaque. An opaque View guarantees that it will
8583      * draw all the pixels overlapping its bounds using a fully opaque color.
8584      *
8585      * Subclasses of View should override this method whenever possible to indicate
8586      * whether an instance is opaque. Opaque Views are treated in a special way by
8587      * the View hierarchy, possibly allowing it to perform optimizations during
8588      * invalidate/draw passes.
8589      *
8590      * @return True if this View is guaranteed to be fully opaque, false otherwise.
8591      */
8592     @ViewDebug.ExportedProperty(category = "drawing")
8593     public boolean isOpaque() {
8594         return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK &&
8595                 ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1)
8596                         >= 1.0f - ViewConfiguration.ALPHA_THRESHOLD);
8597     }
8598 
8599     /**
8600      * @hide
8601      */
8602     protected void computeOpaqueFlags() {
8603         // Opaque if:
8604         //   - Has a background
8605         //   - Background is opaque
8606         //   - Doesn't have scrollbars or scrollbars are inside overlay
8607 
8608         if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
8609             mPrivateFlags |= OPAQUE_BACKGROUND;
8610         } else {
8611             mPrivateFlags &= ~OPAQUE_BACKGROUND;
8612         }
8613 
8614         final int flags = mViewFlags;
8615         if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
8616                 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
8617             mPrivateFlags |= OPAQUE_SCROLLBARS;
8618         } else {
8619             mPrivateFlags &= ~OPAQUE_SCROLLBARS;
8620         }
8621     }
8622 
8623     /**
8624      * @hide
8625      */
8626     protected boolean hasOpaqueScrollbars() {
8627         return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
8628     }
8629 
8630     /**
8631      * @return A handler associated with the thread running the View. This
8632      * handler can be used to pump events in the UI events queue.
8633      */
8634     public Handler getHandler() {
8635         if (mAttachInfo != null) {
8636             return mAttachInfo.mHandler;
8637         }
8638         return null;
8639     }
8640 
8641     /**
8642      * <p>Causes the Runnable to be added to the message queue.
8643      * The runnable will be run on the user interface thread.</p>
8644      *
8645      * <p>This method can be invoked from outside of the UI thread
8646      * only when this View is attached to a window.</p>
8647      *
8648      * @param action The Runnable that will be executed.
8649      *
8650      * @return Returns true if the Runnable was successfully placed in to the
8651      *         message queue.  Returns false on failure, usually because the
8652      *         looper processing the message queue is exiting.
8653      */
8654     public boolean post(Runnable action) {
8655         Handler handler;
8656         AttachInfo attachInfo = mAttachInfo;
8657         if (attachInfo != null) {
8658             handler = attachInfo.mHandler;
8659         } else {
8660             // Assume that post will succeed later
8661             ViewRootImpl.getRunQueue().post(action);
8662             return true;
8663         }
8664 
8665         return handler.post(action);
8666     }
8667 
8668     /**
8669      * <p>Causes the Runnable to be added to the message queue, to be run
8670      * after the specified amount of time elapses.
8671      * The runnable will be run on the user interface thread.</p>
8672      *
8673      * <p>This method can be invoked from outside of the UI thread
8674      * only when this View is attached to a window.</p>
8675      *
8676      * @param action The Runnable that will be executed.
8677      * @param delayMillis The delay (in milliseconds) until the Runnable
8678      *        will be executed.
8679      *
8680      * @return true if the Runnable was successfully placed in to the
8681      *         message queue.  Returns false on failure, usually because the
8682      *         looper processing the message queue is exiting.  Note that a
8683      *         result of true does not mean the Runnable will be processed --
8684      *         if the looper is quit before the delivery time of the message
8685      *         occurs then the message will be dropped.
8686      */
8687     public boolean postDelayed(Runnable action, long delayMillis) {
8688         Handler handler;
8689         AttachInfo attachInfo = mAttachInfo;
8690         if (attachInfo != null) {
8691             handler = attachInfo.mHandler;
8692         } else {
8693             // Assume that post will succeed later
8694             ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
8695             return true;
8696         }
8697 
8698         return handler.postDelayed(action, delayMillis);
8699     }
8700 
8701     /**
8702      * <p>Removes the specified Runnable from the message queue.</p>
8703      *
8704      * <p>This method can be invoked from outside of the UI thread
8705      * only when this View is attached to a window.</p>
8706      *
8707      * @param action The Runnable to remove from the message handling queue
8708      *
8709      * @return true if this view could ask the Handler to remove the Runnable,
8710      *         false otherwise. When the returned value is true, the Runnable
8711      *         may or may not have been actually removed from the message queue
8712      *         (for instance, if the Runnable was not in the queue already.)
8713      */
8714     public boolean removeCallbacks(Runnable action) {
8715         Handler handler;
8716         AttachInfo attachInfo = mAttachInfo;
8717         if (attachInfo != null) {
8718             handler = attachInfo.mHandler;
8719         } else {
8720             // Assume that post will succeed later
8721             ViewRootImpl.getRunQueue().removeCallbacks(action);
8722             return true;
8723         }
8724 
8725         handler.removeCallbacks(action);
8726         return true;
8727     }
8728 
8729     /**
8730      * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
8731      * Use this to invalidate the View from a non-UI thread.</p>
8732      *
8733      * <p>This method can be invoked from outside of the UI thread
8734      * only when this View is attached to a window.</p>
8735      *
8736      * @see #invalidate()
8737      */
8738     public void postInvalidate() {
8739         postInvalidateDelayed(0);
8740     }
8741 
8742     /**
8743      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
8744      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
8745      *
8746      * <p>This method can be invoked from outside of the UI thread
8747      * only when this View is attached to a window.</p>
8748      *
8749      * @param left The left coordinate of the rectangle to invalidate.
8750      * @param top The top coordinate of the rectangle to invalidate.
8751      * @param right The right coordinate of the rectangle to invalidate.
8752      * @param bottom The bottom coordinate of the rectangle to invalidate.
8753      *
8754      * @see #invalidate(int, int, int, int)
8755      * @see #invalidate(Rect)
8756      */
8757     public void postInvalidate(int left, int top, int right, int bottom) {
8758         postInvalidateDelayed(0, left, top, right, bottom);
8759     }
8760 
8761     /**
8762      * <p>Cause an invalidate to happen on a subsequent cycle through the event
8763      * loop. Waits for the specified amount of time.</p>
8764      *
8765      * <p>This method can be invoked from outside of the UI thread
8766      * only when this View is attached to a window.</p>
8767      *
8768      * @param delayMilliseconds the duration in milliseconds to delay the
8769      *         invalidation by
8770      */
8771     public void postInvalidateDelayed(long delayMilliseconds) {
8772         // We try only with the AttachInfo because there's no point in invalidating
8773         // if we are not attached to our window
8774         AttachInfo attachInfo = mAttachInfo;
8775         if (attachInfo != null) {
8776             Message msg = Message.obtain();
8777             msg.what = AttachInfo.INVALIDATE_MSG;
8778             msg.obj = this;
8779             attachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
8780         }
8781     }
8782 
8783     /**
8784      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
8785      * through the event loop. Waits for the specified amount of time.</p>
8786      *
8787      * <p>This method can be invoked from outside of the UI thread
8788      * only when this View is attached to a window.</p>
8789      *
8790      * @param delayMilliseconds the duration in milliseconds to delay the
8791      *         invalidation by
8792      * @param left The left coordinate of the rectangle to invalidate.
8793      * @param top The top coordinate of the rectangle to invalidate.
8794      * @param right The right coordinate of the rectangle to invalidate.
8795      * @param bottom The bottom coordinate of the rectangle to invalidate.
8796      */
8797     public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
8798             int right, int bottom) {
8799 
8800         // We try only with the AttachInfo because there's no point in invalidating
8801         // if we are not attached to our window
8802         AttachInfo attachInfo = mAttachInfo;
8803         if (attachInfo != null) {
8804             final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
8805             info.target = this;
8806             info.left = left;
8807             info.top = top;
8808             info.right = right;
8809             info.bottom = bottom;
8810 
8811             final Message msg = Message.obtain();
8812             msg.what = AttachInfo.INVALIDATE_RECT_MSG;
8813             msg.obj = info;
8814             attachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
8815         }
8816     }
8817 
8818     /**
8819      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
8820      * This event is sent at most once every
8821      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
8822      */
8823     private void postSendViewScrolledAccessibilityEventCallback() {
8824         if (mSendViewScrolledAccessibilityEvent == null) {
8825             mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
8826         }
8827         if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
8828             mSendViewScrolledAccessibilityEvent.mIsPending = true;
8829             postDelayed(mSendViewScrolledAccessibilityEvent,
8830                     ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
8831         }
8832     }
8833 
8834     /**
8835      * Called by a parent to request that a child update its values for mScrollX
8836      * and mScrollY if necessary. This will typically be done if the child is
8837      * animating a scroll using a {@link android.widget.Scroller Scroller}
8838      * object.
8839      */
8840     public void computeScroll() {
8841     }
8842 
8843     /**
8844      * <p>Indicate whether the horizontal edges are faded when the view is
8845      * scrolled horizontally.</p>
8846      *
8847      * @return true if the horizontal edges should are faded on scroll, false
8848      *         otherwise
8849      *
8850      * @see #setHorizontalFadingEdgeEnabled(boolean)
8851      * @attr ref android.R.styleable#View_requiresFadingEdge
8852      */
8853     public boolean isHorizontalFadingEdgeEnabled() {
8854         return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
8855     }
8856 
8857     /**
8858      * <p>Define whether the horizontal edges should be faded when this view
8859      * is scrolled horizontally.</p>
8860      *
8861      * @param horizontalFadingEdgeEnabled true if the horizontal edges should
8862      *                                    be faded when the view is scrolled
8863      *                                    horizontally
8864      *
8865      * @see #isHorizontalFadingEdgeEnabled()
8866      * @attr ref android.R.styleable#View_requiresFadingEdge
8867      */
8868     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
8869         if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
8870             if (horizontalFadingEdgeEnabled) {
8871                 initScrollCache();
8872             }
8873 
8874             mViewFlags ^= FADING_EDGE_HORIZONTAL;
8875         }
8876     }
8877 
8878     /**
8879      * <p>Indicate whether the vertical edges are faded when the view is
8880      * scrolled horizontally.</p>
8881      *
8882      * @return true if the vertical edges should are faded on scroll, false
8883      *         otherwise
8884      *
8885      * @see #setVerticalFadingEdgeEnabled(boolean)
8886      * @attr ref android.R.styleable#View_requiresFadingEdge
8887      */
8888     public boolean isVerticalFadingEdgeEnabled() {
8889         return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
8890     }
8891 
8892     /**
8893      * <p>Define whether the vertical edges should be faded when this view
8894      * is scrolled vertically.</p>
8895      *
8896      * @param verticalFadingEdgeEnabled true if the vertical edges should
8897      *                                  be faded when the view is scrolled
8898      *                                  vertically
8899      *
8900      * @see #isVerticalFadingEdgeEnabled()
8901      * @attr ref android.R.styleable#View_requiresFadingEdge
8902      */
8903     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
8904         if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
8905             if (verticalFadingEdgeEnabled) {
8906                 initScrollCache();
8907             }
8908 
8909             mViewFlags ^= FADING_EDGE_VERTICAL;
8910         }
8911     }
8912 
8913     /**
8914      * Returns the strength, or intensity, of the top faded edge. The strength is
8915      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
8916      * returns 0.0 or 1.0 but no value in between.
8917      *
8918      * Subclasses should override this method to provide a smoother fade transition
8919      * when scrolling occurs.
8920      *
8921      * @return the intensity of the top fade as a float between 0.0f and 1.0f
8922      */
8923     protected float getTopFadingEdgeStrength() {
8924         return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
8925     }
8926 
8927     /**
8928      * Returns the strength, or intensity, of the bottom faded edge. The strength is
8929      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
8930      * returns 0.0 or 1.0 but no value in between.
8931      *
8932      * Subclasses should override this method to provide a smoother fade transition
8933      * when scrolling occurs.
8934      *
8935      * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
8936      */
8937     protected float getBottomFadingEdgeStrength() {
8938         return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
8939                 computeVerticalScrollRange() ? 1.0f : 0.0f;
8940     }
8941 
8942     /**
8943      * Returns the strength, or intensity, of the left faded edge. The strength is
8944      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
8945      * returns 0.0 or 1.0 but no value in between.
8946      *
8947      * Subclasses should override this method to provide a smoother fade transition
8948      * when scrolling occurs.
8949      *
8950      * @return the intensity of the left fade as a float between 0.0f and 1.0f
8951      */
8952     protected float getLeftFadingEdgeStrength() {
8953         return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
8954     }
8955 
8956     /**
8957      * Returns the strength, or intensity, of the right faded edge. The strength is
8958      * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
8959      * returns 0.0 or 1.0 but no value in between.
8960      *
8961      * Subclasses should override this method to provide a smoother fade transition
8962      * when scrolling occurs.
8963      *
8964      * @return the intensity of the right fade as a float between 0.0f and 1.0f
8965      */
8966     protected float getRightFadingEdgeStrength() {
8967         return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
8968                 computeHorizontalScrollRange() ? 1.0f : 0.0f;
8969     }
8970 
8971     /**
8972      * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
8973      * scrollbar is not drawn by default.</p>
8974      *
8975      * @return true if the horizontal scrollbar should be painted, false
8976      *         otherwise
8977      *
8978      * @see #setHorizontalScrollBarEnabled(boolean)
8979      */
8980     public boolean isHorizontalScrollBarEnabled() {
8981         return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
8982     }
8983 
8984     /**
8985      * <p>Define whether the horizontal scrollbar should be drawn or not. The
8986      * scrollbar is not drawn by default.</p>
8987      *
8988      * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
8989      *                                   be painted
8990      *
8991      * @see #isHorizontalScrollBarEnabled()
8992      */
8993     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
8994         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
8995             mViewFlags ^= SCROLLBARS_HORIZONTAL;
8996             computeOpaqueFlags();
8997             resolvePadding();
8998         }
8999     }
9000 
9001     /**
9002      * <p>Indicate whether the vertical scrollbar should be drawn or not. The
9003      * scrollbar is not drawn by default.</p>
9004      *
9005      * @return true if the vertical scrollbar should be painted, false
9006      *         otherwise
9007      *
9008      * @see #setVerticalScrollBarEnabled(boolean)
9009      */
9010     public boolean isVerticalScrollBarEnabled() {
9011         return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
9012     }
9013 
9014     /**
9015      * <p>Define whether the vertical scrollbar should be drawn or not. The
9016      * scrollbar is not drawn by default.</p>
9017      *
9018      * @param verticalScrollBarEnabled true if the vertical scrollbar should
9019      *                                 be painted
9020      *
9021      * @see #isVerticalScrollBarEnabled()
9022      */
9023     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
9024         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
9025             mViewFlags ^= SCROLLBARS_VERTICAL;
9026             computeOpaqueFlags();
9027             resolvePadding();
9028         }
9029     }
9030 
9031     /**
9032      * @hide
9033      */
9034     protected void recomputePadding() {
9035         setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
9036     }
9037 
9038     /**
9039      * Define whether scrollbars will fade when the view is not scrolling.
9040      *
9041      * @param fadeScrollbars wheter to enable fading
9042      *
9043      */
9044     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
9045         initScrollCache();
9046         final ScrollabilityCache scrollabilityCache = mScrollCache;
9047         scrollabilityCache.fadeScrollBars = fadeScrollbars;
9048         if (fadeScrollbars) {
9049             scrollabilityCache.state = ScrollabilityCache.OFF;
9050         } else {
9051             scrollabilityCache.state = ScrollabilityCache.ON;
9052         }
9053     }
9054 
9055     /**
9056      *
9057      * Returns true if scrollbars will fade when this view is not scrolling
9058      *
9059      * @return true if scrollbar fading is enabled
9060      */
9061     public boolean isScrollbarFadingEnabled() {
9062         return mScrollCache != null && mScrollCache.fadeScrollBars;
9063     }
9064 
9065     /**
9066      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
9067      * inset. When inset, they add to the padding of the view. And the scrollbars
9068      * can be drawn inside the padding area or on the edge of the view. For example,
9069      * if a view has a background drawable and you want to draw the scrollbars
9070      * inside the padding specified by the drawable, you can use
9071      * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
9072      * appear at the edge of the view, ignoring the padding, then you can use
9073      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
9074      * @param style the style of the scrollbars. Should be one of
9075      * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
9076      * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
9077      * @see #SCROLLBARS_INSIDE_OVERLAY
9078      * @see #SCROLLBARS_INSIDE_INSET
9079      * @see #SCROLLBARS_OUTSIDE_OVERLAY
9080      * @see #SCROLLBARS_OUTSIDE_INSET
9081      */
9082     public void setScrollBarStyle(int style) {
9083         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
9084             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
9085             computeOpaqueFlags();
9086             resolvePadding();
9087         }
9088     }
9089 
9090     /**
9091      * <p>Returns the current scrollbar style.</p>
9092      * @return the current scrollbar style
9093      * @see #SCROLLBARS_INSIDE_OVERLAY
9094      * @see #SCROLLBARS_INSIDE_INSET
9095      * @see #SCROLLBARS_OUTSIDE_OVERLAY
9096      * @see #SCROLLBARS_OUTSIDE_INSET
9097      */
9098     @ViewDebug.ExportedProperty(mapping = {
9099             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
9100             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
9101             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
9102             @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
9103     })
9104     public int getScrollBarStyle() {
9105         return mViewFlags & SCROLLBARS_STYLE_MASK;
9106     }
9107 
9108     /**
9109      * <p>Compute the horizontal range that the horizontal scrollbar
9110      * represents.</p>
9111      *
9112      * <p>The range is expressed in arbitrary units that must be the same as the
9113      * units used by {@link #computeHorizontalScrollExtent()} and
9114      * {@link #computeHorizontalScrollOffset()}.</p>
9115      *
9116      * <p>The default range is the drawing width of this view.</p>
9117      *
9118      * @return the total horizontal range represented by the horizontal
9119      *         scrollbar
9120      *
9121      * @see #computeHorizontalScrollExtent()
9122      * @see #computeHorizontalScrollOffset()
9123      * @see android.widget.ScrollBarDrawable
9124      */
9125     protected int computeHorizontalScrollRange() {
9126         return getWidth();
9127     }
9128 
9129     /**
9130      * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
9131      * within the horizontal range. This value is used to compute the position
9132      * of the thumb within the scrollbar's track.</p>
9133      *
9134      * <p>The range is expressed in arbitrary units that must be the same as the
9135      * units used by {@link #computeHorizontalScrollRange()} and
9136      * {@link #computeHorizontalScrollExtent()}.</p>
9137      *
9138      * <p>The default offset is the scroll offset of this view.</p>
9139      *
9140      * @return the horizontal offset of the scrollbar's thumb
9141      *
9142      * @see #computeHorizontalScrollRange()
9143      * @see #computeHorizontalScrollExtent()
9144      * @see android.widget.ScrollBarDrawable
9145      */
9146     protected int computeHorizontalScrollOffset() {
9147         return mScrollX;
9148     }
9149 
9150     /**
9151      * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
9152      * within the horizontal range. This value is used to compute the length
9153      * of the thumb within the scrollbar's track.</p>
9154      *
9155      * <p>The range is expressed in arbitrary units that must be the same as the
9156      * units used by {@link #computeHorizontalScrollRange()} and
9157      * {@link #computeHorizontalScrollOffset()}.</p>
9158      *
9159      * <p>The default extent is the drawing width of this view.</p>
9160      *
9161      * @return the horizontal extent of the scrollbar's thumb
9162      *
9163      * @see #computeHorizontalScrollRange()
9164      * @see #computeHorizontalScrollOffset()
9165      * @see android.widget.ScrollBarDrawable
9166      */
9167     protected int computeHorizontalScrollExtent() {
9168         return getWidth();
9169     }
9170 
9171     /**
9172      * <p>Compute the vertical range that the vertical scrollbar represents.</p>
9173      *
9174      * <p>The range is expressed in arbitrary units that must be the same as the
9175      * units used by {@link #computeVerticalScrollExtent()} and
9176      * {@link #computeVerticalScrollOffset()}.</p>
9177      *
9178      * @return the total vertical range represented by the vertical scrollbar
9179      *
9180      * <p>The default range is the drawing height of this view.</p>
9181      *
9182      * @see #computeVerticalScrollExtent()
9183      * @see #computeVerticalScrollOffset()
9184      * @see android.widget.ScrollBarDrawable
9185      */
9186     protected int computeVerticalScrollRange() {
9187         return getHeight();
9188     }
9189 
9190     /**
9191      * <p>Compute the vertical offset of the vertical scrollbar's thumb
9192      * within the horizontal range. This value is used to compute the position
9193      * of the thumb within the scrollbar's track.</p>
9194      *
9195      * <p>The range is expressed in arbitrary units that must be the same as the
9196      * units used by {@link #computeVerticalScrollRange()} and
9197      * {@link #computeVerticalScrollExtent()}.</p>
9198      *
9199      * <p>The default offset is the scroll offset of this view.</p>
9200      *
9201      * @return the vertical offset of the scrollbar's thumb
9202      *
9203      * @see #computeVerticalScrollRange()
9204      * @see #computeVerticalScrollExtent()
9205      * @see android.widget.ScrollBarDrawable
9206      */
9207     protected int computeVerticalScrollOffset() {
9208         return mScrollY;
9209     }
9210 
9211     /**
9212      * <p>Compute the vertical extent of the horizontal scrollbar's thumb
9213      * within the vertical range. This value is used to compute the length
9214      * of the thumb within the scrollbar's track.</p>
9215      *
9216      * <p>The range is expressed in arbitrary units that must be the same as the
9217      * units used by {@link #computeVerticalScrollRange()} and
9218      * {@link #computeVerticalScrollOffset()}.</p>
9219      *
9220      * <p>The default extent is the drawing height of this view.</p>
9221      *
9222      * @return the vertical extent of the scrollbar's thumb
9223      *
9224      * @see #computeVerticalScrollRange()
9225      * @see #computeVerticalScrollOffset()
9226      * @see android.widget.ScrollBarDrawable
9227      */
9228     protected int computeVerticalScrollExtent() {
9229         return getHeight();
9230     }
9231 
9232     /**
9233      * Check if this view can be scrolled horizontally in a certain direction.
9234      *
9235      * @param direction Negative to check scrolling left, positive to check scrolling right.
9236      * @return true if this view can be scrolled in the specified direction, false otherwise.
9237      */
9238     public boolean canScrollHorizontally(int direction) {
9239         final int offset = computeHorizontalScrollOffset();
9240         final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
9241         if (range == 0) return false;
9242         if (direction < 0) {
9243             return offset > 0;
9244         } else {
9245             return offset < range - 1;
9246         }
9247     }
9248 
9249     /**
9250      * Check if this view can be scrolled vertically in a certain direction.
9251      *
9252      * @param direction Negative to check scrolling up, positive to check scrolling down.
9253      * @return true if this view can be scrolled in the specified direction, false otherwise.
9254      */
9255     public boolean canScrollVertically(int direction) {
9256         final int offset = computeVerticalScrollOffset();
9257         final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
9258         if (range == 0) return false;
9259         if (direction < 0) {
9260             return offset > 0;
9261         } else {
9262             return offset < range - 1;
9263         }
9264     }
9265 
9266     /**
9267      * <p>Request the drawing of the horizontal and the vertical scrollbar. The
9268      * scrollbars are painted only if they have been awakened first.</p>
9269      *
9270      * @param canvas the canvas on which to draw the scrollbars
9271      *
9272      * @see #awakenScrollBars(int)
9273      */
9274     protected final void onDrawScrollBars(Canvas canvas) {
9275         // scrollbars are drawn only when the animation is running
9276         final ScrollabilityCache cache = mScrollCache;
9277         if (cache != null) {
9278 
9279             int state = cache.state;
9280 
9281             if (state == ScrollabilityCache.OFF) {
9282                 return;
9283             }
9284 
9285             boolean invalidate = false;
9286 
9287             if (state == ScrollabilityCache.FADING) {
9288                 // We're fading -- get our fade interpolation
9289                 if (cache.interpolatorValues == null) {
9290                     cache.interpolatorValues = new float[1];
9291                 }
9292 
9293                 float[] values = cache.interpolatorValues;
9294 
9295                 // Stops the animation if we're done
9296                 if (cache.scrollBarInterpolator.timeToValues(values) ==
9297                         Interpolator.Result.FREEZE_END) {
9298                     cache.state = ScrollabilityCache.OFF;
9299                 } else {
9300                     cache.scrollBar.setAlpha(Math.round(values[0]));
9301                 }
9302 
9303                 // This will make the scroll bars inval themselves after
9304                 // drawing. We only want this when we're fading so that
9305                 // we prevent excessive redraws
9306                 invalidate = true;
9307             } else {
9308                 // We're just on -- but we may have been fading before so
9309                 // reset alpha
9310                 cache.scrollBar.setAlpha(255);
9311             }
9312 
9313 
9314             final int viewFlags = mViewFlags;
9315 
9316             final boolean drawHorizontalScrollBar =
9317                 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
9318             final boolean drawVerticalScrollBar =
9319                 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
9320                 && !isVerticalScrollBarHidden();
9321 
9322             if (drawVerticalScrollBar || drawHorizontalScrollBar) {
9323                 final int width = mRight - mLeft;
9324                 final int height = mBottom - mTop;
9325 
9326                 final ScrollBarDrawable scrollBar = cache.scrollBar;
9327 
9328                 final int scrollX = mScrollX;
9329                 final int scrollY = mScrollY;
9330                 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
9331 
9332                 int left, top, right, bottom;
9333 
9334                 if (drawHorizontalScrollBar) {
9335                     int size = scrollBar.getSize(false);
9336                     if (size <= 0) {
9337                         size = cache.scrollBarSize;
9338                     }
9339 
9340                     scrollBar.setParameters(computeHorizontalScrollRange(),
9341                                             computeHorizontalScrollOffset(),
9342                                             computeHorizontalScrollExtent(), false);
9343                     final int verticalScrollBarGap = drawVerticalScrollBar ?
9344                             getVerticalScrollbarWidth() : 0;
9345                     top = scrollY + height - size - (mUserPaddingBottom & inside);
9346                     left = scrollX + (mPaddingLeft & inside);
9347                     right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
9348                     bottom = top + size;
9349                     onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
9350                     if (invalidate) {
9351                         invalidate(left, top, right, bottom);
9352                     }
9353                 }
9354 
9355                 if (drawVerticalScrollBar) {
9356                     int size = scrollBar.getSize(true);
9357                     if (size <= 0) {
9358                         size = cache.scrollBarSize;
9359                     }
9360 
9361                     scrollBar.setParameters(computeVerticalScrollRange(),
9362                                             computeVerticalScrollOffset(),
9363                                             computeVerticalScrollExtent(), true);
9364                     switch (mVerticalScrollbarPosition) {
9365                         default:
9366                         case SCROLLBAR_POSITION_DEFAULT:
9367                         case SCROLLBAR_POSITION_RIGHT:
9368                             left = scrollX + width - size - (mUserPaddingRight & inside);
9369                             break;
9370                         case SCROLLBAR_POSITION_LEFT:
9371                             left = scrollX + (mUserPaddingLeft & inside);
9372                             break;
9373                     }
9374                     top = scrollY + (mPaddingTop & inside);
9375                     right = left + size;
9376                     bottom = scrollY + height - (mUserPaddingBottom & inside);
9377                     onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
9378                     if (invalidate) {
9379                         invalidate(left, top, right, bottom);
9380                     }
9381                 }
9382             }
9383         }
9384     }
9385 
9386     /**
9387      * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
9388      * FastScroller is visible.
9389      * @return whether to temporarily hide the vertical scrollbar
9390      * @hide
9391      */
9392     protected boolean isVerticalScrollBarHidden() {
9393         return false;
9394     }
9395 
9396     /**
9397      * <p>Draw the horizontal scrollbar if
9398      * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
9399      *
9400      * @param canvas the canvas on which to draw the scrollbar
9401      * @param scrollBar the scrollbar's drawable
9402      *
9403      * @see #isHorizontalScrollBarEnabled()
9404      * @see #computeHorizontalScrollRange()
9405      * @see #computeHorizontalScrollExtent()
9406      * @see #computeHorizontalScrollOffset()
9407      * @see android.widget.ScrollBarDrawable
9408      * @hide
9409      */
9410     protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
9411             int l, int t, int r, int b) {
9412         scrollBar.setBounds(l, t, r, b);
9413         scrollBar.draw(canvas);
9414     }
9415 
9416     /**
9417      * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
9418      * returns true.</p>
9419      *
9420      * @param canvas the canvas on which to draw the scrollbar
9421      * @param scrollBar the scrollbar's drawable
9422      *
9423      * @see #isVerticalScrollBarEnabled()
9424      * @see #computeVerticalScrollRange()
9425      * @see #computeVerticalScrollExtent()
9426      * @see #computeVerticalScrollOffset()
9427      * @see android.widget.ScrollBarDrawable
9428      * @hide
9429      */
9430     protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
9431             int l, int t, int r, int b) {
9432         scrollBar.setBounds(l, t, r, b);
9433         scrollBar.draw(canvas);
9434     }
9435 
9436     /**
9437      * Implement this to do your drawing.
9438      *
9439      * @param canvas the canvas on which the background will be drawn
9440      */
9441     protected void onDraw(Canvas canvas) {
9442     }
9443 
9444     /*
9445      * Caller is responsible for calling requestLayout if necessary.
9446      * (This allows addViewInLayout to not request a new layout.)
9447      */
9448     void assignParent(ViewParent parent) {
9449         if (mParent == null) {
9450             mParent = parent;
9451         } else if (parent == null) {
9452             mParent = null;
9453         } else {
9454             throw new RuntimeException("view " + this + " being added, but"
9455                     + " it already has a parent");
9456         }
9457     }
9458 
9459     /**
9460      * This is called when the view is attached to a window.  At this point it
9461      * has a Surface and will start drawing.  Note that this function is
9462      * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
9463      * however it may be called any time before the first onDraw -- including
9464      * before or after {@link #onMeasure(int, int)}.
9465      *
9466      * @see #onDetachedFromWindow()
9467      */
9468     protected void onAttachedToWindow() {
9469         if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
9470             mParent.requestTransparentRegion(this);
9471         }
9472         if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
9473             initialAwakenScrollBars();
9474             mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
9475         }
9476         jumpDrawablesToCurrentState();
9477         // Order is important here: LayoutDirection MUST be resolved before Padding
9478         // and TextDirection
9479         resolveLayoutDirectionIfNeeded();
9480         resolvePadding();
9481         resolveTextDirection();
9482         if (isFocused()) {
9483             InputMethodManager imm = InputMethodManager.peekInstance();
9484             imm.focusIn(this);
9485         }
9486     }
9487 
9488     /**
9489      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
9490      * that the parent directionality can and will be resolved before its children.
9491      */
9492     private void resolveLayoutDirectionIfNeeded() {
9493         // Do not resolve if it is not needed
9494         if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) == LAYOUT_DIRECTION_RESOLVED) return;
9495 
9496         // Clear any previous layout direction resolution
9497         mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_RTL;
9498 
9499         // Reset also TextDirection as a change into LayoutDirection may impact the selected
9500         // TextDirectionHeuristic
9501         resetResolvedTextDirection();
9502 
9503         // Set resolved depending on layout direction
9504         switch (getLayoutDirection()) {
9505             case LAYOUT_DIRECTION_INHERIT:
9506                 // We cannot do the resolution if there is no parent
9507                 if (mParent == null) return;
9508 
9509                 // If this is root view, no need to look at parent's layout dir.
9510                 if (mParent instanceof ViewGroup) {
9511                     ViewGroup viewGroup = ((ViewGroup) mParent);
9512 
9513                     // Check if the parent view group can resolve
9514                     if (! viewGroup.canResolveLayoutDirection()) {
9515                         return;
9516                     }
9517                     if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
9518                         mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9519                     }
9520                 }
9521                 break;
9522             case LAYOUT_DIRECTION_RTL:
9523                 mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9524                 break;
9525             case LAYOUT_DIRECTION_LOCALE:
9526                 if(isLayoutDirectionRtl(Locale.getDefault())) {
9527                     mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9528                 }
9529                 break;
9530             default:
9531                 // Nothing to do, LTR by default
9532         }
9533 
9534         // Set to resolved
9535         mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
9536     }
9537 
9538     /**
9539      * @hide
9540      */
9541     protected void resolvePadding() {
9542         // If the user specified the absolute padding (either with android:padding or
9543         // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
9544         // use the default padding or the padding from the background drawable
9545         // (stored at this point in mPadding*)
9546         switch (getResolvedLayoutDirection()) {
9547             case LAYOUT_DIRECTION_RTL:
9548                 // Start user padding override Right user padding. Otherwise, if Right user
9549                 // padding is not defined, use the default Right padding. If Right user padding
9550                 // is defined, just use it.
9551                 if (mUserPaddingStart >= 0) {
9552                     mUserPaddingRight = mUserPaddingStart;
9553                 } else if (mUserPaddingRight < 0) {
9554                     mUserPaddingRight = mPaddingRight;
9555                 }
9556                 if (mUserPaddingEnd >= 0) {
9557                     mUserPaddingLeft = mUserPaddingEnd;
9558                 } else if (mUserPaddingLeft < 0) {
9559                     mUserPaddingLeft = mPaddingLeft;
9560                 }
9561                 break;
9562             case LAYOUT_DIRECTION_LTR:
9563             default:
9564                 // Start user padding override Left user padding. Otherwise, if Left user
9565                 // padding is not defined, use the default left padding. If Left user padding
9566                 // is defined, just use it.
9567                 if (mUserPaddingStart >= 0) {
9568                     mUserPaddingLeft = mUserPaddingStart;
9569                 } else if (mUserPaddingLeft < 0) {
9570                     mUserPaddingLeft = mPaddingLeft;
9571                 }
9572                 if (mUserPaddingEnd >= 0) {
9573                     mUserPaddingRight = mUserPaddingEnd;
9574                 } else if (mUserPaddingRight < 0) {
9575                     mUserPaddingRight = mPaddingRight;
9576                 }
9577         }
9578 
9579         mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
9580 
9581         recomputePadding();
9582     }
9583 
9584     /**
9585      * Return true if layout direction resolution can be done
9586      *
9587      * @hide
9588      */
9589     protected boolean canResolveLayoutDirection() {
9590         switch (getLayoutDirection()) {
9591             case LAYOUT_DIRECTION_INHERIT:
9592                 return (mParent != null);
9593             default:
9594                 return true;
9595         }
9596     }
9597 
9598     /**
9599      * Reset the resolved layout direction.
9600      *
9601      * Subclasses need to override this method to clear cached information that depends on the
9602      * resolved layout direction, or to inform child views that inherit their layout direction.
9603      * Overrides must also call the superclass implementation at the start of their implementation.
9604      *
9605      * @hide
9606      */
9607     protected void resetResolvedLayoutDirection() {
9608         // Reset the current View resolution
9609         mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED;
9610     }
9611 
9612     /**
9613      * Check if a Locale is corresponding to a RTL script.
9614      *
9615      * @param locale Locale to check
9616      * @return true if a Locale is corresponding to a RTL script.
9617      *
9618      * @hide
9619      */
9620     protected static boolean isLayoutDirectionRtl(Locale locale) {
9621         return (LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE ==
9622                 LocaleUtil.getLayoutDirectionFromLocale(locale));
9623     }
9624 
9625     /**
9626      * This is called when the view is detached from a window.  At this point it
9627      * no longer has a surface for drawing.
9628      *
9629      * @see #onAttachedToWindow()
9630      */
9631     protected void onDetachedFromWindow() {
9632         mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
9633 
9634         removeUnsetPressCallback();
9635         removeLongPressCallback();
9636         removePerformClickCallback();
9637         removeSendViewScrolledAccessibilityEventCallback();
9638 
9639         destroyDrawingCache();
9640 
9641         destroyLayer();
9642 
9643         if (mDisplayList != null) {
9644             mDisplayList.invalidate();
9645         }
9646 
9647         if (mAttachInfo != null) {
9648             mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_MSG, this);
9649         }
9650 
9651         mCurrentAnimation = null;
9652 
9653         resetResolvedLayoutDirection();
9654         resetResolvedTextDirection();
9655     }
9656 
9657     /**
9658      * @return The number of times this view has been attached to a window
9659      */
9660     protected int getWindowAttachCount() {
9661         return mWindowAttachCount;
9662     }
9663 
9664     /**
9665      * Retrieve a unique token identifying the window this view is attached to.
9666      * @return Return the window's token for use in
9667      * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
9668      */
9669     public IBinder getWindowToken() {
9670         return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
9671     }
9672 
9673     /**
9674      * Retrieve a unique token identifying the top-level "real" window of
9675      * the window that this view is attached to.  That is, this is like
9676      * {@link #getWindowToken}, except if the window this view in is a panel
9677      * window (attached to another containing window), then the token of
9678      * the containing window is returned instead.
9679      *
9680      * @return Returns the associated window token, either
9681      * {@link #getWindowToken()} or the containing window's token.
9682      */
9683     public IBinder getApplicationWindowToken() {
9684         AttachInfo ai = mAttachInfo;
9685         if (ai != null) {
9686             IBinder appWindowToken = ai.mPanelParentWindowToken;
9687             if (appWindowToken == null) {
9688                 appWindowToken = ai.mWindowToken;
9689             }
9690             return appWindowToken;
9691         }
9692         return null;
9693     }
9694 
9695     /**
9696      * Retrieve private session object this view hierarchy is using to
9697      * communicate with the window manager.
9698      * @return the session object to communicate with the window manager
9699      */
9700     /*package*/ IWindowSession getWindowSession() {
9701         return mAttachInfo != null ? mAttachInfo.mSession : null;
9702     }
9703 
9704     /**
9705      * @param info the {@link android.view.View.AttachInfo} to associated with
9706      *        this view
9707      */
9708     void dispatchAttachedToWindow(AttachInfo info, int visibility) {
9709         //System.out.println("Attached! " + this);
9710         mAttachInfo = info;
9711         mWindowAttachCount++;
9712         // We will need to evaluate the drawable state at least once.
9713         mPrivateFlags |= DRAWABLE_STATE_DIRTY;
9714         if (mFloatingTreeObserver != null) {
9715             info.mTreeObserver.merge(mFloatingTreeObserver);
9716             mFloatingTreeObserver = null;
9717         }
9718         if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
9719             mAttachInfo.mScrollContainers.add(this);
9720             mPrivateFlags |= SCROLL_CONTAINER_ADDED;
9721         }
9722         performCollectViewAttributes(visibility);
9723         onAttachedToWindow();
9724 
9725         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
9726                 mOnAttachStateChangeListeners;
9727         if (listeners != null && listeners.size() > 0) {
9728             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
9729             // perform the dispatching. The iterator is a safe guard against listeners that
9730             // could mutate the list by calling the various add/remove methods. This prevents
9731             // the array from being modified while we iterate it.
9732             for (OnAttachStateChangeListener listener : listeners) {
9733                 listener.onViewAttachedToWindow(this);
9734             }
9735         }
9736 
9737         int vis = info.mWindowVisibility;
9738         if (vis != GONE) {
9739             onWindowVisibilityChanged(vis);
9740         }
9741         if ((mPrivateFlags&DRAWABLE_STATE_DIRTY) != 0) {
9742             // If nobody has evaluated the drawable state yet, then do it now.
9743             refreshDrawableState();
9744         }
9745     }
9746 
9747     void dispatchDetachedFromWindow() {
9748         AttachInfo info = mAttachInfo;
9749         if (info != null) {
9750             int vis = info.mWindowVisibility;
9751             if (vis != GONE) {
9752                 onWindowVisibilityChanged(GONE);
9753             }
9754         }
9755 
9756         onDetachedFromWindow();
9757 
9758         final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
9759                 mOnAttachStateChangeListeners;
9760         if (listeners != null && listeners.size() > 0) {
9761             // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
9762             // perform the dispatching. The iterator is a safe guard against listeners that
9763             // could mutate the list by calling the various add/remove methods. This prevents
9764             // the array from being modified while we iterate it.
9765             for (OnAttachStateChangeListener listener : listeners) {
9766                 listener.onViewDetachedFromWindow(this);
9767             }
9768         }
9769 
9770         if ((mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0) {
9771             mAttachInfo.mScrollContainers.remove(this);
9772             mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
9773         }
9774 
9775         mAttachInfo = null;
9776     }
9777 
9778     /**
9779      * Store this view hierarchy's frozen state into the given container.
9780      *
9781      * @param container The SparseArray in which to save the view's state.
9782      *
9783      * @see #restoreHierarchyState(android.util.SparseArray)
9784      * @see #dispatchSaveInstanceState(android.util.SparseArray)
9785      * @see #onSaveInstanceState()
9786      */
9787     public void saveHierarchyState(SparseArray<Parcelable> container) {
9788         dispatchSaveInstanceState(container);
9789     }
9790 
9791     /**
9792      * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
9793      * this view and its children. May be overridden to modify how freezing happens to a
9794      * view's children; for example, some views may want to not store state for their children.
9795      *
9796      * @param container The SparseArray in which to save the view's state.
9797      *
9798      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
9799      * @see #saveHierarchyState(android.util.SparseArray)
9800      * @see #onSaveInstanceState()
9801      */
9802     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
9803         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
9804             mPrivateFlags &= ~SAVE_STATE_CALLED;
9805             Parcelable state = onSaveInstanceState();
9806             if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
9807                 throw new IllegalStateException(
9808                         "Derived class did not call super.onSaveInstanceState()");
9809             }
9810             if (state != null) {
9811                 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
9812                 // + ": " + state);
9813                 container.put(mID, state);
9814             }
9815         }
9816     }
9817 
9818     /**
9819      * Hook allowing a view to generate a representation of its internal state
9820      * that can later be used to create a new instance with that same state.
9821      * This state should only contain information that is not persistent or can
9822      * not be reconstructed later. For example, you will never store your
9823      * current position on screen because that will be computed again when a
9824      * new instance of the view is placed in its view hierarchy.
9825      * <p>
9826      * Some examples of things you may store here: the current cursor position
9827      * in a text view (but usually not the text itself since that is stored in a
9828      * content provider or other persistent storage), the currently selected
9829      * item in a list view.
9830      *
9831      * @return Returns a Parcelable object containing the view's current dynamic
9832      *         state, or null if there is nothing interesting to save. The
9833      *         default implementation returns null.
9834      * @see #onRestoreInstanceState(android.os.Parcelable)
9835      * @see #saveHierarchyState(android.util.SparseArray)
9836      * @see #dispatchSaveInstanceState(android.util.SparseArray)
9837      * @see #setSaveEnabled(boolean)
9838      */
9839     protected Parcelable onSaveInstanceState() {
9840         mPrivateFlags |= SAVE_STATE_CALLED;
9841         return BaseSavedState.EMPTY_STATE;
9842     }
9843 
9844     /**
9845      * Restore this view hierarchy's frozen state from the given container.
9846      *
9847      * @param container The SparseArray which holds previously frozen states.
9848      *
9849      * @see #saveHierarchyState(android.util.SparseArray)
9850      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
9851      * @see #onRestoreInstanceState(android.os.Parcelable)
9852      */
9853     public void restoreHierarchyState(SparseArray<Parcelable> container) {
9854         dispatchRestoreInstanceState(container);
9855     }
9856 
9857     /**
9858      * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
9859      * state for this view and its children. May be overridden to modify how restoring
9860      * happens to a view's children; for example, some views may want to not store state
9861      * for their children.
9862      *
9863      * @param container The SparseArray which holds previously saved state.
9864      *
9865      * @see #dispatchSaveInstanceState(android.util.SparseArray)
9866      * @see #restoreHierarchyState(android.util.SparseArray)
9867      * @see #onRestoreInstanceState(android.os.Parcelable)
9868      */
9869     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
9870         if (mID != NO_ID) {
9871             Parcelable state = container.get(mID);
9872             if (state != null) {
9873                 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
9874                 // + ": " + state);
9875                 mPrivateFlags &= ~SAVE_STATE_CALLED;
9876                 onRestoreInstanceState(state);
9877                 if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
9878                     throw new IllegalStateException(
9879                             "Derived class did not call super.onRestoreInstanceState()");
9880                 }
9881             }
9882         }
9883     }
9884 
9885     /**
9886      * Hook allowing a view to re-apply a representation of its internal state that had previously
9887      * been generated by {@link #onSaveInstanceState}. This function will never be called with a
9888      * null state.
9889      *
9890      * @param state The frozen state that had previously been returned by
9891      *        {@link #onSaveInstanceState}.
9892      *
9893      * @see #onSaveInstanceState()
9894      * @see #restoreHierarchyState(android.util.SparseArray)
9895      * @see #dispatchRestoreInstanceState(android.util.SparseArray)
9896      */
9897     protected void onRestoreInstanceState(Parcelable state) {
9898         mPrivateFlags |= SAVE_STATE_CALLED;
9899         if (state != BaseSavedState.EMPTY_STATE && state != null) {
9900             throw new IllegalArgumentException("Wrong state class, expecting View State but "
9901                     + "received " + state.getClass().toString() + " instead. This usually happens "
9902                     + "when two views of different type have the same id in the same hierarchy. "
9903                     + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
9904                     + "other views do not use the same id.");
9905         }
9906     }
9907 
9908     /**
9909      * <p>Return the time at which the drawing of the view hierarchy started.</p>
9910      *
9911      * @return the drawing start time in milliseconds
9912      */
9913     public long getDrawingTime() {
9914         return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
9915     }
9916 
9917     /**
9918      * <p>Enables or disables the duplication of the parent's state into this view. When
9919      * duplication is enabled, this view gets its drawable state from its parent rather
9920      * than from its own internal properties.</p>
9921      *
9922      * <p>Note: in the current implementation, setting this property to true after the
9923      * view was added to a ViewGroup might have no effect at all. This property should
9924      * always be used from XML or set to true before adding this view to a ViewGroup.</p>
9925      *
9926      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
9927      * property is enabled, an exception will be thrown.</p>
9928      *
9929      * <p>Note: if the child view uses and updates additionnal states which are unknown to the
9930      * parent, these states should not be affected by this method.</p>
9931      *
9932      * @param enabled True to enable duplication of the parent's drawable state, false
9933      *                to disable it.
9934      *
9935      * @see #getDrawableState()
9936      * @see #isDuplicateParentStateEnabled()
9937      */
9938     public void setDuplicateParentStateEnabled(boolean enabled) {
9939         setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
9940     }
9941 
9942     /**
9943      * <p>Indicates whether this duplicates its drawable state from its parent.</p>
9944      *
9945      * @return True if this view's drawable state is duplicated from the parent,
9946      *         false otherwise
9947      *
9948      * @see #getDrawableState()
9949      * @see #setDuplicateParentStateEnabled(boolean)
9950      */
9951     public boolean isDuplicateParentStateEnabled() {
9952         return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
9953     }
9954 
9955     /**
9956      * <p>Specifies the type of layer backing this view. The layer can be
9957      * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
9958      * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
9959      *
9960      * <p>A layer is associated with an optional {@link android.graphics.Paint}
9961      * instance that controls how the layer is composed on screen. The following
9962      * properties of the paint are taken into account when composing the layer:</p>
9963      * <ul>
9964      * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
9965      * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
9966      * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
9967      * </ul>
9968      *
9969      * <p>If this view has an alpha value set to < 1.0 by calling
9970      * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
9971      * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
9972      * equivalent to setting a hardware layer on this view and providing a paint with
9973      * the desired alpha value.<p>
9974      *
9975      * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
9976      * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
9977      * for more information on when and how to use layers.</p>
9978      *
9979      * @param layerType The ype of layer to use with this view, must be one of
9980      *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
9981      *        {@link #LAYER_TYPE_HARDWARE}
9982      * @param paint The paint used to compose the layer. This argument is optional
9983      *        and can be null. It is ignored when the layer type is
9984      *        {@link #LAYER_TYPE_NONE}
9985      *
9986      * @see #getLayerType()
9987      * @see #LAYER_TYPE_NONE
9988      * @see #LAYER_TYPE_SOFTWARE
9989      * @see #LAYER_TYPE_HARDWARE
9990      * @see #setAlpha(float)
9991      *
9992      * @attr ref android.R.styleable#View_layerType
9993      */
9994     public void setLayerType(int layerType, Paint paint) {
9995         if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
9996             throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
9997                     + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
9998         }
9999 
10000         if (layerType == mLayerType) {
10001             if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
10002                 mLayerPaint = paint == null ? new Paint() : paint;
10003                 invalidateParentCaches();
10004                 invalidate(true);
10005             }
10006             return;
10007         }
10008 
10009         // Destroy any previous software drawing cache if needed
10010         switch (mLayerType) {
10011             case LAYER_TYPE_HARDWARE:
10012                 destroyLayer();
10013                 // fall through - unaccelerated views may use software layer mechanism instead
10014             case LAYER_TYPE_SOFTWARE:
10015                 destroyDrawingCache();
10016                 break;
10017             default:
10018                 break;
10019         }
10020 
10021         mLayerType = layerType;
10022         final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
10023         mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
10024         mLocalDirtyRect = layerDisabled ? null : new Rect();
10025 
10026         invalidateParentCaches();
10027         invalidate(true);
10028     }
10029 
10030     /**
10031      * Indicates whether this view has a static layer. A view with layer type
10032      * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
10033      * dynamic.
10034      */
10035     boolean hasStaticLayer() {
10036         return mLayerType == LAYER_TYPE_NONE;
10037     }
10038 
10039     /**
10040      * Indicates what type of layer is currently associated with this view. By default
10041      * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
10042      * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
10043      * for more information on the different types of layers.
10044      *
10045      * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
10046      *         {@link #LAYER_TYPE_HARDWARE}
10047      *
10048      * @see #setLayerType(int, android.graphics.Paint)
10049      * @see #buildLayer()
10050      * @see #LAYER_TYPE_NONE
10051      * @see #LAYER_TYPE_SOFTWARE
10052      * @see #LAYER_TYPE_HARDWARE
10053      */
10054     public int getLayerType() {
10055         return mLayerType;
10056     }
10057 
10058     /**
10059      * Forces this view's layer to be created and this view to be rendered
10060      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
10061      * invoking this method will have no effect.
10062      *
10063      * This method can for instance be used to render a view into its layer before
10064      * starting an animation. If this view is complex, rendering into the layer
10065      * before starting the animation will avoid skipping frames.
10066      *
10067      * @throws IllegalStateException If this view is not attached to a window
10068      *
10069      * @see #setLayerType(int, android.graphics.Paint)
10070      */
10071     public void buildLayer() {
10072         if (mLayerType == LAYER_TYPE_NONE) return;
10073 
10074         if (mAttachInfo == null) {
10075             throw new IllegalStateException("This view must be attached to a window first");
10076         }
10077 
10078         switch (mLayerType) {
10079             case LAYER_TYPE_HARDWARE:
10080                 getHardwareLayer();
10081                 break;
10082             case LAYER_TYPE_SOFTWARE:
10083                 buildDrawingCache(true);
10084                 break;
10085         }
10086     }
10087 
10088     /**
10089      * <p>Returns a hardware layer that can be used to draw this view again
10090      * without executing its draw method.</p>
10091      *
10092      * @return A HardwareLayer ready to render, or null if an error occurred.
10093      */
10094     HardwareLayer getHardwareLayer() {
10095         if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
10096                 !mAttachInfo.mHardwareRenderer.isEnabled()) {
10097             return null;
10098         }
10099 
10100         final int width = mRight - mLeft;
10101         final int height = mBottom - mTop;
10102 
10103         if (width == 0 || height == 0) {
10104             return null;
10105         }
10106 
10107         if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
10108             if (mHardwareLayer == null) {
10109                 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
10110                         width, height, isOpaque());
10111                 mLocalDirtyRect.setEmpty();
10112             } else if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
10113                 mHardwareLayer.resize(width, height);
10114                 mLocalDirtyRect.setEmpty();
10115             }
10116 
10117             HardwareCanvas currentCanvas = mAttachInfo.mHardwareCanvas;
10118             final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas);
10119             mAttachInfo.mHardwareCanvas = canvas;
10120             try {
10121                 canvas.setViewport(width, height);
10122                 canvas.onPreDraw(mLocalDirtyRect);
10123                 mLocalDirtyRect.setEmpty();
10124 
10125                 final int restoreCount = canvas.save();
10126 
10127                 computeScroll();
10128                 canvas.translate(-mScrollX, -mScrollY);
10129 
10130                 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10131 
10132                 // Fast path for layouts with no backgrounds
10133                 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10134                     mPrivateFlags &= ~DIRTY_MASK;
10135                     dispatchDraw(canvas);
10136                 } else {
10137                     draw(canvas);
10138                 }
10139 
10140                 canvas.restoreToCount(restoreCount);
10141             } finally {
10142                 canvas.onPostDraw();
10143                 mHardwareLayer.end(currentCanvas);
10144                 mAttachInfo.mHardwareCanvas = currentCanvas;
10145             }
10146         }
10147 
10148         return mHardwareLayer;
10149     }
10150 
10151     /**
10152      * Destroys this View's hardware layer if possible.
10153      *
10154      * @return True if the layer was destroyed, false otherwise.
10155      *
10156      * @see #setLayerType(int, android.graphics.Paint)
10157      * @see #LAYER_TYPE_HARDWARE
10158      */
10159     boolean destroyLayer() {
10160         if (mHardwareLayer != null) {
10161             mHardwareLayer.destroy();
10162             mHardwareLayer = null;
10163             return true;
10164         }
10165         return false;
10166     }
10167 
10168     /**
10169      * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
10170      * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
10171      * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
10172      * the cache is enabled. To benefit from the cache, you must request the drawing cache by
10173      * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
10174      * null.</p>
10175      *
10176      * <p>Enabling the drawing cache is similar to
10177      * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
10178      * acceleration is turned off. When hardware acceleration is turned on, enabling the
10179      * drawing cache has no effect on rendering because the system uses a different mechanism
10180      * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
10181      * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
10182      * for information on how to enable software and hardware layers.</p>
10183      *
10184      * <p>This API can be used to manually generate
10185      * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
10186      * {@link #getDrawingCache()}.</p>
10187      *
10188      * @param enabled true to enable the drawing cache, false otherwise
10189      *
10190      * @see #isDrawingCacheEnabled()
10191      * @see #getDrawingCache()
10192      * @see #buildDrawingCache()
10193      * @see #setLayerType(int, android.graphics.Paint)
10194      */
10195     public void setDrawingCacheEnabled(boolean enabled) {
10196         mCachingFailed = false;
10197         setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
10198     }
10199 
10200     /**
10201      * <p>Indicates whether the drawing cache is enabled for this view.</p>
10202      *
10203      * @return true if the drawing cache is enabled
10204      *
10205      * @see #setDrawingCacheEnabled(boolean)
10206      * @see #getDrawingCache()
10207      */
10208     @ViewDebug.ExportedProperty(category = "drawing")
10209     public boolean isDrawingCacheEnabled() {
10210         return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
10211     }
10212 
10213     /**
10214      * Debugging utility which recursively outputs the dirty state of a view and its
10215      * descendants.
10216      *
10217      * @hide
10218      */
10219     @SuppressWarnings({"UnusedDeclaration"})
10220     public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
10221         Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.DIRTY_MASK) +
10222                 ") DRAWN(" + (mPrivateFlags & DRAWN) + ")" + " CACHE_VALID(" +
10223                 (mPrivateFlags & View.DRAWING_CACHE_VALID) +
10224                 ") INVALIDATED(" + (mPrivateFlags & INVALIDATED) + ")");
10225         if (clear) {
10226             mPrivateFlags &= clearMask;
10227         }
10228         if (this instanceof ViewGroup) {
10229             ViewGroup parent = (ViewGroup) this;
10230             final int count = parent.getChildCount();
10231             for (int i = 0; i < count; i++) {
10232                 final View child = parent.getChildAt(i);
10233                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
10234             }
10235         }
10236     }
10237 
10238     /**
10239      * This method is used by ViewGroup to cause its children to restore or recreate their
10240      * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
10241      * to recreate its own display list, which would happen if it went through the normal
10242      * draw/dispatchDraw mechanisms.
10243      *
10244      * @hide
10245      */
10246     protected void dispatchGetDisplayList() {}
10247 
10248     /**
10249      * A view that is not attached or hardware accelerated cannot create a display list.
10250      * This method checks these conditions and returns the appropriate result.
10251      *
10252      * @return true if view has the ability to create a display list, false otherwise.
10253      *
10254      * @hide
10255      */
10256     public boolean canHaveDisplayList() {
10257         return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
10258     }
10259 
10260     /**
10261      * <p>Returns a display list that can be used to draw this view again
10262      * without executing its draw method.</p>
10263      *
10264      * @return A DisplayList ready to replay, or null if caching is not enabled.
10265      *
10266      * @hide
10267      */
10268     public DisplayList getDisplayList() {
10269         if (!canHaveDisplayList()) {
10270             return null;
10271         }
10272 
10273         if (((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
10274                 mDisplayList == null || !mDisplayList.isValid() ||
10275                 mRecreateDisplayList)) {
10276             // Don't need to recreate the display list, just need to tell our
10277             // children to restore/recreate theirs
10278             if (mDisplayList != null && mDisplayList.isValid() &&
10279                     !mRecreateDisplayList) {
10280                 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10281                 mPrivateFlags &= ~DIRTY_MASK;
10282                 dispatchGetDisplayList();
10283 
10284                 return mDisplayList;
10285             }
10286 
10287             // If we got here, we're recreating it. Mark it as such to ensure that
10288             // we copy in child display lists into ours in drawChild()
10289             mRecreateDisplayList = true;
10290             if (mDisplayList == null) {
10291                 mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList();
10292                 // If we're creating a new display list, make sure our parent gets invalidated
10293                 // since they will need to recreate their display list to account for this
10294                 // new child display list.
10295                 invalidateParentCaches();
10296             }
10297 
10298             final HardwareCanvas canvas = mDisplayList.start();
10299             int restoreCount = 0;
10300             try {
10301                 int width = mRight - mLeft;
10302                 int height = mBottom - mTop;
10303 
10304                 canvas.setViewport(width, height);
10305                 // The dirty rect should always be null for a display list
10306                 canvas.onPreDraw(null);
10307 
10308                 computeScroll();
10309 
10310                 restoreCount = canvas.save();
10311                 canvas.translate(-mScrollX, -mScrollY);
10312                 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10313                 mPrivateFlags &= ~DIRTY_MASK;
10314 
10315                 // Fast path for layouts with no backgrounds
10316                 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10317                     dispatchDraw(canvas);
10318                 } else {
10319                     draw(canvas);
10320                 }
10321             } finally {
10322                 canvas.restoreToCount(restoreCount);
10323                 canvas.onPostDraw();
10324 
10325                 mDisplayList.end();
10326             }
10327         } else {
10328             mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10329             mPrivateFlags &= ~DIRTY_MASK;
10330         }
10331 
10332         return mDisplayList;
10333     }
10334 
10335     /**
10336      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
10337      *
10338      * @return A non-scaled bitmap representing this view or null if cache is disabled.
10339      *
10340      * @see #getDrawingCache(boolean)
10341      */
10342     public Bitmap getDrawingCache() {
10343         return getDrawingCache(false);
10344     }
10345 
10346     /**
10347      * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
10348      * is null when caching is disabled. If caching is enabled and the cache is not ready,
10349      * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
10350      * draw from the cache when the cache is enabled. To benefit from the cache, you must
10351      * request the drawing cache by calling this method and draw it on screen if the
10352      * returned bitmap is not null.</p>
10353      *
10354      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
10355      * this method will create a bitmap of the same size as this view. Because this bitmap
10356      * will be drawn scaled by the parent ViewGroup, the result on screen might show
10357      * scaling artifacts. To avoid such artifacts, you should call this method by setting
10358      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
10359      * size than the view. This implies that your application must be able to handle this
10360      * size.</p>
10361      *
10362      * @param autoScale Indicates whether the generated bitmap should be scaled based on
10363      *        the current density of the screen when the application is in compatibility
10364      *        mode.
10365      *
10366      * @return A bitmap representing this view or null if cache is disabled.
10367      *
10368      * @see #setDrawingCacheEnabled(boolean)
10369      * @see #isDrawingCacheEnabled()
10370      * @see #buildDrawingCache(boolean)
10371      * @see #destroyDrawingCache()
10372      */
10373     public Bitmap getDrawingCache(boolean autoScale) {
10374         if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
10375             return null;
10376         }
10377         if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
10378             buildDrawingCache(autoScale);
10379         }
10380         return autoScale ? mDrawingCache : mUnscaledDrawingCache;
10381     }
10382 
10383     /**
10384      * <p>Frees the resources used by the drawing cache. If you call
10385      * {@link #buildDrawingCache()} manually without calling
10386      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
10387      * should cleanup the cache with this method afterwards.</p>
10388      *
10389      * @see #setDrawingCacheEnabled(boolean)
10390      * @see #buildDrawingCache()
10391      * @see #getDrawingCache()
10392      */
10393     public void destroyDrawingCache() {
10394         if (mDrawingCache != null) {
10395             mDrawingCache.recycle();
10396             mDrawingCache = null;
10397         }
10398         if (mUnscaledDrawingCache != null) {
10399             mUnscaledDrawingCache.recycle();
10400             mUnscaledDrawingCache = null;
10401         }
10402     }
10403 
10404     /**
10405      * Setting a solid background color for the drawing cache's bitmaps will improve
10406      * performance and memory usage. Note, though that this should only be used if this
10407      * view will always be drawn on top of a solid color.
10408      *
10409      * @param color The background color to use for the drawing cache's bitmap
10410      *
10411      * @see #setDrawingCacheEnabled(boolean)
10412      * @see #buildDrawingCache()
10413      * @see #getDrawingCache()
10414      */
10415     public void setDrawingCacheBackgroundColor(int color) {
10416         if (color != mDrawingCacheBackgroundColor) {
10417             mDrawingCacheBackgroundColor = color;
10418             mPrivateFlags &= ~DRAWING_CACHE_VALID;
10419         }
10420     }
10421 
10422     /**
10423      * @see #setDrawingCacheBackgroundColor(int)
10424      *
10425      * @return The background color to used for the drawing cache's bitmap
10426      */
10427     public int getDrawingCacheBackgroundColor() {
10428         return mDrawingCacheBackgroundColor;
10429     }
10430 
10431     /**
10432      * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
10433      *
10434      * @see #buildDrawingCache(boolean)
10435      */
10436     public void buildDrawingCache() {
10437         buildDrawingCache(false);
10438     }
10439 
10440     /**
10441      * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
10442      *
10443      * <p>If you call {@link #buildDrawingCache()} manually without calling
10444      * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
10445      * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
10446      *
10447      * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
10448      * this method will create a bitmap of the same size as this view. Because this bitmap
10449      * will be drawn scaled by the parent ViewGroup, the result on screen might show
10450      * scaling artifacts. To avoid such artifacts, you should call this method by setting
10451      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
10452      * size than the view. This implies that your application must be able to handle this
10453      * size.</p>
10454      *
10455      * <p>You should avoid calling this method when hardware acceleration is enabled. If
10456      * you do not need the drawing cache bitmap, calling this method will increase memory
10457      * usage and cause the view to be rendered in software once, thus negatively impacting
10458      * performance.</p>
10459      *
10460      * @see #getDrawingCache()
10461      * @see #destroyDrawingCache()
10462      */
10463     public void buildDrawingCache(boolean autoScale) {
10464         if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
10465                 mDrawingCache == null : mUnscaledDrawingCache == null)) {
10466             mCachingFailed = false;
10467 
10468             if (ViewDebug.TRACE_HIERARCHY) {
10469                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
10470             }
10471 
10472             int width = mRight - mLeft;
10473             int height = mBottom - mTop;
10474 
10475             final AttachInfo attachInfo = mAttachInfo;
10476             final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
10477 
10478             if (autoScale && scalingRequired) {
10479                 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
10480                 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
10481             }
10482 
10483             final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
10484             final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
10485             final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
10486 
10487             if (width <= 0 || height <= 0 ||
10488                      // Projected bitmap size in bytes
10489                     (width * height * (opaque && !use32BitCache ? 2 : 4) >
10490                             ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
10491                 destroyDrawingCache();
10492                 mCachingFailed = true;
10493                 return;
10494             }
10495 
10496             boolean clear = true;
10497             Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
10498 
10499             if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
10500                 Bitmap.Config quality;
10501                 if (!opaque) {
10502                     // Never pick ARGB_4444 because it looks awful
10503                     // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
10504                     switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
10505                         case DRAWING_CACHE_QUALITY_AUTO:
10506                             quality = Bitmap.Config.ARGB_8888;
10507                             break;
10508                         case DRAWING_CACHE_QUALITY_LOW:
10509                             quality = Bitmap.Config.ARGB_8888;
10510                             break;
10511                         case DRAWING_CACHE_QUALITY_HIGH:
10512                             quality = Bitmap.Config.ARGB_8888;
10513                             break;
10514                         default:
10515                             quality = Bitmap.Config.ARGB_8888;
10516                             break;
10517                     }
10518                 } else {
10519                     // Optimization for translucent windows
10520                     // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
10521                     quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
10522                 }
10523 
10524                 // Try to cleanup memory
10525                 if (bitmap != null) bitmap.recycle();
10526 
10527                 try {
10528                     bitmap = Bitmap.createBitmap(width, height, quality);
10529                     bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
10530                     if (autoScale) {
10531                         mDrawingCache = bitmap;
10532                     } else {
10533                         mUnscaledDrawingCache = bitmap;
10534                     }
10535                     if (opaque && use32BitCache) bitmap.setHasAlpha(false);
10536                 } catch (OutOfMemoryError e) {
10537                     // If there is not enough memory to create the bitmap cache, just
10538                     // ignore the issue as bitmap caches are not required to draw the
10539                     // view hierarchy
10540                     if (autoScale) {
10541                         mDrawingCache = null;
10542                     } else {
10543                         mUnscaledDrawingCache = null;
10544                     }
10545                     mCachingFailed = true;
10546                     return;
10547                 }
10548 
10549                 clear = drawingCacheBackgroundColor != 0;
10550             }
10551 
10552             Canvas canvas;
10553             if (attachInfo != null) {
10554                 canvas = attachInfo.mCanvas;
10555                 if (canvas == null) {
10556                     canvas = new Canvas();
10557                 }
10558                 canvas.setBitmap(bitmap);
10559                 // Temporarily clobber the cached Canvas in case one of our children
10560                 // is also using a drawing cache. Without this, the children would
10561                 // steal the canvas by attaching their own bitmap to it and bad, bad
10562                 // thing would happen (invisible views, corrupted drawings, etc.)
10563                 attachInfo.mCanvas = null;
10564             } else {
10565                 // This case should hopefully never or seldom happen
10566                 canvas = new Canvas(bitmap);
10567             }
10568 
10569             if (clear) {
10570                 bitmap.eraseColor(drawingCacheBackgroundColor);
10571             }
10572 
10573             computeScroll();
10574             final int restoreCount = canvas.save();
10575 
10576             if (autoScale && scalingRequired) {
10577                 final float scale = attachInfo.mApplicationScale;
10578                 canvas.scale(scale, scale);
10579             }
10580 
10581             canvas.translate(-mScrollX, -mScrollY);
10582 
10583             mPrivateFlags |= DRAWN;
10584             if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
10585                     mLayerType != LAYER_TYPE_NONE) {
10586                 mPrivateFlags |= DRAWING_CACHE_VALID;
10587             }
10588 
10589             // Fast path for layouts with no backgrounds
10590             if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10591                 if (ViewDebug.TRACE_HIERARCHY) {
10592                     ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
10593                 }
10594                 mPrivateFlags &= ~DIRTY_MASK;
10595                 dispatchDraw(canvas);
10596             } else {
10597                 draw(canvas);
10598             }
10599 
10600             canvas.restoreToCount(restoreCount);
10601             canvas.setBitmap(null);
10602 
10603             if (attachInfo != null) {
10604                 // Restore the cached Canvas for our siblings
10605                 attachInfo.mCanvas = canvas;
10606             }
10607         }
10608     }
10609 
10610     /**
10611      * Create a snapshot of the view into a bitmap.  We should probably make
10612      * some form of this public, but should think about the API.
10613      */
10614     Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
10615         int width = mRight - mLeft;
10616         int height = mBottom - mTop;
10617 
10618         final AttachInfo attachInfo = mAttachInfo;
10619         final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
10620         width = (int) ((width * scale) + 0.5f);
10621         height = (int) ((height * scale) + 0.5f);
10622 
10623         Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
10624         if (bitmap == null) {
10625             throw new OutOfMemoryError();
10626         }
10627 
10628         Resources resources = getResources();
10629         if (resources != null) {
10630             bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
10631         }
10632 
10633         Canvas canvas;
10634         if (attachInfo != null) {
10635             canvas = attachInfo.mCanvas;
10636             if (canvas == null) {
10637                 canvas = new Canvas();
10638             }
10639             canvas.setBitmap(bitmap);
10640             // Temporarily clobber the cached Canvas in case one of our children
10641             // is also using a drawing cache. Without this, the children would
10642             // steal the canvas by attaching their own bitmap to it and bad, bad
10643             // things would happen (invisible views, corrupted drawings, etc.)
10644             attachInfo.mCanvas = null;
10645         } else {
10646             // This case should hopefully never or seldom happen
10647             canvas = new Canvas(bitmap);
10648         }
10649 
10650         if ((backgroundColor & 0xff000000) != 0) {
10651             bitmap.eraseColor(backgroundColor);
10652         }
10653 
10654         computeScroll();
10655         final int restoreCount = canvas.save();
10656         canvas.scale(scale, scale);
10657         canvas.translate(-mScrollX, -mScrollY);
10658 
10659         // Temporarily remove the dirty mask
10660         int flags = mPrivateFlags;
10661         mPrivateFlags &= ~DIRTY_MASK;
10662 
10663         // Fast path for layouts with no backgrounds
10664         if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10665             dispatchDraw(canvas);
10666         } else {
10667             draw(canvas);
10668         }
10669 
10670         mPrivateFlags = flags;
10671 
10672         canvas.restoreToCount(restoreCount);
10673         canvas.setBitmap(null);
10674 
10675         if (attachInfo != null) {
10676             // Restore the cached Canvas for our siblings
10677             attachInfo.mCanvas = canvas;
10678         }
10679 
10680         return bitmap;
10681     }
10682 
10683     /**
10684      * Indicates whether this View is currently in edit mode. A View is usually
10685      * in edit mode when displayed within a developer tool. For instance, if
10686      * this View is being drawn by a visual user interface builder, this method
10687      * should return true.
10688      *
10689      * Subclasses should check the return value of this method to provide
10690      * different behaviors if their normal behavior might interfere with the
10691      * host environment. For instance: the class spawns a thread in its
10692      * constructor, the drawing code relies on device-specific features, etc.
10693      *
10694      * This method is usually checked in the drawing code of custom widgets.
10695      *
10696      * @return True if this View is in edit mode, false otherwise.
10697      */
10698     public boolean isInEditMode() {
10699         return false;
10700     }
10701 
10702     /**
10703      * If the View draws content inside its padding and enables fading edges,
10704      * it needs to support padding offsets. Padding offsets are added to the
10705      * fading edges to extend the length of the fade so that it covers pixels
10706      * drawn inside the padding.
10707      *
10708      * Subclasses of this class should override this method if they need
10709      * to draw content inside the padding.
10710      *
10711      * @return True if padding offset must be applied, false otherwise.
10712      *
10713      * @see #getLeftPaddingOffset()
10714      * @see #getRightPaddingOffset()
10715      * @see #getTopPaddingOffset()
10716      * @see #getBottomPaddingOffset()
10717      *
10718      * @since CURRENT
10719      */
10720     protected boolean isPaddingOffsetRequired() {
10721         return false;
10722     }
10723 
10724     /**
10725      * Amount by which to extend the left fading region. Called only when
10726      * {@link #isPaddingOffsetRequired()} returns true.
10727      *
10728      * @return The left padding offset in pixels.
10729      *
10730      * @see #isPaddingOffsetRequired()
10731      *
10732      * @since CURRENT
10733      */
10734     protected int getLeftPaddingOffset() {
10735         return 0;
10736     }
10737 
10738     /**
10739      * Amount by which to extend the right fading region. Called only when
10740      * {@link #isPaddingOffsetRequired()} returns true.
10741      *
10742      * @return The right padding offset in pixels.
10743      *
10744      * @see #isPaddingOffsetRequired()
10745      *
10746      * @since CURRENT
10747      */
10748     protected int getRightPaddingOffset() {
10749         return 0;
10750     }
10751 
10752     /**
10753      * Amount by which to extend the top fading region. Called only when
10754      * {@link #isPaddingOffsetRequired()} returns true.
10755      *
10756      * @return The top padding offset in pixels.
10757      *
10758      * @see #isPaddingOffsetRequired()
10759      *
10760      * @since CURRENT
10761      */
10762     protected int getTopPaddingOffset() {
10763         return 0;
10764     }
10765 
10766     /**
10767      * Amount by which to extend the bottom fading region. Called only when
10768      * {@link #isPaddingOffsetRequired()} returns true.
10769      *
10770      * @return The bottom padding offset in pixels.
10771      *
10772      * @see #isPaddingOffsetRequired()
10773      *
10774      * @since CURRENT
10775      */
10776     protected int getBottomPaddingOffset() {
10777         return 0;
10778     }
10779 
10780     /**
10781      * @hide
10782      * @param offsetRequired
10783      */
10784     protected int getFadeTop(boolean offsetRequired) {
10785         int top = mPaddingTop;
10786         if (offsetRequired) top += getTopPaddingOffset();
10787         return top;
10788     }
10789 
10790     /**
10791      * @hide
10792      * @param offsetRequired
10793      */
10794     protected int getFadeHeight(boolean offsetRequired) {
10795         int padding = mPaddingTop;
10796         if (offsetRequired) padding += getTopPaddingOffset();
10797         return mBottom - mTop - mPaddingBottom - padding;
10798     }
10799 
10800     /**
10801      * <p>Indicates whether this view is attached to an hardware accelerated
10802      * window or not.</p>
10803      *
10804      * <p>Even if this method returns true, it does not mean that every call
10805      * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
10806      * accelerated {@link android.graphics.Canvas}. For instance, if this view
10807      * is drawn onto an offscren {@link android.graphics.Bitmap} and its
10808      * window is hardware accelerated,
10809      * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
10810      * return false, and this method will return true.</p>
10811      *
10812      * @return True if the view is attached to a window and the window is
10813      *         hardware accelerated; false in any other case.
10814      */
10815     public boolean isHardwareAccelerated() {
10816         return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
10817     }
10818 
10819     /**
10820      * Manually render this view (and all of its children) to the given Canvas.
10821      * The view must have already done a full layout before this function is
10822      * called.  When implementing a view, implement
10823      * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
10824      * If you do need to override this method, call the superclass version.
10825      *
10826      * @param canvas The Canvas to which the View is rendered.
10827      */
10828     public void draw(Canvas canvas) {
10829         if (ViewDebug.TRACE_HIERARCHY) {
10830             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
10831         }
10832 
10833         final int privateFlags = mPrivateFlags;
10834         final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
10835                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
10836         mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
10837 
10838         /*
10839          * Draw traversal performs several drawing steps which must be executed
10840          * in the appropriate order:
10841          *
10842          *      1. Draw the background
10843          *      2. If necessary, save the canvas' layers to prepare for fading
10844          *      3. Draw view's content
10845          *      4. Draw children
10846          *      5. If necessary, draw the fading edges and restore layers
10847          *      6. Draw decorations (scrollbars for instance)
10848          */
10849 
10850         // Step 1, draw the background, if needed
10851         int saveCount;
10852 
10853         if (!dirtyOpaque) {
10854             final Drawable background = mBGDrawable;
10855             if (background != null) {
10856                 final int scrollX = mScrollX;
10857                 final int scrollY = mScrollY;
10858 
10859                 if (mBackgroundSizeChanged) {
10860                     background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
10861                     mBackgroundSizeChanged = false;
10862                 }
10863 
10864                 if ((scrollX | scrollY) == 0) {
10865                     background.draw(canvas);
10866                 } else {
10867                     canvas.translate(scrollX, scrollY);
10868                     background.draw(canvas);
10869                     canvas.translate(-scrollX, -scrollY);
10870                 }
10871             }
10872         }
10873 
10874         // skip step 2 & 5 if possible (common case)
10875         final int viewFlags = mViewFlags;
10876         boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
10877         boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
10878         if (!verticalEdges && !horizontalEdges) {
10879             // Step 3, draw the content
10880             if (!dirtyOpaque) onDraw(canvas);
10881 
10882             // Step 4, draw the children
10883             dispatchDraw(canvas);
10884 
10885             // Step 6, draw decorations (scrollbars)
10886             onDrawScrollBars(canvas);
10887 
10888             // we're done...
10889             return;
10890         }
10891 
10892         /*
10893          * Here we do the full fledged routine...
10894          * (this is an uncommon case where speed matters less,
10895          * this is why we repeat some of the tests that have been
10896          * done above)
10897          */
10898 
10899         boolean drawTop = false;
10900         boolean drawBottom = false;
10901         boolean drawLeft = false;
10902         boolean drawRight = false;
10903 
10904         float topFadeStrength = 0.0f;
10905         float bottomFadeStrength = 0.0f;
10906         float leftFadeStrength = 0.0f;
10907         float rightFadeStrength = 0.0f;
10908 
10909         // Step 2, save the canvas' layers
10910         int paddingLeft = mPaddingLeft;
10911 
10912         final boolean offsetRequired = isPaddingOffsetRequired();
10913         if (offsetRequired) {
10914             paddingLeft += getLeftPaddingOffset();
10915         }
10916 
10917         int left = mScrollX + paddingLeft;
10918         int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
10919         int top = mScrollY + getFadeTop(offsetRequired);
10920         int bottom = top + getFadeHeight(offsetRequired);
10921 
10922         if (offsetRequired) {
10923             right += getRightPaddingOffset();
10924             bottom += getBottomPaddingOffset();
10925         }
10926 
10927         final ScrollabilityCache scrollabilityCache = mScrollCache;
10928         final float fadeHeight = scrollabilityCache.fadingEdgeLength;
10929         int length = (int) fadeHeight;
10930 
10931         // clip the fade length if top and bottom fades overlap
10932         // overlapping fades produce odd-looking artifacts
10933         if (verticalEdges && (top + length > bottom - length)) {
10934             length = (bottom - top) / 2;
10935         }
10936 
10937         // also clip horizontal fades if necessary
10938         if (horizontalEdges && (left + length > right - length)) {
10939             length = (right - left) / 2;
10940         }
10941 
10942         if (verticalEdges) {
10943             topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
10944             drawTop = topFadeStrength * fadeHeight > 1.0f;
10945             bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
10946             drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
10947         }
10948 
10949         if (horizontalEdges) {
10950             leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
10951             drawLeft = leftFadeStrength * fadeHeight > 1.0f;
10952             rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
10953             drawRight = rightFadeStrength * fadeHeight > 1.0f;
10954         }
10955 
10956         saveCount = canvas.getSaveCount();
10957 
10958         int solidColor = getSolidColor();
10959         if (solidColor == 0) {
10960             final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
10961 
10962             if (drawTop) {
10963                 canvas.saveLayer(left, top, right, top + length, null, flags);
10964             }
10965 
10966             if (drawBottom) {
10967                 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
10968             }
10969 
10970             if (drawLeft) {
10971                 canvas.saveLayer(left, top, left + length, bottom, null, flags);
10972             }
10973 
10974             if (drawRight) {
10975                 canvas.saveLayer(right - length, top, right, bottom, null, flags);
10976             }
10977         } else {
10978             scrollabilityCache.setFadeColor(solidColor);
10979         }
10980 
10981         // Step 3, draw the content
10982         if (!dirtyOpaque) onDraw(canvas);
10983 
10984         // Step 4, draw the children
10985         dispatchDraw(canvas);
10986 
10987         // Step 5, draw the fade effect and restore layers
10988         final Paint p = scrollabilityCache.paint;
10989         final Matrix matrix = scrollabilityCache.matrix;
10990         final Shader fade = scrollabilityCache.shader;
10991 
10992         if (drawTop) {
10993             matrix.setScale(1, fadeHeight * topFadeStrength);
10994             matrix.postTranslate(left, top);
10995             fade.setLocalMatrix(matrix);
10996             canvas.drawRect(left, top, right, top + length, p);
10997         }
10998 
10999         if (drawBottom) {
11000             matrix.setScale(1, fadeHeight * bottomFadeStrength);
11001             matrix.postRotate(180);
11002             matrix.postTranslate(left, bottom);
11003             fade.setLocalMatrix(matrix);
11004             canvas.drawRect(left, bottom - length, right, bottom, p);
11005         }
11006 
11007         if (drawLeft) {
11008             matrix.setScale(1, fadeHeight * leftFadeStrength);
11009             matrix.postRotate(-90);
11010             matrix.postTranslate(left, top);
11011             fade.setLocalMatrix(matrix);
11012             canvas.drawRect(left, top, left + length, bottom, p);
11013         }
11014 
11015         if (drawRight) {
11016             matrix.setScale(1, fadeHeight * rightFadeStrength);
11017             matrix.postRotate(90);
11018             matrix.postTranslate(right, top);
11019             fade.setLocalMatrix(matrix);
11020             canvas.drawRect(right - length, top, right, bottom, p);
11021         }
11022 
11023         canvas.restoreToCount(saveCount);
11024 
11025         // Step 6, draw decorations (scrollbars)
11026         onDrawScrollBars(canvas);
11027     }
11028 
11029     /**
11030      * Override this if your view is known to always be drawn on top of a solid color background,
11031      * and needs to draw fading edges. Returning a non-zero color enables the view system to
11032      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
11033      * should be set to 0xFF.
11034      *
11035      * @see #setVerticalFadingEdgeEnabled(boolean)
11036      * @see #setHorizontalFadingEdgeEnabled(boolean)
11037      *
11038      * @return The known solid color background for this view, or 0 if the color may vary
11039      */
11040     @ViewDebug.ExportedProperty(category = "drawing")
11041     public int getSolidColor() {
11042         return 0;
11043     }
11044 
11045     /**
11046      * Build a human readable string representation of the specified view flags.
11047      *
11048      * @param flags the view flags to convert to a string
11049      * @return a String representing the supplied flags
11050      */
11051     private static String printFlags(int flags) {
11052         String output = "";
11053         int numFlags = 0;
11054         if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
11055             output += "TAKES_FOCUS";
11056             numFlags++;
11057         }
11058 
11059         switch (flags & VISIBILITY_MASK) {
11060         case INVISIBLE:
11061             if (numFlags > 0) {
11062                 output += " ";
11063             }
11064             output += "INVISIBLE";
11065             // USELESS HERE numFlags++;
11066             break;
11067         case GONE:
11068             if (numFlags > 0) {
11069                 output += " ";
11070             }
11071             output += "GONE";
11072             // USELESS HERE numFlags++;
11073             break;
11074         default:
11075             break;
11076         }
11077         return output;
11078     }
11079 
11080     /**
11081      * Build a human readable string representation of the specified private
11082      * view flags.
11083      *
11084      * @param privateFlags the private view flags to convert to a string
11085      * @return a String representing the supplied flags
11086      */
11087     private static String printPrivateFlags(int privateFlags) {
11088         String output = "";
11089         int numFlags = 0;
11090 
11091         if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
11092             output += "WANTS_FOCUS";
11093             numFlags++;
11094         }
11095 
11096         if ((privateFlags & FOCUSED) == FOCUSED) {
11097             if (numFlags > 0) {
11098                 output += " ";
11099             }
11100             output += "FOCUSED";
11101             numFlags++;
11102         }
11103 
11104         if ((privateFlags & SELECTED) == SELECTED) {
11105             if (numFlags > 0) {
11106                 output += " ";
11107             }
11108             output += "SELECTED";
11109             numFlags++;
11110         }
11111 
11112         if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
11113             if (numFlags > 0) {
11114                 output += " ";
11115             }
11116             output += "IS_ROOT_NAMESPACE";
11117             numFlags++;
11118         }
11119 
11120         if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
11121             if (numFlags > 0) {
11122                 output += " ";
11123             }
11124             output += "HAS_BOUNDS";
11125             numFlags++;
11126         }
11127 
11128         if ((privateFlags & DRAWN) == DRAWN) {
11129             if (numFlags > 0) {
11130                 output += " ";
11131             }
11132             output += "DRAWN";
11133             // USELESS HERE numFlags++;
11134         }
11135         return output;
11136     }
11137 
11138     /**
11139      * <p>Indicates whether or not this view's layout will be requested during
11140      * the next hierarchy layout pass.</p>
11141      *
11142      * @return true if the layout will be forced during next layout pass
11143      */
11144     public boolean isLayoutRequested() {
11145         return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
11146     }
11147 
11148     /**
11149      * Assign a size and position to a view and all of its
11150      * descendants
11151      *
11152      * <p>This is the second phase of the layout mechanism.
11153      * (The first is measuring). In this phase, each parent calls
11154      * layout on all of its children to position them.
11155      * This is typically done using the child measurements
11156      * that were stored in the measure pass().</p>
11157      *
11158      * <p>Derived classes should not override this method.
11159      * Derived classes with children should override
11160      * onLayout. In that method, they should
11161      * call layout on each of their children.</p>
11162      *
11163      * @param l Left position, relative to parent
11164      * @param t Top position, relative to parent
11165      * @param r Right position, relative to parent
11166      * @param b Bottom position, relative to parent
11167      */
11168     @SuppressWarnings({"unchecked"})
11169     public void layout(int l, int t, int r, int b) {
11170         int oldL = mLeft;
11171         int oldT = mTop;
11172         int oldB = mBottom;
11173         int oldR = mRight;
11174         boolean changed = setFrame(l, t, r, b);
11175         if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
11176             if (ViewDebug.TRACE_HIERARCHY) {
11177                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
11178             }
11179 
11180             onLayout(changed, l, t, r, b);
11181             mPrivateFlags &= ~LAYOUT_REQUIRED;
11182 
11183             if (mOnLayoutChangeListeners != null) {
11184                 ArrayList<OnLayoutChangeListener> listenersCopy =
11185                         (ArrayList<OnLayoutChangeListener>) mOnLayoutChangeListeners.clone();
11186                 int numListeners = listenersCopy.size();
11187                 for (int i = 0; i < numListeners; ++i) {
11188                     listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
11189                 }
11190             }
11191         }
11192         mPrivateFlags &= ~FORCE_LAYOUT;
11193     }
11194 
11195     /**
11196      * Called from layout when this view should
11197      * assign a size and position to each of its children.
11198      *
11199      * Derived classes with children should override
11200      * this method and call layout on each of
11201      * their children.
11202      * @param changed This is a new size or position for this view
11203      * @param left Left position, relative to parent
11204      * @param top Top position, relative to parent
11205      * @param right Right position, relative to parent
11206      * @param bottom Bottom position, relative to parent
11207      */
11208     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
11209     }
11210 
11211     /**
11212      * Assign a size and position to this view.
11213      *
11214      * This is called from layout.
11215      *
11216      * @param left Left position, relative to parent
11217      * @param top Top position, relative to parent
11218      * @param right Right position, relative to parent
11219      * @param bottom Bottom position, relative to parent
11220      * @return true if the new size and position are different than the
11221      *         previous ones
11222      * {@hide}
11223      */
11224     protected boolean setFrame(int left, int top, int right, int bottom) {
11225         boolean changed = false;
11226 
11227         if (DBG) {
11228             Log.d("View", this + " View.setFrame(" + left + "," + top + ","
11229                     + right + "," + bottom + ")");
11230         }
11231 
11232         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
11233             changed = true;
11234 
11235             // Remember our drawn bit
11236             int drawn = mPrivateFlags & DRAWN;
11237 
11238             int oldWidth = mRight - mLeft;
11239             int oldHeight = mBottom - mTop;
11240             int newWidth = right - left;
11241             int newHeight = bottom - top;
11242             boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
11243 
11244             // Invalidate our old position
11245             invalidate(sizeChanged);
11246 
11247             mLeft = left;
11248             mTop = top;
11249             mRight = right;
11250             mBottom = bottom;
11251 
11252             mPrivateFlags |= HAS_BOUNDS;
11253 
11254 
11255             if (sizeChanged) {
11256                 if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
11257                     // A change in dimension means an auto-centered pivot point changes, too
11258                     if (mTransformationInfo != null) {
11259                         mTransformationInfo.mMatrixDirty = true;
11260                     }
11261                 }
11262                 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
11263             }
11264 
11265             if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
11266                 // If we are visible, force the DRAWN bit to on so that
11267                 // this invalidate will go through (at least to our parent).
11268                 // This is because someone may have invalidated this view
11269                 // before this call to setFrame came in, thereby clearing
11270                 // the DRAWN bit.
11271                 mPrivateFlags |= DRAWN;
11272                 invalidate(sizeChanged);
11273                 // parent display list may need to be recreated based on a change in the bounds
11274                 // of any child
11275                 invalidateParentCaches();
11276             }
11277 
11278             // Reset drawn bit to original value (invalidate turns it off)
11279             mPrivateFlags |= drawn;
11280 
11281             mBackgroundSizeChanged = true;
11282         }
11283         return changed;
11284     }
11285 
11286     /**
11287      * Finalize inflating a view from XML.  This is called as the last phase
11288      * of inflation, after all child views have been added.
11289      *
11290      * <p>Even if the subclass overrides onFinishInflate, they should always be
11291      * sure to call the super method, so that we get called.
11292      */
11293     protected void onFinishInflate() {
11294     }
11295 
11296     /**
11297      * Returns the resources associated with this view.
11298      *
11299      * @return Resources object.
11300      */
11301     public Resources getResources() {
11302         return mResources;
11303     }
11304 
11305     /**
11306      * Invalidates the specified Drawable.
11307      *
11308      * @param drawable the drawable to invalidate
11309      */
11310     public void invalidateDrawable(Drawable drawable) {
11311         if (verifyDrawable(drawable)) {
11312             final Rect dirty = drawable.getBounds();
11313             final int scrollX = mScrollX;
11314             final int scrollY = mScrollY;
11315 
11316             invalidate(dirty.left + scrollX, dirty.top + scrollY,
11317                     dirty.right + scrollX, dirty.bottom + scrollY);
11318         }
11319     }
11320 
11321     /**
11322      * Schedules an action on a drawable to occur at a specified time.
11323      *
11324      * @param who the recipient of the action
11325      * @param what the action to run on the drawable
11326      * @param when the time at which the action must occur. Uses the
11327      *        {@link SystemClock#uptimeMillis} timebase.
11328      */
11329     public void scheduleDrawable(Drawable who, Runnable what, long when) {
11330         if (verifyDrawable(who) && what != null && mAttachInfo != null) {
11331             mAttachInfo.mHandler.postAtTime(what, who, when);
11332         }
11333     }
11334 
11335     /**
11336      * Cancels a scheduled action on a drawable.
11337      *
11338      * @param who the recipient of the action
11339      * @param what the action to cancel
11340      */
11341     public void unscheduleDrawable(Drawable who, Runnable what) {
11342         if (verifyDrawable(who) && what != null && mAttachInfo != null) {
11343             mAttachInfo.mHandler.removeCallbacks(what, who);
11344         }
11345     }
11346 
11347     /**
11348      * Unschedule any events associated with the given Drawable.  This can be
11349      * used when selecting a new Drawable into a view, so that the previous
11350      * one is completely unscheduled.
11351      *
11352      * @param who The Drawable to unschedule.
11353      *
11354      * @see #drawableStateChanged
11355      */
11356     public void unscheduleDrawable(Drawable who) {
11357         if (mAttachInfo != null) {
11358             mAttachInfo.mHandler.removeCallbacksAndMessages(who);
11359         }
11360     }
11361 
11362     /**
11363     * Return the layout direction of a given Drawable.
11364     *
11365     * @param who the Drawable to query
11366     *
11367     * @hide
11368     */
11369     public int getResolvedLayoutDirection(Drawable who) {
11370         return (who == mBGDrawable) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT;
11371     }
11372 
11373     /**
11374      * If your view subclass is displaying its own Drawable objects, it should
11375      * override this function and return true for any Drawable it is
11376      * displaying.  This allows animations for those drawables to be
11377      * scheduled.
11378      *
11379      * <p>Be sure to call through to the super class when overriding this
11380      * function.
11381      *
11382      * @param who The Drawable to verify.  Return true if it is one you are
11383      *            displaying, else return the result of calling through to the
11384      *            super class.
11385      *
11386      * @return boolean If true than the Drawable is being displayed in the
11387      *         view; else false and it is not allowed to animate.
11388      *
11389      * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
11390      * @see #drawableStateChanged()
11391      */
11392     protected boolean verifyDrawable(Drawable who) {
11393         return who == mBGDrawable;
11394     }
11395 
11396     /**
11397      * This function is called whenever the state of the view changes in such
11398      * a way that it impacts the state of drawables being shown.
11399      *
11400      * <p>Be sure to call through to the superclass when overriding this
11401      * function.
11402      *
11403      * @see Drawable#setState(int[])
11404      */
11405     protected void drawableStateChanged() {
11406         Drawable d = mBGDrawable;
11407         if (d != null && d.isStateful()) {
11408             d.setState(getDrawableState());
11409         }
11410     }
11411 
11412     /**
11413      * Call this to force a view to update its drawable state. This will cause
11414      * drawableStateChanged to be called on this view. Views that are interested
11415      * in the new state should call getDrawableState.
11416      *
11417      * @see #drawableStateChanged
11418      * @see #getDrawableState
11419      */
11420     public void refreshDrawableState() {
11421         mPrivateFlags |= DRAWABLE_STATE_DIRTY;
11422         drawableStateChanged();
11423 
11424         ViewParent parent = mParent;
11425         if (parent != null) {
11426             parent.childDrawableStateChanged(this);
11427         }
11428     }
11429 
11430     /**
11431      * Return an array of resource IDs of the drawable states representing the
11432      * current state of the view.
11433      *
11434      * @return The current drawable state
11435      *
11436      * @see Drawable#setState(int[])
11437      * @see #drawableStateChanged()
11438      * @see #onCreateDrawableState(int)
11439      */
11440     public final int[] getDrawableState() {
11441         if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
11442             return mDrawableState;
11443         } else {
11444             mDrawableState = onCreateDrawableState(0);
11445             mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
11446             return mDrawableState;
11447         }
11448     }
11449 
11450     /**
11451      * Generate the new {@link android.graphics.drawable.Drawable} state for
11452      * this view. This is called by the view
11453      * system when the cached Drawable state is determined to be invalid.  To
11454      * retrieve the current state, you should use {@link #getDrawableState}.
11455      *
11456      * @param extraSpace if non-zero, this is the number of extra entries you
11457      * would like in the returned array in which you can place your own
11458      * states.
11459      *
11460      * @return Returns an array holding the current {@link Drawable} state of
11461      * the view.
11462      *
11463      * @see #mergeDrawableStates(int[], int[])
11464      */
11465     protected int[] onCreateDrawableState(int extraSpace) {
11466         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
11467                 mParent instanceof View) {
11468             return ((View) mParent).onCreateDrawableState(extraSpace);
11469         }
11470 
11471         int[] drawableState;
11472 
11473         int privateFlags = mPrivateFlags;
11474 
11475         int viewStateIndex = 0;
11476         if ((privateFlags & PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
11477         if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
11478         if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
11479         if ((privateFlags & SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
11480         if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
11481         if ((privateFlags & ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
11482         if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
11483                 HardwareRenderer.isAvailable()) {
11484             // This is set if HW acceleration is requested, even if the current
11485             // process doesn't allow it.  This is just to allow app preview
11486             // windows to better match their app.
11487             viewStateIndex |= VIEW_STATE_ACCELERATED;
11488         }
11489         if ((privateFlags & HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
11490 
11491         final int privateFlags2 = mPrivateFlags2;
11492         if ((privateFlags2 & DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
11493         if ((privateFlags2 & DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
11494 
11495         drawableState = VIEW_STATE_SETS[viewStateIndex];
11496 
11497         //noinspection ConstantIfStatement
11498         if (false) {
11499             Log.i("View", "drawableStateIndex=" + viewStateIndex);
11500             Log.i("View", toString()
11501                     + " pressed=" + ((privateFlags & PRESSED) != 0)
11502                     + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
11503                     + " fo=" + hasFocus()
11504                     + " sl=" + ((privateFlags & SELECTED) != 0)
11505                     + " wf=" + hasWindowFocus()
11506                     + ": " + Arrays.toString(drawableState));
11507         }
11508 
11509         if (extraSpace == 0) {
11510             return drawableState;
11511         }
11512 
11513         final int[] fullState;
11514         if (drawableState != null) {
11515             fullState = new int[drawableState.length + extraSpace];
11516             System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
11517         } else {
11518             fullState = new int[extraSpace];
11519         }
11520 
11521         return fullState;
11522     }
11523 
11524     /**
11525      * Merge your own state values in <var>additionalState</var> into the base
11526      * state values <var>baseState</var> that were returned by
11527      * {@link #onCreateDrawableState(int)}.
11528      *
11529      * @param baseState The base state values returned by
11530      * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
11531      * own additional state values.
11532      *
11533      * @param additionalState The additional state values you would like
11534      * added to <var>baseState</var>; this array is not modified.
11535      *
11536      * @return As a convenience, the <var>baseState</var> array you originally
11537      * passed into the function is returned.
11538      *
11539      * @see #onCreateDrawableState(int)
11540      */
11541     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
11542         final int N = baseState.length;
11543         int i = N - 1;
11544         while (i >= 0 && baseState[i] == 0) {
11545             i--;
11546         }
11547         System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
11548         return baseState;
11549     }
11550 
11551     /**
11552      * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
11553      * on all Drawable objects associated with this view.
11554      */
11555     public void jumpDrawablesToCurrentState() {
11556         if (mBGDrawable != null) {
11557             mBGDrawable.jumpToCurrentState();
11558         }
11559     }
11560 
11561     /**
11562      * Sets the background color for this view.
11563      * @param color the color of the background
11564      */
11565     @RemotableViewMethod
11566     public void setBackgroundColor(int color) {
11567         if (mBGDrawable instanceof ColorDrawable) {
11568             ((ColorDrawable) mBGDrawable).setColor(color);
11569         } else {
11570             setBackgroundDrawable(new ColorDrawable(color));
11571         }
11572     }
11573 
11574     /**
11575      * Set the background to a given resource. The resource should refer to
11576      * a Drawable object or 0 to remove the background.
11577      * @param resid The identifier of the resource.
11578      * @attr ref android.R.styleable#View_background
11579      */
11580     @RemotableViewMethod
11581     public void setBackgroundResource(int resid) {
11582         if (resid != 0 && resid == mBackgroundResource) {
11583             return;
11584         }
11585 
11586         Drawable d= null;
11587         if (resid != 0) {
11588             d = mResources.getDrawable(resid);
11589         }
11590         setBackgroundDrawable(d);
11591 
11592         mBackgroundResource = resid;
11593     }
11594 
11595     /**
11596      * Set the background to a given Drawable, or remove the background. If the
11597      * background has padding, this View's padding is set to the background's
11598      * padding. However, when a background is removed, this View's padding isn't
11599      * touched. If setting the padding is desired, please use
11600      * {@link #setPadding(int, int, int, int)}.
11601      *
11602      * @param d The Drawable to use as the background, or null to remove the
11603      *        background
11604      */
11605     public void setBackgroundDrawable(Drawable d) {
11606         if (d == mBGDrawable) {
11607             return;
11608         }
11609 
11610         boolean requestLayout = false;
11611 
11612         mBackgroundResource = 0;
11613 
11614         /*
11615          * Regardless of whether we're setting a new background or not, we want
11616          * to clear the previous drawable.
11617          */
11618         if (mBGDrawable != null) {
11619             mBGDrawable.setCallback(null);
11620             unscheduleDrawable(mBGDrawable);
11621         }
11622 
11623         if (d != null) {
11624             Rect padding = sThreadLocal.get();
11625             if (padding == null) {
11626                 padding = new Rect();
11627                 sThreadLocal.set(padding);
11628             }
11629             if (d.getPadding(padding)) {
11630                 switch (d.getResolvedLayoutDirectionSelf()) {
11631                     case LAYOUT_DIRECTION_RTL:
11632                         setPadding(padding.right, padding.top, padding.left, padding.bottom);
11633                         break;
11634                     case LAYOUT_DIRECTION_LTR:
11635                     default:
11636                         setPadding(padding.left, padding.top, padding.right, padding.bottom);
11637                 }
11638             }
11639 
11640             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
11641             // if it has a different minimum size, we should layout again
11642             if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
11643                     mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
11644                 requestLayout = true;
11645             }
11646 
11647             d.setCallback(this);
11648             if (d.isStateful()) {
11649                 d.setState(getDrawableState());
11650             }
11651             d.setVisible(getVisibility() == VISIBLE, false);
11652             mBGDrawable = d;
11653 
11654             if ((mPrivateFlags & SKIP_DRAW) != 0) {
11655                 mPrivateFlags &= ~SKIP_DRAW;
11656                 mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
11657                 requestLayout = true;
11658             }
11659         } else {
11660             /* Remove the background */
11661             mBGDrawable = null;
11662 
11663             if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
11664                 /*
11665                  * This view ONLY drew the background before and we're removing
11666                  * the background, so now it won't draw anything
11667                  * (hence we SKIP_DRAW)
11668                  */
11669                 mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
11670                 mPrivateFlags |= SKIP_DRAW;
11671             }
11672 
11673             /*
11674              * When the background is set, we try to apply its padding to this
11675              * View. When the background is removed, we don't touch this View's
11676              * padding. This is noted in the Javadocs. Hence, we don't need to
11677              * requestLayout(), the invalidate() below is sufficient.
11678              */
11679 
11680             // The old background's minimum size could have affected this
11681             // View's layout, so let's requestLayout
11682             requestLayout = true;
11683         }
11684 
11685         computeOpaqueFlags();
11686 
11687         if (requestLayout) {
11688             requestLayout();
11689         }
11690 
11691         mBackgroundSizeChanged = true;
11692         invalidate(true);
11693     }
11694 
11695     /**
11696      * Gets the background drawable
11697      * @return The drawable used as the background for this view, if any.
11698      */
11699     public Drawable getBackground() {
11700         return mBGDrawable;
11701     }
11702 
11703     /**
11704      * Sets the padding. The view may add on the space required to display
11705      * the scrollbars, depending on the style and visibility of the scrollbars.
11706      * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
11707      * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
11708      * from the values set in this call.
11709      *
11710      * @attr ref android.R.styleable#View_padding
11711      * @attr ref android.R.styleable#View_paddingBottom
11712      * @attr ref android.R.styleable#View_paddingLeft
11713      * @attr ref android.R.styleable#View_paddingRight
11714      * @attr ref android.R.styleable#View_paddingTop
11715      * @param left the left padding in pixels
11716      * @param top the top padding in pixels
11717      * @param right the right padding in pixels
11718      * @param bottom the bottom padding in pixels
11719      */
11720     public void setPadding(int left, int top, int right, int bottom) {
11721         boolean changed = false;
11722 
11723         mUserPaddingRelative = false;
11724 
11725         mUserPaddingLeft = left;
11726         mUserPaddingRight = right;
11727         mUserPaddingBottom = bottom;
11728 
11729         final int viewFlags = mViewFlags;
11730 
11731         // Common case is there are no scroll bars.
11732         if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
11733             if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
11734                 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
11735                         ? 0 : getVerticalScrollbarWidth();
11736                 switch (mVerticalScrollbarPosition) {
11737                     case SCROLLBAR_POSITION_DEFAULT:
11738                         if (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
11739                             left += offset;
11740                         } else {
11741                             right += offset;
11742                         }
11743                         break;
11744                     case SCROLLBAR_POSITION_RIGHT:
11745                         right += offset;
11746                         break;
11747                     case SCROLLBAR_POSITION_LEFT:
11748                         left += offset;
11749                         break;
11750                 }
11751             }
11752             if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
11753                 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
11754                         ? 0 : getHorizontalScrollbarHeight();
11755             }
11756         }
11757 
11758         if (mPaddingLeft != left) {
11759             changed = true;
11760             mPaddingLeft = left;
11761         }
11762         if (mPaddingTop != top) {
11763             changed = true;
11764             mPaddingTop = top;
11765         }
11766         if (mPaddingRight != right) {
11767             changed = true;
11768             mPaddingRight = right;
11769         }
11770         if (mPaddingBottom != bottom) {
11771             changed = true;
11772             mPaddingBottom = bottom;
11773         }
11774 
11775         if (changed) {
11776             requestLayout();
11777         }
11778     }
11779 
11780     /**
11781      * Sets the relative padding. The view may add on the space required to display
11782      * the scrollbars, depending on the style and visibility of the scrollbars.
11783      * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
11784      * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
11785      * from the values set in this call.
11786      *
11787      * @attr ref android.R.styleable#View_padding
11788      * @attr ref android.R.styleable#View_paddingBottom
11789      * @attr ref android.R.styleable#View_paddingStart
11790      * @attr ref android.R.styleable#View_paddingEnd
11791      * @attr ref android.R.styleable#View_paddingTop
11792      * @param start the start padding in pixels
11793      * @param top the top padding in pixels
11794      * @param end the end padding in pixels
11795      * @param bottom the bottom padding in pixels
11796      *
11797      * @hide
11798      */
11799     public void setPaddingRelative(int start, int top, int end, int bottom) {
11800         mUserPaddingRelative = true;
11801 
11802         mUserPaddingStart = start;
11803         mUserPaddingEnd = end;
11804 
11805         switch(getResolvedLayoutDirection()) {
11806             case LAYOUT_DIRECTION_RTL:
11807                 setPadding(end, top, start, bottom);
11808                 break;
11809             case LAYOUT_DIRECTION_LTR:
11810             default:
11811                 setPadding(start, top, end, bottom);
11812         }
11813     }
11814 
11815     /**
11816      * Returns the top padding of this view.
11817      *
11818      * @return the top padding in pixels
11819      */
11820     public int getPaddingTop() {
11821         return mPaddingTop;
11822     }
11823 
11824     /**
11825      * Returns the bottom padding of this view. If there are inset and enabled
11826      * scrollbars, this value may include the space required to display the
11827      * scrollbars as well.
11828      *
11829      * @return the bottom padding in pixels
11830      */
11831     public int getPaddingBottom() {
11832         return mPaddingBottom;
11833     }
11834 
11835     /**
11836      * Returns the left padding of this view. If there are inset and enabled
11837      * scrollbars, this value may include the space required to display the
11838      * scrollbars as well.
11839      *
11840      * @return the left padding in pixels
11841      */
11842     public int getPaddingLeft() {
11843         return mPaddingLeft;
11844     }
11845 
11846     /**
11847      * Returns the start padding of this view. If there are inset and enabled
11848      * scrollbars, this value may include the space required to display the
11849      * scrollbars as well.
11850      *
11851      * @return the start padding in pixels
11852      *
11853      * @hide
11854      */
11855     public int getPaddingStart() {
11856         return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
11857                 mPaddingRight : mPaddingLeft;
11858     }
11859 
11860     /**
11861      * Returns the right padding of this view. If there are inset and enabled
11862      * scrollbars, this value may include the space required to display the
11863      * scrollbars as well.
11864      *
11865      * @return the right padding in pixels
11866      */
11867     public int getPaddingRight() {
11868         return mPaddingRight;
11869     }
11870 
11871     /**
11872      * Returns the end padding of this view. If there are inset and enabled
11873      * scrollbars, this value may include the space required to display the
11874      * scrollbars as well.
11875      *
11876      * @return the end padding in pixels
11877      *
11878      * @hide
11879      */
11880     public int getPaddingEnd() {
11881         return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
11882                 mPaddingLeft : mPaddingRight;
11883     }
11884 
11885     /**
11886      * Return if the padding as been set thru relative values
11887      * {@link #setPaddingRelative(int, int, int, int)} or thru
11888      * @attr ref android.R.styleable#View_paddingStart or
11889      * @attr ref android.R.styleable#View_paddingEnd
11890      *
11891      * @return true if the padding is relative or false if it is not.
11892      *
11893      * @hide
11894      */
11895     public boolean isPaddingRelative() {
11896         return mUserPaddingRelative;
11897     }
11898 
11899     /**
11900      * Changes the selection state of this view. A view can be selected or not.
11901      * Note that selection is not the same as focus. Views are typically
11902      * selected in the context of an AdapterView like ListView or GridView;
11903      * the selected view is the view that is highlighted.
11904      *
11905      * @param selected true if the view must be selected, false otherwise
11906      */
11907     public void setSelected(boolean selected) {
11908         if (((mPrivateFlags & SELECTED) != 0) != selected) {
11909             mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
11910             if (!selected) resetPressedState();
11911             invalidate(true);
11912             refreshDrawableState();
11913             dispatchSetSelected(selected);
11914         }
11915     }
11916 
11917     /**
11918      * Dispatch setSelected to all of this View's children.
11919      *
11920      * @see #setSelected(boolean)
11921      *
11922      * @param selected The new selected state
11923      */
11924     protected void dispatchSetSelected(boolean selected) {
11925     }
11926 
11927     /**
11928      * Indicates the selection state of this view.
11929      *
11930      * @return true if the view is selected, false otherwise
11931      */
11932     @ViewDebug.ExportedProperty
11933     public boolean isSelected() {
11934         return (mPrivateFlags & SELECTED) != 0;
11935     }
11936 
11937     /**
11938      * Changes the activated state of this view. A view can be activated or not.
11939      * Note that activation is not the same as selection.  Selection is
11940      * a transient property, representing the view (hierarchy) the user is
11941      * currently interacting with.  Activation is a longer-term state that the
11942      * user can move views in and out of.  For example, in a list view with
11943      * single or multiple selection enabled, the views in the current selection
11944      * set are activated.  (Um, yeah, we are deeply sorry about the terminology
11945      * here.)  The activated state is propagated down to children of the view it
11946      * is set on.
11947      *
11948      * @param activated true if the view must be activated, false otherwise
11949      */
11950     public void setActivated(boolean activated) {
11951         if (((mPrivateFlags & ACTIVATED) != 0) != activated) {
11952             mPrivateFlags = (mPrivateFlags & ~ACTIVATED) | (activated ? ACTIVATED : 0);
11953             invalidate(true);
11954             refreshDrawableState();
11955             dispatchSetActivated(activated);
11956         }
11957     }
11958 
11959     /**
11960      * Dispatch setActivated to all of this View's children.
11961      *
11962      * @see #setActivated(boolean)
11963      *
11964      * @param activated The new activated state
11965      */
11966     protected void dispatchSetActivated(boolean activated) {
11967     }
11968 
11969     /**
11970      * Indicates the activation state of this view.
11971      *
11972      * @return true if the view is activated, false otherwise
11973      */
11974     @ViewDebug.ExportedProperty
11975     public boolean isActivated() {
11976         return (mPrivateFlags & ACTIVATED) != 0;
11977     }
11978 
11979     /**
11980      * Returns the ViewTreeObserver for this view's hierarchy. The view tree
11981      * observer can be used to get notifications when global events, like
11982      * layout, happen.
11983      *
11984      * The returned ViewTreeObserver observer is not guaranteed to remain
11985      * valid for the lifetime of this View. If the caller of this method keeps
11986      * a long-lived reference to ViewTreeObserver, it should always check for
11987      * the return value of {@link ViewTreeObserver#isAlive()}.
11988      *
11989      * @return The ViewTreeObserver for this view's hierarchy.
11990      */
11991     public ViewTreeObserver getViewTreeObserver() {
11992         if (mAttachInfo != null) {
11993             return mAttachInfo.mTreeObserver;
11994         }
11995         if (mFloatingTreeObserver == null) {
11996             mFloatingTreeObserver = new ViewTreeObserver();
11997         }
11998         return mFloatingTreeObserver;
11999     }
12000 
12001     /**
12002      * <p>Finds the topmost view in the current view hierarchy.</p>
12003      *
12004      * @return the topmost view containing this view
12005      */
12006     public View getRootView() {
12007         if (mAttachInfo != null) {
12008             final View v = mAttachInfo.mRootView;
12009             if (v != null) {
12010                 return v;
12011             }
12012         }
12013 
12014         View parent = this;
12015 
12016         while (parent.mParent != null && parent.mParent instanceof View) {
12017             parent = (View) parent.mParent;
12018         }
12019 
12020         return parent;
12021     }
12022 
12023     /**
12024      * <p>Computes the coordinates of this view on the screen. The argument
12025      * must be an array of two integers. After the method returns, the array
12026      * contains the x and y location in that order.</p>
12027      *
12028      * @param location an array of two integers in which to hold the coordinates
12029      */
12030     public void getLocationOnScreen(int[] location) {
12031         getLocationInWindow(location);
12032 
12033         final AttachInfo info = mAttachInfo;
12034         if (info != null) {
12035             location[0] += info.mWindowLeft;
12036             location[1] += info.mWindowTop;
12037         }
12038     }
12039 
12040     /**
12041      * <p>Computes the coordinates of this view in its window. The argument
12042      * must be an array of two integers. After the method returns, the array
12043      * contains the x and y location in that order.</p>
12044      *
12045      * @param location an array of two integers in which to hold the coordinates
12046      */
12047     public void getLocationInWindow(int[] location) {
12048         if (location == null || location.length < 2) {
12049             throw new IllegalArgumentException("location must be an array of "
12050                     + "two integers");
12051         }
12052 
12053         location[0] = mLeft;
12054         location[1] = mTop;
12055         if (mTransformationInfo != null) {
12056             location[0] += (int) (mTransformationInfo.mTranslationX + 0.5f);
12057             location[1] += (int) (mTransformationInfo.mTranslationY + 0.5f);
12058         }
12059 
12060         ViewParent viewParent = mParent;
12061         while (viewParent instanceof View) {
12062             final View view = (View)viewParent;
12063             location[0] += view.mLeft - view.mScrollX;
12064             location[1] += view.mTop - view.mScrollY;
12065             if (view.mTransformationInfo != null) {
12066                 location[0] += (int) (view.mTransformationInfo.mTranslationX + 0.5f);
12067                 location[1] += (int) (view.mTransformationInfo.mTranslationY + 0.5f);
12068             }
12069             viewParent = view.mParent;
12070         }
12071 
12072         if (viewParent instanceof ViewRootImpl) {
12073             // *cough*
12074             final ViewRootImpl vr = (ViewRootImpl)viewParent;
12075             location[1] -= vr.mCurScrollY;
12076         }
12077     }
12078 
12079     /**
12080      * {@hide}
12081      * @param id the id of the view to be found
12082      * @return the view of the specified id, null if cannot be found
12083      */
12084     protected View findViewTraversal(int id) {
12085         if (id == mID) {
12086             return this;
12087         }
12088         return null;
12089     }
12090 
12091     /**
12092      * {@hide}
12093      * @param tag the tag of the view to be found
12094      * @return the view of specified tag, null if cannot be found
12095      */
12096     protected View findViewWithTagTraversal(Object tag) {
12097         if (tag != null && tag.equals(mTag)) {
12098             return this;
12099         }
12100         return null;
12101     }
12102 
12103     /**
12104      * {@hide}
12105      * @param predicate The predicate to evaluate.
12106      * @param childToSkip If not null, ignores this child during the recursive traversal.
12107      * @return The first view that matches the predicate or null.
12108      */
12109     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
12110         if (predicate.apply(this)) {
12111             return this;
12112         }
12113         return null;
12114     }
12115 
12116     /**
12117      * Look for a child view with the given id.  If this view has the given
12118      * id, return this view.
12119      *
12120      * @param id The id to search for.
12121      * @return The view that has the given id in the hierarchy or null
12122      */
12123     public final View findViewById(int id) {
12124         if (id < 0) {
12125             return null;
12126         }
12127         return findViewTraversal(id);
12128     }
12129 
12130     /**
12131      * Finds a view by its unuque and stable accessibility id.
12132      *
12133      * @param accessibilityId The searched accessibility id.
12134      * @return The found view.
12135      */
12136     final View findViewByAccessibilityId(int accessibilityId) {
12137         if (accessibilityId < 0) {
12138             return null;
12139         }
12140         return findViewByAccessibilityIdTraversal(accessibilityId);
12141     }
12142 
12143     /**
12144      * Performs the traversal to find a view by its unuque and stable accessibility id.
12145      *
12146      * <strong>Note:</strong>This method does not stop at the root namespace
12147      * boundary since the user can touch the screen at an arbitrary location
12148      * potentially crossing the root namespace bounday which will send an
12149      * accessibility event to accessibility services and they should be able
12150      * to obtain the event source. Also accessibility ids are guaranteed to be
12151      * unique in the window.
12152      *
12153      * @param accessibilityId The accessibility id.
12154      * @return The found view.
12155      */
12156     View findViewByAccessibilityIdTraversal(int accessibilityId) {
12157         if (getAccessibilityViewId() == accessibilityId) {
12158             return this;
12159         }
12160         return null;
12161     }
12162 
12163     /**
12164      * Look for a child view with the given tag.  If this view has the given
12165      * tag, return this view.
12166      *
12167      * @param tag The tag to search for, using "tag.equals(getTag())".
12168      * @return The View that has the given tag in the hierarchy or null
12169      */
12170     public final View findViewWithTag(Object tag) {
12171         if (tag == null) {
12172             return null;
12173         }
12174         return findViewWithTagTraversal(tag);
12175     }
12176 
12177     /**
12178      * {@hide}
12179      * Look for a child view that matches the specified predicate.
12180      * If this view matches the predicate, return this view.
12181      *
12182      * @param predicate The predicate to evaluate.
12183      * @return The first view that matches the predicate or null.
12184      */
12185     public final View findViewByPredicate(Predicate<View> predicate) {
12186         return findViewByPredicateTraversal(predicate, null);
12187     }
12188 
12189     /**
12190      * {@hide}
12191      * Look for a child view that matches the specified predicate,
12192      * starting with the specified view and its descendents and then
12193      * recusively searching the ancestors and siblings of that view
12194      * until this view is reached.
12195      *
12196      * This method is useful in cases where the predicate does not match
12197      * a single unique view (perhaps multiple views use the same id)
12198      * and we are trying to find the view that is "closest" in scope to the
12199      * starting view.
12200      *
12201      * @param start The view to start from.
12202      * @param predicate The predicate to evaluate.
12203      * @return The first view that matches the predicate or null.
12204      */
12205     public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
12206         View childToSkip = null;
12207         for (;;) {
12208             View view = start.findViewByPredicateTraversal(predicate, childToSkip);
12209             if (view != null || start == this) {
12210                 return view;
12211             }
12212 
12213             ViewParent parent = start.getParent();
12214             if (parent == null || !(parent instanceof View)) {
12215                 return null;
12216             }
12217 
12218             childToSkip = start;
12219             start = (View) parent;
12220         }
12221     }
12222 
12223     /**
12224      * Sets the identifier for this view. The identifier does not have to be
12225      * unique in this view's hierarchy. The identifier should be a positive
12226      * number.
12227      *
12228      * @see #NO_ID
12229      * @see #getId()
12230      * @see #findViewById(int)
12231      *
12232      * @param id a number used to identify the view
12233      *
12234      * @attr ref android.R.styleable#View_id
12235      */
12236     public void setId(int id) {
12237         mID = id;
12238     }
12239 
12240     /**
12241      * {@hide}
12242      *
12243      * @param isRoot true if the view belongs to the root namespace, false
12244      *        otherwise
12245      */
12246     public void setIsRootNamespace(boolean isRoot) {
12247         if (isRoot) {
12248             mPrivateFlags |= IS_ROOT_NAMESPACE;
12249         } else {
12250             mPrivateFlags &= ~IS_ROOT_NAMESPACE;
12251         }
12252     }
12253 
12254     /**
12255      * {@hide}
12256      *
12257      * @return true if the view belongs to the root namespace, false otherwise
12258      */
12259     public boolean isRootNamespace() {
12260         return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
12261     }
12262 
12263     /**
12264      * Returns this view's identifier.
12265      *
12266      * @return a positive integer used to identify the view or {@link #NO_ID}
12267      *         if the view has no ID
12268      *
12269      * @see #setId(int)
12270      * @see #findViewById(int)
12271      * @attr ref android.R.styleable#View_id
12272      */
12273     @ViewDebug.CapturedViewProperty
12274     public int getId() {
12275         return mID;
12276     }
12277 
12278     /**
12279      * Returns this view's tag.
12280      *
12281      * @return the Object stored in this view as a tag
12282      *
12283      * @see #setTag(Object)
12284      * @see #getTag(int)
12285      */
12286     @ViewDebug.ExportedProperty
12287     public Object getTag() {
12288         return mTag;
12289     }
12290 
12291     /**
12292      * Sets the tag associated with this view. A tag can be used to mark
12293      * a view in its hierarchy and does not have to be unique within the
12294      * hierarchy. Tags can also be used to store data within a view without
12295      * resorting to another data structure.
12296      *
12297      * @param tag an Object to tag the view with
12298      *
12299      * @see #getTag()
12300      * @see #setTag(int, Object)
12301      */
12302     public void setTag(final Object tag) {
12303         mTag = tag;
12304     }
12305 
12306     /**
12307      * Returns the tag associated with this view and the specified key.
12308      *
12309      * @param key The key identifying the tag
12310      *
12311      * @return the Object stored in this view as a tag
12312      *
12313      * @see #setTag(int, Object)
12314      * @see #getTag()
12315      */
12316     public Object getTag(int key) {
12317         if (mKeyedTags != null) return mKeyedTags.get(key);
12318         return null;
12319     }
12320 
12321     /**
12322      * Sets a tag associated with this view and a key. A tag can be used
12323      * to mark a view in its hierarchy and does not have to be unique within
12324      * the hierarchy. Tags can also be used to store data within a view
12325      * without resorting to another data structure.
12326      *
12327      * The specified key should be an id declared in the resources of the
12328      * application to ensure it is unique (see the <a
12329      * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
12330      * Keys identified as belonging to
12331      * the Android framework or not associated with any package will cause
12332      * an {@link IllegalArgumentException} to be thrown.
12333      *
12334      * @param key The key identifying the tag
12335      * @param tag An Object to tag the view with
12336      *
12337      * @throws IllegalArgumentException If they specified key is not valid
12338      *
12339      * @see #setTag(Object)
12340      * @see #getTag(int)
12341      */
12342     public void setTag(int key, final Object tag) {
12343         // If the package id is 0x00 or 0x01, it's either an undefined package
12344         // or a framework id
12345         if ((key >>> 24) < 2) {
12346             throw new IllegalArgumentException("The key must be an application-specific "
12347                     + "resource id.");
12348         }
12349 
12350         setKeyedTag(key, tag);
12351     }
12352 
12353     /**
12354      * Variation of {@link #setTag(int, Object)} that enforces the key to be a
12355      * framework id.
12356      *
12357      * @hide
12358      */
12359     public void setTagInternal(int key, Object tag) {
12360         if ((key >>> 24) != 0x1) {
12361             throw new IllegalArgumentException("The key must be a framework-specific "
12362                     + "resource id.");
12363         }
12364 
12365         setKeyedTag(key, tag);
12366     }
12367 
12368     private void setKeyedTag(int key, Object tag) {
12369         if (mKeyedTags == null) {
12370             mKeyedTags = new SparseArray<Object>();
12371         }
12372 
12373         mKeyedTags.put(key, tag);
12374     }
12375 
12376     /**
12377      * @param consistency The type of consistency. See ViewDebug for more information.
12378      *
12379      * @hide
12380      */
12381     protected boolean dispatchConsistencyCheck(int consistency) {
12382         return onConsistencyCheck(consistency);
12383     }
12384 
12385     /**
12386      * Method that subclasses should implement to check their consistency. The type of
12387      * consistency check is indicated by the bit field passed as a parameter.
12388      *
12389      * @param consistency The type of consistency. See ViewDebug for more information.
12390      *
12391      * @throws IllegalStateException if the view is in an inconsistent state.
12392      *
12393      * @hide
12394      */
12395     protected boolean onConsistencyCheck(int consistency) {
12396         boolean result = true;
12397 
12398         final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
12399         final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0;
12400 
12401         if (checkLayout) {
12402             if (getParent() == null) {
12403                 result = false;
12404                 android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
12405                         "View " + this + " does not have a parent.");
12406             }
12407 
12408             if (mAttachInfo == null) {
12409                 result = false;
12410                 android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
12411                         "View " + this + " is not attached to a window.");
12412             }
12413         }
12414 
12415         if (checkDrawing) {
12416             // Do not check the DIRTY/DRAWN flags because views can call invalidate()
12417             // from their draw() method
12418 
12419             if ((mPrivateFlags & DRAWN) != DRAWN &&
12420                     (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
12421                 result = false;
12422                 android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
12423                         "View " + this + " was invalidated but its drawing cache is valid.");
12424             }
12425         }
12426 
12427         return result;
12428     }
12429 
12430     /**
12431      * Prints information about this view in the log output, with the tag
12432      * {@link #VIEW_LOG_TAG}.
12433      *
12434      * @hide
12435      */
12436     public void debug() {
12437         debug(0);
12438     }
12439 
12440     /**
12441      * Prints information about this view in the log output, with the tag
12442      * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
12443      * indentation defined by the <code>depth</code>.
12444      *
12445      * @param depth the indentation level
12446      *
12447      * @hide
12448      */
12449     protected void debug(int depth) {
12450         String output = debugIndent(depth - 1);
12451 
12452         output += "+ " + this;
12453         int id = getId();
12454         if (id != -1) {
12455             output += " (id=" + id + ")";
12456         }
12457         Object tag = getTag();
12458         if (tag != null) {
12459             output += " (tag=" + tag + ")";
12460         }
12461         Log.d(VIEW_LOG_TAG, output);
12462 
12463         if ((mPrivateFlags & FOCUSED) != 0) {
12464             output = debugIndent(depth) + " FOCUSED";
12465             Log.d(VIEW_LOG_TAG, output);
12466         }
12467 
12468         output = debugIndent(depth);
12469         output += "frame={" + mLeft + ", " + mTop + ", " + mRight
12470                 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
12471                 + "} ";
12472         Log.d(VIEW_LOG_TAG, output);
12473 
12474         if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
12475                 || mPaddingBottom != 0) {
12476             output = debugIndent(depth);
12477             output += "padding={" + mPaddingLeft + ", " + mPaddingTop
12478                     + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
12479             Log.d(VIEW_LOG_TAG, output);
12480         }
12481 
12482         output = debugIndent(depth);
12483         output += "mMeasureWidth=" + mMeasuredWidth +
12484                 " mMeasureHeight=" + mMeasuredHeight;
12485         Log.d(VIEW_LOG_TAG, output);
12486 
12487         output = debugIndent(depth);
12488         if (mLayoutParams == null) {
12489             output += "BAD! no layout params";
12490         } else {
12491             output = mLayoutParams.debug(output);
12492         }
12493         Log.d(VIEW_LOG_TAG, output);
12494 
12495         output = debugIndent(depth);
12496         output += "flags={";
12497         output += View.printFlags(mViewFlags);
12498         output += "}";
12499         Log.d(VIEW_LOG_TAG, output);
12500 
12501         output = debugIndent(depth);
12502         output += "privateFlags={";
12503         output += View.printPrivateFlags(mPrivateFlags);
12504         output += "}";
12505         Log.d(VIEW_LOG_TAG, output);
12506     }
12507 
12508     /**
12509      * Creates an string of whitespaces used for indentation.
12510      *
12511      * @param depth the indentation level
12512      * @return a String containing (depth * 2 + 3) * 2 white spaces
12513      *
12514      * @hide
12515      */
12516     protected static String debugIndent(int depth) {
12517         StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
12518         for (int i = 0; i < (depth * 2) + 3; i++) {
12519             spaces.append(' ').append(' ');
12520         }
12521         return spaces.toString();
12522     }
12523 
12524     /**
12525      * <p>Return the offset of the widget's text baseline from the widget's top
12526      * boundary. If this widget does not support baseline alignment, this
12527      * method returns -1. </p>
12528      *
12529      * @return the offset of the baseline within the widget's bounds or -1
12530      *         if baseline alignment is not supported
12531      */
12532     @ViewDebug.ExportedProperty(category = "layout")
12533     public int getBaseline() {
12534         return -1;
12535     }
12536 
12537     /**
12538      * Call this when something has changed which has invalidated the
12539      * layout of this view. This will schedule a layout pass of the view
12540      * tree.
12541      */
12542     public void requestLayout() {
12543         if (ViewDebug.TRACE_HIERARCHY) {
12544             ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT);
12545         }
12546 
12547         mPrivateFlags |= FORCE_LAYOUT;
12548         mPrivateFlags |= INVALIDATED;
12549 
12550         if (mParent != null) {
12551             if (mLayoutParams != null) {
12552                 mLayoutParams.resolveWithDirection(getResolvedLayoutDirection());
12553             }
12554             if (!mParent.isLayoutRequested()) {
12555                 mParent.requestLayout();
12556             }
12557         }
12558     }
12559 
12560     /**
12561      * Forces this view to be laid out during the next layout pass.
12562      * This method does not call requestLayout() or forceLayout()
12563      * on the parent.
12564      */
12565     public void forceLayout() {
12566         mPrivateFlags |= FORCE_LAYOUT;
12567         mPrivateFlags |= INVALIDATED;
12568     }
12569 
12570     /**
12571      * <p>
12572      * This is called to find out how big a view should be. The parent
12573      * supplies constraint information in the width and height parameters.
12574      * </p>
12575      *
12576      * <p>
12577      * The actual mesurement work of a view is performed in
12578      * {@link #onMeasure(int, int)}, called by this method. Therefore, only
12579      * {@link #onMeasure(int, int)} can and must be overriden by subclasses.
12580      * </p>
12581      *
12582      *
12583      * @param widthMeasureSpec Horizontal space requirements as imposed by the
12584      *        parent
12585      * @param heightMeasureSpec Vertical space requirements as imposed by the
12586      *        parent
12587      *
12588      * @see #onMeasure(int, int)
12589      */
12590     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
12591         if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
12592                 widthMeasureSpec != mOldWidthMeasureSpec ||
12593                 heightMeasureSpec != mOldHeightMeasureSpec) {
12594 
12595             // first clears the measured dimension flag
12596             mPrivateFlags &= ~MEASURED_DIMENSION_SET;
12597 
12598             if (ViewDebug.TRACE_HIERARCHY) {
12599                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
12600             }
12601 
12602             // measure ourselves, this should set the measured dimension flag back
12603             onMeasure(widthMeasureSpec, heightMeasureSpec);
12604 
12605             // flag not set, setMeasuredDimension() was not invoked, we raise
12606             // an exception to warn the developer
12607             if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
12608                 throw new IllegalStateException("onMeasure() did not set the"
12609                         + " measured dimension by calling"
12610                         + " setMeasuredDimension()");
12611             }
12612 
12613             mPrivateFlags |= LAYOUT_REQUIRED;
12614         }
12615 
12616         mOldWidthMeasureSpec = widthMeasureSpec;
12617         mOldHeightMeasureSpec = heightMeasureSpec;
12618     }
12619 
12620     /**
12621      * <p>
12622      * Measure the view and its content to determine the measured width and the
12623      * measured height. This method is invoked by {@link #measure(int, int)} and
12624      * should be overriden by subclasses to provide accurate and efficient
12625      * measurement of their contents.
12626      * </p>
12627      *
12628      * <p>
12629      * <strong>CONTRACT:</strong> When overriding this method, you
12630      * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
12631      * measured width and height of this view. Failure to do so will trigger an
12632      * <code>IllegalStateException</code>, thrown by
12633      * {@link #measure(int, int)}. Calling the superclass'
12634      * {@link #onMeasure(int, int)} is a valid use.
12635      * </p>
12636      *
12637      * <p>
12638      * The base class implementation of measure defaults to the background size,
12639      * unless a larger size is allowed by the MeasureSpec. Subclasses should
12640      * override {@link #onMeasure(int, int)} to provide better measurements of
12641      * their content.
12642      * </p>
12643      *
12644      * <p>
12645      * If this method is overridden, it is the subclass's responsibility to make
12646      * sure the measured height and width are at least the view's minimum height
12647      * and width ({@link #getSuggestedMinimumHeight()} and
12648      * {@link #getSuggestedMinimumWidth()}).
12649      * </p>
12650      *
12651      * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
12652      *                         The requirements are encoded with
12653      *                         {@link android.view.View.MeasureSpec}.
12654      * @param heightMeasureSpec vertical space requirements as imposed by the parent.
12655      *                         The requirements are encoded with
12656      *                         {@link android.view.View.MeasureSpec}.
12657      *
12658      * @see #getMeasuredWidth()
12659      * @see #getMeasuredHeight()
12660      * @see #setMeasuredDimension(int, int)
12661      * @see #getSuggestedMinimumHeight()
12662      * @see #getSuggestedMinimumWidth()
12663      * @see android.view.View.MeasureSpec#getMode(int)
12664      * @see android.view.View.MeasureSpec#getSize(int)
12665      */
12666     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
12667         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
12668                 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
12669     }
12670 
12671     /**
12672      * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
12673      * measured width and measured height. Failing to do so will trigger an
12674      * exception at measurement time.</p>
12675      *
12676      * @param measuredWidth The measured width of this view.  May be a complex
12677      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
12678      * {@link #MEASURED_STATE_TOO_SMALL}.
12679      * @param measuredHeight The measured height of this view.  May be a complex
12680      * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
12681      * {@link #MEASURED_STATE_TOO_SMALL}.
12682      */
12683     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
12684         mMeasuredWidth = measuredWidth;
12685         mMeasuredHeight = measuredHeight;
12686 
12687         mPrivateFlags |= MEASURED_DIMENSION_SET;
12688     }
12689 
12690     /**
12691      * Merge two states as returned by {@link #getMeasuredState()}.
12692      * @param curState The current state as returned from a view or the result
12693      * of combining multiple views.
12694      * @param newState The new view state to combine.
12695      * @return Returns a new integer reflecting the combination of the two
12696      * states.
12697      */
12698     public static int combineMeasuredStates(int curState, int newState) {
12699         return curState | newState;
12700     }
12701 
12702     /**
12703      * Version of {@link #resolveSizeAndState(int, int, int)}
12704      * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
12705      */
12706     public static int resolveSize(int size, int measureSpec) {
12707         return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
12708     }
12709 
12710     /**
12711      * Utility to reconcile a desired size and state, with constraints imposed
12712      * by a MeasureSpec.  Will take the desired size, unless a different size
12713      * is imposed by the constraints.  The returned value is a compound integer,
12714      * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
12715      * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
12716      * size is smaller than the size the view wants to be.
12717      *
12718      * @param size How big the view wants to be
12719      * @param measureSpec Constraints imposed by the parent
12720      * @return Size information bit mask as defined by
12721      * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
12722      */
12723     public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
12724         int result = size;
12725         int specMode = MeasureSpec.getMode(measureSpec);
12726         int specSize =  MeasureSpec.getSize(measureSpec);
12727         switch (specMode) {
12728         case MeasureSpec.UNSPECIFIED:
12729             result = size;
12730             break;
12731         case MeasureSpec.AT_MOST:
12732             if (specSize < size) {
12733                 result = specSize | MEASURED_STATE_TOO_SMALL;
12734             } else {
12735                 result = size;
12736             }
12737             break;
12738         case MeasureSpec.EXACTLY:
12739             result = specSize;
12740             break;
12741         }
12742         return result | (childMeasuredState&MEASURED_STATE_MASK);
12743     }
12744 
12745     /**
12746      * Utility to return a default size. Uses the supplied size if the
12747      * MeasureSpec imposed no constraints. Will get larger if allowed
12748      * by the MeasureSpec.
12749      *
12750      * @param size Default size for this view
12751      * @param measureSpec Constraints imposed by the parent
12752      * @return The size this view should be.
12753      */
12754     public static int getDefaultSize(int size, int measureSpec) {
12755         int result = size;
12756         int specMode = MeasureSpec.getMode(measureSpec);
12757         int specSize = MeasureSpec.getSize(measureSpec);
12758 
12759         switch (specMode) {
12760         case MeasureSpec.UNSPECIFIED:
12761             result = size;
12762             break;
12763         case MeasureSpec.AT_MOST:
12764         case MeasureSpec.EXACTLY:
12765             result = specSize;
12766             break;
12767         }
12768         return result;
12769     }
12770 
12771     /**
12772      * Returns the suggested minimum height that the view should use. This
12773      * returns the maximum of the view's minimum height
12774      * and the background's minimum height
12775      * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
12776      * <p>
12777      * When being used in {@link #onMeasure(int, int)}, the caller should still
12778      * ensure the returned height is within the requirements of the parent.
12779      *
12780      * @return The suggested minimum height of the view.
12781      */
12782     protected int getSuggestedMinimumHeight() {
12783         int suggestedMinHeight = mMinHeight;
12784 
12785         if (mBGDrawable != null) {
12786             final int bgMinHeight = mBGDrawable.getMinimumHeight();
12787             if (suggestedMinHeight < bgMinHeight) {
12788                 suggestedMinHeight = bgMinHeight;
12789             }
12790         }
12791 
12792         return suggestedMinHeight;
12793     }
12794 
12795     /**
12796      * Returns the suggested minimum width that the view should use. This
12797      * returns the maximum of the view's minimum width)
12798      * and the background's minimum width
12799      *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
12800      * <p>
12801      * When being used in {@link #onMeasure(int, int)}, the caller should still
12802      * ensure the returned width is within the requirements of the parent.
12803      *
12804      * @return The suggested minimum width of the view.
12805      */
12806     protected int getSuggestedMinimumWidth() {
12807         int suggestedMinWidth = mMinWidth;
12808 
12809         if (mBGDrawable != null) {
12810             final int bgMinWidth = mBGDrawable.getMinimumWidth();
12811             if (suggestedMinWidth < bgMinWidth) {
12812                 suggestedMinWidth = bgMinWidth;
12813             }
12814         }
12815 
12816         return suggestedMinWidth;
12817     }
12818 
12819     /**
12820      * Sets the minimum height of the view. It is not guaranteed the view will
12821      * be able to achieve this minimum height (for example, if its parent layout
12822      * constrains it with less available height).
12823      *
12824      * @param minHeight The minimum height the view will try to be.
12825      */
12826     public void setMinimumHeight(int minHeight) {
12827         mMinHeight = minHeight;
12828     }
12829 
12830     /**
12831      * Sets the minimum width of the view. It is not guaranteed the view will
12832      * be able to achieve this minimum width (for example, if its parent layout
12833      * constrains it with less available width).
12834      *
12835      * @param minWidth The minimum width the view will try to be.
12836      */
12837     public void setMinimumWidth(int minWidth) {
12838         mMinWidth = minWidth;
12839     }
12840 
12841     /**
12842      * Get the animation currently associated with this view.
12843      *
12844      * @return The animation that is currently playing or
12845      *         scheduled to play for this view.
12846      */
12847     public Animation getAnimation() {
12848         return mCurrentAnimation;
12849     }
12850 
12851     /**
12852      * Start the specified animation now.
12853      *
12854      * @param animation the animation to start now
12855      */
12856     public void startAnimation(Animation animation) {
12857         animation.setStartTime(Animation.START_ON_FIRST_FRAME);
12858         setAnimation(animation);
12859         invalidateParentCaches();
12860         invalidate(true);
12861     }
12862 
12863     /**
12864      * Cancels any animations for this view.
12865      */
12866     public void clearAnimation() {
12867         if (mCurrentAnimation != null) {
12868             mCurrentAnimation.detach();
12869         }
12870         mCurrentAnimation = null;
12871         invalidateParentIfNeeded();
12872     }
12873 
12874     /**
12875      * Sets the next animation to play for this view.
12876      * If you want the animation to play immediately, use
12877      * startAnimation. This method provides allows fine-grained
12878      * control over the start time and invalidation, but you
12879      * must make sure that 1) the animation has a start time set, and
12880      * 2) the view will be invalidated when the animation is supposed to
12881      * start.
12882      *
12883      * @param animation The next animation, or null.
12884      */
12885     public void setAnimation(Animation animation) {
12886         mCurrentAnimation = animation;
12887         if (animation != null) {
12888             animation.reset();
12889         }
12890     }
12891 
12892     /**
12893      * Invoked by a parent ViewGroup to notify the start of the animation
12894      * currently associated with this view. If you override this method,
12895      * always call super.onAnimationStart();
12896      *
12897      * @see #setAnimation(android.view.animation.Animation)
12898      * @see #getAnimation()
12899      */
12900     protected void onAnimationStart() {
12901         mPrivateFlags |= ANIMATION_STARTED;
12902     }
12903 
12904     /**
12905      * Invoked by a parent ViewGroup to notify the end of the animation
12906      * currently associated with this view. If you override this method,
12907      * always call super.onAnimationEnd();
12908      *
12909      * @see #setAnimation(android.view.animation.Animation)
12910      * @see #getAnimation()
12911      */
12912     protected void onAnimationEnd() {
12913         mPrivateFlags &= ~ANIMATION_STARTED;
12914     }
12915 
12916     /**
12917      * Invoked if there is a Transform that involves alpha. Subclass that can
12918      * draw themselves with the specified alpha should return true, and then
12919      * respect that alpha when their onDraw() is called. If this returns false
12920      * then the view may be redirected to draw into an offscreen buffer to
12921      * fulfill the request, which will look fine, but may be slower than if the
12922      * subclass handles it internally. The default implementation returns false.
12923      *
12924      * @param alpha The alpha (0..255) to apply to the view's drawing
12925      * @return true if the view can draw with the specified alpha.
12926      */
12927     protected boolean onSetAlpha(int alpha) {
12928         return false;
12929     }
12930 
12931     /**
12932      * This is used by the RootView to perform an optimization when
12933      * the view hierarchy contains one or several SurfaceView.
12934      * SurfaceView is always considered transparent, but its children are not,
12935      * therefore all View objects remove themselves from the global transparent
12936      * region (passed as a parameter to this function).
12937      *
12938      * @param region The transparent region for this ViewAncestor (window).
12939      *
12940      * @return Returns true if the effective visibility of the view at this
12941      * point is opaque, regardless of the transparent region; returns false
12942      * if it is possible for underlying windows to be seen behind the view.
12943      *
12944      * {@hide}
12945      */
12946     public boolean gatherTransparentRegion(Region region) {
12947         final AttachInfo attachInfo = mAttachInfo;
12948         if (region != null && attachInfo != null) {
12949             final int pflags = mPrivateFlags;
12950             if ((pflags & SKIP_DRAW) == 0) {
12951                 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
12952                 // remove it from the transparent region.
12953                 final int[] location = attachInfo.mTransparentLocation;
12954                 getLocationInWindow(location);
12955                 region.op(location[0], location[1], location[0] + mRight - mLeft,
12956                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
12957             } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) {
12958                 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
12959                 // exists, so we remove the background drawable's non-transparent
12960                 // parts from this transparent region.
12961                 applyDrawableToTransparentRegion(mBGDrawable, region);
12962             }
12963         }
12964         return true;
12965     }
12966 
12967     /**
12968      * Play a sound effect for this view.
12969      *
12970      * <p>The framework will play sound effects for some built in actions, such as
12971      * clicking, but you may wish to play these effects in your widget,
12972      * for instance, for internal navigation.
12973      *
12974      * <p>The sound effect will only be played if sound effects are enabled by the user, and
12975      * {@link #isSoundEffectsEnabled()} is true.
12976      *
12977      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
12978      */
12979     public void playSoundEffect(int soundConstant) {
12980         if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
12981             return;
12982         }
12983         mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
12984     }
12985 
12986     /**
12987      * BZZZTT!!1!
12988      *
12989      * <p>Provide haptic feedback to the user for this view.
12990      *
12991      * <p>The framework will provide haptic feedback for some built in actions,
12992      * such as long presses, but you may wish to provide feedback for your
12993      * own widget.
12994      *
12995      * <p>The feedback will only be performed if
12996      * {@link #isHapticFeedbackEnabled()} is true.
12997      *
12998      * @param feedbackConstant One of the constants defined in
12999      * {@link HapticFeedbackConstants}
13000      */
13001     public boolean performHapticFeedback(int feedbackConstant) {
13002         return performHapticFeedback(feedbackConstant, 0);
13003     }
13004 
13005     /**
13006      * BZZZTT!!1!
13007      *
13008      * <p>Like {@link #performHapticFeedback(int)}, with additional options.
13009      *
13010      * @param feedbackConstant One of the constants defined in
13011      * {@link HapticFeedbackConstants}
13012      * @param flags Additional flags as per {@link HapticFeedbackConstants}.
13013      */
13014     public boolean performHapticFeedback(int feedbackConstant, int flags) {
13015         if (mAttachInfo == null) {
13016             return false;
13017         }
13018         //noinspection SimplifiableIfStatement
13019         if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
13020                 && !isHapticFeedbackEnabled()) {
13021             return false;
13022         }
13023         return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
13024                 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
13025     }
13026 
13027     /**
13028      * Request that the visibility of the status bar be changed.
13029      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
13030      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
13031      */
13032     public void setSystemUiVisibility(int visibility) {
13033         if (visibility != mSystemUiVisibility) {
13034             mSystemUiVisibility = visibility;
13035             if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13036                 mParent.recomputeViewAttributes(this);
13037             }
13038         }
13039     }
13040 
13041     /**
13042      * Returns the status bar visibility that this view has requested.
13043      * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
13044      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
13045      */
13046     public int getSystemUiVisibility() {
13047         return mSystemUiVisibility;
13048     }
13049 
13050     /**
13051      * Set a listener to receive callbacks when the visibility of the system bar changes.
13052      * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
13053      */
13054     public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
13055         mOnSystemUiVisibilityChangeListener = l;
13056         if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13057             mParent.recomputeViewAttributes(this);
13058         }
13059     }
13060 
13061     /**
13062      * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
13063      * the view hierarchy.
13064      */
13065     public void dispatchSystemUiVisibilityChanged(int visibility) {
13066         if (mOnSystemUiVisibilityChangeListener != null) {
13067             mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
13068                     visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
13069         }
13070     }
13071 
13072     void updateLocalSystemUiVisibility(int localValue, int localChanges) {
13073         int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
13074         if (val != mSystemUiVisibility) {
13075             setSystemUiVisibility(val);
13076         }
13077     }
13078 
13079     /**
13080      * Creates an image that the system displays during the drag and drop
13081      * operation. This is called a &quot;drag shadow&quot;. The default implementation
13082      * for a DragShadowBuilder based on a View returns an image that has exactly the same
13083      * appearance as the given View. The default also positions the center of the drag shadow
13084      * directly under the touch point. If no View is provided (the constructor with no parameters
13085      * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
13086      * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
13087      * default is an invisible drag shadow.
13088      * <p>
13089      * You are not required to use the View you provide to the constructor as the basis of the
13090      * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
13091      * anything you want as the drag shadow.
13092      * </p>
13093      * <p>
13094      *  You pass a DragShadowBuilder object to the system when you start the drag. The system
13095      *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
13096      *  size and position of the drag shadow. It uses this data to construct a
13097      *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
13098      *  so that your application can draw the shadow image in the Canvas.
13099      * </p>
13100      *
13101      * <div class="special reference">
13102      * <h3>Developer Guides</h3>
13103      * <p>For a guide to implementing drag and drop features, read the
13104      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
13105      * </div>
13106      */
13107     public static class DragShadowBuilder {
13108         private final WeakReference<View> mView;
13109 
13110         /**
13111          * Constructs a shadow image builder based on a View. By default, the resulting drag
13112          * shadow will have the same appearance and dimensions as the View, with the touch point
13113          * over the center of the View.
13114          * @param view A View. Any View in scope can be used.
13115          */
13116         public DragShadowBuilder(View view) {
13117             mView = new WeakReference<View>(view);
13118         }
13119 
13120         /**
13121          * Construct a shadow builder object with no associated View.  This
13122          * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
13123          * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
13124          * to supply the drag shadow's dimensions and appearance without
13125          * reference to any View object. If they are not overridden, then the result is an
13126          * invisible drag shadow.
13127          */
13128         public DragShadowBuilder() {
13129             mView = new WeakReference<View>(null);
13130         }
13131 
13132         /**
13133          * Returns the View object that had been passed to the
13134          * {@link #View.DragShadowBuilder(View)}
13135          * constructor.  If that View parameter was {@code null} or if the
13136          * {@link #View.DragShadowBuilder()}
13137          * constructor was used to instantiate the builder object, this method will return
13138          * null.
13139          *
13140          * @return The View object associate with this builder object.
13141          */
13142         @SuppressWarnings({"JavadocReference"})
13143         final public View getView() {
13144             return mView.get();
13145         }
13146 
13147         /**
13148          * Provides the metrics for the shadow image. These include the dimensions of
13149          * the shadow image, and the point within that shadow that should
13150          * be centered under the touch location while dragging.
13151          * <p>
13152          * The default implementation sets the dimensions of the shadow to be the
13153          * same as the dimensions of the View itself and centers the shadow under
13154          * the touch point.
13155          * </p>
13156          *
13157          * @param shadowSize A {@link android.graphics.Point} containing the width and height
13158          * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
13159          * desired width and must set {@link android.graphics.Point#y} to the desired height of the
13160          * image.
13161          *
13162          * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
13163          * shadow image that should be underneath the touch point during the drag and drop
13164          * operation. Your application must set {@link android.graphics.Point#x} to the
13165          * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
13166          */
13167         public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
13168             final View view = mView.get();
13169             if (view != null) {
13170                 shadowSize.set(view.getWidth(), view.getHeight());
13171                 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
13172             } else {
13173                 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
13174             }
13175         }
13176 
13177         /**
13178          * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
13179          * based on the dimensions it received from the
13180          * {@link #onProvideShadowMetrics(Point, Point)} callback.
13181          *
13182          * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
13183          */
13184         public void onDrawShadow(Canvas canvas) {
13185             final View view = mView.get();
13186             if (view != null) {
13187                 view.draw(canvas);
13188             } else {
13189                 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
13190             }
13191         }
13192     }
13193 
13194     /**
13195      * Starts a drag and drop operation. When your application calls this method, it passes a
13196      * {@link android.view.View.DragShadowBuilder} object to the system. The
13197      * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
13198      * to get metrics for the drag shadow, and then calls the object's
13199      * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
13200      * <p>
13201      *  Once the system has the drag shadow, it begins the drag and drop operation by sending
13202      *  drag events to all the View objects in your application that are currently visible. It does
13203      *  this either by calling the View object's drag listener (an implementation of
13204      *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
13205      *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
13206      *  Both are passed a {@link android.view.DragEvent} object that has a
13207      *  {@link android.view.DragEvent#getAction()} value of
13208      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
13209      * </p>
13210      * <p>
13211      * Your application can invoke startDrag() on any attached View object. The View object does not
13212      * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
13213      * be related to the View the user selected for dragging.
13214      * </p>
13215      * @param data A {@link android.content.ClipData} object pointing to the data to be
13216      * transferred by the drag and drop operation.
13217      * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
13218      * drag shadow.
13219      * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
13220      * drop operation. This Object is put into every DragEvent object sent by the system during the
13221      * current drag.
13222      * <p>
13223      * myLocalState is a lightweight mechanism for the sending information from the dragged View
13224      * to the target Views. For example, it can contain flags that differentiate between a
13225      * a copy operation and a move operation.
13226      * </p>
13227      * @param flags Flags that control the drag and drop operation. No flags are currently defined,
13228      * so the parameter should be set to 0.
13229      * @return {@code true} if the method completes successfully, or
13230      * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
13231      * do a drag, and so no drag operation is in progress.
13232      */
13233     public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
13234             Object myLocalState, int flags) {
13235         if (ViewDebug.DEBUG_DRAG) {
13236             Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
13237         }
13238         boolean okay = false;
13239 
13240         Point shadowSize = new Point();
13241         Point shadowTouchPoint = new Point();
13242         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
13243 
13244         if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
13245                 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
13246             throw new IllegalStateException("Drag shadow dimensions must not be negative");
13247         }
13248 
13249         if (ViewDebug.DEBUG_DRAG) {
13250             Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
13251                     + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
13252         }
13253         Surface surface = new Surface();
13254         try {
13255             IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
13256                     flags, shadowSize.x, shadowSize.y, surface);
13257             if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
13258                     + " surface=" + surface);
13259             if (token != null) {
13260                 Canvas canvas = surface.lockCanvas(null);
13261                 try {
13262                     canvas.drawColor(0, PorterDuff.Mode.CLEAR);
13263                     shadowBuilder.onDrawShadow(canvas);
13264                 } finally {
13265                     surface.unlockCanvasAndPost(canvas);
13266                 }
13267 
13268                 final ViewRootImpl root = getViewRootImpl();
13269 
13270                 // Cache the local state object for delivery with DragEvents
13271                 root.setLocalDragState(myLocalState);
13272 
13273                 // repurpose 'shadowSize' for the last touch point
13274                 root.getLastTouchPoint(shadowSize);
13275 
13276                 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
13277                         shadowSize.x, shadowSize.y,
13278                         shadowTouchPoint.x, shadowTouchPoint.y, data);
13279                 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
13280 
13281                 // Off and running!  Release our local surface instance; the drag
13282                 // shadow surface is now managed by the system process.
13283                 surface.release();
13284             }
13285         } catch (Exception e) {
13286             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
13287             surface.destroy();
13288         }
13289 
13290         return okay;
13291     }
13292 
13293     /**
13294      * Handles drag events sent by the system following a call to
13295      * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
13296      *<p>
13297      * When the system calls this method, it passes a
13298      * {@link android.view.DragEvent} object. A call to
13299      * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
13300      * in DragEvent. The method uses these to determine what is happening in the drag and drop
13301      * operation.
13302      * @param event The {@link android.view.DragEvent} sent by the system.
13303      * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
13304      * in DragEvent, indicating the type of drag event represented by this object.
13305      * @return {@code true} if the method was successful, otherwise {@code false}.
13306      * <p>
13307      *  The method should return {@code true} in response to an action type of
13308      *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
13309      *  operation.
13310      * </p>
13311      * <p>
13312      *  The method should also return {@code true} in response to an action type of
13313      *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
13314      *  {@code false} if it didn't.
13315      * </p>
13316      */
13317     public boolean onDragEvent(DragEvent event) {
13318         return false;
13319     }
13320 
13321     /**
13322      * Detects if this View is enabled and has a drag event listener.
13323      * If both are true, then it calls the drag event listener with the
13324      * {@link android.view.DragEvent} it received. If the drag event listener returns
13325      * {@code true}, then dispatchDragEvent() returns {@code true}.
13326      * <p>
13327      * For all other cases, the method calls the
13328      * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
13329      * method and returns its result.
13330      * </p>
13331      * <p>
13332      * This ensures that a drag event is always consumed, even if the View does not have a drag
13333      * event listener. However, if the View has a listener and the listener returns true, then
13334      * onDragEvent() is not called.
13335      * </p>
13336      */
13337     public boolean dispatchDragEvent(DragEvent event) {
13338         //noinspection SimplifiableIfStatement
13339         if (mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
13340                 && mOnDragListener.onDrag(this, event)) {
13341             return true;
13342         }
13343         return onDragEvent(event);
13344     }
13345 
13346     boolean canAcceptDrag() {
13347         return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
13348     }
13349 
13350     /**
13351      * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
13352      * it is ever exposed at all.
13353      * @hide
13354      */
13355     public void onCloseSystemDialogs(String reason) {
13356     }
13357 
13358     /**
13359      * Given a Drawable whose bounds have been set to draw into this view,
13360      * update a Region being computed for
13361      * {@link #gatherTransparentRegion(android.graphics.Region)} so
13362      * that any non-transparent parts of the Drawable are removed from the
13363      * given transparent region.
13364      *
13365      * @param dr The Drawable whose transparency is to be applied to the region.
13366      * @param region A Region holding the current transparency information,
13367      * where any parts of the region that are set are considered to be
13368      * transparent.  On return, this region will be modified to have the
13369      * transparency information reduced by the corresponding parts of the
13370      * Drawable that are not transparent.
13371      * {@hide}
13372      */
13373     public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
13374         if (DBG) {
13375             Log.i("View", "Getting transparent region for: " + this);
13376         }
13377         final Region r = dr.getTransparentRegion();
13378         final Rect db = dr.getBounds();
13379         final AttachInfo attachInfo = mAttachInfo;
13380         if (r != null && attachInfo != null) {
13381             final int w = getRight()-getLeft();
13382             final int h = getBottom()-getTop();
13383             if (db.left > 0) {
13384                 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
13385                 r.op(0, 0, db.left, h, Region.Op.UNION);
13386             }
13387             if (db.right < w) {
13388                 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
13389                 r.op(db.right, 0, w, h, Region.Op.UNION);
13390             }
13391             if (db.top > 0) {
13392                 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
13393                 r.op(0, 0, w, db.top, Region.Op.UNION);
13394             }
13395             if (db.bottom < h) {
13396                 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
13397                 r.op(0, db.bottom, w, h, Region.Op.UNION);
13398             }
13399             final int[] location = attachInfo.mTransparentLocation;
13400             getLocationInWindow(location);
13401             r.translate(location[0], location[1]);
13402             region.op(r, Region.Op.INTERSECT);
13403         } else {
13404             region.op(db, Region.Op.DIFFERENCE);
13405         }
13406     }
13407 
13408     private void checkForLongClick(int delayOffset) {
13409         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
13410             mHasPerformedLongPress = false;
13411 
13412             if (mPendingCheckForLongPress == null) {
13413                 mPendingCheckForLongPress = new CheckForLongPress();
13414             }
13415             mPendingCheckForLongPress.rememberWindowAttachCount();
13416             postDelayed(mPendingCheckForLongPress,
13417                     ViewConfiguration.getLongPressTimeout() - delayOffset);
13418         }
13419     }
13420 
13421     /**
13422      * Inflate a view from an XML resource.  This convenience method wraps the {@link
13423      * LayoutInflater} class, which provides a full range of options for view inflation.
13424      *
13425      * @param context The Context object for your activity or application.
13426      * @param resource The resource ID to inflate
13427      * @param root A view group that will be the parent.  Used to properly inflate the
13428      * layout_* parameters.
13429      * @see LayoutInflater
13430      */
13431     public static View inflate(Context context, int resource, ViewGroup root) {
13432         LayoutInflater factory = LayoutInflater.from(context);
13433         return factory.inflate(resource, root);
13434     }
13435 
13436     /**
13437      * Scroll the view with standard behavior for scrolling beyond the normal
13438      * content boundaries. Views that call this method should override
13439      * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
13440      * results of an over-scroll operation.
13441      *
13442      * Views can use this method to handle any touch or fling-based scrolling.
13443      *
13444      * @param deltaX Change in X in pixels
13445      * @param deltaY Change in Y in pixels
13446      * @param scrollX Current X scroll value in pixels before applying deltaX
13447      * @param scrollY Current Y scroll value in pixels before applying deltaY
13448      * @param scrollRangeX Maximum content scroll range along the X axis
13449      * @param scrollRangeY Maximum content scroll range along the Y axis
13450      * @param maxOverScrollX Number of pixels to overscroll by in either direction
13451      *          along the X axis.
13452      * @param maxOverScrollY Number of pixels to overscroll by in either direction
13453      *          along the Y axis.
13454      * @param isTouchEvent true if this scroll operation is the result of a touch event.
13455      * @return true if scrolling was clamped to an over-scroll boundary along either
13456      *          axis, false otherwise.
13457      */
13458     @SuppressWarnings({"UnusedParameters"})
13459     protected boolean overScrollBy(int deltaX, int deltaY,
13460             int scrollX, int scrollY,
13461             int scrollRangeX, int scrollRangeY,
13462             int maxOverScrollX, int maxOverScrollY,
13463             boolean isTouchEvent) {
13464         final int overScrollMode = mOverScrollMode;
13465         final boolean canScrollHorizontal =
13466                 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
13467         final boolean canScrollVertical =
13468                 computeVerticalScrollRange() > computeVerticalScrollExtent();
13469         final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
13470                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
13471         final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
13472                 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
13473 
13474         int newScrollX = scrollX + deltaX;
13475         if (!overScrollHorizontal) {
13476             maxOverScrollX = 0;
13477         }
13478 
13479         int newScrollY = scrollY + deltaY;
13480         if (!overScrollVertical) {
13481             maxOverScrollY = 0;
13482         }
13483 
13484         // Clamp values if at the limits and record
13485         final int left = -maxOverScrollX;
13486         final int right = maxOverScrollX + scrollRangeX;
13487         final int top = -maxOverScrollY;
13488         final int bottom = maxOverScrollY + scrollRangeY;
13489 
13490         boolean clampedX = false;
13491         if (newScrollX > right) {
13492             newScrollX = right;
13493             clampedX = true;
13494         } else if (newScrollX < left) {
13495             newScrollX = left;
13496             clampedX = true;
13497         }
13498 
13499         boolean clampedY = false;
13500         if (newScrollY > bottom) {
13501             newScrollY = bottom;
13502             clampedY = true;
13503         } else if (newScrollY < top) {
13504             newScrollY = top;
13505             clampedY = true;
13506         }
13507 
13508         onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
13509 
13510         return clampedX || clampedY;
13511     }
13512 
13513     /**
13514      * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
13515      * respond to the results of an over-scroll operation.
13516      *
13517      * @param scrollX New X scroll value in pixels
13518      * @param scrollY New Y scroll value in pixels
13519      * @param clampedX True if scrollX was clamped to an over-scroll boundary
13520      * @param clampedY True if scrollY was clamped to an over-scroll boundary
13521      */
13522     protected void onOverScrolled(int scrollX, int scrollY,
13523             boolean clampedX, boolean clampedY) {
13524         // Intentionally empty.
13525     }
13526 
13527     /**
13528      * Returns the over-scroll mode for this view. The result will be
13529      * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
13530      * (allow over-scrolling only if the view content is larger than the container),
13531      * or {@link #OVER_SCROLL_NEVER}.
13532      *
13533      * @return This view's over-scroll mode.
13534      */
13535     public int getOverScrollMode() {
13536         return mOverScrollMode;
13537     }
13538 
13539     /**
13540      * Set the over-scroll mode for this view. Valid over-scroll modes are
13541      * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
13542      * (allow over-scrolling only if the view content is larger than the container),
13543      * or {@link #OVER_SCROLL_NEVER}.
13544      *
13545      * Setting the over-scroll mode of a view will have an effect only if the
13546      * view is capable of scrolling.
13547      *
13548      * @param overScrollMode The new over-scroll mode for this view.
13549      */
13550     public void setOverScrollMode(int overScrollMode) {
13551         if (overScrollMode != OVER_SCROLL_ALWAYS &&
13552                 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
13553                 overScrollMode != OVER_SCROLL_NEVER) {
13554             throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
13555         }
13556         mOverScrollMode = overScrollMode;
13557     }
13558 
13559     /**
13560      * Gets a scale factor that determines the distance the view should scroll
13561      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
13562      * @return The vertical scroll scale factor.
13563      * @hide
13564      */
13565     protected float getVerticalScrollFactor() {
13566         if (mVerticalScrollFactor == 0) {
13567             TypedValue outValue = new TypedValue();
13568             if (!mContext.getTheme().resolveAttribute(
13569                     com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
13570                 throw new IllegalStateException(
13571                         "Expected theme to define listPreferredItemHeight.");
13572             }
13573             mVerticalScrollFactor = outValue.getDimension(
13574                     mContext.getResources().getDisplayMetrics());
13575         }
13576         return mVerticalScrollFactor;
13577     }
13578 
13579     /**
13580      * Gets a scale factor that determines the distance the view should scroll
13581      * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
13582      * @return The horizontal scroll scale factor.
13583      * @hide
13584      */
13585     protected float getHorizontalScrollFactor() {
13586         // TODO: Should use something else.
13587         return getVerticalScrollFactor();
13588     }
13589 
13590     /**
13591      * Return the value specifying the text direction or policy that was set with
13592      * {@link #setTextDirection(int)}.
13593      *
13594      * @return the defined text direction. It can be one of:
13595      *
13596      * {@link #TEXT_DIRECTION_INHERIT},
13597      * {@link #TEXT_DIRECTION_FIRST_STRONG}
13598      * {@link #TEXT_DIRECTION_ANY_RTL},
13599      * {@link #TEXT_DIRECTION_LTR},
13600      * {@link #TEXT_DIRECTION_RTL},
13601      *
13602      * @hide
13603      */
13604     public int getTextDirection() {
13605         return mTextDirection;
13606     }
13607 
13608     /**
13609      * Set the text direction.
13610      *
13611      * @param textDirection the direction to set. Should be one of:
13612      *
13613      * {@link #TEXT_DIRECTION_INHERIT},
13614      * {@link #TEXT_DIRECTION_FIRST_STRONG}
13615      * {@link #TEXT_DIRECTION_ANY_RTL},
13616      * {@link #TEXT_DIRECTION_LTR},
13617      * {@link #TEXT_DIRECTION_RTL},
13618      *
13619      * @hide
13620      */
13621     public void setTextDirection(int textDirection) {
13622         if (textDirection != mTextDirection) {
13623             mTextDirection = textDirection;
13624             resetResolvedTextDirection();
13625             requestLayout();
13626         }
13627     }
13628 
13629     /**
13630      * Return the resolved text direction.
13631      *
13632      * @return the resolved text direction. Return one of:
13633      *
13634      * {@link #TEXT_DIRECTION_FIRST_STRONG}
13635      * {@link #TEXT_DIRECTION_ANY_RTL},
13636      * {@link #TEXT_DIRECTION_LTR},
13637      * {@link #TEXT_DIRECTION_RTL},
13638      *
13639      * @hide
13640      */
13641     public int getResolvedTextDirection() {
13642         if (mResolvedTextDirection == TEXT_DIRECTION_INHERIT) {
13643             resolveTextDirection();
13644         }
13645         return mResolvedTextDirection;
13646     }
13647 
13648     /**
13649      * Resolve the text direction.
13650      *
13651      * @hide
13652      */
13653     protected void resolveTextDirection() {
13654         if (mTextDirection != TEXT_DIRECTION_INHERIT) {
13655             mResolvedTextDirection = mTextDirection;
13656             return;
13657         }
13658         if (mParent != null && mParent instanceof ViewGroup) {
13659             mResolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
13660             return;
13661         }
13662         mResolvedTextDirection = TEXT_DIRECTION_FIRST_STRONG;
13663     }
13664 
13665     /**
13666      * Reset resolved text direction. Will be resolved during a call to getResolvedTextDirection().
13667      *
13668      * @hide
13669      */
13670     protected void resetResolvedTextDirection() {
13671         mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
13672     }
13673 
13674     //
13675     // Properties
13676     //
13677     /**
13678      * A Property wrapper around the <code>alpha</code> functionality handled by the
13679      * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
13680      */
13681     public static Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
13682         @Override
13683         public void setValue(View object, float value) {
13684             object.setAlpha(value);
13685         }
13686 
13687         @Override
13688         public Float get(View object) {
13689             return object.getAlpha();
13690         }
13691     };
13692 
13693     /**
13694      * A Property wrapper around the <code>translationX</code> functionality handled by the
13695      * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
13696      */
13697     public static Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
13698         @Override
13699         public void setValue(View object, float value) {
13700             object.setTranslationX(value);
13701         }
13702 
13703                 @Override
13704         public Float get(View object) {
13705             return object.getTranslationX();
13706         }
13707     };
13708 
13709     /**
13710      * A Property wrapper around the <code>translationY</code> functionality handled by the
13711      * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
13712      */
13713     public static Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
13714         @Override
13715         public void setValue(View object, float value) {
13716             object.setTranslationY(value);
13717         }
13718 
13719         @Override
13720         public Float get(View object) {
13721             return object.getTranslationY();
13722         }
13723     };
13724 
13725     /**
13726      * A Property wrapper around the <code>x</code> functionality handled by the
13727      * {@link View#setX(float)} and {@link View#getX()} methods.
13728      */
13729     public static Property<View, Float> X = new FloatProperty<View>("x") {
13730         @Override
13731         public void setValue(View object, float value) {
13732             object.setX(value);
13733         }
13734 
13735         @Override
13736         public Float get(View object) {
13737             return object.getX();
13738         }
13739     };
13740 
13741     /**
13742      * A Property wrapper around the <code>y</code> functionality handled by the
13743      * {@link View#setY(float)} and {@link View#getY()} methods.
13744      */
13745     public static Property<View, Float> Y = new FloatProperty<View>("y") {
13746         @Override
13747         public void setValue(View object, float value) {
13748             object.setY(value);
13749         }
13750 
13751         @Override
13752         public Float get(View object) {
13753             return object.getY();
13754         }
13755     };
13756 
13757     /**
13758      * A Property wrapper around the <code>rotation</code> functionality handled by the
13759      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
13760      */
13761     public static Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
13762         @Override
13763         public void setValue(View object, float value) {
13764             object.setRotation(value);
13765         }
13766 
13767         @Override
13768         public Float get(View object) {
13769             return object.getRotation();
13770         }
13771     };
13772 
13773     /**
13774      * A Property wrapper around the <code>rotationX</code> functionality handled by the
13775      * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
13776      */
13777     public static Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
13778         @Override
13779         public void setValue(View object, float value) {
13780             object.setRotationX(value);
13781         }
13782 
13783         @Override
13784         public Float get(View object) {
13785             return object.getRotationX();
13786         }
13787     };
13788 
13789     /**
13790      * A Property wrapper around the <code>rotationY</code> functionality handled by the
13791      * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
13792      */
13793     public static Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
13794         @Override
13795         public void setValue(View object, float value) {
13796             object.setRotationY(value);
13797         }
13798 
13799         @Override
13800         public Float get(View object) {
13801             return object.getRotationY();
13802         }
13803     };
13804 
13805     /**
13806      * A Property wrapper around the <code>scaleX</code> functionality handled by the
13807      * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
13808      */
13809     public static Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
13810         @Override
13811         public void setValue(View object, float value) {
13812             object.setScaleX(value);
13813         }
13814 
13815         @Override
13816         public Float get(View object) {
13817             return object.getScaleX();
13818         }
13819     };
13820 
13821     /**
13822      * A Property wrapper around the <code>scaleY</code> functionality handled by the
13823      * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
13824      */
13825     public static Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
13826         @Override
13827         public void setValue(View object, float value) {
13828             object.setScaleY(value);
13829         }
13830 
13831         @Override
13832         public Float get(View object) {
13833             return object.getScaleY();
13834         }
13835     };
13836 
13837     /**
13838      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
13839      * Each MeasureSpec represents a requirement for either the width or the height.
13840      * A MeasureSpec is comprised of a size and a mode. There are three possible
13841      * modes:
13842      * <dl>
13843      * <dt>UNSPECIFIED</dt>
13844      * <dd>
13845      * The parent has not imposed any constraint on the child. It can be whatever size
13846      * it wants.
13847      * </dd>
13848      *
13849      * <dt>EXACTLY</dt>
13850      * <dd>
13851      * The parent has determined an exact size for the child. The child is going to be
13852      * given those bounds regardless of how big it wants to be.
13853      * </dd>
13854      *
13855      * <dt>AT_MOST</dt>
13856      * <dd>
13857      * The child can be as large as it wants up to the specified size.
13858      * </dd>
13859      * </dl>
13860      *
13861      * MeasureSpecs are implemented as ints to reduce object allocation. This class
13862      * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
13863      */
13864     public static class MeasureSpec {
13865         private static final int MODE_SHIFT = 30;
13866         private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
13867 
13868         /**
13869          * Measure specification mode: The parent has not imposed any constraint
13870          * on the child. It can be whatever size it wants.
13871          */
13872         public static final int UNSPECIFIED = 0 << MODE_SHIFT;
13873 
13874         /**
13875          * Measure specification mode: The parent has determined an exact size
13876          * for the child. The child is going to be given those bounds regardless
13877          * of how big it wants to be.
13878          */
13879         public static final int EXACTLY     = 1 << MODE_SHIFT;
13880 
13881         /**
13882          * Measure specification mode: The child can be as large as it wants up
13883          * to the specified size.
13884          */
13885         public static final int AT_MOST     = 2 << MODE_SHIFT;
13886 
13887         /**
13888          * Creates a measure specification based on the supplied size and mode.
13889          *
13890          * The mode must always be one of the following:
13891          * <ul>
13892          *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
13893          *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
13894          *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
13895          * </ul>
13896          *
13897          * @param size the size of the measure specification
13898          * @param mode the mode of the measure specification
13899          * @return the measure specification based on size and mode
13900          */
13901         public static int makeMeasureSpec(int size, int mode) {
13902             return size + mode;
13903         }
13904 
13905         /**
13906          * Extracts the mode from the supplied measure specification.
13907          *
13908          * @param measureSpec the measure specification to extract the mode from
13909          * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
13910          *         {@link android.view.View.MeasureSpec#AT_MOST} or
13911          *         {@link android.view.View.MeasureSpec#EXACTLY}
13912          */
13913         public static int getMode(int measureSpec) {
13914             return (measureSpec & MODE_MASK);
13915         }
13916 
13917         /**
13918          * Extracts the size from the supplied measure specification.
13919          *
13920          * @param measureSpec the measure specification to extract the size from
13921          * @return the size in pixels defined in the supplied measure specification
13922          */
13923         public static int getSize(int measureSpec) {
13924             return (measureSpec & ~MODE_MASK);
13925         }
13926 
13927         /**
13928          * Returns a String representation of the specified measure
13929          * specification.
13930          *
13931          * @param measureSpec the measure specification to convert to a String
13932          * @return a String with the following format: "MeasureSpec: MODE SIZE"
13933          */
13934         public static String toString(int measureSpec) {
13935             int mode = getMode(measureSpec);
13936             int size = getSize(measureSpec);
13937 
13938             StringBuilder sb = new StringBuilder("MeasureSpec: ");
13939 
13940             if (mode == UNSPECIFIED)
13941                 sb.append("UNSPECIFIED ");
13942             else if (mode == EXACTLY)
13943                 sb.append("EXACTLY ");
13944             else if (mode == AT_MOST)
13945                 sb.append("AT_MOST ");
13946             else
13947                 sb.append(mode).append(" ");
13948 
13949             sb.append(size);
13950             return sb.toString();
13951         }
13952     }
13953 
13954     class CheckForLongPress implements Runnable {
13955 
13956         private int mOriginalWindowAttachCount;
13957 
13958         public void run() {
13959             if (isPressed() && (mParent != null)
13960                     && mOriginalWindowAttachCount == mWindowAttachCount) {
13961                 if (performLongClick()) {
13962                     mHasPerformedLongPress = true;
13963                 }
13964             }
13965         }
13966 
13967         public void rememberWindowAttachCount() {
13968             mOriginalWindowAttachCount = mWindowAttachCount;
13969         }
13970     }
13971 
13972     private final class CheckForTap implements Runnable {
13973         public void run() {
13974             mPrivateFlags &= ~PREPRESSED;
13975             mPrivateFlags |= PRESSED;
13976             refreshDrawableState();
13977             checkForLongClick(ViewConfiguration.getTapTimeout());
13978         }
13979     }
13980 
13981     private final class PerformClick implements Runnable {
13982         public void run() {
13983             performClick();
13984         }
13985     }
13986 
13987     /** @hide */
13988     public void hackTurnOffWindowResizeAnim(boolean off) {
13989         mAttachInfo.mTurnOffWindowResizeAnim = off;
13990     }
13991 
13992     /**
13993      * This method returns a ViewPropertyAnimator object, which can be used to animate
13994      * specific properties on this View.
13995      *
13996      * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
13997      */
13998     public ViewPropertyAnimator animate() {
13999         if (mAnimator == null) {
14000             mAnimator = new ViewPropertyAnimator(this);
14001         }
14002         return mAnimator;
14003     }
14004 
14005     /**
14006      * Interface definition for a callback to be invoked when a key event is
14007      * dispatched to this view. The callback will be invoked before the key
14008      * event is given to the view.
14009      */
14010     public interface OnKeyListener {
14011         /**
14012          * Called when a key is dispatched to a view. This allows listeners to
14013          * get a chance to respond before the target view.
14014          *
14015          * @param v The view the key has been dispatched to.
14016          * @param keyCode The code for the physical key that was pressed
14017          * @param event The KeyEvent object containing full information about
14018          *        the event.
14019          * @return True if the listener has consumed the event, false otherwise.
14020          */
14021         boolean onKey(View v, int keyCode, KeyEvent event);
14022     }
14023 
14024     /**
14025      * Interface definition for a callback to be invoked when a touch event is
14026      * dispatched to this view. The callback will be invoked before the touch
14027      * event is given to the view.
14028      */
14029     public interface OnTouchListener {
14030         /**
14031          * Called when a touch event is dispatched to a view. This allows listeners to
14032          * get a chance to respond before the target view.
14033          *
14034          * @param v The view the touch event has been dispatched to.
14035          * @param event The MotionEvent object containing full information about
14036          *        the event.
14037          * @return True if the listener has consumed the event, false otherwise.
14038          */
14039         boolean onTouch(View v, MotionEvent event);
14040     }
14041 
14042     /**
14043      * Interface definition for a callback to be invoked when a hover event is
14044      * dispatched to this view. The callback will be invoked before the hover
14045      * event is given to the view.
14046      */
14047     public interface OnHoverListener {
14048         /**
14049          * Called when a hover event is dispatched to a view. This allows listeners to
14050          * get a chance to respond before the target view.
14051          *
14052          * @param v The view the hover event has been dispatched to.
14053          * @param event The MotionEvent object containing full information about
14054          *        the event.
14055          * @return True if the listener has consumed the event, false otherwise.
14056          */
14057         boolean onHover(View v, MotionEvent event);
14058     }
14059 
14060     /**
14061      * Interface definition for a callback to be invoked when a generic motion event is
14062      * dispatched to this view. The callback will be invoked before the generic motion
14063      * event is given to the view.
14064      */
14065     public interface OnGenericMotionListener {
14066         /**
14067          * Called when a generic motion event is dispatched to a view. This allows listeners to
14068          * get a chance to respond before the target view.
14069          *
14070          * @param v The view the generic motion event has been dispatched to.
14071          * @param event The MotionEvent object containing full information about
14072          *        the event.
14073          * @return True if the listener has consumed the event, false otherwise.
14074          */
14075         boolean onGenericMotion(View v, MotionEvent event);
14076     }
14077 
14078     /**
14079      * Interface definition for a callback to be invoked when a view has been clicked and held.
14080      */
14081     public interface OnLongClickListener {
14082         /**
14083          * Called when a view has been clicked and held.
14084          *
14085          * @param v The view that was clicked and held.
14086          *
14087          * @return true if the callback consumed the long click, false otherwise.
14088          */
14089         boolean onLongClick(View v);
14090     }
14091 
14092     /**
14093      * Interface definition for a callback to be invoked when a drag is being dispatched
14094      * to this view.  The callback will be invoked before the hosting view's own
14095      * onDrag(event) method.  If the listener wants to fall back to the hosting view's
14096      * onDrag(event) behavior, it should return 'false' from this callback.
14097      *
14098      * <div class="special reference">
14099      * <h3>Developer Guides</h3>
14100      * <p>For a guide to implementing drag and drop features, read the
14101      * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
14102      * </div>
14103      */
14104     public interface OnDragListener {
14105         /**
14106          * Called when a drag event is dispatched to a view. This allows listeners
14107          * to get a chance to override base View behavior.
14108          *
14109          * @param v The View that received the drag event.
14110          * @param event The {@link android.view.DragEvent} object for the drag event.
14111          * @return {@code true} if the drag event was handled successfully, or {@code false}
14112          * if the drag event was not handled. Note that {@code false} will trigger the View
14113          * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
14114          */
14115         boolean onDrag(View v, DragEvent event);
14116     }
14117 
14118     /**
14119      * Interface definition for a callback to be invoked when the focus state of
14120      * a view changed.
14121      */
14122     public interface OnFocusChangeListener {
14123         /**
14124          * Called when the focus state of a view has changed.
14125          *
14126          * @param v The view whose state has changed.
14127          * @param hasFocus The new focus state of v.
14128          */
14129         void onFocusChange(View v, boolean hasFocus);
14130     }
14131 
14132     /**
14133      * Interface definition for a callback to be invoked when a view is clicked.
14134      */
14135     public interface OnClickListener {
14136         /**
14137          * Called when a view has been clicked.
14138          *
14139          * @param v The view that was clicked.
14140          */
14141         void onClick(View v);
14142     }
14143 
14144     /**
14145      * Interface definition for a callback to be invoked when the context menu
14146      * for this view is being built.
14147      */
14148     public interface OnCreateContextMenuListener {
14149         /**
14150          * Called when the context menu for this view is being built. It is not
14151          * safe to hold onto the menu after this method returns.
14152          *
14153          * @param menu The context menu that is being built
14154          * @param v The view for which the context menu is being built
14155          * @param menuInfo Extra information about the item for which the
14156          *            context menu should be shown. This information will vary
14157          *            depending on the class of v.
14158          */
14159         void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
14160     }
14161 
14162     /**
14163      * Interface definition for a callback to be invoked when the status bar changes
14164      * visibility.  This reports <strong>global</strong> changes to the system UI
14165      * state, not just what the application is requesting.
14166      *
14167      * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
14168      */
14169     public interface OnSystemUiVisibilityChangeListener {
14170         /**
14171          * Called when the status bar changes visibility because of a call to
14172          * {@link View#setSystemUiVisibility(int)}.
14173          *
14174          * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
14175          * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  This tells you the
14176          * <strong>global</strong> state of the UI visibility flags, not what your
14177          * app is currently applying.
14178          */
14179         public void onSystemUiVisibilityChange(int visibility);
14180     }
14181 
14182     /**
14183      * Interface definition for a callback to be invoked when this view is attached
14184      * or detached from its window.
14185      */
14186     public interface OnAttachStateChangeListener {
14187         /**
14188          * Called when the view is attached to a window.
14189          * @param v The view that was attached
14190          */
14191         public void onViewAttachedToWindow(View v);
14192         /**
14193          * Called when the view is detached from a window.
14194          * @param v The view that was detached
14195          */
14196         public void onViewDetachedFromWindow(View v);
14197     }
14198 
14199     private final class UnsetPressedState implements Runnable {
14200         public void run() {
14201             setPressed(false);
14202         }
14203     }
14204 
14205     /**
14206      * Base class for derived classes that want to save and restore their own
14207      * state in {@link android.view.View#onSaveInstanceState()}.
14208      */
14209     public static class BaseSavedState extends AbsSavedState {
14210         /**
14211          * Constructor used when reading from a parcel. Reads the state of the superclass.
14212          *
14213          * @param source
14214          */
14215         public BaseSavedState(Parcel source) {
14216             super(source);
14217         }
14218 
14219         /**
14220          * Constructor called by derived classes when creating their SavedState objects
14221          *
14222          * @param superState The state of the superclass of this view
14223          */
14224         public BaseSavedState(Parcelable superState) {
14225             super(superState);
14226         }
14227 
14228         public static final Parcelable.Creator<BaseSavedState> CREATOR =
14229                 new Parcelable.Creator<BaseSavedState>() {
14230             public BaseSavedState createFromParcel(Parcel in) {
14231                 return new BaseSavedState(in);
14232             }
14233 
14234             public BaseSavedState[] newArray(int size) {
14235                 return new BaseSavedState[size];
14236             }
14237         };
14238     }
14239 
14240     /**
14241      * A set of information given to a view when it is attached to its parent
14242      * window.
14243      */
14244     static class AttachInfo {
14245         interface Callbacks {
14246             void playSoundEffect(int effectId);
14247             boolean performHapticFeedback(int effectId, boolean always);
14248         }
14249 
14250         /**
14251          * InvalidateInfo is used to post invalidate(int, int, int, int) messages
14252          * to a Handler. This class contains the target (View) to invalidate and
14253          * the coordinates of the dirty rectangle.
14254          *
14255          * For performance purposes, this class also implements a pool of up to
14256          * POOL_LIMIT objects that get reused. This reduces memory allocations
14257          * whenever possible.
14258          */
14259         static class InvalidateInfo implements Poolable<InvalidateInfo> {
14260             private static final int POOL_LIMIT = 10;
14261             private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
14262                     Pools.finitePool(new PoolableManager<InvalidateInfo>() {
14263                         public InvalidateInfo newInstance() {
14264                             return new InvalidateInfo();
14265                         }
14266 
14267                         public void onAcquired(InvalidateInfo element) {
14268                         }
14269 
14270                         public void onReleased(InvalidateInfo element) {
14271                             element.target = null;
14272                         }
14273                     }, POOL_LIMIT)
14274             );
14275 
14276             private InvalidateInfo mNext;
14277             private boolean mIsPooled;
14278 
14279             View target;
14280 
14281             int left;
14282             int top;
14283             int right;
14284             int bottom;
14285 
14286             public void setNextPoolable(InvalidateInfo element) {
14287                 mNext = element;
14288             }
14289 
14290             public InvalidateInfo getNextPoolable() {
14291                 return mNext;
14292             }
14293 
14294             static InvalidateInfo acquire() {
14295                 return sPool.acquire();
14296             }
14297 
14298             void release() {
14299                 sPool.release(this);
14300             }
14301 
14302             public boolean isPooled() {
14303                 return mIsPooled;
14304             }
14305 
14306             public void setPooled(boolean isPooled) {
14307                 mIsPooled = isPooled;
14308             }
14309         }
14310 
14311         final IWindowSession mSession;
14312 
14313         final IWindow mWindow;
14314 
14315         final IBinder mWindowToken;
14316 
14317         final Callbacks mRootCallbacks;
14318 
14319         HardwareCanvas mHardwareCanvas;
14320 
14321         /**
14322          * The top view of the hierarchy.
14323          */
14324         View mRootView;
14325 
14326         IBinder mPanelParentWindowToken;
14327         Surface mSurface;
14328 
14329         boolean mHardwareAccelerated;
14330         boolean mHardwareAccelerationRequested;
14331         HardwareRenderer mHardwareRenderer;
14332 
14333         /**
14334          * Scale factor used by the compatibility mode
14335          */
14336         float mApplicationScale;
14337 
14338         /**
14339          * Indicates whether the application is in compatibility mode
14340          */
14341         boolean mScalingRequired;
14342 
14343         /**
14344          * If set, ViewAncestor doesn't use its lame animation for when the window resizes.
14345          */
14346         boolean mTurnOffWindowResizeAnim;
14347 
14348         /**
14349          * Left position of this view's window
14350          */
14351         int mWindowLeft;
14352 
14353         /**
14354          * Top position of this view's window
14355          */
14356         int mWindowTop;
14357 
14358         /**
14359          * Indicates whether views need to use 32-bit drawing caches
14360          */
14361         boolean mUse32BitDrawingCache;
14362 
14363         /**
14364          * For windows that are full-screen but using insets to layout inside
14365          * of the screen decorations, these are the current insets for the
14366          * content of the window.
14367          */
14368         final Rect mContentInsets = new Rect();
14369 
14370         /**
14371          * For windows that are full-screen but using insets to layout inside
14372          * of the screen decorations, these are the current insets for the
14373          * actual visible parts of the window.
14374          */
14375         final Rect mVisibleInsets = new Rect();
14376 
14377         /**
14378          * The internal insets given by this window.  This value is
14379          * supplied by the client (through
14380          * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
14381          * be given to the window manager when changed to be used in laying
14382          * out windows behind it.
14383          */
14384         final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
14385                 = new ViewTreeObserver.InternalInsetsInfo();
14386 
14387         /**
14388          * All views in the window's hierarchy that serve as scroll containers,
14389          * used to determine if the window can be resized or must be panned
14390          * to adjust for a soft input area.
14391          */
14392         final ArrayList<View> mScrollContainers = new ArrayList<View>();
14393 
14394         final KeyEvent.DispatcherState mKeyDispatchState
14395                 = new KeyEvent.DispatcherState();
14396 
14397         /**
14398          * Indicates whether the view's window currently has the focus.
14399          */
14400         boolean mHasWindowFocus;
14401 
14402         /**
14403          * The current visibility of the window.
14404          */
14405         int mWindowVisibility;
14406 
14407         /**
14408          * Indicates the time at which drawing started to occur.
14409          */
14410         long mDrawingTime;
14411 
14412         /**
14413          * Indicates whether or not ignoring the DIRTY_MASK flags.
14414          */
14415         boolean mIgnoreDirtyState;
14416 
14417         /**
14418          * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
14419          * to avoid clearing that flag prematurely.
14420          */
14421         boolean mSetIgnoreDirtyState = false;
14422 
14423         /**
14424          * Indicates whether the view's window is currently in touch mode.
14425          */
14426         boolean mInTouchMode;
14427 
14428         /**
14429          * Indicates that ViewAncestor should trigger a global layout change
14430          * the next time it performs a traversal
14431          */
14432         boolean mRecomputeGlobalAttributes;
14433 
14434         /**
14435          * Always report new attributes at next traversal.
14436          */
14437         boolean mForceReportNewAttributes;
14438 
14439         /**
14440          * Set during a traveral if any views want to keep the screen on.
14441          */
14442         boolean mKeepScreenOn;
14443 
14444         /**
14445          * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
14446          */
14447         int mSystemUiVisibility;
14448 
14449         /**
14450          * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
14451          * attached.
14452          */
14453         boolean mHasSystemUiListeners;
14454 
14455         /**
14456          * Set if the visibility of any views has changed.
14457          */
14458         boolean mViewVisibilityChanged;
14459 
14460         /**
14461          * Set to true if a view has been scrolled.
14462          */
14463         boolean mViewScrollChanged;
14464 
14465         /**
14466          * Global to the view hierarchy used as a temporary for dealing with
14467          * x/y points in the transparent region computations.
14468          */
14469         final int[] mTransparentLocation = new int[2];
14470 
14471         /**
14472          * Global to the view hierarchy used as a temporary for dealing with
14473          * x/y points in the ViewGroup.invalidateChild implementation.
14474          */
14475         final int[] mInvalidateChildLocation = new int[2];
14476 
14477 
14478         /**
14479          * Global to the view hierarchy used as a temporary for dealing with
14480          * x/y location when view is transformed.
14481          */
14482         final float[] mTmpTransformLocation = new float[2];
14483 
14484         /**
14485          * The view tree observer used to dispatch global events like
14486          * layout, pre-draw, touch mode change, etc.
14487          */
14488         final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
14489 
14490         /**
14491          * A Canvas used by the view hierarchy to perform bitmap caching.
14492          */
14493         Canvas mCanvas;
14494 
14495         /**
14496          * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
14497          * handler can be used to pump events in the UI events queue.
14498          */
14499         final Handler mHandler;
14500 
14501         /**
14502          * Identifier for messages requesting the view to be invalidated.
14503          * Such messages should be sent to {@link #mHandler}.
14504          */
14505         static final int INVALIDATE_MSG = 0x1;
14506 
14507         /**
14508          * Identifier for messages requesting the view to invalidate a region.
14509          * Such messages should be sent to {@link #mHandler}.
14510          */
14511         static final int INVALIDATE_RECT_MSG = 0x2;
14512 
14513         /**
14514          * Temporary for use in computing invalidate rectangles while
14515          * calling up the hierarchy.
14516          */
14517         final Rect mTmpInvalRect = new Rect();
14518 
14519         /**
14520          * Temporary for use in computing hit areas with transformed views
14521          */
14522         final RectF mTmpTransformRect = new RectF();
14523 
14524         /**
14525          * Temporary list for use in collecting focusable descendents of a view.
14526          */
14527         final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24);
14528 
14529         /**
14530          * The id of the window for accessibility purposes.
14531          */
14532         int mAccessibilityWindowId = View.NO_ID;
14533 
14534         /**
14535          * Creates a new set of attachment information with the specified
14536          * events handler and thread.
14537          *
14538          * @param handler the events handler the view must use
14539          */
14540         AttachInfo(IWindowSession session, IWindow window,
14541                 Handler handler, Callbacks effectPlayer) {
14542             mSession = session;
14543             mWindow = window;
14544             mWindowToken = window.asBinder();
14545             mHandler = handler;
14546             mRootCallbacks = effectPlayer;
14547         }
14548     }
14549 
14550     /**
14551      * <p>ScrollabilityCache holds various fields used by a View when scrolling
14552      * is supported. This avoids keeping too many unused fields in most
14553      * instances of View.</p>
14554      */
14555     private static class ScrollabilityCache implements Runnable {
14556 
14557         /**
14558          * Scrollbars are not visible
14559          */
14560         public static final int OFF = 0;
14561 
14562         /**
14563          * Scrollbars are visible
14564          */
14565         public static final int ON = 1;
14566 
14567         /**
14568          * Scrollbars are fading away
14569          */
14570         public static final int FADING = 2;
14571 
14572         public boolean fadeScrollBars;
14573 
14574         public int fadingEdgeLength;
14575         public int scrollBarDefaultDelayBeforeFade;
14576         public int scrollBarFadeDuration;
14577 
14578         public int scrollBarSize;
14579         public ScrollBarDrawable scrollBar;
14580         public float[] interpolatorValues;
14581         public View host;
14582 
14583         public final Paint paint;
14584         public final Matrix matrix;
14585         public Shader shader;
14586 
14587         public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
14588 
14589         private static final float[] OPAQUE = { 255 };
14590         private static final float[] TRANSPARENT = { 0.0f };
14591 
14592         /**
14593          * When fading should start. This time moves into the future every time
14594          * a new scroll happens. Measured based on SystemClock.uptimeMillis()
14595          */
14596         public long fadeStartTime;
14597 
14598 
14599         /**
14600          * The current state of the scrollbars: ON, OFF, or FADING
14601          */
14602         public int state = OFF;
14603 
14604         private int mLastColor;
14605 
14606         public ScrollabilityCache(ViewConfiguration configuration, View host) {
14607             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
14608             scrollBarSize = configuration.getScaledScrollBarSize();
14609             scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
14610             scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
14611 
14612             paint = new Paint();
14613             matrix = new Matrix();
14614             // use use a height of 1, and then wack the matrix each time we
14615             // actually use it.
14616             shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
14617 
14618             paint.setShader(shader);
14619             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
14620             this.host = host;
14621         }
14622 
14623         public void setFadeColor(int color) {
14624             if (color != 0 && color != mLastColor) {
14625                 mLastColor = color;
14626                 color |= 0xFF000000;
14627 
14628                 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
14629                         color & 0x00FFFFFF, Shader.TileMode.CLAMP);
14630 
14631                 paint.setShader(shader);
14632                 // Restore the default transfer mode (src_over)
14633                 paint.setXfermode(null);
14634             }
14635         }
14636 
14637         public void run() {
14638             long now = AnimationUtils.currentAnimationTimeMillis();
14639             if (now >= fadeStartTime) {
14640 
14641                 // the animation fades the scrollbars out by changing
14642                 // the opacity (alpha) from fully opaque to fully
14643                 // transparent
14644                 int nextFrame = (int) now;
14645                 int framesCount = 0;
14646 
14647                 Interpolator interpolator = scrollBarInterpolator;
14648 
14649                 // Start opaque
14650                 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
14651 
14652                 // End transparent
14653                 nextFrame += scrollBarFadeDuration;
14654                 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
14655 
14656                 state = FADING;
14657 
14658                 // Kick off the fade animation
14659                 host.invalidate(true);
14660             }
14661         }
14662     }
14663 
14664     /**
14665      * Resuable callback for sending
14666      * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
14667      */
14668     private class SendViewScrolledAccessibilityEvent implements Runnable {
14669         public volatile boolean mIsPending;
14670 
14671         public void run() {
14672             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
14673             mIsPending = false;
14674         }
14675     }
14676 
14677     /**
14678      * <p>
14679      * This class represents a delegate that can be registered in a {@link View}
14680      * to enhance accessibility support via composition rather via inheritance.
14681      * It is specifically targeted to widget developers that extend basic View
14682      * classes i.e. classes in package android.view, that would like their
14683      * applications to be backwards compatible.
14684      * </p>
14685      * <p>
14686      * A scenario in which a developer would like to use an accessibility delegate
14687      * is overriding a method introduced in a later API version then the minimal API
14688      * version supported by the application. For example, the method
14689      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
14690      * in API version 4 when the accessibility APIs were first introduced. If a
14691      * developer would like his application to run on API version 4 devices (assuming
14692      * all other APIs used by the application are version 4 or lower) and take advantage
14693      * of this method, instead of overriding the method which would break the application's
14694      * backwards compatibility, he can override the corresponding method in this
14695      * delegate and register the delegate in the target View if the API version of
14696      * the system is high enough i.e. the API version is same or higher to the API
14697      * version that introduced
14698      * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
14699      * </p>
14700      * <p>
14701      * Here is an example implementation:
14702      * </p>
14703      * <code><pre><p>
14704      * if (Build.VERSION.SDK_INT >= 14) {
14705      *     // If the API version is equal of higher than the version in
14706      *     // which onInitializeAccessibilityNodeInfo was introduced we
14707      *     // register a delegate with a customized implementation.
14708      *     View view = findViewById(R.id.view_id);
14709      *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
14710      *         public void onInitializeAccessibilityNodeInfo(View host,
14711      *                 AccessibilityNodeInfo info) {
14712      *             // Let the default implementation populate the info.
14713      *             super.onInitializeAccessibilityNodeInfo(host, info);
14714      *             // Set some other information.
14715      *             info.setEnabled(host.isEnabled());
14716      *         }
14717      *     });
14718      * }
14719      * </code></pre></p>
14720      * <p>
14721      * This delegate contains methods that correspond to the accessibility methods
14722      * in View. If a delegate has been specified the implementation in View hands
14723      * off handling to the corresponding method in this delegate. The default
14724      * implementation the delegate methods behaves exactly as the corresponding
14725      * method in View for the case of no accessibility delegate been set. Hence,
14726      * to customize the behavior of a View method, clients can override only the
14727      * corresponding delegate method without altering the behavior of the rest
14728      * accessibility related methods of the host view.
14729      * </p>
14730      */
14731     public static class AccessibilityDelegate {
14732 
14733         /**
14734          * Sends an accessibility event of the given type. If accessibility is not
14735          * enabled this method has no effect.
14736          * <p>
14737          * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
14738          *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
14739          * been set.
14740          * </p>
14741          *
14742          * @param host The View hosting the delegate.
14743          * @param eventType The type of the event to send.
14744          *
14745          * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
14746          */
14747         public void sendAccessibilityEvent(View host, int eventType) {
14748             host.sendAccessibilityEventInternal(eventType);
14749         }
14750 
14751         /**
14752          * Sends an accessibility event. This method behaves exactly as
14753          * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
14754          * empty {@link AccessibilityEvent} and does not perform a check whether
14755          * accessibility is enabled.
14756          * <p>
14757          * The default implementation behaves as
14758          * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
14759          *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
14760          * the case of no accessibility delegate been set.
14761          * </p>
14762          *
14763          * @param host The View hosting the delegate.
14764          * @param event The event to send.
14765          *
14766          * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
14767          *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
14768          */
14769         public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
14770             host.sendAccessibilityEventUncheckedInternal(event);
14771         }
14772 
14773         /**
14774          * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
14775          * to its children for adding their text content to the event.
14776          * <p>
14777          * The default implementation behaves as
14778          * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
14779          *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
14780          * the case of no accessibility delegate been set.
14781          * </p>
14782          *
14783          * @param host The View hosting the delegate.
14784          * @param event The event.
14785          * @return True if the event population was completed.
14786          *
14787          * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
14788          *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
14789          */
14790         public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
14791             return host.dispatchPopulateAccessibilityEventInternal(event);
14792         }
14793 
14794         /**
14795          * Gives a chance to the host View to populate the accessibility event with its
14796          * text content.
14797          * <p>
14798          * The default implementation behaves as
14799          * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
14800          *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
14801          * the case of no accessibility delegate been set.
14802          * </p>
14803          *
14804          * @param host The View hosting the delegate.
14805          * @param event The accessibility event which to populate.
14806          *
14807          * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
14808          *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
14809          */
14810         public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
14811             host.onPopulateAccessibilityEventInternal(event);
14812         }
14813 
14814         /**
14815          * Initializes an {@link AccessibilityEvent} with information about the
14816          * the host View which is the event source.
14817          * <p>
14818          * The default implementation behaves as
14819          * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
14820          *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
14821          * the case of no accessibility delegate been set.
14822          * </p>
14823          *
14824          * @param host The View hosting the delegate.
14825          * @param event The event to initialize.
14826          *
14827          * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
14828          *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
14829          */
14830         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
14831             host.onInitializeAccessibilityEventInternal(event);
14832         }
14833 
14834         /**
14835          * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
14836          * <p>
14837          * The default implementation behaves as
14838          * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
14839          *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
14840          * the case of no accessibility delegate been set.
14841          * </p>
14842          *
14843          * @param host The View hosting the delegate.
14844          * @param info The instance to initialize.
14845          *
14846          * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
14847          *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
14848          */
14849         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
14850             host.onInitializeAccessibilityNodeInfoInternal(info);
14851         }
14852 
14853         /**
14854          * Called when a child of the host View has requested sending an
14855          * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
14856          * to augment the event.
14857          * <p>
14858          * The default implementation behaves as
14859          * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
14860          *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
14861          * the case of no accessibility delegate been set.
14862          * </p>
14863          *
14864          * @param host The View hosting the delegate.
14865          * @param child The child which requests sending the event.
14866          * @param event The event to be sent.
14867          * @return True if the event should be sent
14868          *
14869          * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
14870          *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
14871          */
14872         public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
14873                 AccessibilityEvent event) {
14874             return host.onRequestSendAccessibilityEventInternal(child, event);
14875         }
14876     }
14877 }
14878