View.java revision 7853c579fa52e4365c6e44ba38aeb3299d776f44
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
17package android.view;
18
19import android.content.ClipData;
20import android.content.Context;
21import android.content.res.Configuration;
22import android.content.res.Resources;
23import android.content.res.TypedArray;
24import android.graphics.Bitmap;
25import android.graphics.Camera;
26import android.graphics.Canvas;
27import android.graphics.Interpolator;
28import android.graphics.LinearGradient;
29import android.graphics.Matrix;
30import android.graphics.Paint;
31import android.graphics.PixelFormat;
32import android.graphics.Point;
33import android.graphics.PorterDuff;
34import android.graphics.PorterDuffXfermode;
35import android.graphics.Rect;
36import android.graphics.RectF;
37import android.graphics.Region;
38import android.graphics.Shader;
39import android.graphics.drawable.ColorDrawable;
40import android.graphics.drawable.Drawable;
41import android.os.Handler;
42import android.os.IBinder;
43import android.os.Message;
44import android.os.Parcel;
45import android.os.Parcelable;
46import android.os.RemoteException;
47import android.os.SystemClock;
48import android.text.TextUtils;
49import android.util.AttributeSet;
50import android.util.FloatProperty;
51import android.util.LocaleUtil;
52import android.util.Log;
53import android.util.Pool;
54import android.util.Poolable;
55import android.util.PoolableManager;
56import android.util.Pools;
57import android.util.Property;
58import android.util.SparseArray;
59import android.util.TypedValue;
60import android.view.ContextMenu.ContextMenuInfo;
61import android.view.accessibility.AccessibilityEvent;
62import android.view.accessibility.AccessibilityEventSource;
63import android.view.accessibility.AccessibilityManager;
64import android.view.accessibility.AccessibilityNodeInfo;
65import android.view.animation.Animation;
66import android.view.animation.AnimationUtils;
67import android.view.inputmethod.EditorInfo;
68import android.view.inputmethod.InputConnection;
69import android.view.inputmethod.InputMethodManager;
70import android.widget.ScrollBarDrawable;
71
72import static android.os.Build.VERSION_CODES.*;
73
74import com.android.internal.R;
75import com.android.internal.util.Predicate;
76import com.android.internal.view.menu.MenuBuilder;
77
78import java.lang.ref.WeakReference;
79import java.lang.reflect.InvocationTargetException;
80import java.lang.reflect.Method;
81import java.util.ArrayList;
82import java.util.Arrays;
83import java.util.Locale;
84import 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 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 */
631public 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
1491    /**
1492     * Temporary Rect currently for use in setBackground().  This will probably
1493     * be extended in the future to hold our own class with more than just
1494     * a Rect. :)
1495     */
1496    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1497
1498    /**
1499     * Map used to store views' tags.
1500     */
1501    private SparseArray<Object> mKeyedTags;
1502
1503    /**
1504     * The next available accessiiblity id.
1505     */
1506    private static int sNextAccessibilityViewId;
1507
1508    /**
1509     * The animation currently associated with this view.
1510     * @hide
1511     */
1512    protected Animation mCurrentAnimation = null;
1513
1514    /**
1515     * Width as measured during measure pass.
1516     * {@hide}
1517     */
1518    @ViewDebug.ExportedProperty(category = "measurement")
1519    int mMeasuredWidth;
1520
1521    /**
1522     * Height as measured during measure pass.
1523     * {@hide}
1524     */
1525    @ViewDebug.ExportedProperty(category = "measurement")
1526    int mMeasuredHeight;
1527
1528    /**
1529     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1530     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1531     * its display list. This flag, used only when hw accelerated, allows us to clear the
1532     * flag while retaining this information until it's needed (at getDisplayList() time and
1533     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1534     *
1535     * {@hide}
1536     */
1537    boolean mRecreateDisplayList = false;
1538
1539    /**
1540     * The view's identifier.
1541     * {@hide}
1542     *
1543     * @see #setId(int)
1544     * @see #getId()
1545     */
1546    @ViewDebug.ExportedProperty(resolveId = true)
1547    int mID = NO_ID;
1548
1549    /**
1550     * The stable ID of this view for accessibility porposes.
1551     */
1552    int mAccessibilityViewId = NO_ID;
1553
1554    /**
1555     * The view's tag.
1556     * {@hide}
1557     *
1558     * @see #setTag(Object)
1559     * @see #getTag()
1560     */
1561    protected Object mTag;
1562
1563    // for mPrivateFlags:
1564    /** {@hide} */
1565    static final int WANTS_FOCUS                    = 0x00000001;
1566    /** {@hide} */
1567    static final int FOCUSED                        = 0x00000002;
1568    /** {@hide} */
1569    static final int SELECTED                       = 0x00000004;
1570    /** {@hide} */
1571    static final int IS_ROOT_NAMESPACE              = 0x00000008;
1572    /** {@hide} */
1573    static final int HAS_BOUNDS                     = 0x00000010;
1574    /** {@hide} */
1575    static final int DRAWN                          = 0x00000020;
1576    /**
1577     * When this flag is set, this view is running an animation on behalf of its
1578     * children and should therefore not cancel invalidate requests, even if they
1579     * lie outside of this view's bounds.
1580     *
1581     * {@hide}
1582     */
1583    static final int DRAW_ANIMATION                 = 0x00000040;
1584    /** {@hide} */
1585    static final int SKIP_DRAW                      = 0x00000080;
1586    /** {@hide} */
1587    static final int ONLY_DRAWS_BACKGROUND          = 0x00000100;
1588    /** {@hide} */
1589    static final int REQUEST_TRANSPARENT_REGIONS    = 0x00000200;
1590    /** {@hide} */
1591    static final int DRAWABLE_STATE_DIRTY           = 0x00000400;
1592    /** {@hide} */
1593    static final int MEASURED_DIMENSION_SET         = 0x00000800;
1594    /** {@hide} */
1595    static final int FORCE_LAYOUT                   = 0x00001000;
1596    /** {@hide} */
1597    static final int LAYOUT_REQUIRED                = 0x00002000;
1598
1599    private static final int PRESSED                = 0x00004000;
1600
1601    /** {@hide} */
1602    static final int DRAWING_CACHE_VALID            = 0x00008000;
1603    /**
1604     * Flag used to indicate that this view should be drawn once more (and only once
1605     * more) after its animation has completed.
1606     * {@hide}
1607     */
1608    static final int ANIMATION_STARTED              = 0x00010000;
1609
1610    private static final int SAVE_STATE_CALLED      = 0x00020000;
1611
1612    /**
1613     * Indicates that the View returned true when onSetAlpha() was called and that
1614     * the alpha must be restored.
1615     * {@hide}
1616     */
1617    static final int ALPHA_SET                      = 0x00040000;
1618
1619    /**
1620     * Set by {@link #setScrollContainer(boolean)}.
1621     */
1622    static final int SCROLL_CONTAINER               = 0x00080000;
1623
1624    /**
1625     * Set by {@link #setScrollContainer(boolean)}.
1626     */
1627    static final int SCROLL_CONTAINER_ADDED         = 0x00100000;
1628
1629    /**
1630     * View flag indicating whether this view was invalidated (fully or partially.)
1631     *
1632     * @hide
1633     */
1634    static final int DIRTY                          = 0x00200000;
1635
1636    /**
1637     * View flag indicating whether this view was invalidated by an opaque
1638     * invalidate request.
1639     *
1640     * @hide
1641     */
1642    static final int DIRTY_OPAQUE                   = 0x00400000;
1643
1644    /**
1645     * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
1646     *
1647     * @hide
1648     */
1649    static final int DIRTY_MASK                     = 0x00600000;
1650
1651    /**
1652     * Indicates whether the background is opaque.
1653     *
1654     * @hide
1655     */
1656    static final int OPAQUE_BACKGROUND              = 0x00800000;
1657
1658    /**
1659     * Indicates whether the scrollbars are opaque.
1660     *
1661     * @hide
1662     */
1663    static final int OPAQUE_SCROLLBARS              = 0x01000000;
1664
1665    /**
1666     * Indicates whether the view is opaque.
1667     *
1668     * @hide
1669     */
1670    static final int OPAQUE_MASK                    = 0x01800000;
1671
1672    /**
1673     * Indicates a prepressed state;
1674     * the short time between ACTION_DOWN and recognizing
1675     * a 'real' press. Prepressed is used to recognize quick taps
1676     * even when they are shorter than ViewConfiguration.getTapTimeout().
1677     *
1678     * @hide
1679     */
1680    private static final int PREPRESSED             = 0x02000000;
1681
1682    /**
1683     * Indicates whether the view is temporarily detached.
1684     *
1685     * @hide
1686     */
1687    static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
1688
1689    /**
1690     * Indicates that we should awaken scroll bars once attached
1691     *
1692     * @hide
1693     */
1694    private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1695
1696    /**
1697     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1698     * @hide
1699     */
1700    private static final int HOVERED              = 0x10000000;
1701
1702    /**
1703     * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
1704     * for transform operations
1705     *
1706     * @hide
1707     */
1708    private static final int PIVOT_EXPLICITLY_SET = 0x20000000;
1709
1710    /** {@hide} */
1711    static final int ACTIVATED                    = 0x40000000;
1712
1713    /**
1714     * Indicates that this view was specifically invalidated, not just dirtied because some
1715     * child view was invalidated. The flag is used to determine when we need to recreate
1716     * a view's display list (as opposed to just returning a reference to its existing
1717     * display list).
1718     *
1719     * @hide
1720     */
1721    static final int INVALIDATED                  = 0x80000000;
1722
1723    /* Masks for mPrivateFlags2 */
1724
1725    /**
1726     * Indicates that this view has reported that it can accept the current drag's content.
1727     * Cleared when the drag operation concludes.
1728     * @hide
1729     */
1730    static final int DRAG_CAN_ACCEPT              = 0x00000001;
1731
1732    /**
1733     * Indicates that this view is currently directly under the drag location in a
1734     * drag-and-drop operation involving content that it can accept.  Cleared when
1735     * the drag exits the view, or when the drag operation concludes.
1736     * @hide
1737     */
1738    static final int DRAG_HOVERED                 = 0x00000002;
1739
1740    /**
1741     * Indicates whether the view layout direction has been resolved and drawn to the
1742     * right-to-left direction.
1743     *
1744     * @hide
1745     */
1746    static final int LAYOUT_DIRECTION_RESOLVED_RTL = 0x00000004;
1747
1748    /**
1749     * Indicates whether the view layout direction has been resolved.
1750     *
1751     * @hide
1752     */
1753    static final int LAYOUT_DIRECTION_RESOLVED = 0x00000008;
1754
1755
1756    /* End of masks for mPrivateFlags2 */
1757
1758    static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
1759
1760    /**
1761     * Always allow a user to over-scroll this view, provided it is a
1762     * view that can scroll.
1763     *
1764     * @see #getOverScrollMode()
1765     * @see #setOverScrollMode(int)
1766     */
1767    public static final int OVER_SCROLL_ALWAYS = 0;
1768
1769    /**
1770     * Allow a user to over-scroll this view only if the content is large
1771     * enough to meaningfully scroll, provided it is a view that can scroll.
1772     *
1773     * @see #getOverScrollMode()
1774     * @see #setOverScrollMode(int)
1775     */
1776    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
1777
1778    /**
1779     * Never allow a user to over-scroll this view.
1780     *
1781     * @see #getOverScrollMode()
1782     * @see #setOverScrollMode(int)
1783     */
1784    public static final int OVER_SCROLL_NEVER = 2;
1785
1786    /**
1787     * View has requested the system UI (status bar) to be visible (the default).
1788     *
1789     * @see #setSystemUiVisibility(int)
1790     */
1791    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
1792
1793    /**
1794     * View has requested the system UI to enter an unobtrusive "low profile" mode.
1795     *
1796     * This is for use in games, book readers, video players, or any other "immersive" application
1797     * where the usual system chrome is deemed too distracting.
1798     *
1799     * In low profile mode, the status bar and/or navigation icons may dim.
1800     *
1801     * @see #setSystemUiVisibility(int)
1802     */
1803    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
1804
1805    /**
1806     * View has requested that the system navigation be temporarily hidden.
1807     *
1808     * This is an even less obtrusive state than that called for by
1809     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
1810     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
1811     * those to disappear. This is useful (in conjunction with the
1812     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
1813     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
1814     * window flags) for displaying content using every last pixel on the display.
1815     *
1816     * There is a limitation: because navigation controls are so important, the least user
1817     * interaction will cause them to reappear immediately.
1818     *
1819     * @see #setSystemUiVisibility(int)
1820     */
1821    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
1822
1823    /**
1824     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
1825     */
1826    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
1827
1828    /**
1829     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
1830     */
1831    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
1832
1833    /**
1834     * @hide
1835     *
1836     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1837     * out of the public fields to keep the undefined bits out of the developer's way.
1838     *
1839     * Flag to make the status bar not expandable.  Unless you also
1840     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
1841     */
1842    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
1843
1844    /**
1845     * @hide
1846     *
1847     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1848     * out of the public fields to keep the undefined bits out of the developer's way.
1849     *
1850     * Flag to hide notification icons and scrolling ticker text.
1851     */
1852    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
1853
1854    /**
1855     * @hide
1856     *
1857     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1858     * out of the public fields to keep the undefined bits out of the developer's way.
1859     *
1860     * Flag to disable incoming notification alerts.  This will not block
1861     * icons, but it will block sound, vibrating and other visual or aural notifications.
1862     */
1863    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
1864
1865    /**
1866     * @hide
1867     *
1868     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1869     * out of the public fields to keep the undefined bits out of the developer's way.
1870     *
1871     * Flag to hide only the scrolling ticker.  Note that
1872     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
1873     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
1874     */
1875    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
1876
1877    /**
1878     * @hide
1879     *
1880     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1881     * out of the public fields to keep the undefined bits out of the developer's way.
1882     *
1883     * Flag to hide the center system info area.
1884     */
1885    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
1886
1887    /**
1888     * @hide
1889     *
1890     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1891     * out of the public fields to keep the undefined bits out of the developer's way.
1892     *
1893     * Flag to hide only the navigation buttons.  Don't use this
1894     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
1895     *
1896     * THIS DOES NOT DISABLE THE BACK BUTTON
1897     */
1898    public static final int STATUS_BAR_DISABLE_NAVIGATION = 0x00200000;
1899
1900    /**
1901     * @hide
1902     *
1903     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1904     * out of the public fields to keep the undefined bits out of the developer's way.
1905     *
1906     * Flag to hide only the back button.  Don't use this
1907     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
1908     */
1909    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
1910
1911    /**
1912     * @hide
1913     *
1914     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1915     * out of the public fields to keep the undefined bits out of the developer's way.
1916     *
1917     * Flag to hide only the clock.  You might use this if your activity has
1918     * its own clock making the status bar's clock redundant.
1919     */
1920    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
1921
1922    /**
1923     * @hide
1924     */
1925    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
1926
1927    /**
1928     * Find views that render the specified text.
1929     *
1930     * @see #findViewsWithText(ArrayList, CharSequence, int)
1931     */
1932    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
1933
1934    /**
1935     * Find find views that contain the specified content description.
1936     *
1937     * @see #findViewsWithText(ArrayList, CharSequence, int)
1938     */
1939    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
1940
1941    /**
1942     * Controls the over-scroll mode for this view.
1943     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
1944     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
1945     * and {@link #OVER_SCROLL_NEVER}.
1946     */
1947    private int mOverScrollMode;
1948
1949    /**
1950     * The parent this view is attached to.
1951     * {@hide}
1952     *
1953     * @see #getParent()
1954     */
1955    protected ViewParent mParent;
1956
1957    /**
1958     * {@hide}
1959     */
1960    AttachInfo mAttachInfo;
1961
1962    /**
1963     * {@hide}
1964     */
1965    @ViewDebug.ExportedProperty(flagMapping = {
1966        @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
1967                name = "FORCE_LAYOUT"),
1968        @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
1969                name = "LAYOUT_REQUIRED"),
1970        @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
1971            name = "DRAWING_CACHE_INVALID", outputIf = false),
1972        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
1973        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
1974        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
1975        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
1976    })
1977    int mPrivateFlags;
1978    int mPrivateFlags2;
1979
1980    /**
1981     * This view's request for the visibility of the status bar.
1982     * @hide
1983     */
1984    @ViewDebug.ExportedProperty(flagMapping = {
1985        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
1986                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
1987                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
1988        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
1989                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
1990                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
1991        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
1992                                equals = SYSTEM_UI_FLAG_VISIBLE,
1993                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
1994    })
1995    int mSystemUiVisibility;
1996
1997    /**
1998     * Count of how many windows this view has been attached to.
1999     */
2000    int mWindowAttachCount;
2001
2002    /**
2003     * The layout parameters associated with this view and used by the parent
2004     * {@link android.view.ViewGroup} to determine how this view should be
2005     * laid out.
2006     * {@hide}
2007     */
2008    protected ViewGroup.LayoutParams mLayoutParams;
2009
2010    /**
2011     * The view flags hold various views states.
2012     * {@hide}
2013     */
2014    @ViewDebug.ExportedProperty
2015    int mViewFlags;
2016
2017    static class TransformationInfo {
2018        /**
2019         * The transform matrix for the View. This transform is calculated internally
2020         * based on the rotation, scaleX, and scaleY properties. The identity matrix
2021         * is used by default. Do *not* use this variable directly; instead call
2022         * getMatrix(), which will automatically recalculate the matrix if necessary
2023         * to get the correct matrix based on the latest rotation and scale properties.
2024         */
2025        private final Matrix mMatrix = new Matrix();
2026
2027        /**
2028         * The transform matrix for the View. This transform is calculated internally
2029         * based on the rotation, scaleX, and scaleY properties. The identity matrix
2030         * is used by default. Do *not* use this variable directly; instead call
2031         * getInverseMatrix(), which will automatically recalculate the matrix if necessary
2032         * to get the correct matrix based on the latest rotation and scale properties.
2033         */
2034        private Matrix mInverseMatrix;
2035
2036        /**
2037         * An internal variable that tracks whether we need to recalculate the
2038         * transform matrix, based on whether the rotation or scaleX/Y properties
2039         * have changed since the matrix was last calculated.
2040         */
2041        boolean mMatrixDirty = false;
2042
2043        /**
2044         * An internal variable that tracks whether we need to recalculate the
2045         * transform matrix, based on whether the rotation or scaleX/Y properties
2046         * have changed since the matrix was last calculated.
2047         */
2048        private boolean mInverseMatrixDirty = true;
2049
2050        /**
2051         * A variable that tracks whether we need to recalculate the
2052         * transform matrix, based on whether the rotation or scaleX/Y properties
2053         * have changed since the matrix was last calculated. This variable
2054         * is only valid after a call to updateMatrix() or to a function that
2055         * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
2056         */
2057        private boolean mMatrixIsIdentity = true;
2058
2059        /**
2060         * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
2061         */
2062        private Camera mCamera = null;
2063
2064        /**
2065         * This matrix is used when computing the matrix for 3D rotations.
2066         */
2067        private Matrix matrix3D = null;
2068
2069        /**
2070         * These prev values are used to recalculate a centered pivot point when necessary. The
2071         * pivot point is only used in matrix operations (when rotation, scale, or translation are
2072         * set), so thes values are only used then as well.
2073         */
2074        private int mPrevWidth = -1;
2075        private int mPrevHeight = -1;
2076
2077        /**
2078         * The degrees rotation around the vertical axis through the pivot point.
2079         */
2080        @ViewDebug.ExportedProperty
2081        float mRotationY = 0f;
2082
2083        /**
2084         * The degrees rotation around the horizontal axis through the pivot point.
2085         */
2086        @ViewDebug.ExportedProperty
2087        float mRotationX = 0f;
2088
2089        /**
2090         * The degrees rotation around the pivot point.
2091         */
2092        @ViewDebug.ExportedProperty
2093        float mRotation = 0f;
2094
2095        /**
2096         * The amount of translation of the object away from its left property (post-layout).
2097         */
2098        @ViewDebug.ExportedProperty
2099        float mTranslationX = 0f;
2100
2101        /**
2102         * The amount of translation of the object away from its top property (post-layout).
2103         */
2104        @ViewDebug.ExportedProperty
2105        float mTranslationY = 0f;
2106
2107        /**
2108         * The amount of scale in the x direction around the pivot point. A
2109         * value of 1 means no scaling is applied.
2110         */
2111        @ViewDebug.ExportedProperty
2112        float mScaleX = 1f;
2113
2114        /**
2115         * The amount of scale in the y direction around the pivot point. A
2116         * value of 1 means no scaling is applied.
2117         */
2118        @ViewDebug.ExportedProperty
2119        float mScaleY = 1f;
2120
2121        /**
2122         * The amount of scale in the x direction around the pivot point. A
2123         * value of 1 means no scaling is applied.
2124         */
2125        @ViewDebug.ExportedProperty
2126        float mPivotX = 0f;
2127
2128        /**
2129         * The amount of scale in the y direction around the pivot point. A
2130         * value of 1 means no scaling is applied.
2131         */
2132        @ViewDebug.ExportedProperty
2133        float mPivotY = 0f;
2134
2135        /**
2136         * The opacity of the View. This is a value from 0 to 1, where 0 means
2137         * completely transparent and 1 means completely opaque.
2138         */
2139        @ViewDebug.ExportedProperty
2140        float mAlpha = 1f;
2141    }
2142
2143    TransformationInfo mTransformationInfo;
2144
2145    private boolean mLastIsOpaque;
2146
2147    /**
2148     * Convenience value to check for float values that are close enough to zero to be considered
2149     * zero.
2150     */
2151    private static final float NONZERO_EPSILON = .001f;
2152
2153    /**
2154     * The distance in pixels from the left edge of this view's parent
2155     * to the left edge of this view.
2156     * {@hide}
2157     */
2158    @ViewDebug.ExportedProperty(category = "layout")
2159    protected int mLeft;
2160    /**
2161     * The distance in pixels from the left edge of this view's parent
2162     * to the right edge of this view.
2163     * {@hide}
2164     */
2165    @ViewDebug.ExportedProperty(category = "layout")
2166    protected int mRight;
2167    /**
2168     * The distance in pixels from the top edge of this view's parent
2169     * to the top edge of this view.
2170     * {@hide}
2171     */
2172    @ViewDebug.ExportedProperty(category = "layout")
2173    protected int mTop;
2174    /**
2175     * The distance in pixels from the top edge of this view's parent
2176     * to the bottom edge of this view.
2177     * {@hide}
2178     */
2179    @ViewDebug.ExportedProperty(category = "layout")
2180    protected int mBottom;
2181
2182    /**
2183     * The offset, in pixels, by which the content of this view is scrolled
2184     * horizontally.
2185     * {@hide}
2186     */
2187    @ViewDebug.ExportedProperty(category = "scrolling")
2188    protected int mScrollX;
2189    /**
2190     * The offset, in pixels, by which the content of this view is scrolled
2191     * vertically.
2192     * {@hide}
2193     */
2194    @ViewDebug.ExportedProperty(category = "scrolling")
2195    protected int mScrollY;
2196
2197    /**
2198     * The left padding in pixels, that is the distance in pixels between the
2199     * left edge of this view and the left edge of its content.
2200     * {@hide}
2201     */
2202    @ViewDebug.ExportedProperty(category = "padding")
2203    protected int mPaddingLeft;
2204    /**
2205     * The right padding in pixels, that is the distance in pixels between the
2206     * right edge of this view and the right edge of its content.
2207     * {@hide}
2208     */
2209    @ViewDebug.ExportedProperty(category = "padding")
2210    protected int mPaddingRight;
2211    /**
2212     * The top padding in pixels, that is the distance in pixels between the
2213     * top edge of this view and the top edge of its content.
2214     * {@hide}
2215     */
2216    @ViewDebug.ExportedProperty(category = "padding")
2217    protected int mPaddingTop;
2218    /**
2219     * The bottom padding in pixels, that is the distance in pixels between the
2220     * bottom edge of this view and the bottom edge of its content.
2221     * {@hide}
2222     */
2223    @ViewDebug.ExportedProperty(category = "padding")
2224    protected int mPaddingBottom;
2225
2226    /**
2227     * Briefly describes the view and is primarily used for accessibility support.
2228     */
2229    private CharSequence mContentDescription;
2230
2231    /**
2232     * Cache the paddingRight set by the user to append to the scrollbar's size.
2233     *
2234     * @hide
2235     */
2236    @ViewDebug.ExportedProperty(category = "padding")
2237    protected int mUserPaddingRight;
2238
2239    /**
2240     * Cache the paddingBottom set by the user to append to the scrollbar's size.
2241     *
2242     * @hide
2243     */
2244    @ViewDebug.ExportedProperty(category = "padding")
2245    protected int mUserPaddingBottom;
2246
2247    /**
2248     * Cache the paddingLeft set by the user to append to the scrollbar's size.
2249     *
2250     * @hide
2251     */
2252    @ViewDebug.ExportedProperty(category = "padding")
2253    protected int mUserPaddingLeft;
2254
2255    /**
2256     * Cache if the user padding is relative.
2257     *
2258     */
2259    @ViewDebug.ExportedProperty(category = "padding")
2260    boolean mUserPaddingRelative;
2261
2262    /**
2263     * Cache the paddingStart set by the user to append to the scrollbar's size.
2264     *
2265     */
2266    @ViewDebug.ExportedProperty(category = "padding")
2267    int mUserPaddingStart;
2268
2269    /**
2270     * Cache the paddingEnd set by the user to append to the scrollbar's size.
2271     *
2272     */
2273    @ViewDebug.ExportedProperty(category = "padding")
2274    int mUserPaddingEnd;
2275
2276    /**
2277     * @hide
2278     */
2279    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
2280    /**
2281     * @hide
2282     */
2283    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
2284
2285    private Drawable mBGDrawable;
2286
2287    private int mBackgroundResource;
2288    private boolean mBackgroundSizeChanged;
2289
2290    /**
2291     * Listener used to dispatch focus change events.
2292     * This field should be made private, so it is hidden from the SDK.
2293     * {@hide}
2294     */
2295    protected OnFocusChangeListener mOnFocusChangeListener;
2296
2297    /**
2298     * Listeners for layout change events.
2299     */
2300    private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
2301
2302    /**
2303     * Listeners for attach events.
2304     */
2305    private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
2306
2307    /**
2308     * Listener used to dispatch click events.
2309     * This field should be made private, so it is hidden from the SDK.
2310     * {@hide}
2311     */
2312    protected OnClickListener mOnClickListener;
2313
2314    /**
2315     * Listener used to dispatch long click events.
2316     * This field should be made private, so it is hidden from the SDK.
2317     * {@hide}
2318     */
2319    protected OnLongClickListener mOnLongClickListener;
2320
2321    /**
2322     * Listener used to build the context menu.
2323     * This field should be made private, so it is hidden from the SDK.
2324     * {@hide}
2325     */
2326    protected OnCreateContextMenuListener mOnCreateContextMenuListener;
2327
2328    private OnKeyListener mOnKeyListener;
2329
2330    private OnTouchListener mOnTouchListener;
2331
2332    private OnHoverListener mOnHoverListener;
2333
2334    private OnGenericMotionListener mOnGenericMotionListener;
2335
2336    private OnDragListener mOnDragListener;
2337
2338    private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
2339
2340    /**
2341     * The application environment this view lives in.
2342     * This field should be made private, so it is hidden from the SDK.
2343     * {@hide}
2344     */
2345    protected Context mContext;
2346
2347    private final Resources mResources;
2348
2349    private ScrollabilityCache mScrollCache;
2350
2351    private int[] mDrawableState = null;
2352
2353    /**
2354     * Set to true when drawing cache is enabled and cannot be created.
2355     *
2356     * @hide
2357     */
2358    public boolean mCachingFailed;
2359
2360    private Bitmap mDrawingCache;
2361    private Bitmap mUnscaledDrawingCache;
2362    private HardwareLayer mHardwareLayer;
2363    DisplayList mDisplayList;
2364
2365    /**
2366     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
2367     * the user may specify which view to go to next.
2368     */
2369    private int mNextFocusLeftId = View.NO_ID;
2370
2371    /**
2372     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
2373     * the user may specify which view to go to next.
2374     */
2375    private int mNextFocusRightId = View.NO_ID;
2376
2377    /**
2378     * When this view has focus and the next focus is {@link #FOCUS_UP},
2379     * the user may specify which view to go to next.
2380     */
2381    private int mNextFocusUpId = View.NO_ID;
2382
2383    /**
2384     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
2385     * the user may specify which view to go to next.
2386     */
2387    private int mNextFocusDownId = View.NO_ID;
2388
2389    /**
2390     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
2391     * the user may specify which view to go to next.
2392     */
2393    int mNextFocusForwardId = View.NO_ID;
2394
2395    private CheckForLongPress mPendingCheckForLongPress;
2396    private CheckForTap mPendingCheckForTap = null;
2397    private PerformClick mPerformClick;
2398    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
2399
2400    private UnsetPressedState mUnsetPressedState;
2401
2402    /**
2403     * Whether the long press's action has been invoked.  The tap's action is invoked on the
2404     * up event while a long press is invoked as soon as the long press duration is reached, so
2405     * a long press could be performed before the tap is checked, in which case the tap's action
2406     * should not be invoked.
2407     */
2408    private boolean mHasPerformedLongPress;
2409
2410    /**
2411     * The minimum height of the view. We'll try our best to have the height
2412     * of this view to at least this amount.
2413     */
2414    @ViewDebug.ExportedProperty(category = "measurement")
2415    private int mMinHeight;
2416
2417    /**
2418     * The minimum width of the view. We'll try our best to have the width
2419     * of this view to at least this amount.
2420     */
2421    @ViewDebug.ExportedProperty(category = "measurement")
2422    private int mMinWidth;
2423
2424    /**
2425     * The delegate to handle touch events that are physically in this view
2426     * but should be handled by another view.
2427     */
2428    private TouchDelegate mTouchDelegate = null;
2429
2430    /**
2431     * Solid color to use as a background when creating the drawing cache. Enables
2432     * the cache to use 16 bit bitmaps instead of 32 bit.
2433     */
2434    private int mDrawingCacheBackgroundColor = 0;
2435
2436    /**
2437     * Special tree observer used when mAttachInfo is null.
2438     */
2439    private ViewTreeObserver mFloatingTreeObserver;
2440
2441    /**
2442     * Cache the touch slop from the context that created the view.
2443     */
2444    private int mTouchSlop;
2445
2446    /**
2447     * Object that handles automatic animation of view properties.
2448     */
2449    private ViewPropertyAnimator mAnimator = null;
2450
2451    /**
2452     * Flag indicating that a drag can cross window boundaries.  When
2453     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
2454     * with this flag set, all visible applications will be able to participate
2455     * in the drag operation and receive the dragged content.
2456     *
2457     * @hide
2458     */
2459    public static final int DRAG_FLAG_GLOBAL = 1;
2460
2461    /**
2462     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
2463     */
2464    private float mVerticalScrollFactor;
2465
2466    /**
2467     * Position of the vertical scroll bar.
2468     */
2469    private int mVerticalScrollbarPosition;
2470
2471    /**
2472     * Position the scroll bar at the default position as determined by the system.
2473     */
2474    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
2475
2476    /**
2477     * Position the scroll bar along the left edge.
2478     */
2479    public static final int SCROLLBAR_POSITION_LEFT = 1;
2480
2481    /**
2482     * Position the scroll bar along the right edge.
2483     */
2484    public static final int SCROLLBAR_POSITION_RIGHT = 2;
2485
2486    /**
2487     * Indicates that the view does not have a layer.
2488     *
2489     * @see #getLayerType()
2490     * @see #setLayerType(int, android.graphics.Paint)
2491     * @see #LAYER_TYPE_SOFTWARE
2492     * @see #LAYER_TYPE_HARDWARE
2493     */
2494    public static final int LAYER_TYPE_NONE = 0;
2495
2496    /**
2497     * <p>Indicates that the view has a software layer. A software layer is backed
2498     * by a bitmap and causes the view to be rendered using Android's software
2499     * rendering pipeline, even if hardware acceleration is enabled.</p>
2500     *
2501     * <p>Software layers have various usages:</p>
2502     * <p>When the application is not using hardware acceleration, a software layer
2503     * is useful to apply a specific color filter and/or blending mode and/or
2504     * translucency to a view and all its children.</p>
2505     * <p>When the application is using hardware acceleration, a software layer
2506     * is useful to render drawing primitives not supported by the hardware
2507     * accelerated pipeline. It can also be used to cache a complex view tree
2508     * into a texture and reduce the complexity of drawing operations. For instance,
2509     * when animating a complex view tree with a translation, a software layer can
2510     * be used to render the view tree only once.</p>
2511     * <p>Software layers should be avoided when the affected view tree updates
2512     * often. Every update will require to re-render the software layer, which can
2513     * potentially be slow (particularly when hardware acceleration is turned on
2514     * since the layer will have to be uploaded into a hardware texture after every
2515     * update.)</p>
2516     *
2517     * @see #getLayerType()
2518     * @see #setLayerType(int, android.graphics.Paint)
2519     * @see #LAYER_TYPE_NONE
2520     * @see #LAYER_TYPE_HARDWARE
2521     */
2522    public static final int LAYER_TYPE_SOFTWARE = 1;
2523
2524    /**
2525     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
2526     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
2527     * OpenGL hardware) and causes the view to be rendered using Android's hardware
2528     * rendering pipeline, but only if hardware acceleration is turned on for the
2529     * view hierarchy. When hardware acceleration is turned off, hardware layers
2530     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
2531     *
2532     * <p>A hardware layer is useful to apply a specific color filter and/or
2533     * blending mode and/or translucency to a view and all its children.</p>
2534     * <p>A hardware layer can be used to cache a complex view tree into a
2535     * texture and reduce the complexity of drawing operations. For instance,
2536     * when animating a complex view tree with a translation, a hardware layer can
2537     * be used to render the view tree only once.</p>
2538     * <p>A hardware layer can also be used to increase the rendering quality when
2539     * rotation transformations are applied on a view. It can also be used to
2540     * prevent potential clipping issues when applying 3D transforms on a view.</p>
2541     *
2542     * @see #getLayerType()
2543     * @see #setLayerType(int, android.graphics.Paint)
2544     * @see #LAYER_TYPE_NONE
2545     * @see #LAYER_TYPE_SOFTWARE
2546     */
2547    public static final int LAYER_TYPE_HARDWARE = 2;
2548
2549    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
2550            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
2551            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
2552            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
2553    })
2554    int mLayerType = LAYER_TYPE_NONE;
2555    Paint mLayerPaint;
2556    Rect mLocalDirtyRect;
2557
2558    /**
2559     * Set to true when the view is sending hover accessibility events because it
2560     * is the innermost hovered view.
2561     */
2562    private boolean mSendingHoverAccessibilityEvents;
2563
2564    /**
2565     * Delegate for injecting accessiblity functionality.
2566     */
2567    AccessibilityDelegate mAccessibilityDelegate;
2568
2569    /**
2570     * Text direction is inherited thru {@link ViewGroup}
2571     * @hide
2572     */
2573    public static final int TEXT_DIRECTION_INHERIT = 0;
2574
2575    /**
2576     * Text direction is using "first strong algorithm". The first strong directional character
2577     * determines the paragraph direction. If there is no strong directional character, the
2578     * paragraph direction is the view's resolved ayout direction.
2579     *
2580     * @hide
2581     */
2582    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2583
2584    /**
2585     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2586     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2587     * If there are neither, the paragraph direction is the view's resolved layout direction.
2588     *
2589     * @hide
2590     */
2591    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2592
2593    /**
2594     * Text direction is forced to LTR.
2595     *
2596     * @hide
2597     */
2598    public static final int TEXT_DIRECTION_LTR = 3;
2599
2600    /**
2601     * Text direction is forced to RTL.
2602     *
2603     * @hide
2604     */
2605    public static final int TEXT_DIRECTION_RTL = 4;
2606
2607    /**
2608     * Default text direction is inherited
2609     *
2610     * @hide
2611     */
2612    protected static int DEFAULT_TEXT_DIRECTION = TEXT_DIRECTION_INHERIT;
2613
2614    /**
2615     * The text direction that has been defined by {@link #setTextDirection(int)}.
2616     *
2617     * {@hide}
2618     */
2619    @ViewDebug.ExportedProperty(category = "text", mapping = {
2620            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
2621            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
2622            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
2623            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
2624            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
2625    })
2626    private int mTextDirection = DEFAULT_TEXT_DIRECTION;
2627
2628    /**
2629     * The resolved text direction.  This needs resolution if the value is
2630     * TEXT_DIRECTION_INHERIT.  The resolution matches mTextDirection if that is
2631     * not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds up the parent
2632     * chain of the view.
2633     *
2634     * {@hide}
2635     */
2636    @ViewDebug.ExportedProperty(category = "text", mapping = {
2637            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
2638            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
2639            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
2640            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
2641            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL")
2642    })
2643    private int mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
2644
2645    /**
2646     * Consistency verifier for debugging purposes.
2647     * @hide
2648     */
2649    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
2650            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
2651                    new InputEventConsistencyVerifier(this, 0) : null;
2652
2653    /**
2654     * Simple constructor to use when creating a view from code.
2655     *
2656     * @param context The Context the view is running in, through which it can
2657     *        access the current theme, resources, etc.
2658     */
2659    public View(Context context) {
2660        mContext = context;
2661        mResources = context != null ? context.getResources() : null;
2662        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | LAYOUT_DIRECTION_INHERIT;
2663        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
2664        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
2665        mUserPaddingStart = -1;
2666        mUserPaddingEnd = -1;
2667        mUserPaddingRelative = false;
2668    }
2669
2670    /**
2671     * Constructor that is called when inflating a view from XML. This is called
2672     * when a view is being constructed from an XML file, supplying attributes
2673     * that were specified in the XML file. This version uses a default style of
2674     * 0, so the only attribute values applied are those in the Context's Theme
2675     * and the given AttributeSet.
2676     *
2677     * <p>
2678     * The method onFinishInflate() will be called after all children have been
2679     * added.
2680     *
2681     * @param context The Context the view is running in, through which it can
2682     *        access the current theme, resources, etc.
2683     * @param attrs The attributes of the XML tag that is inflating the view.
2684     * @see #View(Context, AttributeSet, int)
2685     */
2686    public View(Context context, AttributeSet attrs) {
2687        this(context, attrs, 0);
2688    }
2689
2690    /**
2691     * Perform inflation from XML and apply a class-specific base style. This
2692     * constructor of View allows subclasses to use their own base style when
2693     * they are inflating. For example, a Button class's constructor would call
2694     * this version of the super class constructor and supply
2695     * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
2696     * the theme's button style to modify all of the base view attributes (in
2697     * particular its background) as well as the Button class's attributes.
2698     *
2699     * @param context The Context the view is running in, through which it can
2700     *        access the current theme, resources, etc.
2701     * @param attrs The attributes of the XML tag that is inflating the view.
2702     * @param defStyle The default style to apply to this view. If 0, no style
2703     *        will be applied (beyond what is included in the theme). This may
2704     *        either be an attribute resource, whose value will be retrieved
2705     *        from the current theme, or an explicit style resource.
2706     * @see #View(Context, AttributeSet)
2707     */
2708    public View(Context context, AttributeSet attrs, int defStyle) {
2709        this(context);
2710
2711        TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
2712                defStyle, 0);
2713
2714        Drawable background = null;
2715
2716        int leftPadding = -1;
2717        int topPadding = -1;
2718        int rightPadding = -1;
2719        int bottomPadding = -1;
2720        int startPadding = -1;
2721        int endPadding = -1;
2722
2723        int padding = -1;
2724
2725        int viewFlagValues = 0;
2726        int viewFlagMasks = 0;
2727
2728        boolean setScrollContainer = false;
2729
2730        int x = 0;
2731        int y = 0;
2732
2733        float tx = 0;
2734        float ty = 0;
2735        float rotation = 0;
2736        float rotationX = 0;
2737        float rotationY = 0;
2738        float sx = 1f;
2739        float sy = 1f;
2740        boolean transformSet = false;
2741
2742        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
2743
2744        int overScrollMode = mOverScrollMode;
2745        final int N = a.getIndexCount();
2746        for (int i = 0; i < N; i++) {
2747            int attr = a.getIndex(i);
2748            switch (attr) {
2749                case com.android.internal.R.styleable.View_background:
2750                    background = a.getDrawable(attr);
2751                    break;
2752                case com.android.internal.R.styleable.View_padding:
2753                    padding = a.getDimensionPixelSize(attr, -1);
2754                    break;
2755                 case com.android.internal.R.styleable.View_paddingLeft:
2756                    leftPadding = a.getDimensionPixelSize(attr, -1);
2757                    break;
2758                case com.android.internal.R.styleable.View_paddingTop:
2759                    topPadding = a.getDimensionPixelSize(attr, -1);
2760                    break;
2761                case com.android.internal.R.styleable.View_paddingRight:
2762                    rightPadding = a.getDimensionPixelSize(attr, -1);
2763                    break;
2764                case com.android.internal.R.styleable.View_paddingBottom:
2765                    bottomPadding = a.getDimensionPixelSize(attr, -1);
2766                    break;
2767                case com.android.internal.R.styleable.View_paddingStart:
2768                    startPadding = a.getDimensionPixelSize(attr, -1);
2769                    break;
2770                case com.android.internal.R.styleable.View_paddingEnd:
2771                    endPadding = a.getDimensionPixelSize(attr, -1);
2772                    break;
2773                case com.android.internal.R.styleable.View_scrollX:
2774                    x = a.getDimensionPixelOffset(attr, 0);
2775                    break;
2776                case com.android.internal.R.styleable.View_scrollY:
2777                    y = a.getDimensionPixelOffset(attr, 0);
2778                    break;
2779                case com.android.internal.R.styleable.View_alpha:
2780                    setAlpha(a.getFloat(attr, 1f));
2781                    break;
2782                case com.android.internal.R.styleable.View_transformPivotX:
2783                    setPivotX(a.getDimensionPixelOffset(attr, 0));
2784                    break;
2785                case com.android.internal.R.styleable.View_transformPivotY:
2786                    setPivotY(a.getDimensionPixelOffset(attr, 0));
2787                    break;
2788                case com.android.internal.R.styleable.View_translationX:
2789                    tx = a.getDimensionPixelOffset(attr, 0);
2790                    transformSet = true;
2791                    break;
2792                case com.android.internal.R.styleable.View_translationY:
2793                    ty = a.getDimensionPixelOffset(attr, 0);
2794                    transformSet = true;
2795                    break;
2796                case com.android.internal.R.styleable.View_rotation:
2797                    rotation = a.getFloat(attr, 0);
2798                    transformSet = true;
2799                    break;
2800                case com.android.internal.R.styleable.View_rotationX:
2801                    rotationX = a.getFloat(attr, 0);
2802                    transformSet = true;
2803                    break;
2804                case com.android.internal.R.styleable.View_rotationY:
2805                    rotationY = a.getFloat(attr, 0);
2806                    transformSet = true;
2807                    break;
2808                case com.android.internal.R.styleable.View_scaleX:
2809                    sx = a.getFloat(attr, 1f);
2810                    transformSet = true;
2811                    break;
2812                case com.android.internal.R.styleable.View_scaleY:
2813                    sy = a.getFloat(attr, 1f);
2814                    transformSet = true;
2815                    break;
2816                case com.android.internal.R.styleable.View_id:
2817                    mID = a.getResourceId(attr, NO_ID);
2818                    break;
2819                case com.android.internal.R.styleable.View_tag:
2820                    mTag = a.getText(attr);
2821                    break;
2822                case com.android.internal.R.styleable.View_fitsSystemWindows:
2823                    if (a.getBoolean(attr, false)) {
2824                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
2825                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
2826                    }
2827                    break;
2828                case com.android.internal.R.styleable.View_focusable:
2829                    if (a.getBoolean(attr, false)) {
2830                        viewFlagValues |= FOCUSABLE;
2831                        viewFlagMasks |= FOCUSABLE_MASK;
2832                    }
2833                    break;
2834                case com.android.internal.R.styleable.View_focusableInTouchMode:
2835                    if (a.getBoolean(attr, false)) {
2836                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
2837                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
2838                    }
2839                    break;
2840                case com.android.internal.R.styleable.View_clickable:
2841                    if (a.getBoolean(attr, false)) {
2842                        viewFlagValues |= CLICKABLE;
2843                        viewFlagMasks |= CLICKABLE;
2844                    }
2845                    break;
2846                case com.android.internal.R.styleable.View_longClickable:
2847                    if (a.getBoolean(attr, false)) {
2848                        viewFlagValues |= LONG_CLICKABLE;
2849                        viewFlagMasks |= LONG_CLICKABLE;
2850                    }
2851                    break;
2852                case com.android.internal.R.styleable.View_saveEnabled:
2853                    if (!a.getBoolean(attr, true)) {
2854                        viewFlagValues |= SAVE_DISABLED;
2855                        viewFlagMasks |= SAVE_DISABLED_MASK;
2856                    }
2857                    break;
2858                case com.android.internal.R.styleable.View_duplicateParentState:
2859                    if (a.getBoolean(attr, false)) {
2860                        viewFlagValues |= DUPLICATE_PARENT_STATE;
2861                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
2862                    }
2863                    break;
2864                case com.android.internal.R.styleable.View_visibility:
2865                    final int visibility = a.getInt(attr, 0);
2866                    if (visibility != 0) {
2867                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
2868                        viewFlagMasks |= VISIBILITY_MASK;
2869                    }
2870                    break;
2871                case com.android.internal.R.styleable.View_layoutDirection:
2872                    // Clear any HORIZONTAL_DIRECTION flag already set
2873                    viewFlagValues &= ~LAYOUT_DIRECTION_MASK;
2874                    // Set the HORIZONTAL_DIRECTION flags depending on the value of the attribute
2875                    final int layoutDirection = a.getInt(attr, -1);
2876                    if (layoutDirection != -1) {
2877                        viewFlagValues |= LAYOUT_DIRECTION_FLAGS[layoutDirection];
2878                    } else {
2879                        // Set to default (LAYOUT_DIRECTION_INHERIT)
2880                        viewFlagValues |= LAYOUT_DIRECTION_DEFAULT;
2881                    }
2882                    viewFlagMasks |= LAYOUT_DIRECTION_MASK;
2883                    break;
2884                case com.android.internal.R.styleable.View_drawingCacheQuality:
2885                    final int cacheQuality = a.getInt(attr, 0);
2886                    if (cacheQuality != 0) {
2887                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
2888                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
2889                    }
2890                    break;
2891                case com.android.internal.R.styleable.View_contentDescription:
2892                    mContentDescription = a.getString(attr);
2893                    break;
2894                case com.android.internal.R.styleable.View_soundEffectsEnabled:
2895                    if (!a.getBoolean(attr, true)) {
2896                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
2897                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
2898                    }
2899                    break;
2900                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
2901                    if (!a.getBoolean(attr, true)) {
2902                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
2903                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
2904                    }
2905                    break;
2906                case R.styleable.View_scrollbars:
2907                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
2908                    if (scrollbars != SCROLLBARS_NONE) {
2909                        viewFlagValues |= scrollbars;
2910                        viewFlagMasks |= SCROLLBARS_MASK;
2911                        initializeScrollbars(a);
2912                    }
2913                    break;
2914                //noinspection deprecation
2915                case R.styleable.View_fadingEdge:
2916                    if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) {
2917                        // Ignore the attribute starting with ICS
2918                        break;
2919                    }
2920                    // With builds < ICS, fall through and apply fading edges
2921                case R.styleable.View_requiresFadingEdge:
2922                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
2923                    if (fadingEdge != FADING_EDGE_NONE) {
2924                        viewFlagValues |= fadingEdge;
2925                        viewFlagMasks |= FADING_EDGE_MASK;
2926                        initializeFadingEdge(a);
2927                    }
2928                    break;
2929                case R.styleable.View_scrollbarStyle:
2930                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
2931                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
2932                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
2933                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
2934                    }
2935                    break;
2936                case R.styleable.View_isScrollContainer:
2937                    setScrollContainer = true;
2938                    if (a.getBoolean(attr, false)) {
2939                        setScrollContainer(true);
2940                    }
2941                    break;
2942                case com.android.internal.R.styleable.View_keepScreenOn:
2943                    if (a.getBoolean(attr, false)) {
2944                        viewFlagValues |= KEEP_SCREEN_ON;
2945                        viewFlagMasks |= KEEP_SCREEN_ON;
2946                    }
2947                    break;
2948                case R.styleable.View_filterTouchesWhenObscured:
2949                    if (a.getBoolean(attr, false)) {
2950                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
2951                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
2952                    }
2953                    break;
2954                case R.styleable.View_nextFocusLeft:
2955                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
2956                    break;
2957                case R.styleable.View_nextFocusRight:
2958                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
2959                    break;
2960                case R.styleable.View_nextFocusUp:
2961                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
2962                    break;
2963                case R.styleable.View_nextFocusDown:
2964                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
2965                    break;
2966                case R.styleable.View_nextFocusForward:
2967                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
2968                    break;
2969                case R.styleable.View_minWidth:
2970                    mMinWidth = a.getDimensionPixelSize(attr, 0);
2971                    break;
2972                case R.styleable.View_minHeight:
2973                    mMinHeight = a.getDimensionPixelSize(attr, 0);
2974                    break;
2975                case R.styleable.View_onClick:
2976                    if (context.isRestricted()) {
2977                        throw new IllegalStateException("The android:onClick attribute cannot "
2978                                + "be used within a restricted context");
2979                    }
2980
2981                    final String handlerName = a.getString(attr);
2982                    if (handlerName != null) {
2983                        setOnClickListener(new OnClickListener() {
2984                            private Method mHandler;
2985
2986                            public void onClick(View v) {
2987                                if (mHandler == null) {
2988                                    try {
2989                                        mHandler = getContext().getClass().getMethod(handlerName,
2990                                                View.class);
2991                                    } catch (NoSuchMethodException e) {
2992                                        int id = getId();
2993                                        String idText = id == NO_ID ? "" : " with id '"
2994                                                + getContext().getResources().getResourceEntryName(
2995                                                    id) + "'";
2996                                        throw new IllegalStateException("Could not find a method " +
2997                                                handlerName + "(View) in the activity "
2998                                                + getContext().getClass() + " for onClick handler"
2999                                                + " on view " + View.this.getClass() + idText, e);
3000                                    }
3001                                }
3002
3003                                try {
3004                                    mHandler.invoke(getContext(), View.this);
3005                                } catch (IllegalAccessException e) {
3006                                    throw new IllegalStateException("Could not execute non "
3007                                            + "public method of the activity", e);
3008                                } catch (InvocationTargetException e) {
3009                                    throw new IllegalStateException("Could not execute "
3010                                            + "method of the activity", e);
3011                                }
3012                            }
3013                        });
3014                    }
3015                    break;
3016                case R.styleable.View_overScrollMode:
3017                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3018                    break;
3019                case R.styleable.View_verticalScrollbarPosition:
3020                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3021                    break;
3022                case R.styleable.View_layerType:
3023                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3024                    break;
3025                case R.styleable.View_textDirection:
3026                    mTextDirection = a.getInt(attr, DEFAULT_TEXT_DIRECTION);
3027                    break;
3028            }
3029        }
3030
3031        a.recycle();
3032
3033        setOverScrollMode(overScrollMode);
3034
3035        if (background != null) {
3036            setBackgroundDrawable(background);
3037        }
3038
3039        mUserPaddingRelative = (startPadding >= 0 || endPadding >= 0);
3040
3041        // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved
3042        // layout direction). Those cached values will be used later during padding resolution.
3043        mUserPaddingStart = startPadding;
3044        mUserPaddingEnd = endPadding;
3045
3046        if (padding >= 0) {
3047            leftPadding = padding;
3048            topPadding = padding;
3049            rightPadding = padding;
3050            bottomPadding = padding;
3051        }
3052
3053        // If the user specified the padding (either with android:padding or
3054        // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
3055        // use the default padding or the padding from the background drawable
3056        // (stored at this point in mPadding*)
3057        setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
3058                topPadding >= 0 ? topPadding : mPaddingTop,
3059                rightPadding >= 0 ? rightPadding : mPaddingRight,
3060                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
3061
3062        if (viewFlagMasks != 0) {
3063            setFlags(viewFlagValues, viewFlagMasks);
3064        }
3065
3066        // Needs to be called after mViewFlags is set
3067        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3068            recomputePadding();
3069        }
3070
3071        if (x != 0 || y != 0) {
3072            scrollTo(x, y);
3073        }
3074
3075        if (transformSet) {
3076            setTranslationX(tx);
3077            setTranslationY(ty);
3078            setRotation(rotation);
3079            setRotationX(rotationX);
3080            setRotationY(rotationY);
3081            setScaleX(sx);
3082            setScaleY(sy);
3083        }
3084
3085        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
3086            setScrollContainer(true);
3087        }
3088
3089        computeOpaqueFlags();
3090    }
3091
3092    /**
3093     * Non-public constructor for use in testing
3094     */
3095    View() {
3096        mResources = null;
3097    }
3098
3099    /**
3100     * <p>
3101     * Initializes the fading edges from a given set of styled attributes. This
3102     * method should be called by subclasses that need fading edges and when an
3103     * instance of these subclasses is created programmatically rather than
3104     * being inflated from XML. This method is automatically called when the XML
3105     * is inflated.
3106     * </p>
3107     *
3108     * @param a the styled attributes set to initialize the fading edges from
3109     */
3110    protected void initializeFadingEdge(TypedArray a) {
3111        initScrollCache();
3112
3113        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
3114                R.styleable.View_fadingEdgeLength,
3115                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
3116    }
3117
3118    /**
3119     * Returns the size of the vertical faded edges used to indicate that more
3120     * content in this view is visible.
3121     *
3122     * @return The size in pixels of the vertical faded edge or 0 if vertical
3123     *         faded edges are not enabled for this view.
3124     * @attr ref android.R.styleable#View_fadingEdgeLength
3125     */
3126    public int getVerticalFadingEdgeLength() {
3127        if (isVerticalFadingEdgeEnabled()) {
3128            ScrollabilityCache cache = mScrollCache;
3129            if (cache != null) {
3130                return cache.fadingEdgeLength;
3131            }
3132        }
3133        return 0;
3134    }
3135
3136    /**
3137     * Set the size of the faded edge used to indicate that more content in this
3138     * view is available.  Will not change whether the fading edge is enabled; use
3139     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
3140     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
3141     * for the vertical or horizontal fading edges.
3142     *
3143     * @param length The size in pixels of the faded edge used to indicate that more
3144     *        content in this view is visible.
3145     */
3146    public void setFadingEdgeLength(int length) {
3147        initScrollCache();
3148        mScrollCache.fadingEdgeLength = length;
3149    }
3150
3151    /**
3152     * Returns the size of the horizontal faded edges used to indicate that more
3153     * content in this view is visible.
3154     *
3155     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
3156     *         faded edges are not enabled for this view.
3157     * @attr ref android.R.styleable#View_fadingEdgeLength
3158     */
3159    public int getHorizontalFadingEdgeLength() {
3160        if (isHorizontalFadingEdgeEnabled()) {
3161            ScrollabilityCache cache = mScrollCache;
3162            if (cache != null) {
3163                return cache.fadingEdgeLength;
3164            }
3165        }
3166        return 0;
3167    }
3168
3169    /**
3170     * Returns the width of the vertical scrollbar.
3171     *
3172     * @return The width in pixels of the vertical scrollbar or 0 if there
3173     *         is no vertical scrollbar.
3174     */
3175    public int getVerticalScrollbarWidth() {
3176        ScrollabilityCache cache = mScrollCache;
3177        if (cache != null) {
3178            ScrollBarDrawable scrollBar = cache.scrollBar;
3179            if (scrollBar != null) {
3180                int size = scrollBar.getSize(true);
3181                if (size <= 0) {
3182                    size = cache.scrollBarSize;
3183                }
3184                return size;
3185            }
3186            return 0;
3187        }
3188        return 0;
3189    }
3190
3191    /**
3192     * Returns the height of the horizontal scrollbar.
3193     *
3194     * @return The height in pixels of the horizontal scrollbar or 0 if
3195     *         there is no horizontal scrollbar.
3196     */
3197    protected int getHorizontalScrollbarHeight() {
3198        ScrollabilityCache cache = mScrollCache;
3199        if (cache != null) {
3200            ScrollBarDrawable scrollBar = cache.scrollBar;
3201            if (scrollBar != null) {
3202                int size = scrollBar.getSize(false);
3203                if (size <= 0) {
3204                    size = cache.scrollBarSize;
3205                }
3206                return size;
3207            }
3208            return 0;
3209        }
3210        return 0;
3211    }
3212
3213    /**
3214     * <p>
3215     * Initializes the scrollbars from a given set of styled attributes. This
3216     * method should be called by subclasses that need scrollbars and when an
3217     * instance of these subclasses is created programmatically rather than
3218     * being inflated from XML. This method is automatically called when the XML
3219     * is inflated.
3220     * </p>
3221     *
3222     * @param a the styled attributes set to initialize the scrollbars from
3223     */
3224    protected void initializeScrollbars(TypedArray a) {
3225        initScrollCache();
3226
3227        final ScrollabilityCache scrollabilityCache = mScrollCache;
3228
3229        if (scrollabilityCache.scrollBar == null) {
3230            scrollabilityCache.scrollBar = new ScrollBarDrawable();
3231        }
3232
3233        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
3234
3235        if (!fadeScrollbars) {
3236            scrollabilityCache.state = ScrollabilityCache.ON;
3237        }
3238        scrollabilityCache.fadeScrollBars = fadeScrollbars;
3239
3240
3241        scrollabilityCache.scrollBarFadeDuration = a.getInt(
3242                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
3243                        .getScrollBarFadeDuration());
3244        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
3245                R.styleable.View_scrollbarDefaultDelayBeforeFade,
3246                ViewConfiguration.getScrollDefaultDelay());
3247
3248
3249        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
3250                com.android.internal.R.styleable.View_scrollbarSize,
3251                ViewConfiguration.get(mContext).getScaledScrollBarSize());
3252
3253        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
3254        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
3255
3256        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
3257        if (thumb != null) {
3258            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
3259        }
3260
3261        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
3262                false);
3263        if (alwaysDraw) {
3264            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
3265        }
3266
3267        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
3268        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
3269
3270        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
3271        if (thumb != null) {
3272            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
3273        }
3274
3275        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
3276                false);
3277        if (alwaysDraw) {
3278            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
3279        }
3280
3281        // Re-apply user/background padding so that scrollbar(s) get added
3282        resolvePadding();
3283    }
3284
3285    /**
3286     * <p>
3287     * Initalizes the scrollability cache if necessary.
3288     * </p>
3289     */
3290    private void initScrollCache() {
3291        if (mScrollCache == null) {
3292            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
3293        }
3294    }
3295
3296    /**
3297     * Set the position of the vertical scroll bar. Should be one of
3298     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
3299     * {@link #SCROLLBAR_POSITION_RIGHT}.
3300     *
3301     * @param position Where the vertical scroll bar should be positioned.
3302     */
3303    public void setVerticalScrollbarPosition(int position) {
3304        if (mVerticalScrollbarPosition != position) {
3305            mVerticalScrollbarPosition = position;
3306            computeOpaqueFlags();
3307            resolvePadding();
3308        }
3309    }
3310
3311    /**
3312     * @return The position where the vertical scroll bar will show, if applicable.
3313     * @see #setVerticalScrollbarPosition(int)
3314     */
3315    public int getVerticalScrollbarPosition() {
3316        return mVerticalScrollbarPosition;
3317    }
3318
3319    /**
3320     * Register a callback to be invoked when focus of this view changed.
3321     *
3322     * @param l The callback that will run.
3323     */
3324    public void setOnFocusChangeListener(OnFocusChangeListener l) {
3325        mOnFocusChangeListener = l;
3326    }
3327
3328    /**
3329     * Add a listener that will be called when the bounds of the view change due to
3330     * layout processing.
3331     *
3332     * @param listener The listener that will be called when layout bounds change.
3333     */
3334    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
3335        if (mOnLayoutChangeListeners == null) {
3336            mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
3337        }
3338        if (!mOnLayoutChangeListeners.contains(listener)) {
3339            mOnLayoutChangeListeners.add(listener);
3340        }
3341    }
3342
3343    /**
3344     * Remove a listener for layout changes.
3345     *
3346     * @param listener The listener for layout bounds change.
3347     */
3348    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
3349        if (mOnLayoutChangeListeners == null) {
3350            return;
3351        }
3352        mOnLayoutChangeListeners.remove(listener);
3353    }
3354
3355    /**
3356     * Add a listener for attach state changes.
3357     *
3358     * This listener will be called whenever this view is attached or detached
3359     * from a window. Remove the listener using
3360     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
3361     *
3362     * @param listener Listener to attach
3363     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
3364     */
3365    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
3366        if (mOnAttachStateChangeListeners == null) {
3367            mOnAttachStateChangeListeners = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
3368        }
3369        mOnAttachStateChangeListeners.add(listener);
3370    }
3371
3372    /**
3373     * Remove a listener for attach state changes. The listener will receive no further
3374     * notification of window attach/detach events.
3375     *
3376     * @param listener Listener to remove
3377     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
3378     */
3379    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
3380        if (mOnAttachStateChangeListeners == null) {
3381            return;
3382        }
3383        mOnAttachStateChangeListeners.remove(listener);
3384    }
3385
3386    /**
3387     * Returns the focus-change callback registered for this view.
3388     *
3389     * @return The callback, or null if one is not registered.
3390     */
3391    public OnFocusChangeListener getOnFocusChangeListener() {
3392        return mOnFocusChangeListener;
3393    }
3394
3395    /**
3396     * Register a callback to be invoked when this view is clicked. If this view is not
3397     * clickable, it becomes clickable.
3398     *
3399     * @param l The callback that will run
3400     *
3401     * @see #setClickable(boolean)
3402     */
3403    public void setOnClickListener(OnClickListener l) {
3404        if (!isClickable()) {
3405            setClickable(true);
3406        }
3407        mOnClickListener = l;
3408    }
3409
3410    /**
3411     * Register a callback to be invoked when this view is clicked and held. If this view is not
3412     * long clickable, it becomes long clickable.
3413     *
3414     * @param l The callback that will run
3415     *
3416     * @see #setLongClickable(boolean)
3417     */
3418    public void setOnLongClickListener(OnLongClickListener l) {
3419        if (!isLongClickable()) {
3420            setLongClickable(true);
3421        }
3422        mOnLongClickListener = l;
3423    }
3424
3425    /**
3426     * Register a callback to be invoked when the context menu for this view is
3427     * being built. If this view is not long clickable, it becomes long clickable.
3428     *
3429     * @param l The callback that will run
3430     *
3431     */
3432    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
3433        if (!isLongClickable()) {
3434            setLongClickable(true);
3435        }
3436        mOnCreateContextMenuListener = l;
3437    }
3438
3439    /**
3440     * Call this view's OnClickListener, if it is defined.
3441     *
3442     * @return True there was an assigned OnClickListener that was called, false
3443     *         otherwise is returned.
3444     */
3445    public boolean performClick() {
3446        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
3447
3448        if (mOnClickListener != null) {
3449            playSoundEffect(SoundEffectConstants.CLICK);
3450            mOnClickListener.onClick(this);
3451            return true;
3452        }
3453
3454        return false;
3455    }
3456
3457    /**
3458     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
3459     * OnLongClickListener did not consume the event.
3460     *
3461     * @return True if one of the above receivers consumed the event, false otherwise.
3462     */
3463    public boolean performLongClick() {
3464        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
3465
3466        boolean handled = false;
3467        if (mOnLongClickListener != null) {
3468            handled = mOnLongClickListener.onLongClick(View.this);
3469        }
3470        if (!handled) {
3471            handled = showContextMenu();
3472        }
3473        if (handled) {
3474            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
3475        }
3476        return handled;
3477    }
3478
3479    /**
3480     * Performs button-related actions during a touch down event.
3481     *
3482     * @param event The event.
3483     * @return True if the down was consumed.
3484     *
3485     * @hide
3486     */
3487    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
3488        if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
3489            if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
3490                return true;
3491            }
3492        }
3493        return false;
3494    }
3495
3496    /**
3497     * Bring up the context menu for this view.
3498     *
3499     * @return Whether a context menu was displayed.
3500     */
3501    public boolean showContextMenu() {
3502        return getParent().showContextMenuForChild(this);
3503    }
3504
3505    /**
3506     * Bring up the context menu for this view, referring to the item under the specified point.
3507     *
3508     * @param x The referenced x coordinate.
3509     * @param y The referenced y coordinate.
3510     * @param metaState The keyboard modifiers that were pressed.
3511     * @return Whether a context menu was displayed.
3512     *
3513     * @hide
3514     */
3515    public boolean showContextMenu(float x, float y, int metaState) {
3516        return showContextMenu();
3517    }
3518
3519    /**
3520     * Start an action mode.
3521     *
3522     * @param callback Callback that will control the lifecycle of the action mode
3523     * @return The new action mode if it is started, null otherwise
3524     *
3525     * @see ActionMode
3526     */
3527    public ActionMode startActionMode(ActionMode.Callback callback) {
3528        return getParent().startActionModeForChild(this, callback);
3529    }
3530
3531    /**
3532     * Register a callback to be invoked when a key is pressed in this view.
3533     * @param l the key listener to attach to this view
3534     */
3535    public void setOnKeyListener(OnKeyListener l) {
3536        mOnKeyListener = l;
3537    }
3538
3539    /**
3540     * Register a callback to be invoked when a touch event is sent to this view.
3541     * @param l the touch listener to attach to this view
3542     */
3543    public void setOnTouchListener(OnTouchListener l) {
3544        mOnTouchListener = l;
3545    }
3546
3547    /**
3548     * Register a callback to be invoked when a generic motion event is sent to this view.
3549     * @param l the generic motion listener to attach to this view
3550     */
3551    public void setOnGenericMotionListener(OnGenericMotionListener l) {
3552        mOnGenericMotionListener = l;
3553    }
3554
3555    /**
3556     * Register a callback to be invoked when a hover event is sent to this view.
3557     * @param l the hover listener to attach to this view
3558     */
3559    public void setOnHoverListener(OnHoverListener l) {
3560        mOnHoverListener = l;
3561    }
3562
3563    /**
3564     * Register a drag event listener callback object for this View. The parameter is
3565     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
3566     * View, the system calls the
3567     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
3568     * @param l An implementation of {@link android.view.View.OnDragListener}.
3569     */
3570    public void setOnDragListener(OnDragListener l) {
3571        mOnDragListener = l;
3572    }
3573
3574    /**
3575     * Give this view focus. This will cause
3576     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
3577     *
3578     * Note: this does not check whether this {@link View} should get focus, it just
3579     * gives it focus no matter what.  It should only be called internally by framework
3580     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
3581     *
3582     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
3583     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
3584     *        focus moved when requestFocus() is called. It may not always
3585     *        apply, in which case use the default View.FOCUS_DOWN.
3586     * @param previouslyFocusedRect The rectangle of the view that had focus
3587     *        prior in this View's coordinate system.
3588     */
3589    void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
3590        if (DBG) {
3591            System.out.println(this + " requestFocus()");
3592        }
3593
3594        if ((mPrivateFlags & FOCUSED) == 0) {
3595            mPrivateFlags |= FOCUSED;
3596
3597            if (mParent != null) {
3598                mParent.requestChildFocus(this, this);
3599            }
3600
3601            onFocusChanged(true, direction, previouslyFocusedRect);
3602            refreshDrawableState();
3603        }
3604    }
3605
3606    /**
3607     * Request that a rectangle of this view be visible on the screen,
3608     * scrolling if necessary just enough.
3609     *
3610     * <p>A View should call this if it maintains some notion of which part
3611     * of its content is interesting.  For example, a text editing view
3612     * should call this when its cursor moves.
3613     *
3614     * @param rectangle The rectangle.
3615     * @return Whether any parent scrolled.
3616     */
3617    public boolean requestRectangleOnScreen(Rect rectangle) {
3618        return requestRectangleOnScreen(rectangle, false);
3619    }
3620
3621    /**
3622     * Request that a rectangle of this view be visible on the screen,
3623     * scrolling if necessary just enough.
3624     *
3625     * <p>A View should call this if it maintains some notion of which part
3626     * of its content is interesting.  For example, a text editing view
3627     * should call this when its cursor moves.
3628     *
3629     * <p>When <code>immediate</code> is set to true, scrolling will not be
3630     * animated.
3631     *
3632     * @param rectangle The rectangle.
3633     * @param immediate True to forbid animated scrolling, false otherwise
3634     * @return Whether any parent scrolled.
3635     */
3636    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
3637        View child = this;
3638        ViewParent parent = mParent;
3639        boolean scrolled = false;
3640        while (parent != null) {
3641            scrolled |= parent.requestChildRectangleOnScreen(child,
3642                    rectangle, immediate);
3643
3644            // offset rect so next call has the rectangle in the
3645            // coordinate system of its direct child.
3646            rectangle.offset(child.getLeft(), child.getTop());
3647            rectangle.offset(-child.getScrollX(), -child.getScrollY());
3648
3649            if (!(parent instanceof View)) {
3650                break;
3651            }
3652
3653            child = (View) parent;
3654            parent = child.getParent();
3655        }
3656        return scrolled;
3657    }
3658
3659    /**
3660     * Called when this view wants to give up focus. This will cause
3661     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
3662     */
3663    public void clearFocus() {
3664        if (DBG) {
3665            System.out.println(this + " clearFocus()");
3666        }
3667
3668        if ((mPrivateFlags & FOCUSED) != 0) {
3669            mPrivateFlags &= ~FOCUSED;
3670
3671            if (mParent != null) {
3672                mParent.clearChildFocus(this);
3673            }
3674
3675            onFocusChanged(false, 0, null);
3676            refreshDrawableState();
3677        }
3678    }
3679
3680    /**
3681     * Called to clear the focus of a view that is about to be removed.
3682     * Doesn't call clearChildFocus, which prevents this view from taking
3683     * focus again before it has been removed from the parent
3684     */
3685    void clearFocusForRemoval() {
3686        if ((mPrivateFlags & FOCUSED) != 0) {
3687            mPrivateFlags &= ~FOCUSED;
3688
3689            onFocusChanged(false, 0, null);
3690            refreshDrawableState();
3691        }
3692    }
3693
3694    /**
3695     * Called internally by the view system when a new view is getting focus.
3696     * This is what clears the old focus.
3697     */
3698    void unFocus() {
3699        if (DBG) {
3700            System.out.println(this + " unFocus()");
3701        }
3702
3703        if ((mPrivateFlags & FOCUSED) != 0) {
3704            mPrivateFlags &= ~FOCUSED;
3705
3706            onFocusChanged(false, 0, null);
3707            refreshDrawableState();
3708        }
3709    }
3710
3711    /**
3712     * Returns true if this view has focus iteself, or is the ancestor of the
3713     * view that has focus.
3714     *
3715     * @return True if this view has or contains focus, false otherwise.
3716     */
3717    @ViewDebug.ExportedProperty(category = "focus")
3718    public boolean hasFocus() {
3719        return (mPrivateFlags & FOCUSED) != 0;
3720    }
3721
3722    /**
3723     * Returns true if this view is focusable or if it contains a reachable View
3724     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
3725     * is a View whose parents do not block descendants focus.
3726     *
3727     * Only {@link #VISIBLE} views are considered focusable.
3728     *
3729     * @return True if the view is focusable or if the view contains a focusable
3730     *         View, false otherwise.
3731     *
3732     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
3733     */
3734    public boolean hasFocusable() {
3735        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
3736    }
3737
3738    /**
3739     * Called by the view system when the focus state of this view changes.
3740     * When the focus change event is caused by directional navigation, direction
3741     * and previouslyFocusedRect provide insight into where the focus is coming from.
3742     * When overriding, be sure to call up through to the super class so that
3743     * the standard focus handling will occur.
3744     *
3745     * @param gainFocus True if the View has focus; false otherwise.
3746     * @param direction The direction focus has moved when requestFocus()
3747     *                  is called to give this view focus. Values are
3748     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
3749     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
3750     *                  It may not always apply, in which case use the default.
3751     * @param previouslyFocusedRect The rectangle, in this view's coordinate
3752     *        system, of the previously focused view.  If applicable, this will be
3753     *        passed in as finer grained information about where the focus is coming
3754     *        from (in addition to direction).  Will be <code>null</code> otherwise.
3755     */
3756    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
3757        if (gainFocus) {
3758            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
3759        }
3760
3761        InputMethodManager imm = InputMethodManager.peekInstance();
3762        if (!gainFocus) {
3763            if (isPressed()) {
3764                setPressed(false);
3765            }
3766            if (imm != null && mAttachInfo != null
3767                    && mAttachInfo.mHasWindowFocus) {
3768                imm.focusOut(this);
3769            }
3770            onFocusLost();
3771        } else if (imm != null && mAttachInfo != null
3772                && mAttachInfo.mHasWindowFocus) {
3773            imm.focusIn(this);
3774        }
3775
3776        invalidate(true);
3777        if (mOnFocusChangeListener != null) {
3778            mOnFocusChangeListener.onFocusChange(this, gainFocus);
3779        }
3780
3781        if (mAttachInfo != null) {
3782            mAttachInfo.mKeyDispatchState.reset(this);
3783        }
3784    }
3785
3786    /**
3787     * Sends an accessibility event of the given type. If accessiiblity is
3788     * not enabled this method has no effect. The default implementation calls
3789     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
3790     * to populate information about the event source (this View), then calls
3791     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
3792     * populate the text content of the event source including its descendants,
3793     * and last calls
3794     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
3795     * on its parent to resuest sending of the event to interested parties.
3796     * <p>
3797     * If an {@link AccessibilityDelegate} has been specified via calling
3798     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3799     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
3800     * responsible for handling this call.
3801     * </p>
3802     *
3803     * @param eventType The type of the event to send.
3804     *
3805     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
3806     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
3807     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
3808     * @see AccessibilityDelegate
3809     */
3810    public void sendAccessibilityEvent(int eventType) {
3811        if (mAccessibilityDelegate != null) {
3812            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
3813        } else {
3814            sendAccessibilityEventInternal(eventType);
3815        }
3816    }
3817
3818    /**
3819     * @see #sendAccessibilityEvent(int)
3820     *
3821     * Note: Called from the default {@link AccessibilityDelegate}.
3822     */
3823    void sendAccessibilityEventInternal(int eventType) {
3824        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
3825            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
3826        }
3827    }
3828
3829    /**
3830     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
3831     * takes as an argument an empty {@link AccessibilityEvent} and does not
3832     * perform a check whether accessibility is enabled.
3833     * <p>
3834     * If an {@link AccessibilityDelegate} has been specified via calling
3835     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3836     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
3837     * is responsible for handling this call.
3838     * </p>
3839     *
3840     * @param event The event to send.
3841     *
3842     * @see #sendAccessibilityEvent(int)
3843     */
3844    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
3845        if (mAccessibilityDelegate != null) {
3846           mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
3847        } else {
3848            sendAccessibilityEventUncheckedInternal(event);
3849        }
3850    }
3851
3852    /**
3853     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
3854     *
3855     * Note: Called from the default {@link AccessibilityDelegate}.
3856     */
3857    void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
3858        if (!isShown()) {
3859            return;
3860        }
3861        onInitializeAccessibilityEvent(event);
3862        // Only a subset of accessibility events populates text content.
3863        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
3864            dispatchPopulateAccessibilityEvent(event);
3865        }
3866        // In the beginning we called #isShown(), so we know that getParent() is not null.
3867        getParent().requestSendAccessibilityEvent(this, event);
3868    }
3869
3870    /**
3871     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
3872     * to its children for adding their text content to the event. Note that the
3873     * event text is populated in a separate dispatch path since we add to the
3874     * event not only the text of the source but also the text of all its descendants.
3875     * A typical implementation will call
3876     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
3877     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
3878     * on each child. Override this method if custom population of the event text
3879     * content is required.
3880     * <p>
3881     * If an {@link AccessibilityDelegate} has been specified via calling
3882     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3883     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
3884     * is responsible for handling this call.
3885     * </p>
3886     * <p>
3887     * <em>Note:</em> Accessibility events of certain types are not dispatched for
3888     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
3889     * </p>
3890     *
3891     * @param event The event.
3892     *
3893     * @return True if the event population was completed.
3894     */
3895    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
3896        if (mAccessibilityDelegate != null) {
3897            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
3898        } else {
3899            return dispatchPopulateAccessibilityEventInternal(event);
3900        }
3901    }
3902
3903    /**
3904     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
3905     *
3906     * Note: Called from the default {@link AccessibilityDelegate}.
3907     */
3908    boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
3909        onPopulateAccessibilityEvent(event);
3910        return false;
3911    }
3912
3913    /**
3914     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
3915     * giving a chance to this View to populate the accessibility event with its
3916     * text content. While the implementation is free to modify other event
3917     * attributes this should be performed in
3918     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
3919     * <p>
3920     * Example: Adding formatted date string to an accessibility event in addition
3921     *          to the text added by the super implementation.
3922     * </p><p><pre><code>
3923     * public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
3924     *     super.onPopulateAccessibilityEvent(event);
3925     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
3926     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
3927     *         mCurrentDate.getTimeInMillis(), flags);
3928     *     event.getText().add(selectedDateUtterance);
3929     * }
3930     * </code></pre></p>
3931     * <p>
3932     * If an {@link AccessibilityDelegate} has been specified via calling
3933     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3934     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
3935     * is responsible for handling this call.
3936     * </p>
3937     *
3938     * @param event The accessibility event which to populate.
3939     *
3940     * @see #sendAccessibilityEvent(int)
3941     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
3942     */
3943    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
3944        if (mAccessibilityDelegate != null) {
3945            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
3946        } else {
3947            onPopulateAccessibilityEventInternal(event);
3948        }
3949    }
3950
3951    /**
3952     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
3953     *
3954     * Note: Called from the default {@link AccessibilityDelegate}.
3955     */
3956    void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
3957
3958    }
3959
3960    /**
3961     * Initializes an {@link AccessibilityEvent} with information about
3962     * this View which is the event source. In other words, the source of
3963     * an accessibility event is the view whose state change triggered firing
3964     * the event.
3965     * <p>
3966     * Example: Setting the password property of an event in addition
3967     *          to properties set by the super implementation.
3968     * </p><p><pre><code>
3969     * public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
3970     *    super.onInitializeAccessibilityEvent(event);
3971     *    event.setPassword(true);
3972     * }
3973     * </code></pre></p>
3974     * <p>
3975     * If an {@link AccessibilityDelegate} has been specified via calling
3976     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3977     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
3978     * is responsible for handling this call.
3979     * </p>
3980     *
3981     * @param event The event to initialize.
3982     *
3983     * @see #sendAccessibilityEvent(int)
3984     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
3985     */
3986    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
3987        if (mAccessibilityDelegate != null) {
3988            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
3989        } else {
3990            onInitializeAccessibilityEventInternal(event);
3991        }
3992    }
3993
3994    /**
3995     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
3996     *
3997     * Note: Called from the default {@link AccessibilityDelegate}.
3998     */
3999    void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
4000        event.setSource(this);
4001        event.setClassName(getClass().getName());
4002        event.setPackageName(getContext().getPackageName());
4003        event.setEnabled(isEnabled());
4004        event.setContentDescription(mContentDescription);
4005
4006        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
4007            ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
4008            getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
4009                    FOCUSABLES_ALL);
4010            event.setItemCount(focusablesTempList.size());
4011            event.setCurrentItemIndex(focusablesTempList.indexOf(this));
4012            focusablesTempList.clear();
4013        }
4014    }
4015
4016    /**
4017     * Returns an {@link AccessibilityNodeInfo} representing this view from the
4018     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
4019     * This method is responsible for obtaining an accessibility node info from a
4020     * pool of reusable instances and calling
4021     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
4022     * initialize the former.
4023     * <p>
4024     * Note: The client is responsible for recycling the obtained instance by calling
4025     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
4026     * </p>
4027     * @return A populated {@link AccessibilityNodeInfo}.
4028     *
4029     * @see AccessibilityNodeInfo
4030     */
4031    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
4032        AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
4033        onInitializeAccessibilityNodeInfo(info);
4034        return info;
4035    }
4036
4037    /**
4038     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
4039     * The base implementation sets:
4040     * <ul>
4041     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
4042     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
4043     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
4044     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
4045     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
4046     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
4047     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
4048     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
4049     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
4050     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
4051     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
4052     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
4053     * </ul>
4054     * <p>
4055     * Subclasses should override this method, call the super implementation,
4056     * and set additional attributes.
4057     * </p>
4058     * <p>
4059     * If an {@link AccessibilityDelegate} has been specified via calling
4060     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4061     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
4062     * is responsible for handling this call.
4063     * </p>
4064     *
4065     * @param info The instance to initialize.
4066     */
4067    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
4068        if (mAccessibilityDelegate != null) {
4069            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
4070        } else {
4071            onInitializeAccessibilityNodeInfoInternal(info);
4072        }
4073    }
4074
4075    /**
4076     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
4077     *
4078     * Note: Called from the default {@link AccessibilityDelegate}.
4079     */
4080    void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
4081        Rect bounds = mAttachInfo.mTmpInvalRect;
4082        getDrawingRect(bounds);
4083        info.setBoundsInParent(bounds);
4084
4085        int[] locationOnScreen = mAttachInfo.mInvalidateChildLocation;
4086        getLocationOnScreen(locationOnScreen);
4087        bounds.offsetTo(0, 0);
4088        bounds.offset(locationOnScreen[0], locationOnScreen[1]);
4089        info.setBoundsInScreen(bounds);
4090
4091        ViewParent parent = getParent();
4092        if (parent instanceof View) {
4093            View parentView = (View) parent;
4094            info.setParent(parentView);
4095        }
4096
4097        info.setPackageName(mContext.getPackageName());
4098        info.setClassName(getClass().getName());
4099        info.setContentDescription(getContentDescription());
4100
4101        info.setEnabled(isEnabled());
4102        info.setClickable(isClickable());
4103        info.setFocusable(isFocusable());
4104        info.setFocused(isFocused());
4105        info.setSelected(isSelected());
4106        info.setLongClickable(isLongClickable());
4107
4108        // TODO: These make sense only if we are in an AdapterView but all
4109        // views can be selected. Maybe from accessiiblity perspective
4110        // we should report as selectable view in an AdapterView.
4111        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
4112        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
4113
4114        if (isFocusable()) {
4115            if (isFocused()) {
4116                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
4117            } else {
4118                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
4119            }
4120        }
4121    }
4122
4123    /**
4124     * Sets a delegate for implementing accessibility support via compositon as
4125     * opposed to inheritance. The delegate's primary use is for implementing
4126     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
4127     *
4128     * @param delegate The delegate instance.
4129     *
4130     * @see AccessibilityDelegate
4131     */
4132    public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
4133        mAccessibilityDelegate = delegate;
4134    }
4135
4136    /**
4137     * Gets the unique identifier of this view on the screen for accessibility purposes.
4138     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
4139     *
4140     * @return The view accessibility id.
4141     *
4142     * @hide
4143     */
4144    public int getAccessibilityViewId() {
4145        if (mAccessibilityViewId == NO_ID) {
4146            mAccessibilityViewId = sNextAccessibilityViewId++;
4147        }
4148        return mAccessibilityViewId;
4149    }
4150
4151    /**
4152     * Gets the unique identifier of the window in which this View reseides.
4153     *
4154     * @return The window accessibility id.
4155     *
4156     * @hide
4157     */
4158    public int getAccessibilityWindowId() {
4159        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
4160    }
4161
4162    /**
4163     * Gets the {@link View} description. It briefly describes the view and is
4164     * primarily used for accessibility support. Set this property to enable
4165     * better accessibility support for your application. This is especially
4166     * true for views that do not have textual representation (For example,
4167     * ImageButton).
4168     *
4169     * @return The content descriptiopn.
4170     *
4171     * @attr ref android.R.styleable#View_contentDescription
4172     */
4173    public CharSequence getContentDescription() {
4174        return mContentDescription;
4175    }
4176
4177    /**
4178     * Sets the {@link View} description. It briefly describes the view and is
4179     * primarily used for accessibility support. Set this property to enable
4180     * better accessibility support for your application. This is especially
4181     * true for views that do not have textual representation (For example,
4182     * ImageButton).
4183     *
4184     * @param contentDescription The content description.
4185     *
4186     * @attr ref android.R.styleable#View_contentDescription
4187     */
4188    public void setContentDescription(CharSequence contentDescription) {
4189        mContentDescription = contentDescription;
4190    }
4191
4192    /**
4193     * Invoked whenever this view loses focus, either by losing window focus or by losing
4194     * focus within its window. This method can be used to clear any state tied to the
4195     * focus. For instance, if a button is held pressed with the trackball and the window
4196     * loses focus, this method can be used to cancel the press.
4197     *
4198     * Subclasses of View overriding this method should always call super.onFocusLost().
4199     *
4200     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
4201     * @see #onWindowFocusChanged(boolean)
4202     *
4203     * @hide pending API council approval
4204     */
4205    protected void onFocusLost() {
4206        resetPressedState();
4207    }
4208
4209    private void resetPressedState() {
4210        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
4211            return;
4212        }
4213
4214        if (isPressed()) {
4215            setPressed(false);
4216
4217            if (!mHasPerformedLongPress) {
4218                removeLongPressCallback();
4219            }
4220        }
4221    }
4222
4223    /**
4224     * Returns true if this view has focus
4225     *
4226     * @return True if this view has focus, false otherwise.
4227     */
4228    @ViewDebug.ExportedProperty(category = "focus")
4229    public boolean isFocused() {
4230        return (mPrivateFlags & FOCUSED) != 0;
4231    }
4232
4233    /**
4234     * Find the view in the hierarchy rooted at this view that currently has
4235     * focus.
4236     *
4237     * @return The view that currently has focus, or null if no focused view can
4238     *         be found.
4239     */
4240    public View findFocus() {
4241        return (mPrivateFlags & FOCUSED) != 0 ? this : null;
4242    }
4243
4244    /**
4245     * Change whether this view is one of the set of scrollable containers in
4246     * its window.  This will be used to determine whether the window can
4247     * resize or must pan when a soft input area is open -- scrollable
4248     * containers allow the window to use resize mode since the container
4249     * will appropriately shrink.
4250     */
4251    public void setScrollContainer(boolean isScrollContainer) {
4252        if (isScrollContainer) {
4253            if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
4254                mAttachInfo.mScrollContainers.add(this);
4255                mPrivateFlags |= SCROLL_CONTAINER_ADDED;
4256            }
4257            mPrivateFlags |= SCROLL_CONTAINER;
4258        } else {
4259            if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
4260                mAttachInfo.mScrollContainers.remove(this);
4261            }
4262            mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
4263        }
4264    }
4265
4266    /**
4267     * Returns the quality of the drawing cache.
4268     *
4269     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
4270     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
4271     *
4272     * @see #setDrawingCacheQuality(int)
4273     * @see #setDrawingCacheEnabled(boolean)
4274     * @see #isDrawingCacheEnabled()
4275     *
4276     * @attr ref android.R.styleable#View_drawingCacheQuality
4277     */
4278    public int getDrawingCacheQuality() {
4279        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
4280    }
4281
4282    /**
4283     * Set the drawing cache quality of this view. This value is used only when the
4284     * drawing cache is enabled
4285     *
4286     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
4287     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
4288     *
4289     * @see #getDrawingCacheQuality()
4290     * @see #setDrawingCacheEnabled(boolean)
4291     * @see #isDrawingCacheEnabled()
4292     *
4293     * @attr ref android.R.styleable#View_drawingCacheQuality
4294     */
4295    public void setDrawingCacheQuality(int quality) {
4296        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
4297    }
4298
4299    /**
4300     * Returns whether the screen should remain on, corresponding to the current
4301     * value of {@link #KEEP_SCREEN_ON}.
4302     *
4303     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
4304     *
4305     * @see #setKeepScreenOn(boolean)
4306     *
4307     * @attr ref android.R.styleable#View_keepScreenOn
4308     */
4309    public boolean getKeepScreenOn() {
4310        return (mViewFlags & KEEP_SCREEN_ON) != 0;
4311    }
4312
4313    /**
4314     * Controls whether the screen should remain on, modifying the
4315     * value of {@link #KEEP_SCREEN_ON}.
4316     *
4317     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
4318     *
4319     * @see #getKeepScreenOn()
4320     *
4321     * @attr ref android.R.styleable#View_keepScreenOn
4322     */
4323    public void setKeepScreenOn(boolean keepScreenOn) {
4324        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
4325    }
4326
4327    /**
4328     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
4329     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4330     *
4331     * @attr ref android.R.styleable#View_nextFocusLeft
4332     */
4333    public int getNextFocusLeftId() {
4334        return mNextFocusLeftId;
4335    }
4336
4337    /**
4338     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
4339     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
4340     * decide automatically.
4341     *
4342     * @attr ref android.R.styleable#View_nextFocusLeft
4343     */
4344    public void setNextFocusLeftId(int nextFocusLeftId) {
4345        mNextFocusLeftId = nextFocusLeftId;
4346    }
4347
4348    /**
4349     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
4350     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4351     *
4352     * @attr ref android.R.styleable#View_nextFocusRight
4353     */
4354    public int getNextFocusRightId() {
4355        return mNextFocusRightId;
4356    }
4357
4358    /**
4359     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
4360     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
4361     * decide automatically.
4362     *
4363     * @attr ref android.R.styleable#View_nextFocusRight
4364     */
4365    public void setNextFocusRightId(int nextFocusRightId) {
4366        mNextFocusRightId = nextFocusRightId;
4367    }
4368
4369    /**
4370     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
4371     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4372     *
4373     * @attr ref android.R.styleable#View_nextFocusUp
4374     */
4375    public int getNextFocusUpId() {
4376        return mNextFocusUpId;
4377    }
4378
4379    /**
4380     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
4381     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
4382     * decide automatically.
4383     *
4384     * @attr ref android.R.styleable#View_nextFocusUp
4385     */
4386    public void setNextFocusUpId(int nextFocusUpId) {
4387        mNextFocusUpId = nextFocusUpId;
4388    }
4389
4390    /**
4391     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
4392     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4393     *
4394     * @attr ref android.R.styleable#View_nextFocusDown
4395     */
4396    public int getNextFocusDownId() {
4397        return mNextFocusDownId;
4398    }
4399
4400    /**
4401     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
4402     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
4403     * decide automatically.
4404     *
4405     * @attr ref android.R.styleable#View_nextFocusDown
4406     */
4407    public void setNextFocusDownId(int nextFocusDownId) {
4408        mNextFocusDownId = nextFocusDownId;
4409    }
4410
4411    /**
4412     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
4413     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4414     *
4415     * @attr ref android.R.styleable#View_nextFocusForward
4416     */
4417    public int getNextFocusForwardId() {
4418        return mNextFocusForwardId;
4419    }
4420
4421    /**
4422     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
4423     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
4424     * decide automatically.
4425     *
4426     * @attr ref android.R.styleable#View_nextFocusForward
4427     */
4428    public void setNextFocusForwardId(int nextFocusForwardId) {
4429        mNextFocusForwardId = nextFocusForwardId;
4430    }
4431
4432    /**
4433     * Returns the visibility of this view and all of its ancestors
4434     *
4435     * @return True if this view and all of its ancestors are {@link #VISIBLE}
4436     */
4437    public boolean isShown() {
4438        View current = this;
4439        //noinspection ConstantConditions
4440        do {
4441            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
4442                return false;
4443            }
4444            ViewParent parent = current.mParent;
4445            if (parent == null) {
4446                return false; // We are not attached to the view root
4447            }
4448            if (!(parent instanceof View)) {
4449                return true;
4450            }
4451            current = (View) parent;
4452        } while (current != null);
4453
4454        return false;
4455    }
4456
4457    /**
4458     * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag
4459     * is set
4460     *
4461     * @param insets Insets for system windows
4462     *
4463     * @return True if this view applied the insets, false otherwise
4464     */
4465    protected boolean fitSystemWindows(Rect insets) {
4466        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
4467            mPaddingLeft = insets.left;
4468            mPaddingTop = insets.top;
4469            mPaddingRight = insets.right;
4470            mPaddingBottom = insets.bottom;
4471            requestLayout();
4472            return true;
4473        }
4474        return false;
4475    }
4476
4477    /**
4478     * Set whether or not this view should account for system screen decorations
4479     * such as the status bar and inset its content. This allows this view to be
4480     * positioned in absolute screen coordinates and remain visible to the user.
4481     *
4482     * <p>This should only be used by top-level window decor views.
4483     *
4484     * @param fitSystemWindows true to inset content for system screen decorations, false for
4485     *                         default behavior.
4486     *
4487     * @attr ref android.R.styleable#View_fitsSystemWindows
4488     */
4489    public void setFitsSystemWindows(boolean fitSystemWindows) {
4490        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
4491    }
4492
4493    /**
4494     * Check for the FITS_SYSTEM_WINDOWS flag. If this method returns true, this view
4495     * will account for system screen decorations such as the status bar and inset its
4496     * content. This allows the view to be positioned in absolute screen coordinates
4497     * and remain visible to the user.
4498     *
4499     * @return true if this view will adjust its content bounds for system screen decorations.
4500     *
4501     * @attr ref android.R.styleable#View_fitsSystemWindows
4502     */
4503    public boolean fitsSystemWindows() {
4504        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
4505    }
4506
4507    /**
4508     * Returns the visibility status for this view.
4509     *
4510     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
4511     * @attr ref android.R.styleable#View_visibility
4512     */
4513    @ViewDebug.ExportedProperty(mapping = {
4514        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
4515        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
4516        @ViewDebug.IntToString(from = GONE,      to = "GONE")
4517    })
4518    public int getVisibility() {
4519        return mViewFlags & VISIBILITY_MASK;
4520    }
4521
4522    /**
4523     * Set the enabled state of this view.
4524     *
4525     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
4526     * @attr ref android.R.styleable#View_visibility
4527     */
4528    @RemotableViewMethod
4529    public void setVisibility(int visibility) {
4530        setFlags(visibility, VISIBILITY_MASK);
4531        if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
4532    }
4533
4534    /**
4535     * Returns the enabled status for this view. The interpretation of the
4536     * enabled state varies by subclass.
4537     *
4538     * @return True if this view is enabled, false otherwise.
4539     */
4540    @ViewDebug.ExportedProperty
4541    public boolean isEnabled() {
4542        return (mViewFlags & ENABLED_MASK) == ENABLED;
4543    }
4544
4545    /**
4546     * Set the enabled state of this view. The interpretation of the enabled
4547     * state varies by subclass.
4548     *
4549     * @param enabled True if this view is enabled, false otherwise.
4550     */
4551    @RemotableViewMethod
4552    public void setEnabled(boolean enabled) {
4553        if (enabled == isEnabled()) return;
4554
4555        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
4556
4557        /*
4558         * The View most likely has to change its appearance, so refresh
4559         * the drawable state.
4560         */
4561        refreshDrawableState();
4562
4563        // Invalidate too, since the default behavior for views is to be
4564        // be drawn at 50% alpha rather than to change the drawable.
4565        invalidate(true);
4566    }
4567
4568    /**
4569     * Set whether this view can receive the focus.
4570     *
4571     * Setting this to false will also ensure that this view is not focusable
4572     * in touch mode.
4573     *
4574     * @param focusable If true, this view can receive the focus.
4575     *
4576     * @see #setFocusableInTouchMode(boolean)
4577     * @attr ref android.R.styleable#View_focusable
4578     */
4579    public void setFocusable(boolean focusable) {
4580        if (!focusable) {
4581            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
4582        }
4583        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
4584    }
4585
4586    /**
4587     * Set whether this view can receive focus while in touch mode.
4588     *
4589     * Setting this to true will also ensure that this view is focusable.
4590     *
4591     * @param focusableInTouchMode If true, this view can receive the focus while
4592     *   in touch mode.
4593     *
4594     * @see #setFocusable(boolean)
4595     * @attr ref android.R.styleable#View_focusableInTouchMode
4596     */
4597    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
4598        // Focusable in touch mode should always be set before the focusable flag
4599        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
4600        // which, in touch mode, will not successfully request focus on this view
4601        // because the focusable in touch mode flag is not set
4602        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
4603        if (focusableInTouchMode) {
4604            setFlags(FOCUSABLE, FOCUSABLE_MASK);
4605        }
4606    }
4607
4608    /**
4609     * Set whether this view should have sound effects enabled for events such as
4610     * clicking and touching.
4611     *
4612     * <p>You may wish to disable sound effects for a view if you already play sounds,
4613     * for instance, a dial key that plays dtmf tones.
4614     *
4615     * @param soundEffectsEnabled whether sound effects are enabled for this view.
4616     * @see #isSoundEffectsEnabled()
4617     * @see #playSoundEffect(int)
4618     * @attr ref android.R.styleable#View_soundEffectsEnabled
4619     */
4620    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
4621        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
4622    }
4623
4624    /**
4625     * @return whether this view should have sound effects enabled for events such as
4626     *     clicking and touching.
4627     *
4628     * @see #setSoundEffectsEnabled(boolean)
4629     * @see #playSoundEffect(int)
4630     * @attr ref android.R.styleable#View_soundEffectsEnabled
4631     */
4632    @ViewDebug.ExportedProperty
4633    public boolean isSoundEffectsEnabled() {
4634        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
4635    }
4636
4637    /**
4638     * Set whether this view should have haptic feedback for events such as
4639     * long presses.
4640     *
4641     * <p>You may wish to disable haptic feedback if your view already controls
4642     * its own haptic feedback.
4643     *
4644     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
4645     * @see #isHapticFeedbackEnabled()
4646     * @see #performHapticFeedback(int)
4647     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
4648     */
4649    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
4650        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
4651    }
4652
4653    /**
4654     * @return whether this view should have haptic feedback enabled for events
4655     * long presses.
4656     *
4657     * @see #setHapticFeedbackEnabled(boolean)
4658     * @see #performHapticFeedback(int)
4659     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
4660     */
4661    @ViewDebug.ExportedProperty
4662    public boolean isHapticFeedbackEnabled() {
4663        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
4664    }
4665
4666    /**
4667     * Returns the layout direction for this view.
4668     *
4669     * @return One of {@link #LAYOUT_DIRECTION_LTR},
4670     *   {@link #LAYOUT_DIRECTION_RTL},
4671     *   {@link #LAYOUT_DIRECTION_INHERIT} or
4672     *   {@link #LAYOUT_DIRECTION_LOCALE}.
4673     * @attr ref android.R.styleable#View_layoutDirection
4674     *
4675     * @hide
4676     */
4677    @ViewDebug.ExportedProperty(category = "layout", mapping = {
4678        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
4679        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
4680        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
4681        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
4682    })
4683    public int getLayoutDirection() {
4684        return mViewFlags & LAYOUT_DIRECTION_MASK;
4685    }
4686
4687    /**
4688     * Set the layout direction for this view. This will propagate a reset of layout direction
4689     * resolution to the view's children and resolve layout direction for this view.
4690     *
4691     * @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR},
4692     *   {@link #LAYOUT_DIRECTION_RTL},
4693     *   {@link #LAYOUT_DIRECTION_INHERIT} or
4694     *   {@link #LAYOUT_DIRECTION_LOCALE}.
4695     *
4696     * @attr ref android.R.styleable#View_layoutDirection
4697     *
4698     * @hide
4699     */
4700    @RemotableViewMethod
4701    public void setLayoutDirection(int layoutDirection) {
4702        if (getLayoutDirection() != layoutDirection) {
4703            resetResolvedLayoutDirection();
4704            // Setting the flag will also request a layout.
4705            setFlags(layoutDirection, LAYOUT_DIRECTION_MASK);
4706        }
4707    }
4708
4709    /**
4710     * Returns the resolved layout direction for this view.
4711     *
4712     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
4713     * {@link #LAYOUT_DIRECTION_LTR} id the layout direction is not RTL.
4714     *
4715     * @hide
4716     */
4717    @ViewDebug.ExportedProperty(category = "layout", mapping = {
4718        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "RESOLVED_DIRECTION_LTR"),
4719        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RESOLVED_DIRECTION_RTL")
4720    })
4721    public int getResolvedLayoutDirection() {
4722        resolveLayoutDirectionIfNeeded();
4723        return ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED_RTL) == LAYOUT_DIRECTION_RESOLVED_RTL) ?
4724                LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
4725    }
4726
4727    /**
4728     * <p>Indicates whether or not this view's layout is right-to-left. This is resolved from
4729     * layout attribute and/or the inherited value from the parent.</p>
4730     *
4731     * @return true if the layout is right-to-left.
4732     *
4733     * @hide
4734     */
4735    @ViewDebug.ExportedProperty(category = "layout")
4736    public boolean isLayoutRtl() {
4737        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
4738    }
4739
4740    /**
4741     * If this view doesn't do any drawing on its own, set this flag to
4742     * allow further optimizations. By default, this flag is not set on
4743     * View, but could be set on some View subclasses such as ViewGroup.
4744     *
4745     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
4746     * you should clear this flag.
4747     *
4748     * @param willNotDraw whether or not this View draw on its own
4749     */
4750    public void setWillNotDraw(boolean willNotDraw) {
4751        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
4752    }
4753
4754    /**
4755     * Returns whether or not this View draws on its own.
4756     *
4757     * @return true if this view has nothing to draw, false otherwise
4758     */
4759    @ViewDebug.ExportedProperty(category = "drawing")
4760    public boolean willNotDraw() {
4761        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
4762    }
4763
4764    /**
4765     * When a View's drawing cache is enabled, drawing is redirected to an
4766     * offscreen bitmap. Some views, like an ImageView, must be able to
4767     * bypass this mechanism if they already draw a single bitmap, to avoid
4768     * unnecessary usage of the memory.
4769     *
4770     * @param willNotCacheDrawing true if this view does not cache its
4771     *        drawing, false otherwise
4772     */
4773    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
4774        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
4775    }
4776
4777    /**
4778     * Returns whether or not this View can cache its drawing or not.
4779     *
4780     * @return true if this view does not cache its drawing, false otherwise
4781     */
4782    @ViewDebug.ExportedProperty(category = "drawing")
4783    public boolean willNotCacheDrawing() {
4784        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
4785    }
4786
4787    /**
4788     * Indicates whether this view reacts to click events or not.
4789     *
4790     * @return true if the view is clickable, false otherwise
4791     *
4792     * @see #setClickable(boolean)
4793     * @attr ref android.R.styleable#View_clickable
4794     */
4795    @ViewDebug.ExportedProperty
4796    public boolean isClickable() {
4797        return (mViewFlags & CLICKABLE) == CLICKABLE;
4798    }
4799
4800    /**
4801     * Enables or disables click events for this view. When a view
4802     * is clickable it will change its state to "pressed" on every click.
4803     * Subclasses should set the view clickable to visually react to
4804     * user's clicks.
4805     *
4806     * @param clickable true to make the view clickable, false otherwise
4807     *
4808     * @see #isClickable()
4809     * @attr ref android.R.styleable#View_clickable
4810     */
4811    public void setClickable(boolean clickable) {
4812        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
4813    }
4814
4815    /**
4816     * Indicates whether this view reacts to long click events or not.
4817     *
4818     * @return true if the view is long clickable, false otherwise
4819     *
4820     * @see #setLongClickable(boolean)
4821     * @attr ref android.R.styleable#View_longClickable
4822     */
4823    public boolean isLongClickable() {
4824        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
4825    }
4826
4827    /**
4828     * Enables or disables long click events for this view. When a view is long
4829     * clickable it reacts to the user holding down the button for a longer
4830     * duration than a tap. This event can either launch the listener or a
4831     * context menu.
4832     *
4833     * @param longClickable true to make the view long clickable, false otherwise
4834     * @see #isLongClickable()
4835     * @attr ref android.R.styleable#View_longClickable
4836     */
4837    public void setLongClickable(boolean longClickable) {
4838        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
4839    }
4840
4841    /**
4842     * Sets the pressed state for this view.
4843     *
4844     * @see #isClickable()
4845     * @see #setClickable(boolean)
4846     *
4847     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
4848     *        the View's internal state from a previously set "pressed" state.
4849     */
4850    public void setPressed(boolean pressed) {
4851        if (pressed) {
4852            mPrivateFlags |= PRESSED;
4853        } else {
4854            mPrivateFlags &= ~PRESSED;
4855        }
4856        refreshDrawableState();
4857        dispatchSetPressed(pressed);
4858    }
4859
4860    /**
4861     * Dispatch setPressed to all of this View's children.
4862     *
4863     * @see #setPressed(boolean)
4864     *
4865     * @param pressed The new pressed state
4866     */
4867    protected void dispatchSetPressed(boolean pressed) {
4868    }
4869
4870    /**
4871     * Indicates whether the view is currently in pressed state. Unless
4872     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
4873     * the pressed state.
4874     *
4875     * @see #setPressed(boolean)
4876     * @see #isClickable()
4877     * @see #setClickable(boolean)
4878     *
4879     * @return true if the view is currently pressed, false otherwise
4880     */
4881    public boolean isPressed() {
4882        return (mPrivateFlags & PRESSED) == PRESSED;
4883    }
4884
4885    /**
4886     * Indicates whether this view will save its state (that is,
4887     * whether its {@link #onSaveInstanceState} method will be called).
4888     *
4889     * @return Returns true if the view state saving is enabled, else false.
4890     *
4891     * @see #setSaveEnabled(boolean)
4892     * @attr ref android.R.styleable#View_saveEnabled
4893     */
4894    public boolean isSaveEnabled() {
4895        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
4896    }
4897
4898    /**
4899     * Controls whether the saving of this view's state is
4900     * enabled (that is, whether its {@link #onSaveInstanceState} method
4901     * will be called).  Note that even if freezing is enabled, the
4902     * view still must have an id assigned to it (via {@link #setId(int)})
4903     * for its state to be saved.  This flag can only disable the
4904     * saving of this view; any child views may still have their state saved.
4905     *
4906     * @param enabled Set to false to <em>disable</em> state saving, or true
4907     * (the default) to allow it.
4908     *
4909     * @see #isSaveEnabled()
4910     * @see #setId(int)
4911     * @see #onSaveInstanceState()
4912     * @attr ref android.R.styleable#View_saveEnabled
4913     */
4914    public void setSaveEnabled(boolean enabled) {
4915        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
4916    }
4917
4918    /**
4919     * Gets whether the framework should discard touches when the view's
4920     * window is obscured by another visible window.
4921     * Refer to the {@link View} security documentation for more details.
4922     *
4923     * @return True if touch filtering is enabled.
4924     *
4925     * @see #setFilterTouchesWhenObscured(boolean)
4926     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
4927     */
4928    @ViewDebug.ExportedProperty
4929    public boolean getFilterTouchesWhenObscured() {
4930        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
4931    }
4932
4933    /**
4934     * Sets whether the framework should discard touches when the view's
4935     * window is obscured by another visible window.
4936     * Refer to the {@link View} security documentation for more details.
4937     *
4938     * @param enabled True if touch filtering should be enabled.
4939     *
4940     * @see #getFilterTouchesWhenObscured
4941     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
4942     */
4943    public void setFilterTouchesWhenObscured(boolean enabled) {
4944        setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
4945                FILTER_TOUCHES_WHEN_OBSCURED);
4946    }
4947
4948    /**
4949     * Indicates whether the entire hierarchy under this view will save its
4950     * state when a state saving traversal occurs from its parent.  The default
4951     * is true; if false, these views will not be saved unless
4952     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
4953     *
4954     * @return Returns true if the view state saving from parent is enabled, else false.
4955     *
4956     * @see #setSaveFromParentEnabled(boolean)
4957     */
4958    public boolean isSaveFromParentEnabled() {
4959        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
4960    }
4961
4962    /**
4963     * Controls whether the entire hierarchy under this view will save its
4964     * state when a state saving traversal occurs from its parent.  The default
4965     * is true; if false, these views will not be saved unless
4966     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
4967     *
4968     * @param enabled Set to false to <em>disable</em> state saving, or true
4969     * (the default) to allow it.
4970     *
4971     * @see #isSaveFromParentEnabled()
4972     * @see #setId(int)
4973     * @see #onSaveInstanceState()
4974     */
4975    public void setSaveFromParentEnabled(boolean enabled) {
4976        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
4977    }
4978
4979
4980    /**
4981     * Returns whether this View is able to take focus.
4982     *
4983     * @return True if this view can take focus, or false otherwise.
4984     * @attr ref android.R.styleable#View_focusable
4985     */
4986    @ViewDebug.ExportedProperty(category = "focus")
4987    public final boolean isFocusable() {
4988        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
4989    }
4990
4991    /**
4992     * When a view is focusable, it may not want to take focus when in touch mode.
4993     * For example, a button would like focus when the user is navigating via a D-pad
4994     * so that the user can click on it, but once the user starts touching the screen,
4995     * the button shouldn't take focus
4996     * @return Whether the view is focusable in touch mode.
4997     * @attr ref android.R.styleable#View_focusableInTouchMode
4998     */
4999    @ViewDebug.ExportedProperty
5000    public final boolean isFocusableInTouchMode() {
5001        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
5002    }
5003
5004    /**
5005     * Find the nearest view in the specified direction that can take focus.
5006     * This does not actually give focus to that view.
5007     *
5008     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5009     *
5010     * @return The nearest focusable in the specified direction, or null if none
5011     *         can be found.
5012     */
5013    public View focusSearch(int direction) {
5014        if (mParent != null) {
5015            return mParent.focusSearch(this, direction);
5016        } else {
5017            return null;
5018        }
5019    }
5020
5021    /**
5022     * This method is the last chance for the focused view and its ancestors to
5023     * respond to an arrow key. This is called when the focused view did not
5024     * consume the key internally, nor could the view system find a new view in
5025     * the requested direction to give focus to.
5026     *
5027     * @param focused The currently focused view.
5028     * @param direction The direction focus wants to move. One of FOCUS_UP,
5029     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
5030     * @return True if the this view consumed this unhandled move.
5031     */
5032    public boolean dispatchUnhandledMove(View focused, int direction) {
5033        return false;
5034    }
5035
5036    /**
5037     * If a user manually specified the next view id for a particular direction,
5038     * use the root to look up the view.
5039     * @param root The root view of the hierarchy containing this view.
5040     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
5041     * or FOCUS_BACKWARD.
5042     * @return The user specified next view, or null if there is none.
5043     */
5044    View findUserSetNextFocus(View root, int direction) {
5045        switch (direction) {
5046            case FOCUS_LEFT:
5047                if (mNextFocusLeftId == View.NO_ID) return null;
5048                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
5049            case FOCUS_RIGHT:
5050                if (mNextFocusRightId == View.NO_ID) return null;
5051                return findViewInsideOutShouldExist(root, mNextFocusRightId);
5052            case FOCUS_UP:
5053                if (mNextFocusUpId == View.NO_ID) return null;
5054                return findViewInsideOutShouldExist(root, mNextFocusUpId);
5055            case FOCUS_DOWN:
5056                if (mNextFocusDownId == View.NO_ID) return null;
5057                return findViewInsideOutShouldExist(root, mNextFocusDownId);
5058            case FOCUS_FORWARD:
5059                if (mNextFocusForwardId == View.NO_ID) return null;
5060                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
5061            case FOCUS_BACKWARD: {
5062                final int id = mID;
5063                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
5064                    @Override
5065                    public boolean apply(View t) {
5066                        return t.mNextFocusForwardId == id;
5067                    }
5068                });
5069            }
5070        }
5071        return null;
5072    }
5073
5074    private View findViewInsideOutShouldExist(View root, final int childViewId) {
5075        View result = root.findViewByPredicateInsideOut(this, new Predicate<View>() {
5076            @Override
5077            public boolean apply(View t) {
5078                return t.mID == childViewId;
5079            }
5080        });
5081
5082        if (result == null) {
5083            Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
5084                    + "by user for id " + childViewId);
5085        }
5086        return result;
5087    }
5088
5089    /**
5090     * Find and return all focusable views that are descendants of this view,
5091     * possibly including this view if it is focusable itself.
5092     *
5093     * @param direction The direction of the focus
5094     * @return A list of focusable views
5095     */
5096    public ArrayList<View> getFocusables(int direction) {
5097        ArrayList<View> result = new ArrayList<View>(24);
5098        addFocusables(result, direction);
5099        return result;
5100    }
5101
5102    /**
5103     * Add any focusable views that are descendants of this view (possibly
5104     * including this view if it is focusable itself) to views.  If we are in touch mode,
5105     * only add views that are also focusable in touch mode.
5106     *
5107     * @param views Focusable views found so far
5108     * @param direction The direction of the focus
5109     */
5110    public void addFocusables(ArrayList<View> views, int direction) {
5111        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
5112    }
5113
5114    /**
5115     * Adds any focusable views that are descendants of this view (possibly
5116     * including this view if it is focusable itself) to views. This method
5117     * adds all focusable views regardless if we are in touch mode or
5118     * only views focusable in touch mode if we are in touch mode depending on
5119     * the focusable mode paramater.
5120     *
5121     * @param views Focusable views found so far or null if all we are interested is
5122     *        the number of focusables.
5123     * @param direction The direction of the focus.
5124     * @param focusableMode The type of focusables to be added.
5125     *
5126     * @see #FOCUSABLES_ALL
5127     * @see #FOCUSABLES_TOUCH_MODE
5128     */
5129    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
5130        if (!isFocusable()) {
5131            return;
5132        }
5133
5134        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE &&
5135                isInTouchMode() && !isFocusableInTouchMode()) {
5136            return;
5137        }
5138
5139        if (views != null) {
5140            views.add(this);
5141        }
5142    }
5143
5144    /**
5145     * Finds the Views that contain given text. The containment is case insensitive.
5146     * The search is performed by either the text that the View renders or the content
5147     * description that describes the view for accessibility purposes and the view does
5148     * not render or both. Clients can specify how the search is to be performed via
5149     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
5150     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
5151     *
5152     * @param outViews The output list of matching Views.
5153     * @param searched The text to match against.
5154     *
5155     * @see #FIND_VIEWS_WITH_TEXT
5156     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
5157     * @see #setContentDescription(CharSequence)
5158     */
5159    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
5160        if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0 && !TextUtils.isEmpty(searched)
5161                && !TextUtils.isEmpty(mContentDescription)) {
5162            String searchedLowerCase = searched.toString().toLowerCase();
5163            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
5164            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
5165                outViews.add(this);
5166            }
5167        }
5168    }
5169
5170    /**
5171     * Find and return all touchable views that are descendants of this view,
5172     * possibly including this view if it is touchable itself.
5173     *
5174     * @return A list of touchable views
5175     */
5176    public ArrayList<View> getTouchables() {
5177        ArrayList<View> result = new ArrayList<View>();
5178        addTouchables(result);
5179        return result;
5180    }
5181
5182    /**
5183     * Add any touchable views that are descendants of this view (possibly
5184     * including this view if it is touchable itself) to views.
5185     *
5186     * @param views Touchable views found so far
5187     */
5188    public void addTouchables(ArrayList<View> views) {
5189        final int viewFlags = mViewFlags;
5190
5191        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
5192                && (viewFlags & ENABLED_MASK) == ENABLED) {
5193            views.add(this);
5194        }
5195    }
5196
5197    /**
5198     * Call this to try to give focus to a specific view or to one of its
5199     * descendants.
5200     *
5201     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
5202     * false), or if it is focusable and it is not focusable in touch mode
5203     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
5204     *
5205     * See also {@link #focusSearch(int)}, which is what you call to say that you
5206     * have focus, and you want your parent to look for the next one.
5207     *
5208     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
5209     * {@link #FOCUS_DOWN} and <code>null</code>.
5210     *
5211     * @return Whether this view or one of its descendants actually took focus.
5212     */
5213    public final boolean requestFocus() {
5214        return requestFocus(View.FOCUS_DOWN);
5215    }
5216
5217
5218    /**
5219     * Call this to try to give focus to a specific view or to one of its
5220     * descendants and give it a hint about what direction focus is heading.
5221     *
5222     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
5223     * false), or if it is focusable and it is not focusable in touch mode
5224     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
5225     *
5226     * See also {@link #focusSearch(int)}, which is what you call to say that you
5227     * have focus, and you want your parent to look for the next one.
5228     *
5229     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
5230     * <code>null</code> set for the previously focused rectangle.
5231     *
5232     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5233     * @return Whether this view or one of its descendants actually took focus.
5234     */
5235    public final boolean requestFocus(int direction) {
5236        return requestFocus(direction, null);
5237    }
5238
5239    /**
5240     * Call this to try to give focus to a specific view or to one of its descendants
5241     * and give it hints about the direction and a specific rectangle that the focus
5242     * is coming from.  The rectangle can help give larger views a finer grained hint
5243     * about where focus is coming from, and therefore, where to show selection, or
5244     * forward focus change internally.
5245     *
5246     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
5247     * false), or if it is focusable and it is not focusable in touch mode
5248     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
5249     *
5250     * A View will not take focus if it is not visible.
5251     *
5252     * A View will not take focus if one of its parents has
5253     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
5254     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
5255     *
5256     * See also {@link #focusSearch(int)}, which is what you call to say that you
5257     * have focus, and you want your parent to look for the next one.
5258     *
5259     * You may wish to override this method if your custom {@link View} has an internal
5260     * {@link View} that it wishes to forward the request to.
5261     *
5262     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5263     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
5264     *        to give a finer grained hint about where focus is coming from.  May be null
5265     *        if there is no hint.
5266     * @return Whether this view or one of its descendants actually took focus.
5267     */
5268    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
5269        // need to be focusable
5270        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
5271                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
5272            return false;
5273        }
5274
5275        // need to be focusable in touch mode if in touch mode
5276        if (isInTouchMode() &&
5277            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
5278               return false;
5279        }
5280
5281        // need to not have any parents blocking us
5282        if (hasAncestorThatBlocksDescendantFocus()) {
5283            return false;
5284        }
5285
5286        handleFocusGainInternal(direction, previouslyFocusedRect);
5287        return true;
5288    }
5289
5290    /** Gets the ViewAncestor, or null if not attached. */
5291    /*package*/ ViewRootImpl getViewRootImpl() {
5292        View root = getRootView();
5293        return root != null ? (ViewRootImpl)root.getParent() : null;
5294    }
5295
5296    /**
5297     * Call this to try to give focus to a specific view or to one of its descendants. This is a
5298     * special variant of {@link #requestFocus() } that will allow views that are not focuable in
5299     * touch mode to request focus when they are touched.
5300     *
5301     * @return Whether this view or one of its descendants actually took focus.
5302     *
5303     * @see #isInTouchMode()
5304     *
5305     */
5306    public final boolean requestFocusFromTouch() {
5307        // Leave touch mode if we need to
5308        if (isInTouchMode()) {
5309            ViewRootImpl viewRoot = getViewRootImpl();
5310            if (viewRoot != null) {
5311                viewRoot.ensureTouchMode(false);
5312            }
5313        }
5314        return requestFocus(View.FOCUS_DOWN);
5315    }
5316
5317    /**
5318     * @return Whether any ancestor of this view blocks descendant focus.
5319     */
5320    private boolean hasAncestorThatBlocksDescendantFocus() {
5321        ViewParent ancestor = mParent;
5322        while (ancestor instanceof ViewGroup) {
5323            final ViewGroup vgAncestor = (ViewGroup) ancestor;
5324            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
5325                return true;
5326            } else {
5327                ancestor = vgAncestor.getParent();
5328            }
5329        }
5330        return false;
5331    }
5332
5333    /**
5334     * @hide
5335     */
5336    public void dispatchStartTemporaryDetach() {
5337        onStartTemporaryDetach();
5338    }
5339
5340    /**
5341     * This is called when a container is going to temporarily detach a child, with
5342     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
5343     * It will either be followed by {@link #onFinishTemporaryDetach()} or
5344     * {@link #onDetachedFromWindow()} when the container is done.
5345     */
5346    public void onStartTemporaryDetach() {
5347        removeUnsetPressCallback();
5348        mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
5349    }
5350
5351    /**
5352     * @hide
5353     */
5354    public void dispatchFinishTemporaryDetach() {
5355        onFinishTemporaryDetach();
5356    }
5357
5358    /**
5359     * Called after {@link #onStartTemporaryDetach} when the container is done
5360     * changing the view.
5361     */
5362    public void onFinishTemporaryDetach() {
5363    }
5364
5365    /**
5366     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
5367     * for this view's window.  Returns null if the view is not currently attached
5368     * to the window.  Normally you will not need to use this directly, but
5369     * just use the standard high-level event callbacks like
5370     * {@link #onKeyDown(int, KeyEvent)}.
5371     */
5372    public KeyEvent.DispatcherState getKeyDispatcherState() {
5373        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
5374    }
5375
5376    /**
5377     * Dispatch a key event before it is processed by any input method
5378     * associated with the view hierarchy.  This can be used to intercept
5379     * key events in special situations before the IME consumes them; a
5380     * typical example would be handling the BACK key to update the application's
5381     * UI instead of allowing the IME to see it and close itself.
5382     *
5383     * @param event The key event to be dispatched.
5384     * @return True if the event was handled, false otherwise.
5385     */
5386    public boolean dispatchKeyEventPreIme(KeyEvent event) {
5387        return onKeyPreIme(event.getKeyCode(), event);
5388    }
5389
5390    /**
5391     * Dispatch a key event to the next view on the focus path. This path runs
5392     * from the top of the view tree down to the currently focused view. If this
5393     * view has focus, it will dispatch to itself. Otherwise it will dispatch
5394     * the next node down the focus path. This method also fires any key
5395     * listeners.
5396     *
5397     * @param event The key event to be dispatched.
5398     * @return True if the event was handled, false otherwise.
5399     */
5400    public boolean dispatchKeyEvent(KeyEvent event) {
5401        if (mInputEventConsistencyVerifier != null) {
5402            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
5403        }
5404
5405        // Give any attached key listener a first crack at the event.
5406        //noinspection SimplifiableIfStatement
5407        if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
5408                && mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
5409            return true;
5410        }
5411
5412        if (event.dispatch(this, mAttachInfo != null
5413                ? mAttachInfo.mKeyDispatchState : null, this)) {
5414            return true;
5415        }
5416
5417        if (mInputEventConsistencyVerifier != null) {
5418            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5419        }
5420        return false;
5421    }
5422
5423    /**
5424     * Dispatches a key shortcut event.
5425     *
5426     * @param event The key event to be dispatched.
5427     * @return True if the event was handled by the view, false otherwise.
5428     */
5429    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
5430        return onKeyShortcut(event.getKeyCode(), event);
5431    }
5432
5433    /**
5434     * Pass the touch screen motion event down to the target view, or this
5435     * view if it is the target.
5436     *
5437     * @param event The motion event to be dispatched.
5438     * @return True if the event was handled by the view, false otherwise.
5439     */
5440    public boolean dispatchTouchEvent(MotionEvent event) {
5441        if (mInputEventConsistencyVerifier != null) {
5442            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
5443        }
5444
5445        if (onFilterTouchEventForSecurity(event)) {
5446            //noinspection SimplifiableIfStatement
5447            if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
5448                    mOnTouchListener.onTouch(this, event)) {
5449                return true;
5450            }
5451
5452            if (onTouchEvent(event)) {
5453                return true;
5454            }
5455        }
5456
5457        if (mInputEventConsistencyVerifier != null) {
5458            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5459        }
5460        return false;
5461    }
5462
5463    /**
5464     * Filter the touch event to apply security policies.
5465     *
5466     * @param event The motion event to be filtered.
5467     * @return True if the event should be dispatched, false if the event should be dropped.
5468     *
5469     * @see #getFilterTouchesWhenObscured
5470     */
5471    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
5472        //noinspection RedundantIfStatement
5473        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
5474                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
5475            // Window is obscured, drop this touch.
5476            return false;
5477        }
5478        return true;
5479    }
5480
5481    /**
5482     * Pass a trackball motion event down to the focused view.
5483     *
5484     * @param event The motion event to be dispatched.
5485     * @return True if the event was handled by the view, false otherwise.
5486     */
5487    public boolean dispatchTrackballEvent(MotionEvent event) {
5488        if (mInputEventConsistencyVerifier != null) {
5489            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
5490        }
5491
5492        return onTrackballEvent(event);
5493    }
5494
5495    /**
5496     * Dispatch a generic motion event.
5497     * <p>
5498     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
5499     * are delivered to the view under the pointer.  All other generic motion events are
5500     * delivered to the focused view.  Hover events are handled specially and are delivered
5501     * to {@link #onHoverEvent(MotionEvent)}.
5502     * </p>
5503     *
5504     * @param event The motion event to be dispatched.
5505     * @return True if the event was handled by the view, false otherwise.
5506     */
5507    public boolean dispatchGenericMotionEvent(MotionEvent event) {
5508        if (mInputEventConsistencyVerifier != null) {
5509            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
5510        }
5511
5512        final int source = event.getSource();
5513        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
5514            final int action = event.getAction();
5515            if (action == MotionEvent.ACTION_HOVER_ENTER
5516                    || action == MotionEvent.ACTION_HOVER_MOVE
5517                    || action == MotionEvent.ACTION_HOVER_EXIT) {
5518                if (dispatchHoverEvent(event)) {
5519                    return true;
5520                }
5521            } else if (dispatchGenericPointerEvent(event)) {
5522                return true;
5523            }
5524        } else if (dispatchGenericFocusedEvent(event)) {
5525            return true;
5526        }
5527
5528        if (dispatchGenericMotionEventInternal(event)) {
5529            return true;
5530        }
5531
5532        if (mInputEventConsistencyVerifier != null) {
5533            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5534        }
5535        return false;
5536    }
5537
5538    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
5539        //noinspection SimplifiableIfStatement
5540        if (mOnGenericMotionListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
5541                && mOnGenericMotionListener.onGenericMotion(this, event)) {
5542            return true;
5543        }
5544
5545        if (onGenericMotionEvent(event)) {
5546            return true;
5547        }
5548
5549        if (mInputEventConsistencyVerifier != null) {
5550            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5551        }
5552        return false;
5553    }
5554
5555    /**
5556     * Dispatch a hover event.
5557     * <p>
5558     * Do not call this method directly.
5559     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
5560     * </p>
5561     *
5562     * @param event The motion event to be dispatched.
5563     * @return True if the event was handled by the view, false otherwise.
5564     */
5565    protected boolean dispatchHoverEvent(MotionEvent event) {
5566        //noinspection SimplifiableIfStatement
5567        if (mOnHoverListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
5568                && mOnHoverListener.onHover(this, event)) {
5569            return true;
5570        }
5571
5572        return onHoverEvent(event);
5573    }
5574
5575    /**
5576     * Returns true if the view has a child to which it has recently sent
5577     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
5578     * it does not have a hovered child, then it must be the innermost hovered view.
5579     * @hide
5580     */
5581    protected boolean hasHoveredChild() {
5582        return false;
5583    }
5584
5585    /**
5586     * Dispatch a generic motion event to the view under the first pointer.
5587     * <p>
5588     * Do not call this method directly.
5589     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
5590     * </p>
5591     *
5592     * @param event The motion event to be dispatched.
5593     * @return True if the event was handled by the view, false otherwise.
5594     */
5595    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
5596        return false;
5597    }
5598
5599    /**
5600     * Dispatch a generic motion event to the currently focused view.
5601     * <p>
5602     * Do not call this method directly.
5603     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
5604     * </p>
5605     *
5606     * @param event The motion event to be dispatched.
5607     * @return True if the event was handled by the view, false otherwise.
5608     */
5609    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
5610        return false;
5611    }
5612
5613    /**
5614     * Dispatch a pointer event.
5615     * <p>
5616     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
5617     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
5618     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
5619     * and should not be expected to handle other pointing device features.
5620     * </p>
5621     *
5622     * @param event The motion event to be dispatched.
5623     * @return True if the event was handled by the view, false otherwise.
5624     * @hide
5625     */
5626    public final boolean dispatchPointerEvent(MotionEvent event) {
5627        if (event.isTouchEvent()) {
5628            return dispatchTouchEvent(event);
5629        } else {
5630            return dispatchGenericMotionEvent(event);
5631        }
5632    }
5633
5634    /**
5635     * Called when the window containing this view gains or loses window focus.
5636     * ViewGroups should override to route to their children.
5637     *
5638     * @param hasFocus True if the window containing this view now has focus,
5639     *        false otherwise.
5640     */
5641    public void dispatchWindowFocusChanged(boolean hasFocus) {
5642        onWindowFocusChanged(hasFocus);
5643    }
5644
5645    /**
5646     * Called when the window containing this view gains or loses focus.  Note
5647     * that this is separate from view focus: to receive key events, both
5648     * your view and its window must have focus.  If a window is displayed
5649     * on top of yours that takes input focus, then your own window will lose
5650     * focus but the view focus will remain unchanged.
5651     *
5652     * @param hasWindowFocus True if the window containing this view now has
5653     *        focus, false otherwise.
5654     */
5655    public void onWindowFocusChanged(boolean hasWindowFocus) {
5656        InputMethodManager imm = InputMethodManager.peekInstance();
5657        if (!hasWindowFocus) {
5658            if (isPressed()) {
5659                setPressed(false);
5660            }
5661            if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
5662                imm.focusOut(this);
5663            }
5664            removeLongPressCallback();
5665            removeTapCallback();
5666            onFocusLost();
5667        } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
5668            imm.focusIn(this);
5669        }
5670        refreshDrawableState();
5671    }
5672
5673    /**
5674     * Returns true if this view is in a window that currently has window focus.
5675     * Note that this is not the same as the view itself having focus.
5676     *
5677     * @return True if this view is in a window that currently has window focus.
5678     */
5679    public boolean hasWindowFocus() {
5680        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
5681    }
5682
5683    /**
5684     * Dispatch a view visibility change down the view hierarchy.
5685     * ViewGroups should override to route to their children.
5686     * @param changedView The view whose visibility changed. Could be 'this' or
5687     * an ancestor view.
5688     * @param visibility The new visibility of changedView: {@link #VISIBLE},
5689     * {@link #INVISIBLE} or {@link #GONE}.
5690     */
5691    protected void dispatchVisibilityChanged(View changedView, int visibility) {
5692        onVisibilityChanged(changedView, visibility);
5693    }
5694
5695    /**
5696     * Called when the visibility of the view or an ancestor of the view is changed.
5697     * @param changedView The view whose visibility changed. Could be 'this' or
5698     * an ancestor view.
5699     * @param visibility The new visibility of changedView: {@link #VISIBLE},
5700     * {@link #INVISIBLE} or {@link #GONE}.
5701     */
5702    protected void onVisibilityChanged(View changedView, int visibility) {
5703        if (visibility == VISIBLE) {
5704            if (mAttachInfo != null) {
5705                initialAwakenScrollBars();
5706            } else {
5707                mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
5708            }
5709        }
5710    }
5711
5712    /**
5713     * Dispatch a hint about whether this view is displayed. For instance, when
5714     * a View moves out of the screen, it might receives a display hint indicating
5715     * the view is not displayed. Applications should not <em>rely</em> on this hint
5716     * as there is no guarantee that they will receive one.
5717     *
5718     * @param hint A hint about whether or not this view is displayed:
5719     * {@link #VISIBLE} or {@link #INVISIBLE}.
5720     */
5721    public void dispatchDisplayHint(int hint) {
5722        onDisplayHint(hint);
5723    }
5724
5725    /**
5726     * Gives this view a hint about whether is displayed or not. For instance, when
5727     * a View moves out of the screen, it might receives a display hint indicating
5728     * the view is not displayed. Applications should not <em>rely</em> on this hint
5729     * as there is no guarantee that they will receive one.
5730     *
5731     * @param hint A hint about whether or not this view is displayed:
5732     * {@link #VISIBLE} or {@link #INVISIBLE}.
5733     */
5734    protected void onDisplayHint(int hint) {
5735    }
5736
5737    /**
5738     * Dispatch a window visibility change down the view hierarchy.
5739     * ViewGroups should override to route to their children.
5740     *
5741     * @param visibility The new visibility of the window.
5742     *
5743     * @see #onWindowVisibilityChanged(int)
5744     */
5745    public void dispatchWindowVisibilityChanged(int visibility) {
5746        onWindowVisibilityChanged(visibility);
5747    }
5748
5749    /**
5750     * Called when the window containing has change its visibility
5751     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
5752     * that this tells you whether or not your window is being made visible
5753     * to the window manager; this does <em>not</em> tell you whether or not
5754     * your window is obscured by other windows on the screen, even if it
5755     * is itself visible.
5756     *
5757     * @param visibility The new visibility of the window.
5758     */
5759    protected void onWindowVisibilityChanged(int visibility) {
5760        if (visibility == VISIBLE) {
5761            initialAwakenScrollBars();
5762        }
5763    }
5764
5765    /**
5766     * Returns the current visibility of the window this view is attached to
5767     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
5768     *
5769     * @return Returns the current visibility of the view's window.
5770     */
5771    public int getWindowVisibility() {
5772        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
5773    }
5774
5775    /**
5776     * Retrieve the overall visible display size in which the window this view is
5777     * attached to has been positioned in.  This takes into account screen
5778     * decorations above the window, for both cases where the window itself
5779     * is being position inside of them or the window is being placed under
5780     * then and covered insets are used for the window to position its content
5781     * inside.  In effect, this tells you the available area where content can
5782     * be placed and remain visible to users.
5783     *
5784     * <p>This function requires an IPC back to the window manager to retrieve
5785     * the requested information, so should not be used in performance critical
5786     * code like drawing.
5787     *
5788     * @param outRect Filled in with the visible display frame.  If the view
5789     * is not attached to a window, this is simply the raw display size.
5790     */
5791    public void getWindowVisibleDisplayFrame(Rect outRect) {
5792        if (mAttachInfo != null) {
5793            try {
5794                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
5795            } catch (RemoteException e) {
5796                return;
5797            }
5798            // XXX This is really broken, and probably all needs to be done
5799            // in the window manager, and we need to know more about whether
5800            // we want the area behind or in front of the IME.
5801            final Rect insets = mAttachInfo.mVisibleInsets;
5802            outRect.left += insets.left;
5803            outRect.top += insets.top;
5804            outRect.right -= insets.right;
5805            outRect.bottom -= insets.bottom;
5806            return;
5807        }
5808        Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
5809        d.getRectSize(outRect);
5810    }
5811
5812    /**
5813     * Dispatch a notification about a resource configuration change down
5814     * the view hierarchy.
5815     * ViewGroups should override to route to their children.
5816     *
5817     * @param newConfig The new resource configuration.
5818     *
5819     * @see #onConfigurationChanged(android.content.res.Configuration)
5820     */
5821    public void dispatchConfigurationChanged(Configuration newConfig) {
5822        onConfigurationChanged(newConfig);
5823    }
5824
5825    /**
5826     * Called when the current configuration of the resources being used
5827     * by the application have changed.  You can use this to decide when
5828     * to reload resources that can changed based on orientation and other
5829     * configuration characterstics.  You only need to use this if you are
5830     * not relying on the normal {@link android.app.Activity} mechanism of
5831     * recreating the activity instance upon a configuration change.
5832     *
5833     * @param newConfig The new resource configuration.
5834     */
5835    protected void onConfigurationChanged(Configuration newConfig) {
5836    }
5837
5838    /**
5839     * Private function to aggregate all per-view attributes in to the view
5840     * root.
5841     */
5842    void dispatchCollectViewAttributes(int visibility) {
5843        performCollectViewAttributes(visibility);
5844    }
5845
5846    void performCollectViewAttributes(int visibility) {
5847        if ((visibility & VISIBILITY_MASK) == VISIBLE && mAttachInfo != null) {
5848            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
5849                mAttachInfo.mKeepScreenOn = true;
5850            }
5851            mAttachInfo.mSystemUiVisibility |= mSystemUiVisibility;
5852            if (mOnSystemUiVisibilityChangeListener != null) {
5853                mAttachInfo.mHasSystemUiListeners = true;
5854            }
5855        }
5856    }
5857
5858    void needGlobalAttributesUpdate(boolean force) {
5859        final AttachInfo ai = mAttachInfo;
5860        if (ai != null) {
5861            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
5862                    || ai.mHasSystemUiListeners) {
5863                ai.mRecomputeGlobalAttributes = true;
5864            }
5865        }
5866    }
5867
5868    /**
5869     * Returns whether the device is currently in touch mode.  Touch mode is entered
5870     * once the user begins interacting with the device by touch, and affects various
5871     * things like whether focus is always visible to the user.
5872     *
5873     * @return Whether the device is in touch mode.
5874     */
5875    @ViewDebug.ExportedProperty
5876    public boolean isInTouchMode() {
5877        if (mAttachInfo != null) {
5878            return mAttachInfo.mInTouchMode;
5879        } else {
5880            return ViewRootImpl.isInTouchMode();
5881        }
5882    }
5883
5884    /**
5885     * Returns the context the view is running in, through which it can
5886     * access the current theme, resources, etc.
5887     *
5888     * @return The view's Context.
5889     */
5890    @ViewDebug.CapturedViewProperty
5891    public final Context getContext() {
5892        return mContext;
5893    }
5894
5895    /**
5896     * Handle a key event before it is processed by any input method
5897     * associated with the view hierarchy.  This can be used to intercept
5898     * key events in special situations before the IME consumes them; a
5899     * typical example would be handling the BACK key to update the application's
5900     * UI instead of allowing the IME to see it and close itself.
5901     *
5902     * @param keyCode The value in event.getKeyCode().
5903     * @param event Description of the key event.
5904     * @return If you handled the event, return true. If you want to allow the
5905     *         event to be handled by the next receiver, return false.
5906     */
5907    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
5908        return false;
5909    }
5910
5911    /**
5912     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
5913     * KeyEvent.Callback.onKeyDown()}: perform press of the view
5914     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
5915     * is released, if the view is enabled and clickable.
5916     *
5917     * @param keyCode A key code that represents the button pressed, from
5918     *                {@link android.view.KeyEvent}.
5919     * @param event   The KeyEvent object that defines the button action.
5920     */
5921    public boolean onKeyDown(int keyCode, KeyEvent event) {
5922        boolean result = false;
5923
5924        switch (keyCode) {
5925            case KeyEvent.KEYCODE_DPAD_CENTER:
5926            case KeyEvent.KEYCODE_ENTER: {
5927                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
5928                    return true;
5929                }
5930                // Long clickable items don't necessarily have to be clickable
5931                if (((mViewFlags & CLICKABLE) == CLICKABLE ||
5932                        (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
5933                        (event.getRepeatCount() == 0)) {
5934                    setPressed(true);
5935                    checkForLongClick(0);
5936                    return true;
5937                }
5938                break;
5939            }
5940        }
5941        return result;
5942    }
5943
5944    /**
5945     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
5946     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
5947     * the event).
5948     */
5949    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
5950        return false;
5951    }
5952
5953    /**
5954     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
5955     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
5956     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
5957     * {@link KeyEvent#KEYCODE_ENTER} is released.
5958     *
5959     * @param keyCode A key code that represents the button pressed, from
5960     *                {@link android.view.KeyEvent}.
5961     * @param event   The KeyEvent object that defines the button action.
5962     */
5963    public boolean onKeyUp(int keyCode, KeyEvent event) {
5964        boolean result = false;
5965
5966        switch (keyCode) {
5967            case KeyEvent.KEYCODE_DPAD_CENTER:
5968            case KeyEvent.KEYCODE_ENTER: {
5969                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
5970                    return true;
5971                }
5972                if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
5973                    setPressed(false);
5974
5975                    if (!mHasPerformedLongPress) {
5976                        // This is a tap, so remove the longpress check
5977                        removeLongPressCallback();
5978
5979                        result = performClick();
5980                    }
5981                }
5982                break;
5983            }
5984        }
5985        return result;
5986    }
5987
5988    /**
5989     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
5990     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
5991     * the event).
5992     *
5993     * @param keyCode     A key code that represents the button pressed, from
5994     *                    {@link android.view.KeyEvent}.
5995     * @param repeatCount The number of times the action was made.
5996     * @param event       The KeyEvent object that defines the button action.
5997     */
5998    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
5999        return false;
6000    }
6001
6002    /**
6003     * Called on the focused view when a key shortcut event is not handled.
6004     * Override this method to implement local key shortcuts for the View.
6005     * Key shortcuts can also be implemented by setting the
6006     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
6007     *
6008     * @param keyCode The value in event.getKeyCode().
6009     * @param event Description of the key event.
6010     * @return If you handled the event, return true. If you want to allow the
6011     *         event to be handled by the next receiver, return false.
6012     */
6013    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
6014        return false;
6015    }
6016
6017    /**
6018     * Check whether the called view is a text editor, in which case it
6019     * would make sense to automatically display a soft input window for
6020     * it.  Subclasses should override this if they implement
6021     * {@link #onCreateInputConnection(EditorInfo)} to return true if
6022     * a call on that method would return a non-null InputConnection, and
6023     * they are really a first-class editor that the user would normally
6024     * start typing on when the go into a window containing your view.
6025     *
6026     * <p>The default implementation always returns false.  This does
6027     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
6028     * will not be called or the user can not otherwise perform edits on your
6029     * view; it is just a hint to the system that this is not the primary
6030     * purpose of this view.
6031     *
6032     * @return Returns true if this view is a text editor, else false.
6033     */
6034    public boolean onCheckIsTextEditor() {
6035        return false;
6036    }
6037
6038    /**
6039     * Create a new InputConnection for an InputMethod to interact
6040     * with the view.  The default implementation returns null, since it doesn't
6041     * support input methods.  You can override this to implement such support.
6042     * This is only needed for views that take focus and text input.
6043     *
6044     * <p>When implementing this, you probably also want to implement
6045     * {@link #onCheckIsTextEditor()} to indicate you will return a
6046     * non-null InputConnection.
6047     *
6048     * @param outAttrs Fill in with attribute information about the connection.
6049     */
6050    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
6051        return null;
6052    }
6053
6054    /**
6055     * Called by the {@link android.view.inputmethod.InputMethodManager}
6056     * when a view who is not the current
6057     * input connection target is trying to make a call on the manager.  The
6058     * default implementation returns false; you can override this to return
6059     * true for certain views if you are performing InputConnection proxying
6060     * to them.
6061     * @param view The View that is making the InputMethodManager call.
6062     * @return Return true to allow the call, false to reject.
6063     */
6064    public boolean checkInputConnectionProxy(View view) {
6065        return false;
6066    }
6067
6068    /**
6069     * Show the context menu for this view. It is not safe to hold on to the
6070     * menu after returning from this method.
6071     *
6072     * You should normally not overload this method. Overload
6073     * {@link #onCreateContextMenu(ContextMenu)} or define an
6074     * {@link OnCreateContextMenuListener} to add items to the context menu.
6075     *
6076     * @param menu The context menu to populate
6077     */
6078    public void createContextMenu(ContextMenu menu) {
6079        ContextMenuInfo menuInfo = getContextMenuInfo();
6080
6081        // Sets the current menu info so all items added to menu will have
6082        // my extra info set.
6083        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
6084
6085        onCreateContextMenu(menu);
6086        if (mOnCreateContextMenuListener != null) {
6087            mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
6088        }
6089
6090        // Clear the extra information so subsequent items that aren't mine don't
6091        // have my extra info.
6092        ((MenuBuilder)menu).setCurrentMenuInfo(null);
6093
6094        if (mParent != null) {
6095            mParent.createContextMenu(menu);
6096        }
6097    }
6098
6099    /**
6100     * Views should implement this if they have extra information to associate
6101     * with the context menu. The return result is supplied as a parameter to
6102     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
6103     * callback.
6104     *
6105     * @return Extra information about the item for which the context menu
6106     *         should be shown. This information will vary across different
6107     *         subclasses of View.
6108     */
6109    protected ContextMenuInfo getContextMenuInfo() {
6110        return null;
6111    }
6112
6113    /**
6114     * Views should implement this if the view itself is going to add items to
6115     * the context menu.
6116     *
6117     * @param menu the context menu to populate
6118     */
6119    protected void onCreateContextMenu(ContextMenu menu) {
6120    }
6121
6122    /**
6123     * Implement this method to handle trackball motion events.  The
6124     * <em>relative</em> movement of the trackball since the last event
6125     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
6126     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
6127     * that a movement of 1 corresponds to the user pressing one DPAD key (so
6128     * they will often be fractional values, representing the more fine-grained
6129     * movement information available from a trackball).
6130     *
6131     * @param event The motion event.
6132     * @return True if the event was handled, false otherwise.
6133     */
6134    public boolean onTrackballEvent(MotionEvent event) {
6135        return false;
6136    }
6137
6138    /**
6139     * Implement this method to handle generic motion events.
6140     * <p>
6141     * Generic motion events describe joystick movements, mouse hovers, track pad
6142     * touches, scroll wheel movements and other input events.  The
6143     * {@link MotionEvent#getSource() source} of the motion event specifies
6144     * the class of input that was received.  Implementations of this method
6145     * must examine the bits in the source before processing the event.
6146     * The following code example shows how this is done.
6147     * </p><p>
6148     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
6149     * are delivered to the view under the pointer.  All other generic motion events are
6150     * delivered to the focused view.
6151     * </p>
6152     * <code>
6153     * public boolean onGenericMotionEvent(MotionEvent event) {
6154     *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
6155     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
6156     *             // process the joystick movement...
6157     *             return true;
6158     *         }
6159     *     }
6160     *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_POINTER) != 0) {
6161     *         switch (event.getAction()) {
6162     *             case MotionEvent.ACTION_HOVER_MOVE:
6163     *                 // process the mouse hover movement...
6164     *                 return true;
6165     *             case MotionEvent.ACTION_SCROLL:
6166     *                 // process the scroll wheel movement...
6167     *                 return true;
6168     *         }
6169     *     }
6170     *     return super.onGenericMotionEvent(event);
6171     * }
6172     * </code>
6173     *
6174     * @param event The generic motion event being processed.
6175     * @return True if the event was handled, false otherwise.
6176     */
6177    public boolean onGenericMotionEvent(MotionEvent event) {
6178        return false;
6179    }
6180
6181    /**
6182     * Implement this method to handle hover events.
6183     * <p>
6184     * This method is called whenever a pointer is hovering into, over, or out of the
6185     * bounds of a view and the view is not currently being touched.
6186     * Hover events are represented as pointer events with action
6187     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
6188     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
6189     * </p>
6190     * <ul>
6191     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
6192     * when the pointer enters the bounds of the view.</li>
6193     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
6194     * when the pointer has already entered the bounds of the view and has moved.</li>
6195     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
6196     * when the pointer has exited the bounds of the view or when the pointer is
6197     * about to go down due to a button click, tap, or similar user action that
6198     * causes the view to be touched.</li>
6199     * </ul>
6200     * <p>
6201     * The view should implement this method to return true to indicate that it is
6202     * handling the hover event, such as by changing its drawable state.
6203     * </p><p>
6204     * The default implementation calls {@link #setHovered} to update the hovered state
6205     * of the view when a hover enter or hover exit event is received, if the view
6206     * is enabled and is clickable.  The default implementation also sends hover
6207     * accessibility events.
6208     * </p>
6209     *
6210     * @param event The motion event that describes the hover.
6211     * @return True if the view handled the hover event.
6212     *
6213     * @see #isHovered
6214     * @see #setHovered
6215     * @see #onHoverChanged
6216     */
6217    public boolean onHoverEvent(MotionEvent event) {
6218        // The root view may receive hover (or touch) events that are outside the bounds of
6219        // the window.  This code ensures that we only send accessibility events for
6220        // hovers that are actually within the bounds of the root view.
6221        final int action = event.getAction();
6222        if (!mSendingHoverAccessibilityEvents) {
6223            if ((action == MotionEvent.ACTION_HOVER_ENTER
6224                    || action == MotionEvent.ACTION_HOVER_MOVE)
6225                    && !hasHoveredChild()
6226                    && pointInView(event.getX(), event.getY())) {
6227                mSendingHoverAccessibilityEvents = true;
6228                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
6229            }
6230        } else {
6231            if (action == MotionEvent.ACTION_HOVER_EXIT
6232                    || (action == MotionEvent.ACTION_HOVER_MOVE
6233                            && !pointInView(event.getX(), event.getY()))) {
6234                mSendingHoverAccessibilityEvents = false;
6235                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
6236            }
6237        }
6238
6239        if (isHoverable()) {
6240            switch (action) {
6241                case MotionEvent.ACTION_HOVER_ENTER:
6242                    setHovered(true);
6243                    break;
6244                case MotionEvent.ACTION_HOVER_EXIT:
6245                    setHovered(false);
6246                    break;
6247            }
6248
6249            // Dispatch the event to onGenericMotionEvent before returning true.
6250            // This is to provide compatibility with existing applications that
6251            // handled HOVER_MOVE events in onGenericMotionEvent and that would
6252            // break because of the new default handling for hoverable views
6253            // in onHoverEvent.
6254            // Note that onGenericMotionEvent will be called by default when
6255            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
6256            dispatchGenericMotionEventInternal(event);
6257            return true;
6258        }
6259        return false;
6260    }
6261
6262    /**
6263     * Returns true if the view should handle {@link #onHoverEvent}
6264     * by calling {@link #setHovered} to change its hovered state.
6265     *
6266     * @return True if the view is hoverable.
6267     */
6268    private boolean isHoverable() {
6269        final int viewFlags = mViewFlags;
6270        //noinspection SimplifiableIfStatement
6271        if ((viewFlags & ENABLED_MASK) == DISABLED) {
6272            return false;
6273        }
6274
6275        return (viewFlags & CLICKABLE) == CLICKABLE
6276                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
6277    }
6278
6279    /**
6280     * Returns true if the view is currently hovered.
6281     *
6282     * @return True if the view is currently hovered.
6283     *
6284     * @see #setHovered
6285     * @see #onHoverChanged
6286     */
6287    @ViewDebug.ExportedProperty
6288    public boolean isHovered() {
6289        return (mPrivateFlags & HOVERED) != 0;
6290    }
6291
6292    /**
6293     * Sets whether the view is currently hovered.
6294     * <p>
6295     * Calling this method also changes the drawable state of the view.  This
6296     * enables the view to react to hover by using different drawable resources
6297     * to change its appearance.
6298     * </p><p>
6299     * The {@link #onHoverChanged} method is called when the hovered state changes.
6300     * </p>
6301     *
6302     * @param hovered True if the view is hovered.
6303     *
6304     * @see #isHovered
6305     * @see #onHoverChanged
6306     */
6307    public void setHovered(boolean hovered) {
6308        if (hovered) {
6309            if ((mPrivateFlags & HOVERED) == 0) {
6310                mPrivateFlags |= HOVERED;
6311                refreshDrawableState();
6312                onHoverChanged(true);
6313            }
6314        } else {
6315            if ((mPrivateFlags & HOVERED) != 0) {
6316                mPrivateFlags &= ~HOVERED;
6317                refreshDrawableState();
6318                onHoverChanged(false);
6319            }
6320        }
6321    }
6322
6323    /**
6324     * Implement this method to handle hover state changes.
6325     * <p>
6326     * This method is called whenever the hover state changes as a result of a
6327     * call to {@link #setHovered}.
6328     * </p>
6329     *
6330     * @param hovered The current hover state, as returned by {@link #isHovered}.
6331     *
6332     * @see #isHovered
6333     * @see #setHovered
6334     */
6335    public void onHoverChanged(boolean hovered) {
6336    }
6337
6338    /**
6339     * Implement this method to handle touch screen motion events.
6340     *
6341     * @param event The motion event.
6342     * @return True if the event was handled, false otherwise.
6343     */
6344    public boolean onTouchEvent(MotionEvent event) {
6345        final int viewFlags = mViewFlags;
6346
6347        if ((viewFlags & ENABLED_MASK) == DISABLED) {
6348            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PRESSED) != 0) {
6349                mPrivateFlags &= ~PRESSED;
6350                refreshDrawableState();
6351            }
6352            // A disabled view that is clickable still consumes the touch
6353            // events, it just doesn't respond to them.
6354            return (((viewFlags & CLICKABLE) == CLICKABLE ||
6355                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
6356        }
6357
6358        if (mTouchDelegate != null) {
6359            if (mTouchDelegate.onTouchEvent(event)) {
6360                return true;
6361            }
6362        }
6363
6364        if (((viewFlags & CLICKABLE) == CLICKABLE ||
6365                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
6366            switch (event.getAction()) {
6367                case MotionEvent.ACTION_UP:
6368                    boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
6369                    if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
6370                        // take focus if we don't have it already and we should in
6371                        // touch mode.
6372                        boolean focusTaken = false;
6373                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
6374                            focusTaken = requestFocus();
6375                        }
6376
6377                        if (prepressed) {
6378                            // The button is being released before we actually
6379                            // showed it as pressed.  Make it show the pressed
6380                            // state now (before scheduling the click) to ensure
6381                            // the user sees it.
6382                            mPrivateFlags |= PRESSED;
6383                            refreshDrawableState();
6384                       }
6385
6386                        if (!mHasPerformedLongPress) {
6387                            // This is a tap, so remove the longpress check
6388                            removeLongPressCallback();
6389
6390                            // Only perform take click actions if we were in the pressed state
6391                            if (!focusTaken) {
6392                                // Use a Runnable and post this rather than calling
6393                                // performClick directly. This lets other visual state
6394                                // of the view update before click actions start.
6395                                if (mPerformClick == null) {
6396                                    mPerformClick = new PerformClick();
6397                                }
6398                                if (!post(mPerformClick)) {
6399                                    performClick();
6400                                }
6401                            }
6402                        }
6403
6404                        if (mUnsetPressedState == null) {
6405                            mUnsetPressedState = new UnsetPressedState();
6406                        }
6407
6408                        if (prepressed) {
6409                            postDelayed(mUnsetPressedState,
6410                                    ViewConfiguration.getPressedStateDuration());
6411                        } else if (!post(mUnsetPressedState)) {
6412                            // If the post failed, unpress right now
6413                            mUnsetPressedState.run();
6414                        }
6415                        removeTapCallback();
6416                    }
6417                    break;
6418
6419                case MotionEvent.ACTION_DOWN:
6420                    mHasPerformedLongPress = false;
6421
6422                    if (performButtonActionOnTouchDown(event)) {
6423                        break;
6424                    }
6425
6426                    // Walk up the hierarchy to determine if we're inside a scrolling container.
6427                    boolean isInScrollingContainer = isInScrollingContainer();
6428
6429                    // For views inside a scrolling container, delay the pressed feedback for
6430                    // a short period in case this is a scroll.
6431                    if (isInScrollingContainer) {
6432                        mPrivateFlags |= PREPRESSED;
6433                        if (mPendingCheckForTap == null) {
6434                            mPendingCheckForTap = new CheckForTap();
6435                        }
6436                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
6437                    } else {
6438                        // Not inside a scrolling container, so show the feedback right away
6439                        mPrivateFlags |= PRESSED;
6440                        refreshDrawableState();
6441                        checkForLongClick(0);
6442                    }
6443                    break;
6444
6445                case MotionEvent.ACTION_CANCEL:
6446                    mPrivateFlags &= ~PRESSED;
6447                    refreshDrawableState();
6448                    removeTapCallback();
6449                    break;
6450
6451                case MotionEvent.ACTION_MOVE:
6452                    final int x = (int) event.getX();
6453                    final int y = (int) event.getY();
6454
6455                    // Be lenient about moving outside of buttons
6456                    if (!pointInView(x, y, mTouchSlop)) {
6457                        // Outside button
6458                        removeTapCallback();
6459                        if ((mPrivateFlags & PRESSED) != 0) {
6460                            // Remove any future long press/tap checks
6461                            removeLongPressCallback();
6462
6463                            // Need to switch from pressed to not pressed
6464                            mPrivateFlags &= ~PRESSED;
6465                            refreshDrawableState();
6466                        }
6467                    }
6468                    break;
6469            }
6470            return true;
6471        }
6472
6473        return false;
6474    }
6475
6476    /**
6477     * @hide
6478     */
6479    public boolean isInScrollingContainer() {
6480        ViewParent p = getParent();
6481        while (p != null && p instanceof ViewGroup) {
6482            if (((ViewGroup) p).shouldDelayChildPressedState()) {
6483                return true;
6484            }
6485            p = p.getParent();
6486        }
6487        return false;
6488    }
6489
6490    /**
6491     * Remove the longpress detection timer.
6492     */
6493    private void removeLongPressCallback() {
6494        if (mPendingCheckForLongPress != null) {
6495          removeCallbacks(mPendingCheckForLongPress);
6496        }
6497    }
6498
6499    /**
6500     * Remove the pending click action
6501     */
6502    private void removePerformClickCallback() {
6503        if (mPerformClick != null) {
6504            removeCallbacks(mPerformClick);
6505        }
6506    }
6507
6508    /**
6509     * Remove the prepress detection timer.
6510     */
6511    private void removeUnsetPressCallback() {
6512        if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
6513            setPressed(false);
6514            removeCallbacks(mUnsetPressedState);
6515        }
6516    }
6517
6518    /**
6519     * Remove the tap detection timer.
6520     */
6521    private void removeTapCallback() {
6522        if (mPendingCheckForTap != null) {
6523            mPrivateFlags &= ~PREPRESSED;
6524            removeCallbacks(mPendingCheckForTap);
6525        }
6526    }
6527
6528    /**
6529     * Cancels a pending long press.  Your subclass can use this if you
6530     * want the context menu to come up if the user presses and holds
6531     * at the same place, but you don't want it to come up if they press
6532     * and then move around enough to cause scrolling.
6533     */
6534    public void cancelLongPress() {
6535        removeLongPressCallback();
6536
6537        /*
6538         * The prepressed state handled by the tap callback is a display
6539         * construct, but the tap callback will post a long press callback
6540         * less its own timeout. Remove it here.
6541         */
6542        removeTapCallback();
6543    }
6544
6545    /**
6546     * Remove the pending callback for sending a
6547     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
6548     */
6549    private void removeSendViewScrolledAccessibilityEventCallback() {
6550        if (mSendViewScrolledAccessibilityEvent != null) {
6551            removeCallbacks(mSendViewScrolledAccessibilityEvent);
6552        }
6553    }
6554
6555    /**
6556     * Sets the TouchDelegate for this View.
6557     */
6558    public void setTouchDelegate(TouchDelegate delegate) {
6559        mTouchDelegate = delegate;
6560    }
6561
6562    /**
6563     * Gets the TouchDelegate for this View.
6564     */
6565    public TouchDelegate getTouchDelegate() {
6566        return mTouchDelegate;
6567    }
6568
6569    /**
6570     * Set flags controlling behavior of this view.
6571     *
6572     * @param flags Constant indicating the value which should be set
6573     * @param mask Constant indicating the bit range that should be changed
6574     */
6575    void setFlags(int flags, int mask) {
6576        int old = mViewFlags;
6577        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
6578
6579        int changed = mViewFlags ^ old;
6580        if (changed == 0) {
6581            return;
6582        }
6583        int privateFlags = mPrivateFlags;
6584
6585        /* Check if the FOCUSABLE bit has changed */
6586        if (((changed & FOCUSABLE_MASK) != 0) &&
6587                ((privateFlags & HAS_BOUNDS) !=0)) {
6588            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
6589                    && ((privateFlags & FOCUSED) != 0)) {
6590                /* Give up focus if we are no longer focusable */
6591                clearFocus();
6592            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
6593                    && ((privateFlags & FOCUSED) == 0)) {
6594                /*
6595                 * Tell the view system that we are now available to take focus
6596                 * if no one else already has it.
6597                 */
6598                if (mParent != null) mParent.focusableViewAvailable(this);
6599            }
6600        }
6601
6602        if ((flags & VISIBILITY_MASK) == VISIBLE) {
6603            if ((changed & VISIBILITY_MASK) != 0) {
6604                /*
6605                 * If this view is becoming visible, invalidate it in case it changed while
6606                 * it was not visible. Marking it drawn ensures that the invalidation will
6607                 * go through.
6608                 */
6609                mPrivateFlags |= DRAWN;
6610                invalidate(true);
6611
6612                needGlobalAttributesUpdate(true);
6613
6614                // a view becoming visible is worth notifying the parent
6615                // about in case nothing has focus.  even if this specific view
6616                // isn't focusable, it may contain something that is, so let
6617                // the root view try to give this focus if nothing else does.
6618                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
6619                    mParent.focusableViewAvailable(this);
6620                }
6621            }
6622        }
6623
6624        /* Check if the GONE bit has changed */
6625        if ((changed & GONE) != 0) {
6626            needGlobalAttributesUpdate(false);
6627            requestLayout();
6628
6629            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
6630                if (hasFocus()) clearFocus();
6631                destroyDrawingCache();
6632                if (mParent instanceof View) {
6633                    // GONE views noop invalidation, so invalidate the parent
6634                    ((View) mParent).invalidate(true);
6635                }
6636                // Mark the view drawn to ensure that it gets invalidated properly the next
6637                // time it is visible and gets invalidated
6638                mPrivateFlags |= DRAWN;
6639            }
6640            if (mAttachInfo != null) {
6641                mAttachInfo.mViewVisibilityChanged = true;
6642            }
6643        }
6644
6645        /* Check if the VISIBLE bit has changed */
6646        if ((changed & INVISIBLE) != 0) {
6647            needGlobalAttributesUpdate(false);
6648            /*
6649             * If this view is becoming invisible, set the DRAWN flag so that
6650             * the next invalidate() will not be skipped.
6651             */
6652            mPrivateFlags |= DRAWN;
6653
6654            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
6655                // root view becoming invisible shouldn't clear focus
6656                if (getRootView() != this) {
6657                    clearFocus();
6658                }
6659            }
6660            if (mAttachInfo != null) {
6661                mAttachInfo.mViewVisibilityChanged = true;
6662            }
6663        }
6664
6665        if ((changed & VISIBILITY_MASK) != 0) {
6666            if (mParent instanceof ViewGroup) {
6667                ((ViewGroup) mParent).onChildVisibilityChanged(this, (flags & VISIBILITY_MASK));
6668                ((View) mParent).invalidate(true);
6669            } else if (mParent != null) {
6670                mParent.invalidateChild(this, null);
6671            }
6672            dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
6673        }
6674
6675        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
6676            destroyDrawingCache();
6677        }
6678
6679        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
6680            destroyDrawingCache();
6681            mPrivateFlags &= ~DRAWING_CACHE_VALID;
6682            invalidateParentCaches();
6683        }
6684
6685        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
6686            destroyDrawingCache();
6687            mPrivateFlags &= ~DRAWING_CACHE_VALID;
6688        }
6689
6690        if ((changed & DRAW_MASK) != 0) {
6691            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
6692                if (mBGDrawable != null) {
6693                    mPrivateFlags &= ~SKIP_DRAW;
6694                    mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
6695                } else {
6696                    mPrivateFlags |= SKIP_DRAW;
6697                }
6698            } else {
6699                mPrivateFlags &= ~SKIP_DRAW;
6700            }
6701            requestLayout();
6702            invalidate(true);
6703        }
6704
6705        if ((changed & KEEP_SCREEN_ON) != 0) {
6706            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
6707                mParent.recomputeViewAttributes(this);
6708            }
6709        }
6710
6711        if ((changed & LAYOUT_DIRECTION_MASK) != 0) {
6712            requestLayout();
6713        }
6714    }
6715
6716    /**
6717     * Change the view's z order in the tree, so it's on top of other sibling
6718     * views
6719     */
6720    public void bringToFront() {
6721        if (mParent != null) {
6722            mParent.bringChildToFront(this);
6723        }
6724    }
6725
6726    /**
6727     * This is called in response to an internal scroll in this view (i.e., the
6728     * view scrolled its own contents). This is typically as a result of
6729     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
6730     * called.
6731     *
6732     * @param l Current horizontal scroll origin.
6733     * @param t Current vertical scroll origin.
6734     * @param oldl Previous horizontal scroll origin.
6735     * @param oldt Previous vertical scroll origin.
6736     */
6737    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
6738        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6739            postSendViewScrolledAccessibilityEventCallback();
6740        }
6741
6742        mBackgroundSizeChanged = true;
6743
6744        final AttachInfo ai = mAttachInfo;
6745        if (ai != null) {
6746            ai.mViewScrollChanged = true;
6747        }
6748    }
6749
6750    /**
6751     * Interface definition for a callback to be invoked when the layout bounds of a view
6752     * changes due to layout processing.
6753     */
6754    public interface OnLayoutChangeListener {
6755        /**
6756         * Called when the focus state of a view has changed.
6757         *
6758         * @param v The view whose state has changed.
6759         * @param left The new value of the view's left property.
6760         * @param top The new value of the view's top property.
6761         * @param right The new value of the view's right property.
6762         * @param bottom The new value of the view's bottom property.
6763         * @param oldLeft The previous value of the view's left property.
6764         * @param oldTop The previous value of the view's top property.
6765         * @param oldRight The previous value of the view's right property.
6766         * @param oldBottom The previous value of the view's bottom property.
6767         */
6768        void onLayoutChange(View v, int left, int top, int right, int bottom,
6769            int oldLeft, int oldTop, int oldRight, int oldBottom);
6770    }
6771
6772    /**
6773     * This is called during layout when the size of this view has changed. If
6774     * you were just added to the view hierarchy, you're called with the old
6775     * values of 0.
6776     *
6777     * @param w Current width of this view.
6778     * @param h Current height of this view.
6779     * @param oldw Old width of this view.
6780     * @param oldh Old height of this view.
6781     */
6782    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
6783    }
6784
6785    /**
6786     * Called by draw to draw the child views. This may be overridden
6787     * by derived classes to gain control just before its children are drawn
6788     * (but after its own view has been drawn).
6789     * @param canvas the canvas on which to draw the view
6790     */
6791    protected void dispatchDraw(Canvas canvas) {
6792    }
6793
6794    /**
6795     * Gets the parent of this view. Note that the parent is a
6796     * ViewParent and not necessarily a View.
6797     *
6798     * @return Parent of this view.
6799     */
6800    public final ViewParent getParent() {
6801        return mParent;
6802    }
6803
6804    /**
6805     * Set the horizontal scrolled position of your view. This will cause a call to
6806     * {@link #onScrollChanged(int, int, int, int)} and the view will be
6807     * invalidated.
6808     * @param value the x position to scroll to
6809     */
6810    public void setScrollX(int value) {
6811        scrollTo(value, mScrollY);
6812    }
6813
6814    /**
6815     * Set the vertical scrolled position of your view. This will cause a call to
6816     * {@link #onScrollChanged(int, int, int, int)} and the view will be
6817     * invalidated.
6818     * @param value the y position to scroll to
6819     */
6820    public void setScrollY(int value) {
6821        scrollTo(mScrollX, value);
6822    }
6823
6824    /**
6825     * Return the scrolled left position of this view. This is the left edge of
6826     * the displayed part of your view. You do not need to draw any pixels
6827     * farther left, since those are outside of the frame of your view on
6828     * screen.
6829     *
6830     * @return The left edge of the displayed part of your view, in pixels.
6831     */
6832    public final int getScrollX() {
6833        return mScrollX;
6834    }
6835
6836    /**
6837     * Return the scrolled top position of this view. This is the top edge of
6838     * the displayed part of your view. You do not need to draw any pixels above
6839     * it, since those are outside of the frame of your view on screen.
6840     *
6841     * @return The top edge of the displayed part of your view, in pixels.
6842     */
6843    public final int getScrollY() {
6844        return mScrollY;
6845    }
6846
6847    /**
6848     * Return the width of the your view.
6849     *
6850     * @return The width of your view, in pixels.
6851     */
6852    @ViewDebug.ExportedProperty(category = "layout")
6853    public final int getWidth() {
6854        return mRight - mLeft;
6855    }
6856
6857    /**
6858     * Return the height of your view.
6859     *
6860     * @return The height of your view, in pixels.
6861     */
6862    @ViewDebug.ExportedProperty(category = "layout")
6863    public final int getHeight() {
6864        return mBottom - mTop;
6865    }
6866
6867    /**
6868     * Return the visible drawing bounds of your view. Fills in the output
6869     * rectangle with the values from getScrollX(), getScrollY(),
6870     * getWidth(), and getHeight().
6871     *
6872     * @param outRect The (scrolled) drawing bounds of the view.
6873     */
6874    public void getDrawingRect(Rect outRect) {
6875        outRect.left = mScrollX;
6876        outRect.top = mScrollY;
6877        outRect.right = mScrollX + (mRight - mLeft);
6878        outRect.bottom = mScrollY + (mBottom - mTop);
6879    }
6880
6881    /**
6882     * Like {@link #getMeasuredWidthAndState()}, but only returns the
6883     * raw width component (that is the result is masked by
6884     * {@link #MEASURED_SIZE_MASK}).
6885     *
6886     * @return The raw measured width of this view.
6887     */
6888    public final int getMeasuredWidth() {
6889        return mMeasuredWidth & MEASURED_SIZE_MASK;
6890    }
6891
6892    /**
6893     * Return the full width measurement information for this view as computed
6894     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
6895     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
6896     * This should be used during measurement and layout calculations only. Use
6897     * {@link #getWidth()} to see how wide a view is after layout.
6898     *
6899     * @return The measured width of this view as a bit mask.
6900     */
6901    public final int getMeasuredWidthAndState() {
6902        return mMeasuredWidth;
6903    }
6904
6905    /**
6906     * Like {@link #getMeasuredHeightAndState()}, but only returns the
6907     * raw width component (that is the result is masked by
6908     * {@link #MEASURED_SIZE_MASK}).
6909     *
6910     * @return The raw measured height of this view.
6911     */
6912    public final int getMeasuredHeight() {
6913        return mMeasuredHeight & MEASURED_SIZE_MASK;
6914    }
6915
6916    /**
6917     * Return the full height measurement information for this view as computed
6918     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
6919     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
6920     * This should be used during measurement and layout calculations only. Use
6921     * {@link #getHeight()} to see how wide a view is after layout.
6922     *
6923     * @return The measured width of this view as a bit mask.
6924     */
6925    public final int getMeasuredHeightAndState() {
6926        return mMeasuredHeight;
6927    }
6928
6929    /**
6930     * Return only the state bits of {@link #getMeasuredWidthAndState()}
6931     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
6932     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
6933     * and the height component is at the shifted bits
6934     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
6935     */
6936    public final int getMeasuredState() {
6937        return (mMeasuredWidth&MEASURED_STATE_MASK)
6938                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
6939                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
6940    }
6941
6942    /**
6943     * The transform matrix of this view, which is calculated based on the current
6944     * roation, scale, and pivot properties.
6945     *
6946     * @see #getRotation()
6947     * @see #getScaleX()
6948     * @see #getScaleY()
6949     * @see #getPivotX()
6950     * @see #getPivotY()
6951     * @return The current transform matrix for the view
6952     */
6953    public Matrix getMatrix() {
6954        if (mTransformationInfo != null) {
6955            updateMatrix();
6956            return mTransformationInfo.mMatrix;
6957        }
6958        return Matrix.IDENTITY_MATRIX;
6959    }
6960
6961    /**
6962     * Utility function to determine if the value is far enough away from zero to be
6963     * considered non-zero.
6964     * @param value A floating point value to check for zero-ness
6965     * @return whether the passed-in value is far enough away from zero to be considered non-zero
6966     */
6967    private static boolean nonzero(float value) {
6968        return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
6969    }
6970
6971    /**
6972     * Returns true if the transform matrix is the identity matrix.
6973     * Recomputes the matrix if necessary.
6974     *
6975     * @return True if the transform matrix is the identity matrix, false otherwise.
6976     */
6977    final boolean hasIdentityMatrix() {
6978        if (mTransformationInfo != null) {
6979            updateMatrix();
6980            return mTransformationInfo.mMatrixIsIdentity;
6981        }
6982        return true;
6983    }
6984
6985    void ensureTransformationInfo() {
6986        if (mTransformationInfo == null) {
6987            mTransformationInfo = new TransformationInfo();
6988        }
6989    }
6990
6991    /**
6992     * Recomputes the transform matrix if necessary.
6993     */
6994    private void updateMatrix() {
6995        final TransformationInfo info = mTransformationInfo;
6996        if (info == null) {
6997            return;
6998        }
6999        if (info.mMatrixDirty) {
7000            // transform-related properties have changed since the last time someone
7001            // asked for the matrix; recalculate it with the current values
7002
7003            // Figure out if we need to update the pivot point
7004            if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7005                if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
7006                    info.mPrevWidth = mRight - mLeft;
7007                    info.mPrevHeight = mBottom - mTop;
7008                    info.mPivotX = info.mPrevWidth / 2f;
7009                    info.mPivotY = info.mPrevHeight / 2f;
7010                }
7011            }
7012            info.mMatrix.reset();
7013            if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
7014                info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
7015                info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
7016                info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
7017            } else {
7018                if (info.mCamera == null) {
7019                    info.mCamera = new Camera();
7020                    info.matrix3D = new Matrix();
7021                }
7022                info.mCamera.save();
7023                info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
7024                info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
7025                info.mCamera.getMatrix(info.matrix3D);
7026                info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
7027                info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
7028                        info.mPivotY + info.mTranslationY);
7029                info.mMatrix.postConcat(info.matrix3D);
7030                info.mCamera.restore();
7031            }
7032            info.mMatrixDirty = false;
7033            info.mMatrixIsIdentity = info.mMatrix.isIdentity();
7034            info.mInverseMatrixDirty = true;
7035        }
7036    }
7037
7038    /**
7039     * Utility method to retrieve the inverse of the current mMatrix property.
7040     * We cache the matrix to avoid recalculating it when transform properties
7041     * have not changed.
7042     *
7043     * @return The inverse of the current matrix of this view.
7044     */
7045    final Matrix getInverseMatrix() {
7046        final TransformationInfo info = mTransformationInfo;
7047        if (info != null) {
7048            updateMatrix();
7049            if (info.mInverseMatrixDirty) {
7050                if (info.mInverseMatrix == null) {
7051                    info.mInverseMatrix = new Matrix();
7052                }
7053                info.mMatrix.invert(info.mInverseMatrix);
7054                info.mInverseMatrixDirty = false;
7055            }
7056            return info.mInverseMatrix;
7057        }
7058        return Matrix.IDENTITY_MATRIX;
7059    }
7060
7061    /**
7062     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
7063     * views are drawn) from the camera to this view. The camera's distance
7064     * affects 3D transformations, for instance rotations around the X and Y
7065     * axis. If the rotationX or rotationY properties are changed and this view is
7066     * large (more than half the size of the screen), it is recommended to always
7067     * use a camera distance that's greater than the height (X axis rotation) or
7068     * the width (Y axis rotation) of this view.</p>
7069     *
7070     * <p>The distance of the camera from the view plane can have an affect on the
7071     * perspective distortion of the view when it is rotated around the x or y axis.
7072     * For example, a large distance will result in a large viewing angle, and there
7073     * will not be much perspective distortion of the view as it rotates. A short
7074     * distance may cause much more perspective distortion upon rotation, and can
7075     * also result in some drawing artifacts if the rotated view ends up partially
7076     * behind the camera (which is why the recommendation is to use a distance at
7077     * least as far as the size of the view, if the view is to be rotated.)</p>
7078     *
7079     * <p>The distance is expressed in "depth pixels." The default distance depends
7080     * on the screen density. For instance, on a medium density display, the
7081     * default distance is 1280. On a high density display, the default distance
7082     * is 1920.</p>
7083     *
7084     * <p>If you want to specify a distance that leads to visually consistent
7085     * results across various densities, use the following formula:</p>
7086     * <pre>
7087     * float scale = context.getResources().getDisplayMetrics().density;
7088     * view.setCameraDistance(distance * scale);
7089     * </pre>
7090     *
7091     * <p>The density scale factor of a high density display is 1.5,
7092     * and 1920 = 1280 * 1.5.</p>
7093     *
7094     * @param distance The distance in "depth pixels", if negative the opposite
7095     *        value is used
7096     *
7097     * @see #setRotationX(float)
7098     * @see #setRotationY(float)
7099     */
7100    public void setCameraDistance(float distance) {
7101        invalidateParentCaches();
7102        invalidate(false);
7103
7104        ensureTransformationInfo();
7105        final float dpi = mResources.getDisplayMetrics().densityDpi;
7106        final TransformationInfo info = mTransformationInfo;
7107        if (info.mCamera == null) {
7108            info.mCamera = new Camera();
7109            info.matrix3D = new Matrix();
7110        }
7111
7112        info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
7113        info.mMatrixDirty = true;
7114
7115        invalidate(false);
7116    }
7117
7118    /**
7119     * The degrees that the view is rotated around the pivot point.
7120     *
7121     * @see #setRotation(float)
7122     * @see #getPivotX()
7123     * @see #getPivotY()
7124     *
7125     * @return The degrees of rotation.
7126     */
7127    public float getRotation() {
7128        return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
7129    }
7130
7131    /**
7132     * Sets the degrees that the view is rotated around the pivot point. Increasing values
7133     * result in clockwise rotation.
7134     *
7135     * @param rotation The degrees of rotation.
7136     *
7137     * @see #getRotation()
7138     * @see #getPivotX()
7139     * @see #getPivotY()
7140     * @see #setRotationX(float)
7141     * @see #setRotationY(float)
7142     *
7143     * @attr ref android.R.styleable#View_rotation
7144     */
7145    public void setRotation(float rotation) {
7146        ensureTransformationInfo();
7147        final TransformationInfo info = mTransformationInfo;
7148        if (info.mRotation != rotation) {
7149            invalidateParentCaches();
7150            // Double-invalidation is necessary to capture view's old and new areas
7151            invalidate(false);
7152            info.mRotation = rotation;
7153            info.mMatrixDirty = true;
7154            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7155            invalidate(false);
7156        }
7157    }
7158
7159    /**
7160     * The degrees that the view is rotated around the vertical axis through the pivot point.
7161     *
7162     * @see #getPivotX()
7163     * @see #getPivotY()
7164     * @see #setRotationY(float)
7165     *
7166     * @return The degrees of Y rotation.
7167     */
7168    public float getRotationY() {
7169        return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
7170    }
7171
7172    /**
7173     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
7174     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
7175     * down the y axis.
7176     *
7177     * When rotating large views, it is recommended to adjust the camera distance
7178     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
7179     *
7180     * @param rotationY The degrees of Y rotation.
7181     *
7182     * @see #getRotationY()
7183     * @see #getPivotX()
7184     * @see #getPivotY()
7185     * @see #setRotation(float)
7186     * @see #setRotationX(float)
7187     * @see #setCameraDistance(float)
7188     *
7189     * @attr ref android.R.styleable#View_rotationY
7190     */
7191    public void setRotationY(float rotationY) {
7192        ensureTransformationInfo();
7193        final TransformationInfo info = mTransformationInfo;
7194        if (info.mRotationY != rotationY) {
7195            invalidateParentCaches();
7196            // Double-invalidation is necessary to capture view's old and new areas
7197            invalidate(false);
7198            info.mRotationY = rotationY;
7199            info.mMatrixDirty = true;
7200            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7201            invalidate(false);
7202        }
7203    }
7204
7205    /**
7206     * The degrees that the view is rotated around the horizontal axis through the pivot point.
7207     *
7208     * @see #getPivotX()
7209     * @see #getPivotY()
7210     * @see #setRotationX(float)
7211     *
7212     * @return The degrees of X rotation.
7213     */
7214    public float getRotationX() {
7215        return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
7216    }
7217
7218    /**
7219     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
7220     * Increasing values result in clockwise rotation from the viewpoint of looking down the
7221     * x axis.
7222     *
7223     * When rotating large views, it is recommended to adjust the camera distance
7224     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
7225     *
7226     * @param rotationX The degrees of X rotation.
7227     *
7228     * @see #getRotationX()
7229     * @see #getPivotX()
7230     * @see #getPivotY()
7231     * @see #setRotation(float)
7232     * @see #setRotationY(float)
7233     * @see #setCameraDistance(float)
7234     *
7235     * @attr ref android.R.styleable#View_rotationX
7236     */
7237    public void setRotationX(float rotationX) {
7238        ensureTransformationInfo();
7239        final TransformationInfo info = mTransformationInfo;
7240        if (info.mRotationX != rotationX) {
7241            invalidateParentCaches();
7242            // Double-invalidation is necessary to capture view's old and new areas
7243            invalidate(false);
7244            info.mRotationX = rotationX;
7245            info.mMatrixDirty = true;
7246            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7247            invalidate(false);
7248        }
7249    }
7250
7251    /**
7252     * The amount that the view is scaled in x around the pivot point, as a proportion of
7253     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
7254     *
7255     * <p>By default, this is 1.0f.
7256     *
7257     * @see #getPivotX()
7258     * @see #getPivotY()
7259     * @return The scaling factor.
7260     */
7261    public float getScaleX() {
7262        return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
7263    }
7264
7265    /**
7266     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
7267     * the view's unscaled width. A value of 1 means that no scaling is applied.
7268     *
7269     * @param scaleX The scaling factor.
7270     * @see #getPivotX()
7271     * @see #getPivotY()
7272     *
7273     * @attr ref android.R.styleable#View_scaleX
7274     */
7275    public void setScaleX(float scaleX) {
7276        ensureTransformationInfo();
7277        final TransformationInfo info = mTransformationInfo;
7278        if (info.mScaleX != scaleX) {
7279            invalidateParentCaches();
7280            // Double-invalidation is necessary to capture view's old and new areas
7281            invalidate(false);
7282            info.mScaleX = scaleX;
7283            info.mMatrixDirty = true;
7284            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7285            invalidate(false);
7286        }
7287    }
7288
7289    /**
7290     * The amount that the view is scaled in y around the pivot point, as a proportion of
7291     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
7292     *
7293     * <p>By default, this is 1.0f.
7294     *
7295     * @see #getPivotX()
7296     * @see #getPivotY()
7297     * @return The scaling factor.
7298     */
7299    public float getScaleY() {
7300        return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
7301    }
7302
7303    /**
7304     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
7305     * the view's unscaled width. A value of 1 means that no scaling is applied.
7306     *
7307     * @param scaleY The scaling factor.
7308     * @see #getPivotX()
7309     * @see #getPivotY()
7310     *
7311     * @attr ref android.R.styleable#View_scaleY
7312     */
7313    public void setScaleY(float scaleY) {
7314        ensureTransformationInfo();
7315        final TransformationInfo info = mTransformationInfo;
7316        if (info.mScaleY != scaleY) {
7317            invalidateParentCaches();
7318            // Double-invalidation is necessary to capture view's old and new areas
7319            invalidate(false);
7320            info.mScaleY = scaleY;
7321            info.mMatrixDirty = true;
7322            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7323            invalidate(false);
7324        }
7325    }
7326
7327    /**
7328     * The x location of the point around which the view is {@link #setRotation(float) rotated}
7329     * and {@link #setScaleX(float) scaled}.
7330     *
7331     * @see #getRotation()
7332     * @see #getScaleX()
7333     * @see #getScaleY()
7334     * @see #getPivotY()
7335     * @return The x location of the pivot point.
7336     */
7337    public float getPivotX() {
7338        return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
7339    }
7340
7341    /**
7342     * Sets the x location of the point around which the view is
7343     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
7344     * By default, the pivot point is centered on the object.
7345     * Setting this property disables this behavior and causes the view to use only the
7346     * explicitly set pivotX and pivotY values.
7347     *
7348     * @param pivotX The x location of the pivot point.
7349     * @see #getRotation()
7350     * @see #getScaleX()
7351     * @see #getScaleY()
7352     * @see #getPivotY()
7353     *
7354     * @attr ref android.R.styleable#View_transformPivotX
7355     */
7356    public void setPivotX(float pivotX) {
7357        ensureTransformationInfo();
7358        mPrivateFlags |= PIVOT_EXPLICITLY_SET;
7359        final TransformationInfo info = mTransformationInfo;
7360        if (info.mPivotX != pivotX) {
7361            invalidateParentCaches();
7362            // Double-invalidation is necessary to capture view's old and new areas
7363            invalidate(false);
7364            info.mPivotX = pivotX;
7365            info.mMatrixDirty = true;
7366            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7367            invalidate(false);
7368        }
7369    }
7370
7371    /**
7372     * The y location of the point around which the view is {@link #setRotation(float) rotated}
7373     * and {@link #setScaleY(float) scaled}.
7374     *
7375     * @see #getRotation()
7376     * @see #getScaleX()
7377     * @see #getScaleY()
7378     * @see #getPivotY()
7379     * @return The y location of the pivot point.
7380     */
7381    public float getPivotY() {
7382        return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
7383    }
7384
7385    /**
7386     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
7387     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
7388     * Setting this property disables this behavior and causes the view to use only the
7389     * explicitly set pivotX and pivotY values.
7390     *
7391     * @param pivotY The y location of the pivot point.
7392     * @see #getRotation()
7393     * @see #getScaleX()
7394     * @see #getScaleY()
7395     * @see #getPivotY()
7396     *
7397     * @attr ref android.R.styleable#View_transformPivotY
7398     */
7399    public void setPivotY(float pivotY) {
7400        ensureTransformationInfo();
7401        mPrivateFlags |= PIVOT_EXPLICITLY_SET;
7402        final TransformationInfo info = mTransformationInfo;
7403        if (info.mPivotY != pivotY) {
7404            invalidateParentCaches();
7405            // Double-invalidation is necessary to capture view's old and new areas
7406            invalidate(false);
7407            info.mPivotY = pivotY;
7408            info.mMatrixDirty = true;
7409            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7410            invalidate(false);
7411        }
7412    }
7413
7414    /**
7415     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
7416     * completely transparent and 1 means the view is completely opaque.
7417     *
7418     * <p>By default this is 1.0f.
7419     * @return The opacity of the view.
7420     */
7421    public float getAlpha() {
7422        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
7423    }
7424
7425    /**
7426     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
7427     * completely transparent and 1 means the view is completely opaque.</p>
7428     *
7429     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
7430     * responsible for applying the opacity itself. Otherwise, calling this method is
7431     * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
7432     * setting a hardware layer.</p>
7433     *
7434     * @param alpha The opacity of the view.
7435     *
7436     * @see #setLayerType(int, android.graphics.Paint)
7437     *
7438     * @attr ref android.R.styleable#View_alpha
7439     */
7440    public void setAlpha(float alpha) {
7441        ensureTransformationInfo();
7442        mTransformationInfo.mAlpha = alpha;
7443        invalidateParentCaches();
7444        if (onSetAlpha((int) (alpha * 255))) {
7445            mPrivateFlags |= ALPHA_SET;
7446            // subclass is handling alpha - don't optimize rendering cache invalidation
7447            invalidate(true);
7448        } else {
7449            mPrivateFlags &= ~ALPHA_SET;
7450            invalidate(false);
7451        }
7452    }
7453
7454    /**
7455     * Faster version of setAlpha() which performs the same steps except there are
7456     * no calls to invalidate(). The caller of this function should perform proper invalidation
7457     * on the parent and this object. The return value indicates whether the subclass handles
7458     * alpha (the return value for onSetAlpha()).
7459     *
7460     * @param alpha The new value for the alpha property
7461     * @return true if the View subclass handles alpha (the return value for onSetAlpha())
7462     */
7463    boolean setAlphaNoInvalidation(float alpha) {
7464        ensureTransformationInfo();
7465        mTransformationInfo.mAlpha = alpha;
7466        boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
7467        if (subclassHandlesAlpha) {
7468            mPrivateFlags |= ALPHA_SET;
7469        } else {
7470            mPrivateFlags &= ~ALPHA_SET;
7471        }
7472        return subclassHandlesAlpha;
7473    }
7474
7475    /**
7476     * Top position of this view relative to its parent.
7477     *
7478     * @return The top of this view, in pixels.
7479     */
7480    @ViewDebug.CapturedViewProperty
7481    public final int getTop() {
7482        return mTop;
7483    }
7484
7485    /**
7486     * Sets the top position of this view relative to its parent. This method is meant to be called
7487     * by the layout system and should not generally be called otherwise, because the property
7488     * may be changed at any time by the layout.
7489     *
7490     * @param top The top of this view, in pixels.
7491     */
7492    public final void setTop(int top) {
7493        if (top != mTop) {
7494            updateMatrix();
7495            final boolean matrixIsIdentity = mTransformationInfo == null
7496                    || mTransformationInfo.mMatrixIsIdentity;
7497            if (matrixIsIdentity) {
7498                if (mAttachInfo != null) {
7499                    int minTop;
7500                    int yLoc;
7501                    if (top < mTop) {
7502                        minTop = top;
7503                        yLoc = top - mTop;
7504                    } else {
7505                        minTop = mTop;
7506                        yLoc = 0;
7507                    }
7508                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
7509                }
7510            } else {
7511                // Double-invalidation is necessary to capture view's old and new areas
7512                invalidate(true);
7513            }
7514
7515            int width = mRight - mLeft;
7516            int oldHeight = mBottom - mTop;
7517
7518            mTop = top;
7519
7520            onSizeChanged(width, mBottom - mTop, width, oldHeight);
7521
7522            if (!matrixIsIdentity) {
7523                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7524                    // A change in dimension means an auto-centered pivot point changes, too
7525                    mTransformationInfo.mMatrixDirty = true;
7526                }
7527                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7528                invalidate(true);
7529            }
7530            mBackgroundSizeChanged = true;
7531            invalidateParentIfNeeded();
7532        }
7533    }
7534
7535    /**
7536     * Bottom position of this view relative to its parent.
7537     *
7538     * @return The bottom of this view, in pixels.
7539     */
7540    @ViewDebug.CapturedViewProperty
7541    public final int getBottom() {
7542        return mBottom;
7543    }
7544
7545    /**
7546     * True if this view has changed since the last time being drawn.
7547     *
7548     * @return The dirty state of this view.
7549     */
7550    public boolean isDirty() {
7551        return (mPrivateFlags & DIRTY_MASK) != 0;
7552    }
7553
7554    /**
7555     * Sets the bottom position of this view relative to its parent. This method is meant to be
7556     * called by the layout system and should not generally be called otherwise, because the
7557     * property may be changed at any time by the layout.
7558     *
7559     * @param bottom The bottom of this view, in pixels.
7560     */
7561    public final void setBottom(int bottom) {
7562        if (bottom != mBottom) {
7563            updateMatrix();
7564            final boolean matrixIsIdentity = mTransformationInfo == null
7565                    || mTransformationInfo.mMatrixIsIdentity;
7566            if (matrixIsIdentity) {
7567                if (mAttachInfo != null) {
7568                    int maxBottom;
7569                    if (bottom < mBottom) {
7570                        maxBottom = mBottom;
7571                    } else {
7572                        maxBottom = bottom;
7573                    }
7574                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
7575                }
7576            } else {
7577                // Double-invalidation is necessary to capture view's old and new areas
7578                invalidate(true);
7579            }
7580
7581            int width = mRight - mLeft;
7582            int oldHeight = mBottom - mTop;
7583
7584            mBottom = bottom;
7585
7586            onSizeChanged(width, mBottom - mTop, width, oldHeight);
7587
7588            if (!matrixIsIdentity) {
7589                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7590                    // A change in dimension means an auto-centered pivot point changes, too
7591                    mTransformationInfo.mMatrixDirty = true;
7592                }
7593                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7594                invalidate(true);
7595            }
7596            mBackgroundSizeChanged = true;
7597            invalidateParentIfNeeded();
7598        }
7599    }
7600
7601    /**
7602     * Left position of this view relative to its parent.
7603     *
7604     * @return The left edge of this view, in pixels.
7605     */
7606    @ViewDebug.CapturedViewProperty
7607    public final int getLeft() {
7608        return mLeft;
7609    }
7610
7611    /**
7612     * Sets the left position of this view relative to its parent. This method is meant to be called
7613     * by the layout system and should not generally be called otherwise, because the property
7614     * may be changed at any time by the layout.
7615     *
7616     * @param left The bottom of this view, in pixels.
7617     */
7618    public final void setLeft(int left) {
7619        if (left != mLeft) {
7620            updateMatrix();
7621            final boolean matrixIsIdentity = mTransformationInfo == null
7622                    || mTransformationInfo.mMatrixIsIdentity;
7623            if (matrixIsIdentity) {
7624                if (mAttachInfo != null) {
7625                    int minLeft;
7626                    int xLoc;
7627                    if (left < mLeft) {
7628                        minLeft = left;
7629                        xLoc = left - mLeft;
7630                    } else {
7631                        minLeft = mLeft;
7632                        xLoc = 0;
7633                    }
7634                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
7635                }
7636            } else {
7637                // Double-invalidation is necessary to capture view's old and new areas
7638                invalidate(true);
7639            }
7640
7641            int oldWidth = mRight - mLeft;
7642            int height = mBottom - mTop;
7643
7644            mLeft = left;
7645
7646            onSizeChanged(mRight - mLeft, height, oldWidth, height);
7647
7648            if (!matrixIsIdentity) {
7649                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7650                    // A change in dimension means an auto-centered pivot point changes, too
7651                    mTransformationInfo.mMatrixDirty = true;
7652                }
7653                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7654                invalidate(true);
7655            }
7656            mBackgroundSizeChanged = true;
7657            invalidateParentIfNeeded();
7658        }
7659    }
7660
7661    /**
7662     * Right position of this view relative to its parent.
7663     *
7664     * @return The right edge of this view, in pixels.
7665     */
7666    @ViewDebug.CapturedViewProperty
7667    public final int getRight() {
7668        return mRight;
7669    }
7670
7671    /**
7672     * Sets the right position of this view relative to its parent. This method is meant to be called
7673     * by the layout system and should not generally be called otherwise, because the property
7674     * may be changed at any time by the layout.
7675     *
7676     * @param right The bottom of this view, in pixels.
7677     */
7678    public final void setRight(int right) {
7679        if (right != mRight) {
7680            updateMatrix();
7681            final boolean matrixIsIdentity = mTransformationInfo == null
7682                    || mTransformationInfo.mMatrixIsIdentity;
7683            if (matrixIsIdentity) {
7684                if (mAttachInfo != null) {
7685                    int maxRight;
7686                    if (right < mRight) {
7687                        maxRight = mRight;
7688                    } else {
7689                        maxRight = right;
7690                    }
7691                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
7692                }
7693            } else {
7694                // Double-invalidation is necessary to capture view's old and new areas
7695                invalidate(true);
7696            }
7697
7698            int oldWidth = mRight - mLeft;
7699            int height = mBottom - mTop;
7700
7701            mRight = right;
7702
7703            onSizeChanged(mRight - mLeft, height, oldWidth, height);
7704
7705            if (!matrixIsIdentity) {
7706                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7707                    // A change in dimension means an auto-centered pivot point changes, too
7708                    mTransformationInfo.mMatrixDirty = true;
7709                }
7710                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7711                invalidate(true);
7712            }
7713            mBackgroundSizeChanged = true;
7714            invalidateParentIfNeeded();
7715        }
7716    }
7717
7718    /**
7719     * The visual x position of this view, in pixels. This is equivalent to the
7720     * {@link #setTranslationX(float) translationX} property plus the current
7721     * {@link #getLeft() left} property.
7722     *
7723     * @return The visual x position of this view, in pixels.
7724     */
7725    public float getX() {
7726        return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
7727    }
7728
7729    /**
7730     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
7731     * {@link #setTranslationX(float) translationX} property to be the difference between
7732     * the x value passed in and the current {@link #getLeft() left} property.
7733     *
7734     * @param x The visual x position of this view, in pixels.
7735     */
7736    public void setX(float x) {
7737        setTranslationX(x - mLeft);
7738    }
7739
7740    /**
7741     * The visual y position of this view, in pixels. This is equivalent to the
7742     * {@link #setTranslationY(float) translationY} property plus the current
7743     * {@link #getTop() top} property.
7744     *
7745     * @return The visual y position of this view, in pixels.
7746     */
7747    public float getY() {
7748        return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
7749    }
7750
7751    /**
7752     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
7753     * {@link #setTranslationY(float) translationY} property to be the difference between
7754     * the y value passed in and the current {@link #getTop() top} property.
7755     *
7756     * @param y The visual y position of this view, in pixels.
7757     */
7758    public void setY(float y) {
7759        setTranslationY(y - mTop);
7760    }
7761
7762
7763    /**
7764     * The horizontal location of this view relative to its {@link #getLeft() left} position.
7765     * This position is post-layout, in addition to wherever the object's
7766     * layout placed it.
7767     *
7768     * @return The horizontal position of this view relative to its left position, in pixels.
7769     */
7770    public float getTranslationX() {
7771        return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
7772    }
7773
7774    /**
7775     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
7776     * This effectively positions the object post-layout, in addition to wherever the object's
7777     * layout placed it.
7778     *
7779     * @param translationX The horizontal position of this view relative to its left position,
7780     * in pixels.
7781     *
7782     * @attr ref android.R.styleable#View_translationX
7783     */
7784    public void setTranslationX(float translationX) {
7785        ensureTransformationInfo();
7786        final TransformationInfo info = mTransformationInfo;
7787        if (info.mTranslationX != translationX) {
7788            invalidateParentCaches();
7789            // Double-invalidation is necessary to capture view's old and new areas
7790            invalidate(false);
7791            info.mTranslationX = translationX;
7792            info.mMatrixDirty = true;
7793            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7794            invalidate(false);
7795        }
7796    }
7797
7798    /**
7799     * The horizontal location of this view relative to its {@link #getTop() top} position.
7800     * This position is post-layout, in addition to wherever the object's
7801     * layout placed it.
7802     *
7803     * @return The vertical position of this view relative to its top position,
7804     * in pixels.
7805     */
7806    public float getTranslationY() {
7807        return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
7808    }
7809
7810    /**
7811     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
7812     * This effectively positions the object post-layout, in addition to wherever the object's
7813     * layout placed it.
7814     *
7815     * @param translationY The vertical position of this view relative to its top position,
7816     * in pixels.
7817     *
7818     * @attr ref android.R.styleable#View_translationY
7819     */
7820    public void setTranslationY(float translationY) {
7821        ensureTransformationInfo();
7822        final TransformationInfo info = mTransformationInfo;
7823        if (info.mTranslationY != translationY) {
7824            invalidateParentCaches();
7825            // Double-invalidation is necessary to capture view's old and new areas
7826            invalidate(false);
7827            info.mTranslationY = translationY;
7828            info.mMatrixDirty = true;
7829            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7830            invalidate(false);
7831        }
7832    }
7833
7834    /**
7835     * @hide
7836     */
7837    public void setFastTranslationX(float x) {
7838        ensureTransformationInfo();
7839        final TransformationInfo info = mTransformationInfo;
7840        info.mTranslationX = x;
7841        info.mMatrixDirty = true;
7842    }
7843
7844    /**
7845     * @hide
7846     */
7847    public void setFastTranslationY(float y) {
7848        ensureTransformationInfo();
7849        final TransformationInfo info = mTransformationInfo;
7850        info.mTranslationY = y;
7851        info.mMatrixDirty = true;
7852    }
7853
7854    /**
7855     * @hide
7856     */
7857    public void setFastX(float x) {
7858        ensureTransformationInfo();
7859        final TransformationInfo info = mTransformationInfo;
7860        info.mTranslationX = x - mLeft;
7861        info.mMatrixDirty = true;
7862    }
7863
7864    /**
7865     * @hide
7866     */
7867    public void setFastY(float y) {
7868        ensureTransformationInfo();
7869        final TransformationInfo info = mTransformationInfo;
7870        info.mTranslationY = y - mTop;
7871        info.mMatrixDirty = true;
7872    }
7873
7874    /**
7875     * @hide
7876     */
7877    public void setFastScaleX(float x) {
7878        ensureTransformationInfo();
7879        final TransformationInfo info = mTransformationInfo;
7880        info.mScaleX = x;
7881        info.mMatrixDirty = true;
7882    }
7883
7884    /**
7885     * @hide
7886     */
7887    public void setFastScaleY(float y) {
7888        ensureTransformationInfo();
7889        final TransformationInfo info = mTransformationInfo;
7890        info.mScaleY = y;
7891        info.mMatrixDirty = true;
7892    }
7893
7894    /**
7895     * @hide
7896     */
7897    public void setFastAlpha(float alpha) {
7898        ensureTransformationInfo();
7899        mTransformationInfo.mAlpha = alpha;
7900    }
7901
7902    /**
7903     * @hide
7904     */
7905    public void setFastRotationY(float y) {
7906        ensureTransformationInfo();
7907        final TransformationInfo info = mTransformationInfo;
7908        info.mRotationY = y;
7909        info.mMatrixDirty = true;
7910    }
7911
7912    /**
7913     * Hit rectangle in parent's coordinates
7914     *
7915     * @param outRect The hit rectangle of the view.
7916     */
7917    public void getHitRect(Rect outRect) {
7918        updateMatrix();
7919        final TransformationInfo info = mTransformationInfo;
7920        if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
7921            outRect.set(mLeft, mTop, mRight, mBottom);
7922        } else {
7923            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
7924            tmpRect.set(-info.mPivotX, -info.mPivotY,
7925                    getWidth() - info.mPivotX, getHeight() - info.mPivotY);
7926            info.mMatrix.mapRect(tmpRect);
7927            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
7928                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
7929        }
7930    }
7931
7932    /**
7933     * Determines whether the given point, in local coordinates is inside the view.
7934     */
7935    /*package*/ final boolean pointInView(float localX, float localY) {
7936        return localX >= 0 && localX < (mRight - mLeft)
7937                && localY >= 0 && localY < (mBottom - mTop);
7938    }
7939
7940    /**
7941     * Utility method to determine whether the given point, in local coordinates,
7942     * is inside the view, where the area of the view is expanded by the slop factor.
7943     * This method is called while processing touch-move events to determine if the event
7944     * is still within the view.
7945     */
7946    private boolean pointInView(float localX, float localY, float slop) {
7947        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
7948                localY < ((mBottom - mTop) + slop);
7949    }
7950
7951    /**
7952     * When a view has focus and the user navigates away from it, the next view is searched for
7953     * starting from the rectangle filled in by this method.
7954     *
7955     * By default, the rectange is the {@link #getDrawingRect(android.graphics.Rect)})
7956     * of the view.  However, if your view maintains some idea of internal selection,
7957     * such as a cursor, or a selected row or column, you should override this method and
7958     * fill in a more specific rectangle.
7959     *
7960     * @param r The rectangle to fill in, in this view's coordinates.
7961     */
7962    public void getFocusedRect(Rect r) {
7963        getDrawingRect(r);
7964    }
7965
7966    /**
7967     * If some part of this view is not clipped by any of its parents, then
7968     * return that area in r in global (root) coordinates. To convert r to local
7969     * coordinates, offset it by -globalOffset (e.g. r.offset(-globalOffset.x,
7970     * -globalOffset.y)) If the view is completely clipped or translated out,
7971     * return false.
7972     *
7973     * @param r If true is returned, r holds the global coordinates of the
7974     *        visible portion of this view.
7975     * @param globalOffset If true is returned, globalOffset holds the dx,dy
7976     *        between this view and its root. globalOffet may be null.
7977     * @return true if r is non-empty (i.e. part of the view is visible at the
7978     *         root level.
7979     */
7980    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
7981        int width = mRight - mLeft;
7982        int height = mBottom - mTop;
7983        if (width > 0 && height > 0) {
7984            r.set(0, 0, width, height);
7985            if (globalOffset != null) {
7986                globalOffset.set(-mScrollX, -mScrollY);
7987            }
7988            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
7989        }
7990        return false;
7991    }
7992
7993    public final boolean getGlobalVisibleRect(Rect r) {
7994        return getGlobalVisibleRect(r, null);
7995    }
7996
7997    public final boolean getLocalVisibleRect(Rect r) {
7998        Point offset = new Point();
7999        if (getGlobalVisibleRect(r, offset)) {
8000            r.offset(-offset.x, -offset.y); // make r local
8001            return true;
8002        }
8003        return false;
8004    }
8005
8006    /**
8007     * Offset this view's vertical location by the specified number of pixels.
8008     *
8009     * @param offset the number of pixels to offset the view by
8010     */
8011    public void offsetTopAndBottom(int offset) {
8012        if (offset != 0) {
8013            updateMatrix();
8014            final boolean matrixIsIdentity = mTransformationInfo == null
8015                    || mTransformationInfo.mMatrixIsIdentity;
8016            if (matrixIsIdentity) {
8017                final ViewParent p = mParent;
8018                if (p != null && mAttachInfo != null) {
8019                    final Rect r = mAttachInfo.mTmpInvalRect;
8020                    int minTop;
8021                    int maxBottom;
8022                    int yLoc;
8023                    if (offset < 0) {
8024                        minTop = mTop + offset;
8025                        maxBottom = mBottom;
8026                        yLoc = offset;
8027                    } else {
8028                        minTop = mTop;
8029                        maxBottom = mBottom + offset;
8030                        yLoc = 0;
8031                    }
8032                    r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
8033                    p.invalidateChild(this, r);
8034                }
8035            } else {
8036                invalidate(false);
8037            }
8038
8039            mTop += offset;
8040            mBottom += offset;
8041
8042            if (!matrixIsIdentity) {
8043                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
8044                invalidate(false);
8045            }
8046            invalidateParentIfNeeded();
8047        }
8048    }
8049
8050    /**
8051     * Offset this view's horizontal location by the specified amount of pixels.
8052     *
8053     * @param offset the numer of pixels to offset the view by
8054     */
8055    public void offsetLeftAndRight(int offset) {
8056        if (offset != 0) {
8057            updateMatrix();
8058            final boolean matrixIsIdentity = mTransformationInfo == null
8059                    || mTransformationInfo.mMatrixIsIdentity;
8060            if (matrixIsIdentity) {
8061                final ViewParent p = mParent;
8062                if (p != null && mAttachInfo != null) {
8063                    final Rect r = mAttachInfo.mTmpInvalRect;
8064                    int minLeft;
8065                    int maxRight;
8066                    if (offset < 0) {
8067                        minLeft = mLeft + offset;
8068                        maxRight = mRight;
8069                    } else {
8070                        minLeft = mLeft;
8071                        maxRight = mRight + offset;
8072                    }
8073                    r.set(0, 0, maxRight - minLeft, mBottom - mTop);
8074                    p.invalidateChild(this, r);
8075                }
8076            } else {
8077                invalidate(false);
8078            }
8079
8080            mLeft += offset;
8081            mRight += offset;
8082
8083            if (!matrixIsIdentity) {
8084                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
8085                invalidate(false);
8086            }
8087            invalidateParentIfNeeded();
8088        }
8089    }
8090
8091    /**
8092     * Get the LayoutParams associated with this view. All views should have
8093     * layout parameters. These supply parameters to the <i>parent</i> of this
8094     * view specifying how it should be arranged. There are many subclasses of
8095     * ViewGroup.LayoutParams, and these correspond to the different subclasses
8096     * of ViewGroup that are responsible for arranging their children.
8097     *
8098     * This method may return null if this View is not attached to a parent
8099     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
8100     * was not invoked successfully. When a View is attached to a parent
8101     * ViewGroup, this method must not return null.
8102     *
8103     * @return The LayoutParams associated with this view, or null if no
8104     *         parameters have been set yet
8105     */
8106    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
8107    public ViewGroup.LayoutParams getLayoutParams() {
8108        return mLayoutParams;
8109    }
8110
8111    /**
8112     * Set the layout parameters associated with this view. These supply
8113     * parameters to the <i>parent</i> of this view specifying how it should be
8114     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
8115     * correspond to the different subclasses of ViewGroup that are responsible
8116     * for arranging their children.
8117     *
8118     * @param params The layout parameters for this view, cannot be null
8119     */
8120    public void setLayoutParams(ViewGroup.LayoutParams params) {
8121        if (params == null) {
8122            throw new NullPointerException("Layout parameters cannot be null");
8123        }
8124        mLayoutParams = params;
8125        requestLayout();
8126    }
8127
8128    /**
8129     * Set the scrolled position of your view. This will cause a call to
8130     * {@link #onScrollChanged(int, int, int, int)} and the view will be
8131     * invalidated.
8132     * @param x the x position to scroll to
8133     * @param y the y position to scroll to
8134     */
8135    public void scrollTo(int x, int y) {
8136        if (mScrollX != x || mScrollY != y) {
8137            int oldX = mScrollX;
8138            int oldY = mScrollY;
8139            mScrollX = x;
8140            mScrollY = y;
8141            invalidateParentCaches();
8142            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
8143            if (!awakenScrollBars()) {
8144                invalidate(true);
8145            }
8146        }
8147    }
8148
8149    /**
8150     * Move the scrolled position of your view. This will cause a call to
8151     * {@link #onScrollChanged(int, int, int, int)} and the view will be
8152     * invalidated.
8153     * @param x the amount of pixels to scroll by horizontally
8154     * @param y the amount of pixels to scroll by vertically
8155     */
8156    public void scrollBy(int x, int y) {
8157        scrollTo(mScrollX + x, mScrollY + y);
8158    }
8159
8160    /**
8161     * <p>Trigger the scrollbars to draw. When invoked this method starts an
8162     * animation to fade the scrollbars out after a default delay. If a subclass
8163     * provides animated scrolling, the start delay should equal the duration
8164     * of the scrolling animation.</p>
8165     *
8166     * <p>The animation starts only if at least one of the scrollbars is
8167     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
8168     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
8169     * this method returns true, and false otherwise. If the animation is
8170     * started, this method calls {@link #invalidate()}; in that case the
8171     * caller should not call {@link #invalidate()}.</p>
8172     *
8173     * <p>This method should be invoked every time a subclass directly updates
8174     * the scroll parameters.</p>
8175     *
8176     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
8177     * and {@link #scrollTo(int, int)}.</p>
8178     *
8179     * @return true if the animation is played, false otherwise
8180     *
8181     * @see #awakenScrollBars(int)
8182     * @see #scrollBy(int, int)
8183     * @see #scrollTo(int, int)
8184     * @see #isHorizontalScrollBarEnabled()
8185     * @see #isVerticalScrollBarEnabled()
8186     * @see #setHorizontalScrollBarEnabled(boolean)
8187     * @see #setVerticalScrollBarEnabled(boolean)
8188     */
8189    protected boolean awakenScrollBars() {
8190        return mScrollCache != null &&
8191                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
8192    }
8193
8194    /**
8195     * Trigger the scrollbars to draw.
8196     * This method differs from awakenScrollBars() only in its default duration.
8197     * initialAwakenScrollBars() will show the scroll bars for longer than
8198     * usual to give the user more of a chance to notice them.
8199     *
8200     * @return true if the animation is played, false otherwise.
8201     */
8202    private boolean initialAwakenScrollBars() {
8203        return mScrollCache != null &&
8204                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
8205    }
8206
8207    /**
8208     * <p>
8209     * Trigger the scrollbars to draw. When invoked this method starts an
8210     * animation to fade the scrollbars out after a fixed delay. If a subclass
8211     * provides animated scrolling, the start delay should equal the duration of
8212     * the scrolling animation.
8213     * </p>
8214     *
8215     * <p>
8216     * The animation starts only if at least one of the scrollbars is enabled,
8217     * as specified by {@link #isHorizontalScrollBarEnabled()} and
8218     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
8219     * this method returns true, and false otherwise. If the animation is
8220     * started, this method calls {@link #invalidate()}; in that case the caller
8221     * should not call {@link #invalidate()}.
8222     * </p>
8223     *
8224     * <p>
8225     * This method should be invoked everytime a subclass directly updates the
8226     * scroll parameters.
8227     * </p>
8228     *
8229     * @param startDelay the delay, in milliseconds, after which the animation
8230     *        should start; when the delay is 0, the animation starts
8231     *        immediately
8232     * @return true if the animation is played, false otherwise
8233     *
8234     * @see #scrollBy(int, int)
8235     * @see #scrollTo(int, int)
8236     * @see #isHorizontalScrollBarEnabled()
8237     * @see #isVerticalScrollBarEnabled()
8238     * @see #setHorizontalScrollBarEnabled(boolean)
8239     * @see #setVerticalScrollBarEnabled(boolean)
8240     */
8241    protected boolean awakenScrollBars(int startDelay) {
8242        return awakenScrollBars(startDelay, true);
8243    }
8244
8245    /**
8246     * <p>
8247     * Trigger the scrollbars to draw. When invoked this method starts an
8248     * animation to fade the scrollbars out after a fixed delay. If a subclass
8249     * provides animated scrolling, the start delay should equal the duration of
8250     * the scrolling animation.
8251     * </p>
8252     *
8253     * <p>
8254     * The animation starts only if at least one of the scrollbars is enabled,
8255     * as specified by {@link #isHorizontalScrollBarEnabled()} and
8256     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
8257     * this method returns true, and false otherwise. If the animation is
8258     * started, this method calls {@link #invalidate()} if the invalidate parameter
8259     * is set to true; in that case the caller
8260     * should not call {@link #invalidate()}.
8261     * </p>
8262     *
8263     * <p>
8264     * This method should be invoked everytime a subclass directly updates the
8265     * scroll parameters.
8266     * </p>
8267     *
8268     * @param startDelay the delay, in milliseconds, after which the animation
8269     *        should start; when the delay is 0, the animation starts
8270     *        immediately
8271     *
8272     * @param invalidate Wheter this method should call invalidate
8273     *
8274     * @return true if the animation is played, false otherwise
8275     *
8276     * @see #scrollBy(int, int)
8277     * @see #scrollTo(int, int)
8278     * @see #isHorizontalScrollBarEnabled()
8279     * @see #isVerticalScrollBarEnabled()
8280     * @see #setHorizontalScrollBarEnabled(boolean)
8281     * @see #setVerticalScrollBarEnabled(boolean)
8282     */
8283    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
8284        final ScrollabilityCache scrollCache = mScrollCache;
8285
8286        if (scrollCache == null || !scrollCache.fadeScrollBars) {
8287            return false;
8288        }
8289
8290        if (scrollCache.scrollBar == null) {
8291            scrollCache.scrollBar = new ScrollBarDrawable();
8292        }
8293
8294        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
8295
8296            if (invalidate) {
8297                // Invalidate to show the scrollbars
8298                invalidate(true);
8299            }
8300
8301            if (scrollCache.state == ScrollabilityCache.OFF) {
8302                // FIXME: this is copied from WindowManagerService.
8303                // We should get this value from the system when it
8304                // is possible to do so.
8305                final int KEY_REPEAT_FIRST_DELAY = 750;
8306                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
8307            }
8308
8309            // Tell mScrollCache when we should start fading. This may
8310            // extend the fade start time if one was already scheduled
8311            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
8312            scrollCache.fadeStartTime = fadeStartTime;
8313            scrollCache.state = ScrollabilityCache.ON;
8314
8315            // Schedule our fader to run, unscheduling any old ones first
8316            if (mAttachInfo != null) {
8317                mAttachInfo.mHandler.removeCallbacks(scrollCache);
8318                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
8319            }
8320
8321            return true;
8322        }
8323
8324        return false;
8325    }
8326
8327    /**
8328     * Do not invalidate views which are not visible and which are not running an animation. They
8329     * will not get drawn and they should not set dirty flags as if they will be drawn
8330     */
8331    private boolean skipInvalidate() {
8332        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
8333                (!(mParent instanceof ViewGroup) ||
8334                        !((ViewGroup) mParent).isViewTransitioning(this));
8335    }
8336    /**
8337     * Mark the the area defined by dirty as needing to be drawn. If the view is
8338     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
8339     * in the future. This must be called from a UI thread. To call from a non-UI
8340     * thread, call {@link #postInvalidate()}.
8341     *
8342     * WARNING: This method is destructive to dirty.
8343     * @param dirty the rectangle representing the bounds of the dirty region
8344     */
8345    public void invalidate(Rect dirty) {
8346        if (ViewDebug.TRACE_HIERARCHY) {
8347            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
8348        }
8349
8350        if (skipInvalidate()) {
8351            return;
8352        }
8353        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8354                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
8355                (mPrivateFlags & INVALIDATED) != INVALIDATED) {
8356            mPrivateFlags &= ~DRAWING_CACHE_VALID;
8357            mPrivateFlags |= INVALIDATED;
8358            mPrivateFlags |= DIRTY;
8359            final ViewParent p = mParent;
8360            final AttachInfo ai = mAttachInfo;
8361            //noinspection PointlessBooleanExpression,ConstantConditions
8362            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
8363                if (p != null && ai != null && ai.mHardwareAccelerated) {
8364                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
8365                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
8366                    p.invalidateChild(this, null);
8367                    return;
8368                }
8369            }
8370            if (p != null && ai != null) {
8371                final int scrollX = mScrollX;
8372                final int scrollY = mScrollY;
8373                final Rect r = ai.mTmpInvalRect;
8374                r.set(dirty.left - scrollX, dirty.top - scrollY,
8375                        dirty.right - scrollX, dirty.bottom - scrollY);
8376                mParent.invalidateChild(this, r);
8377            }
8378        }
8379    }
8380
8381    /**
8382     * Mark the the area defined by the rect (l,t,r,b) as needing to be drawn.
8383     * The coordinates of the dirty rect are relative to the view.
8384     * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
8385     * will be called at some point in the future. This must be called from
8386     * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
8387     * @param l the left position of the dirty region
8388     * @param t the top position of the dirty region
8389     * @param r the right position of the dirty region
8390     * @param b the bottom position of the dirty region
8391     */
8392    public void invalidate(int l, int t, int r, int b) {
8393        if (ViewDebug.TRACE_HIERARCHY) {
8394            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
8395        }
8396
8397        if (skipInvalidate()) {
8398            return;
8399        }
8400        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8401                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
8402                (mPrivateFlags & INVALIDATED) != INVALIDATED) {
8403            mPrivateFlags &= ~DRAWING_CACHE_VALID;
8404            mPrivateFlags |= INVALIDATED;
8405            mPrivateFlags |= DIRTY;
8406            final ViewParent p = mParent;
8407            final AttachInfo ai = mAttachInfo;
8408            //noinspection PointlessBooleanExpression,ConstantConditions
8409            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
8410                if (p != null && ai != null && ai.mHardwareAccelerated) {
8411                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
8412                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
8413                    p.invalidateChild(this, null);
8414                    return;
8415                }
8416            }
8417            if (p != null && ai != null && l < r && t < b) {
8418                final int scrollX = mScrollX;
8419                final int scrollY = mScrollY;
8420                final Rect tmpr = ai.mTmpInvalRect;
8421                tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
8422                p.invalidateChild(this, tmpr);
8423            }
8424        }
8425    }
8426
8427    /**
8428     * Invalidate the whole view. If the view is visible,
8429     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
8430     * the future. This must be called from a UI thread. To call from a non-UI thread,
8431     * call {@link #postInvalidate()}.
8432     */
8433    public void invalidate() {
8434        invalidate(true);
8435    }
8436
8437    /**
8438     * This is where the invalidate() work actually happens. A full invalidate()
8439     * causes the drawing cache to be invalidated, but this function can be called with
8440     * invalidateCache set to false to skip that invalidation step for cases that do not
8441     * need it (for example, a component that remains at the same dimensions with the same
8442     * content).
8443     *
8444     * @param invalidateCache Whether the drawing cache for this view should be invalidated as
8445     * well. This is usually true for a full invalidate, but may be set to false if the
8446     * View's contents or dimensions have not changed.
8447     */
8448    void invalidate(boolean invalidateCache) {
8449        if (ViewDebug.TRACE_HIERARCHY) {
8450            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
8451        }
8452
8453        if (skipInvalidate()) {
8454            return;
8455        }
8456        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8457                (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||
8458                (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) {
8459            mLastIsOpaque = isOpaque();
8460            mPrivateFlags &= ~DRAWN;
8461            mPrivateFlags |= DIRTY;
8462            if (invalidateCache) {
8463                mPrivateFlags |= INVALIDATED;
8464                mPrivateFlags &= ~DRAWING_CACHE_VALID;
8465            }
8466            final AttachInfo ai = mAttachInfo;
8467            final ViewParent p = mParent;
8468            //noinspection PointlessBooleanExpression,ConstantConditions
8469            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
8470                if (p != null && ai != null && ai.mHardwareAccelerated) {
8471                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
8472                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
8473                    p.invalidateChild(this, null);
8474                    return;
8475                }
8476            }
8477
8478            if (p != null && ai != null) {
8479                final Rect r = ai.mTmpInvalRect;
8480                r.set(0, 0, mRight - mLeft, mBottom - mTop);
8481                // Don't call invalidate -- we don't want to internally scroll
8482                // our own bounds
8483                p.invalidateChild(this, r);
8484            }
8485        }
8486    }
8487
8488    /**
8489     * @hide
8490     */
8491    public void fastInvalidate() {
8492        if (skipInvalidate()) {
8493            return;
8494        }
8495        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8496            (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
8497            (mPrivateFlags & INVALIDATED) != INVALIDATED) {
8498            if (mParent instanceof View) {
8499                ((View) mParent).mPrivateFlags |= INVALIDATED;
8500            }
8501            mPrivateFlags &= ~DRAWN;
8502            mPrivateFlags |= DIRTY;
8503            mPrivateFlags |= INVALIDATED;
8504            mPrivateFlags &= ~DRAWING_CACHE_VALID;
8505            if (mParent != null && mAttachInfo != null) {
8506                if (mAttachInfo.mHardwareAccelerated) {
8507                    mParent.invalidateChild(this, null);
8508                } else {
8509                    final Rect r = mAttachInfo.mTmpInvalRect;
8510                    r.set(0, 0, mRight - mLeft, mBottom - mTop);
8511                    // Don't call invalidate -- we don't want to internally scroll
8512                    // our own bounds
8513                    mParent.invalidateChild(this, r);
8514                }
8515            }
8516        }
8517    }
8518
8519    /**
8520     * Used to indicate that the parent of this view should clear its caches. This functionality
8521     * is used to force the parent to rebuild its display list (when hardware-accelerated),
8522     * which is necessary when various parent-managed properties of the view change, such as
8523     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
8524     * clears the parent caches and does not causes an invalidate event.
8525     *
8526     * @hide
8527     */
8528    protected void invalidateParentCaches() {
8529        if (mParent instanceof View) {
8530            ((View) mParent).mPrivateFlags |= INVALIDATED;
8531        }
8532    }
8533
8534    /**
8535     * Used to indicate that the parent of this view should be invalidated. This functionality
8536     * is used to force the parent to rebuild its display list (when hardware-accelerated),
8537     * which is necessary when various parent-managed properties of the view change, such as
8538     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
8539     * an invalidation event to the parent.
8540     *
8541     * @hide
8542     */
8543    protected void invalidateParentIfNeeded() {
8544        if (isHardwareAccelerated() && mParent instanceof View) {
8545            ((View) mParent).invalidate(true);
8546        }
8547    }
8548
8549    /**
8550     * Indicates whether this View is opaque. An opaque View guarantees that it will
8551     * draw all the pixels overlapping its bounds using a fully opaque color.
8552     *
8553     * Subclasses of View should override this method whenever possible to indicate
8554     * whether an instance is opaque. Opaque Views are treated in a special way by
8555     * the View hierarchy, possibly allowing it to perform optimizations during
8556     * invalidate/draw passes.
8557     *
8558     * @return True if this View is guaranteed to be fully opaque, false otherwise.
8559     */
8560    @ViewDebug.ExportedProperty(category = "drawing")
8561    public boolean isOpaque() {
8562        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK &&
8563                ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1)
8564                        >= 1.0f - ViewConfiguration.ALPHA_THRESHOLD);
8565    }
8566
8567    /**
8568     * @hide
8569     */
8570    protected void computeOpaqueFlags() {
8571        // Opaque if:
8572        //   - Has a background
8573        //   - Background is opaque
8574        //   - Doesn't have scrollbars or scrollbars are inside overlay
8575
8576        if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
8577            mPrivateFlags |= OPAQUE_BACKGROUND;
8578        } else {
8579            mPrivateFlags &= ~OPAQUE_BACKGROUND;
8580        }
8581
8582        final int flags = mViewFlags;
8583        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
8584                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
8585            mPrivateFlags |= OPAQUE_SCROLLBARS;
8586        } else {
8587            mPrivateFlags &= ~OPAQUE_SCROLLBARS;
8588        }
8589    }
8590
8591    /**
8592     * @hide
8593     */
8594    protected boolean hasOpaqueScrollbars() {
8595        return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
8596    }
8597
8598    /**
8599     * @return A handler associated with the thread running the View. This
8600     * handler can be used to pump events in the UI events queue.
8601     */
8602    public Handler getHandler() {
8603        if (mAttachInfo != null) {
8604            return mAttachInfo.mHandler;
8605        }
8606        return null;
8607    }
8608
8609    /**
8610     * <p>Causes the Runnable to be added to the message queue.
8611     * The runnable will be run on the user interface thread.</p>
8612     *
8613     * <p>This method can be invoked from outside of the UI thread
8614     * only when this View is attached to a window.</p>
8615     *
8616     * @param action The Runnable that will be executed.
8617     *
8618     * @return Returns true if the Runnable was successfully placed in to the
8619     *         message queue.  Returns false on failure, usually because the
8620     *         looper processing the message queue is exiting.
8621     */
8622    public boolean post(Runnable action) {
8623        Handler handler;
8624        AttachInfo attachInfo = mAttachInfo;
8625        if (attachInfo != null) {
8626            handler = attachInfo.mHandler;
8627        } else {
8628            // Assume that post will succeed later
8629            ViewRootImpl.getRunQueue().post(action);
8630            return true;
8631        }
8632
8633        return handler.post(action);
8634    }
8635
8636    /**
8637     * <p>Causes the Runnable to be added to the message queue, to be run
8638     * after the specified amount of time elapses.
8639     * The runnable will be run on the user interface thread.</p>
8640     *
8641     * <p>This method can be invoked from outside of the UI thread
8642     * only when this View is attached to a window.</p>
8643     *
8644     * @param action The Runnable that will be executed.
8645     * @param delayMillis The delay (in milliseconds) until the Runnable
8646     *        will be executed.
8647     *
8648     * @return true if the Runnable was successfully placed in to the
8649     *         message queue.  Returns false on failure, usually because the
8650     *         looper processing the message queue is exiting.  Note that a
8651     *         result of true does not mean the Runnable will be processed --
8652     *         if the looper is quit before the delivery time of the message
8653     *         occurs then the message will be dropped.
8654     */
8655    public boolean postDelayed(Runnable action, long delayMillis) {
8656        Handler handler;
8657        AttachInfo attachInfo = mAttachInfo;
8658        if (attachInfo != null) {
8659            handler = attachInfo.mHandler;
8660        } else {
8661            // Assume that post will succeed later
8662            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
8663            return true;
8664        }
8665
8666        return handler.postDelayed(action, delayMillis);
8667    }
8668
8669    /**
8670     * <p>Removes the specified Runnable from the message queue.</p>
8671     *
8672     * <p>This method can be invoked from outside of the UI thread
8673     * only when this View is attached to a window.</p>
8674     *
8675     * @param action The Runnable to remove from the message handling queue
8676     *
8677     * @return true if this view could ask the Handler to remove the Runnable,
8678     *         false otherwise. When the returned value is true, the Runnable
8679     *         may or may not have been actually removed from the message queue
8680     *         (for instance, if the Runnable was not in the queue already.)
8681     */
8682    public boolean removeCallbacks(Runnable action) {
8683        Handler handler;
8684        AttachInfo attachInfo = mAttachInfo;
8685        if (attachInfo != null) {
8686            handler = attachInfo.mHandler;
8687        } else {
8688            // Assume that post will succeed later
8689            ViewRootImpl.getRunQueue().removeCallbacks(action);
8690            return true;
8691        }
8692
8693        handler.removeCallbacks(action);
8694        return true;
8695    }
8696
8697    /**
8698     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
8699     * Use this to invalidate the View from a non-UI thread.</p>
8700     *
8701     * <p>This method can be invoked from outside of the UI thread
8702     * only when this View is attached to a window.</p>
8703     *
8704     * @see #invalidate()
8705     */
8706    public void postInvalidate() {
8707        postInvalidateDelayed(0);
8708    }
8709
8710    /**
8711     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
8712     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
8713     *
8714     * <p>This method can be invoked from outside of the UI thread
8715     * only when this View is attached to a window.</p>
8716     *
8717     * @param left The left coordinate of the rectangle to invalidate.
8718     * @param top The top coordinate of the rectangle to invalidate.
8719     * @param right The right coordinate of the rectangle to invalidate.
8720     * @param bottom The bottom coordinate of the rectangle to invalidate.
8721     *
8722     * @see #invalidate(int, int, int, int)
8723     * @see #invalidate(Rect)
8724     */
8725    public void postInvalidate(int left, int top, int right, int bottom) {
8726        postInvalidateDelayed(0, left, top, right, bottom);
8727    }
8728
8729    /**
8730     * <p>Cause an invalidate to happen on a subsequent cycle through the event
8731     * loop. Waits for the specified amount of time.</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     * @param delayMilliseconds the duration in milliseconds to delay the
8737     *         invalidation by
8738     */
8739    public void postInvalidateDelayed(long delayMilliseconds) {
8740        // We try only with the AttachInfo because there's no point in invalidating
8741        // if we are not attached to our window
8742        AttachInfo attachInfo = mAttachInfo;
8743        if (attachInfo != null) {
8744            Message msg = Message.obtain();
8745            msg.what = AttachInfo.INVALIDATE_MSG;
8746            msg.obj = this;
8747            attachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
8748        }
8749    }
8750
8751    /**
8752     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
8753     * through the event loop. Waits for the specified amount of time.</p>
8754     *
8755     * <p>This method can be invoked from outside of the UI thread
8756     * only when this View is attached to a window.</p>
8757     *
8758     * @param delayMilliseconds the duration in milliseconds to delay the
8759     *         invalidation by
8760     * @param left The left coordinate of the rectangle to invalidate.
8761     * @param top The top coordinate of the rectangle to invalidate.
8762     * @param right The right coordinate of the rectangle to invalidate.
8763     * @param bottom The bottom coordinate of the rectangle to invalidate.
8764     */
8765    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
8766            int right, int bottom) {
8767
8768        // We try only with the AttachInfo because there's no point in invalidating
8769        // if we are not attached to our window
8770        AttachInfo attachInfo = mAttachInfo;
8771        if (attachInfo != null) {
8772            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
8773            info.target = this;
8774            info.left = left;
8775            info.top = top;
8776            info.right = right;
8777            info.bottom = bottom;
8778
8779            final Message msg = Message.obtain();
8780            msg.what = AttachInfo.INVALIDATE_RECT_MSG;
8781            msg.obj = info;
8782            attachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
8783        }
8784    }
8785
8786    /**
8787     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
8788     * This event is sent at most once every
8789     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
8790     */
8791    private void postSendViewScrolledAccessibilityEventCallback() {
8792        if (mSendViewScrolledAccessibilityEvent == null) {
8793            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
8794        }
8795        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
8796            mSendViewScrolledAccessibilityEvent.mIsPending = true;
8797            postDelayed(mSendViewScrolledAccessibilityEvent,
8798                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
8799        }
8800    }
8801
8802    /**
8803     * Called by a parent to request that a child update its values for mScrollX
8804     * and mScrollY if necessary. This will typically be done if the child is
8805     * animating a scroll using a {@link android.widget.Scroller Scroller}
8806     * object.
8807     */
8808    public void computeScroll() {
8809    }
8810
8811    /**
8812     * <p>Indicate whether the horizontal edges are faded when the view is
8813     * scrolled horizontally.</p>
8814     *
8815     * @return true if the horizontal edges should are faded on scroll, false
8816     *         otherwise
8817     *
8818     * @see #setHorizontalFadingEdgeEnabled(boolean)
8819     * @attr ref android.R.styleable#View_requiresFadingEdge
8820     */
8821    public boolean isHorizontalFadingEdgeEnabled() {
8822        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
8823    }
8824
8825    /**
8826     * <p>Define whether the horizontal edges should be faded when this view
8827     * is scrolled horizontally.</p>
8828     *
8829     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
8830     *                                    be faded when the view is scrolled
8831     *                                    horizontally
8832     *
8833     * @see #isHorizontalFadingEdgeEnabled()
8834     * @attr ref android.R.styleable#View_requiresFadingEdge
8835     */
8836    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
8837        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
8838            if (horizontalFadingEdgeEnabled) {
8839                initScrollCache();
8840            }
8841
8842            mViewFlags ^= FADING_EDGE_HORIZONTAL;
8843        }
8844    }
8845
8846    /**
8847     * <p>Indicate whether the vertical edges are faded when the view is
8848     * scrolled horizontally.</p>
8849     *
8850     * @return true if the vertical edges should are faded on scroll, false
8851     *         otherwise
8852     *
8853     * @see #setVerticalFadingEdgeEnabled(boolean)
8854     * @attr ref android.R.styleable#View_requiresFadingEdge
8855     */
8856    public boolean isVerticalFadingEdgeEnabled() {
8857        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
8858    }
8859
8860    /**
8861     * <p>Define whether the vertical edges should be faded when this view
8862     * is scrolled vertically.</p>
8863     *
8864     * @param verticalFadingEdgeEnabled true if the vertical edges should
8865     *                                  be faded when the view is scrolled
8866     *                                  vertically
8867     *
8868     * @see #isVerticalFadingEdgeEnabled()
8869     * @attr ref android.R.styleable#View_requiresFadingEdge
8870     */
8871    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
8872        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
8873            if (verticalFadingEdgeEnabled) {
8874                initScrollCache();
8875            }
8876
8877            mViewFlags ^= FADING_EDGE_VERTICAL;
8878        }
8879    }
8880
8881    /**
8882     * Returns the strength, or intensity, of the top faded edge. The strength is
8883     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
8884     * returns 0.0 or 1.0 but no value in between.
8885     *
8886     * Subclasses should override this method to provide a smoother fade transition
8887     * when scrolling occurs.
8888     *
8889     * @return the intensity of the top fade as a float between 0.0f and 1.0f
8890     */
8891    protected float getTopFadingEdgeStrength() {
8892        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
8893    }
8894
8895    /**
8896     * Returns the strength, or intensity, of the bottom faded edge. The strength is
8897     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
8898     * returns 0.0 or 1.0 but no value in between.
8899     *
8900     * Subclasses should override this method to provide a smoother fade transition
8901     * when scrolling occurs.
8902     *
8903     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
8904     */
8905    protected float getBottomFadingEdgeStrength() {
8906        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
8907                computeVerticalScrollRange() ? 1.0f : 0.0f;
8908    }
8909
8910    /**
8911     * Returns the strength, or intensity, of the left faded edge. The strength is
8912     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
8913     * returns 0.0 or 1.0 but no value in between.
8914     *
8915     * Subclasses should override this method to provide a smoother fade transition
8916     * when scrolling occurs.
8917     *
8918     * @return the intensity of the left fade as a float between 0.0f and 1.0f
8919     */
8920    protected float getLeftFadingEdgeStrength() {
8921        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
8922    }
8923
8924    /**
8925     * Returns the strength, or intensity, of the right faded edge. The strength is
8926     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
8927     * returns 0.0 or 1.0 but no value in between.
8928     *
8929     * Subclasses should override this method to provide a smoother fade transition
8930     * when scrolling occurs.
8931     *
8932     * @return the intensity of the right fade as a float between 0.0f and 1.0f
8933     */
8934    protected float getRightFadingEdgeStrength() {
8935        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
8936                computeHorizontalScrollRange() ? 1.0f : 0.0f;
8937    }
8938
8939    /**
8940     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
8941     * scrollbar is not drawn by default.</p>
8942     *
8943     * @return true if the horizontal scrollbar should be painted, false
8944     *         otherwise
8945     *
8946     * @see #setHorizontalScrollBarEnabled(boolean)
8947     */
8948    public boolean isHorizontalScrollBarEnabled() {
8949        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
8950    }
8951
8952    /**
8953     * <p>Define whether the horizontal scrollbar should be drawn or not. The
8954     * scrollbar is not drawn by default.</p>
8955     *
8956     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
8957     *                                   be painted
8958     *
8959     * @see #isHorizontalScrollBarEnabled()
8960     */
8961    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
8962        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
8963            mViewFlags ^= SCROLLBARS_HORIZONTAL;
8964            computeOpaqueFlags();
8965            resolvePadding();
8966        }
8967    }
8968
8969    /**
8970     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
8971     * scrollbar is not drawn by default.</p>
8972     *
8973     * @return true if the vertical scrollbar should be painted, false
8974     *         otherwise
8975     *
8976     * @see #setVerticalScrollBarEnabled(boolean)
8977     */
8978    public boolean isVerticalScrollBarEnabled() {
8979        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
8980    }
8981
8982    /**
8983     * <p>Define whether the vertical scrollbar should be drawn or not. The
8984     * scrollbar is not drawn by default.</p>
8985     *
8986     * @param verticalScrollBarEnabled true if the vertical scrollbar should
8987     *                                 be painted
8988     *
8989     * @see #isVerticalScrollBarEnabled()
8990     */
8991    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
8992        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
8993            mViewFlags ^= SCROLLBARS_VERTICAL;
8994            computeOpaqueFlags();
8995            resolvePadding();
8996        }
8997    }
8998
8999    /**
9000     * @hide
9001     */
9002    protected void recomputePadding() {
9003        setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
9004    }
9005
9006    /**
9007     * Define whether scrollbars will fade when the view is not scrolling.
9008     *
9009     * @param fadeScrollbars wheter to enable fading
9010     *
9011     */
9012    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
9013        initScrollCache();
9014        final ScrollabilityCache scrollabilityCache = mScrollCache;
9015        scrollabilityCache.fadeScrollBars = fadeScrollbars;
9016        if (fadeScrollbars) {
9017            scrollabilityCache.state = ScrollabilityCache.OFF;
9018        } else {
9019            scrollabilityCache.state = ScrollabilityCache.ON;
9020        }
9021    }
9022
9023    /**
9024     *
9025     * Returns true if scrollbars will fade when this view is not scrolling
9026     *
9027     * @return true if scrollbar fading is enabled
9028     */
9029    public boolean isScrollbarFadingEnabled() {
9030        return mScrollCache != null && mScrollCache.fadeScrollBars;
9031    }
9032
9033    /**
9034     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
9035     * inset. When inset, they add to the padding of the view. And the scrollbars
9036     * can be drawn inside the padding area or on the edge of the view. For example,
9037     * if a view has a background drawable and you want to draw the scrollbars
9038     * inside the padding specified by the drawable, you can use
9039     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
9040     * appear at the edge of the view, ignoring the padding, then you can use
9041     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
9042     * @param style the style of the scrollbars. Should be one of
9043     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
9044     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
9045     * @see #SCROLLBARS_INSIDE_OVERLAY
9046     * @see #SCROLLBARS_INSIDE_INSET
9047     * @see #SCROLLBARS_OUTSIDE_OVERLAY
9048     * @see #SCROLLBARS_OUTSIDE_INSET
9049     */
9050    public void setScrollBarStyle(int style) {
9051        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
9052            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
9053            computeOpaqueFlags();
9054            resolvePadding();
9055        }
9056    }
9057
9058    /**
9059     * <p>Returns the current scrollbar style.</p>
9060     * @return the current scrollbar style
9061     * @see #SCROLLBARS_INSIDE_OVERLAY
9062     * @see #SCROLLBARS_INSIDE_INSET
9063     * @see #SCROLLBARS_OUTSIDE_OVERLAY
9064     * @see #SCROLLBARS_OUTSIDE_INSET
9065     */
9066    @ViewDebug.ExportedProperty(mapping = {
9067            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
9068            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
9069            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
9070            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
9071    })
9072    public int getScrollBarStyle() {
9073        return mViewFlags & SCROLLBARS_STYLE_MASK;
9074    }
9075
9076    /**
9077     * <p>Compute the horizontal range that the horizontal scrollbar
9078     * represents.</p>
9079     *
9080     * <p>The range is expressed in arbitrary units that must be the same as the
9081     * units used by {@link #computeHorizontalScrollExtent()} and
9082     * {@link #computeHorizontalScrollOffset()}.</p>
9083     *
9084     * <p>The default range is the drawing width of this view.</p>
9085     *
9086     * @return the total horizontal range represented by the horizontal
9087     *         scrollbar
9088     *
9089     * @see #computeHorizontalScrollExtent()
9090     * @see #computeHorizontalScrollOffset()
9091     * @see android.widget.ScrollBarDrawable
9092     */
9093    protected int computeHorizontalScrollRange() {
9094        return getWidth();
9095    }
9096
9097    /**
9098     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
9099     * within the horizontal range. This value is used to compute the position
9100     * of the thumb within the scrollbar's track.</p>
9101     *
9102     * <p>The range is expressed in arbitrary units that must be the same as the
9103     * units used by {@link #computeHorizontalScrollRange()} and
9104     * {@link #computeHorizontalScrollExtent()}.</p>
9105     *
9106     * <p>The default offset is the scroll offset of this view.</p>
9107     *
9108     * @return the horizontal offset of the scrollbar's thumb
9109     *
9110     * @see #computeHorizontalScrollRange()
9111     * @see #computeHorizontalScrollExtent()
9112     * @see android.widget.ScrollBarDrawable
9113     */
9114    protected int computeHorizontalScrollOffset() {
9115        return mScrollX;
9116    }
9117
9118    /**
9119     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
9120     * within the horizontal range. This value is used to compute the length
9121     * of the thumb within the scrollbar's track.</p>
9122     *
9123     * <p>The range is expressed in arbitrary units that must be the same as the
9124     * units used by {@link #computeHorizontalScrollRange()} and
9125     * {@link #computeHorizontalScrollOffset()}.</p>
9126     *
9127     * <p>The default extent is the drawing width of this view.</p>
9128     *
9129     * @return the horizontal extent of the scrollbar's thumb
9130     *
9131     * @see #computeHorizontalScrollRange()
9132     * @see #computeHorizontalScrollOffset()
9133     * @see android.widget.ScrollBarDrawable
9134     */
9135    protected int computeHorizontalScrollExtent() {
9136        return getWidth();
9137    }
9138
9139    /**
9140     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
9141     *
9142     * <p>The range is expressed in arbitrary units that must be the same as the
9143     * units used by {@link #computeVerticalScrollExtent()} and
9144     * {@link #computeVerticalScrollOffset()}.</p>
9145     *
9146     * @return the total vertical range represented by the vertical scrollbar
9147     *
9148     * <p>The default range is the drawing height of this view.</p>
9149     *
9150     * @see #computeVerticalScrollExtent()
9151     * @see #computeVerticalScrollOffset()
9152     * @see android.widget.ScrollBarDrawable
9153     */
9154    protected int computeVerticalScrollRange() {
9155        return getHeight();
9156    }
9157
9158    /**
9159     * <p>Compute the vertical offset of the vertical scrollbar's thumb
9160     * within the horizontal range. This value is used to compute the position
9161     * of the thumb within the scrollbar's track.</p>
9162     *
9163     * <p>The range is expressed in arbitrary units that must be the same as the
9164     * units used by {@link #computeVerticalScrollRange()} and
9165     * {@link #computeVerticalScrollExtent()}.</p>
9166     *
9167     * <p>The default offset is the scroll offset of this view.</p>
9168     *
9169     * @return the vertical offset of the scrollbar's thumb
9170     *
9171     * @see #computeVerticalScrollRange()
9172     * @see #computeVerticalScrollExtent()
9173     * @see android.widget.ScrollBarDrawable
9174     */
9175    protected int computeVerticalScrollOffset() {
9176        return mScrollY;
9177    }
9178
9179    /**
9180     * <p>Compute the vertical extent of the horizontal scrollbar's thumb
9181     * within the vertical range. This value is used to compute the length
9182     * of the thumb within the scrollbar's track.</p>
9183     *
9184     * <p>The range is expressed in arbitrary units that must be the same as the
9185     * units used by {@link #computeVerticalScrollRange()} and
9186     * {@link #computeVerticalScrollOffset()}.</p>
9187     *
9188     * <p>The default extent is the drawing height of this view.</p>
9189     *
9190     * @return the vertical extent of the scrollbar's thumb
9191     *
9192     * @see #computeVerticalScrollRange()
9193     * @see #computeVerticalScrollOffset()
9194     * @see android.widget.ScrollBarDrawable
9195     */
9196    protected int computeVerticalScrollExtent() {
9197        return getHeight();
9198    }
9199
9200    /**
9201     * Check if this view can be scrolled horizontally in a certain direction.
9202     *
9203     * @param direction Negative to check scrolling left, positive to check scrolling right.
9204     * @return true if this view can be scrolled in the specified direction, false otherwise.
9205     */
9206    public boolean canScrollHorizontally(int direction) {
9207        final int offset = computeHorizontalScrollOffset();
9208        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
9209        if (range == 0) return false;
9210        if (direction < 0) {
9211            return offset > 0;
9212        } else {
9213            return offset < range - 1;
9214        }
9215    }
9216
9217    /**
9218     * Check if this view can be scrolled vertically in a certain direction.
9219     *
9220     * @param direction Negative to check scrolling up, positive to check scrolling down.
9221     * @return true if this view can be scrolled in the specified direction, false otherwise.
9222     */
9223    public boolean canScrollVertically(int direction) {
9224        final int offset = computeVerticalScrollOffset();
9225        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
9226        if (range == 0) return false;
9227        if (direction < 0) {
9228            return offset > 0;
9229        } else {
9230            return offset < range - 1;
9231        }
9232    }
9233
9234    /**
9235     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
9236     * scrollbars are painted only if they have been awakened first.</p>
9237     *
9238     * @param canvas the canvas on which to draw the scrollbars
9239     *
9240     * @see #awakenScrollBars(int)
9241     */
9242    protected final void onDrawScrollBars(Canvas canvas) {
9243        // scrollbars are drawn only when the animation is running
9244        final ScrollabilityCache cache = mScrollCache;
9245        if (cache != null) {
9246
9247            int state = cache.state;
9248
9249            if (state == ScrollabilityCache.OFF) {
9250                return;
9251            }
9252
9253            boolean invalidate = false;
9254
9255            if (state == ScrollabilityCache.FADING) {
9256                // We're fading -- get our fade interpolation
9257                if (cache.interpolatorValues == null) {
9258                    cache.interpolatorValues = new float[1];
9259                }
9260
9261                float[] values = cache.interpolatorValues;
9262
9263                // Stops the animation if we're done
9264                if (cache.scrollBarInterpolator.timeToValues(values) ==
9265                        Interpolator.Result.FREEZE_END) {
9266                    cache.state = ScrollabilityCache.OFF;
9267                } else {
9268                    cache.scrollBar.setAlpha(Math.round(values[0]));
9269                }
9270
9271                // This will make the scroll bars inval themselves after
9272                // drawing. We only want this when we're fading so that
9273                // we prevent excessive redraws
9274                invalidate = true;
9275            } else {
9276                // We're just on -- but we may have been fading before so
9277                // reset alpha
9278                cache.scrollBar.setAlpha(255);
9279            }
9280
9281
9282            final int viewFlags = mViewFlags;
9283
9284            final boolean drawHorizontalScrollBar =
9285                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
9286            final boolean drawVerticalScrollBar =
9287                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
9288                && !isVerticalScrollBarHidden();
9289
9290            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
9291                final int width = mRight - mLeft;
9292                final int height = mBottom - mTop;
9293
9294                final ScrollBarDrawable scrollBar = cache.scrollBar;
9295
9296                final int scrollX = mScrollX;
9297                final int scrollY = mScrollY;
9298                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
9299
9300                int left, top, right, bottom;
9301
9302                if (drawHorizontalScrollBar) {
9303                    int size = scrollBar.getSize(false);
9304                    if (size <= 0) {
9305                        size = cache.scrollBarSize;
9306                    }
9307
9308                    scrollBar.setParameters(computeHorizontalScrollRange(),
9309                                            computeHorizontalScrollOffset(),
9310                                            computeHorizontalScrollExtent(), false);
9311                    final int verticalScrollBarGap = drawVerticalScrollBar ?
9312                            getVerticalScrollbarWidth() : 0;
9313                    top = scrollY + height - size - (mUserPaddingBottom & inside);
9314                    left = scrollX + (mPaddingLeft & inside);
9315                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
9316                    bottom = top + size;
9317                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
9318                    if (invalidate) {
9319                        invalidate(left, top, right, bottom);
9320                    }
9321                }
9322
9323                if (drawVerticalScrollBar) {
9324                    int size = scrollBar.getSize(true);
9325                    if (size <= 0) {
9326                        size = cache.scrollBarSize;
9327                    }
9328
9329                    scrollBar.setParameters(computeVerticalScrollRange(),
9330                                            computeVerticalScrollOffset(),
9331                                            computeVerticalScrollExtent(), true);
9332                    switch (mVerticalScrollbarPosition) {
9333                        default:
9334                        case SCROLLBAR_POSITION_DEFAULT:
9335                        case SCROLLBAR_POSITION_RIGHT:
9336                            left = scrollX + width - size - (mUserPaddingRight & inside);
9337                            break;
9338                        case SCROLLBAR_POSITION_LEFT:
9339                            left = scrollX + (mUserPaddingLeft & inside);
9340                            break;
9341                    }
9342                    top = scrollY + (mPaddingTop & inside);
9343                    right = left + size;
9344                    bottom = scrollY + height - (mUserPaddingBottom & inside);
9345                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
9346                    if (invalidate) {
9347                        invalidate(left, top, right, bottom);
9348                    }
9349                }
9350            }
9351        }
9352    }
9353
9354    /**
9355     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
9356     * FastScroller is visible.
9357     * @return whether to temporarily hide the vertical scrollbar
9358     * @hide
9359     */
9360    protected boolean isVerticalScrollBarHidden() {
9361        return false;
9362    }
9363
9364    /**
9365     * <p>Draw the horizontal scrollbar if
9366     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
9367     *
9368     * @param canvas the canvas on which to draw the scrollbar
9369     * @param scrollBar the scrollbar's drawable
9370     *
9371     * @see #isHorizontalScrollBarEnabled()
9372     * @see #computeHorizontalScrollRange()
9373     * @see #computeHorizontalScrollExtent()
9374     * @see #computeHorizontalScrollOffset()
9375     * @see android.widget.ScrollBarDrawable
9376     * @hide
9377     */
9378    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
9379            int l, int t, int r, int b) {
9380        scrollBar.setBounds(l, t, r, b);
9381        scrollBar.draw(canvas);
9382    }
9383
9384    /**
9385     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
9386     * returns true.</p>
9387     *
9388     * @param canvas the canvas on which to draw the scrollbar
9389     * @param scrollBar the scrollbar's drawable
9390     *
9391     * @see #isVerticalScrollBarEnabled()
9392     * @see #computeVerticalScrollRange()
9393     * @see #computeVerticalScrollExtent()
9394     * @see #computeVerticalScrollOffset()
9395     * @see android.widget.ScrollBarDrawable
9396     * @hide
9397     */
9398    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
9399            int l, int t, int r, int b) {
9400        scrollBar.setBounds(l, t, r, b);
9401        scrollBar.draw(canvas);
9402    }
9403
9404    /**
9405     * Implement this to do your drawing.
9406     *
9407     * @param canvas the canvas on which the background will be drawn
9408     */
9409    protected void onDraw(Canvas canvas) {
9410    }
9411
9412    /*
9413     * Caller is responsible for calling requestLayout if necessary.
9414     * (This allows addViewInLayout to not request a new layout.)
9415     */
9416    void assignParent(ViewParent parent) {
9417        if (mParent == null) {
9418            mParent = parent;
9419        } else if (parent == null) {
9420            mParent = null;
9421        } else {
9422            throw new RuntimeException("view " + this + " being added, but"
9423                    + " it already has a parent");
9424        }
9425    }
9426
9427    /**
9428     * This is called when the view is attached to a window.  At this point it
9429     * has a Surface and will start drawing.  Note that this function is
9430     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
9431     * however it may be called any time before the first onDraw -- including
9432     * before or after {@link #onMeasure(int, int)}.
9433     *
9434     * @see #onDetachedFromWindow()
9435     */
9436    protected void onAttachedToWindow() {
9437        if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
9438            mParent.requestTransparentRegion(this);
9439        }
9440        if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
9441            initialAwakenScrollBars();
9442            mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
9443        }
9444        jumpDrawablesToCurrentState();
9445        // Order is important here: LayoutDirection MUST be resolved before Padding
9446        // and TextDirection
9447        resolveLayoutDirectionIfNeeded();
9448        resolvePadding();
9449        resolveTextDirection();
9450        if (isFocused()) {
9451            InputMethodManager imm = InputMethodManager.peekInstance();
9452            imm.focusIn(this);
9453        }
9454    }
9455
9456    /**
9457     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
9458     * that the parent directionality can and will be resolved before its children.
9459     */
9460    private void resolveLayoutDirectionIfNeeded() {
9461        // Do not resolve if it is not needed
9462        if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) == LAYOUT_DIRECTION_RESOLVED) return;
9463
9464        // Clear any previous layout direction resolution
9465        mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_RTL;
9466
9467        // Reset also TextDirection as a change into LayoutDirection may impact the selected
9468        // TextDirectionHeuristic
9469        resetResolvedTextDirection();
9470
9471        // Set resolved depending on layout direction
9472        switch (getLayoutDirection()) {
9473            case LAYOUT_DIRECTION_INHERIT:
9474                // We cannot do the resolution if there is no parent
9475                if (mParent == null) return;
9476
9477                // If this is root view, no need to look at parent's layout dir.
9478                if (mParent instanceof ViewGroup) {
9479                    ViewGroup viewGroup = ((ViewGroup) mParent);
9480
9481                    // Check if the parent view group can resolve
9482                    if (! viewGroup.canResolveLayoutDirection()) {
9483                        return;
9484                    }
9485                    if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
9486                        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9487                    }
9488                }
9489                break;
9490            case LAYOUT_DIRECTION_RTL:
9491                mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9492                break;
9493            case LAYOUT_DIRECTION_LOCALE:
9494                if(isLayoutDirectionRtl(Locale.getDefault())) {
9495                    mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9496                }
9497                break;
9498            default:
9499                // Nothing to do, LTR by default
9500        }
9501
9502        // Set to resolved
9503        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
9504    }
9505
9506    /**
9507     * @hide
9508     */
9509    protected void resolvePadding() {
9510        // If the user specified the absolute padding (either with android:padding or
9511        // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
9512        // use the default padding or the padding from the background drawable
9513        // (stored at this point in mPadding*)
9514        switch (getResolvedLayoutDirection()) {
9515            case LAYOUT_DIRECTION_RTL:
9516                // Start user padding override Right user padding. Otherwise, if Right user
9517                // padding is not defined, use the default Right padding. If Right user padding
9518                // is defined, just use it.
9519                if (mUserPaddingStart >= 0) {
9520                    mUserPaddingRight = mUserPaddingStart;
9521                } else if (mUserPaddingRight < 0) {
9522                    mUserPaddingRight = mPaddingRight;
9523                }
9524                if (mUserPaddingEnd >= 0) {
9525                    mUserPaddingLeft = mUserPaddingEnd;
9526                } else if (mUserPaddingLeft < 0) {
9527                    mUserPaddingLeft = mPaddingLeft;
9528                }
9529                break;
9530            case LAYOUT_DIRECTION_LTR:
9531            default:
9532                // Start user padding override Left user padding. Otherwise, if Left user
9533                // padding is not defined, use the default left padding. If Left user padding
9534                // is defined, just use it.
9535                if (mUserPaddingStart >= 0) {
9536                    mUserPaddingLeft = mUserPaddingStart;
9537                } else if (mUserPaddingLeft < 0) {
9538                    mUserPaddingLeft = mPaddingLeft;
9539                }
9540                if (mUserPaddingEnd >= 0) {
9541                    mUserPaddingRight = mUserPaddingEnd;
9542                } else if (mUserPaddingRight < 0) {
9543                    mUserPaddingRight = mPaddingRight;
9544                }
9545        }
9546
9547        mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
9548
9549        recomputePadding();
9550    }
9551
9552    /**
9553     * Return true if layout direction resolution can be done
9554     *
9555     * @hide
9556     */
9557    protected boolean canResolveLayoutDirection() {
9558        switch (getLayoutDirection()) {
9559            case LAYOUT_DIRECTION_INHERIT:
9560                return (mParent != null);
9561            default:
9562                return true;
9563        }
9564    }
9565
9566    /**
9567     * Reset the resolved layout direction.
9568     *
9569     * Subclasses need to override this method to clear cached information that depends on the
9570     * resolved layout direction, or to inform child views that inherit their layout direction.
9571     * Overrides must also call the superclass implementation at the start of their implementation.
9572     *
9573     * @hide
9574     */
9575    protected void resetResolvedLayoutDirection() {
9576        // Reset the current View resolution
9577        mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED;
9578    }
9579
9580    /**
9581     * Check if a Locale is corresponding to a RTL script.
9582     *
9583     * @param locale Locale to check
9584     * @return true if a Locale is corresponding to a RTL script.
9585     *
9586     * @hide
9587     */
9588    protected static boolean isLayoutDirectionRtl(Locale locale) {
9589        return (LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE ==
9590                LocaleUtil.getLayoutDirectionFromLocale(locale));
9591    }
9592
9593    /**
9594     * This is called when the view is detached from a window.  At this point it
9595     * no longer has a surface for drawing.
9596     *
9597     * @see #onAttachedToWindow()
9598     */
9599    protected void onDetachedFromWindow() {
9600        mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
9601
9602        removeUnsetPressCallback();
9603        removeLongPressCallback();
9604        removePerformClickCallback();
9605        removeSendViewScrolledAccessibilityEventCallback();
9606
9607        destroyDrawingCache();
9608
9609        destroyLayer();
9610
9611        if (mDisplayList != null) {
9612            mDisplayList.invalidate();
9613        }
9614
9615        if (mAttachInfo != null) {
9616            mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_MSG, this);
9617        }
9618
9619        mCurrentAnimation = null;
9620
9621        resetResolvedLayoutDirection();
9622        resetResolvedTextDirection();
9623    }
9624
9625    /**
9626     * @return The number of times this view has been attached to a window
9627     */
9628    protected int getWindowAttachCount() {
9629        return mWindowAttachCount;
9630    }
9631
9632    /**
9633     * Retrieve a unique token identifying the window this view is attached to.
9634     * @return Return the window's token for use in
9635     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
9636     */
9637    public IBinder getWindowToken() {
9638        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
9639    }
9640
9641    /**
9642     * Retrieve a unique token identifying the top-level "real" window of
9643     * the window that this view is attached to.  That is, this is like
9644     * {@link #getWindowToken}, except if the window this view in is a panel
9645     * window (attached to another containing window), then the token of
9646     * the containing window is returned instead.
9647     *
9648     * @return Returns the associated window token, either
9649     * {@link #getWindowToken()} or the containing window's token.
9650     */
9651    public IBinder getApplicationWindowToken() {
9652        AttachInfo ai = mAttachInfo;
9653        if (ai != null) {
9654            IBinder appWindowToken = ai.mPanelParentWindowToken;
9655            if (appWindowToken == null) {
9656                appWindowToken = ai.mWindowToken;
9657            }
9658            return appWindowToken;
9659        }
9660        return null;
9661    }
9662
9663    /**
9664     * Retrieve private session object this view hierarchy is using to
9665     * communicate with the window manager.
9666     * @return the session object to communicate with the window manager
9667     */
9668    /*package*/ IWindowSession getWindowSession() {
9669        return mAttachInfo != null ? mAttachInfo.mSession : null;
9670    }
9671
9672    /**
9673     * @param info the {@link android.view.View.AttachInfo} to associated with
9674     *        this view
9675     */
9676    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
9677        //System.out.println("Attached! " + this);
9678        mAttachInfo = info;
9679        mWindowAttachCount++;
9680        // We will need to evaluate the drawable state at least once.
9681        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
9682        if (mFloatingTreeObserver != null) {
9683            info.mTreeObserver.merge(mFloatingTreeObserver);
9684            mFloatingTreeObserver = null;
9685        }
9686        if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
9687            mAttachInfo.mScrollContainers.add(this);
9688            mPrivateFlags |= SCROLL_CONTAINER_ADDED;
9689        }
9690        performCollectViewAttributes(visibility);
9691        onAttachedToWindow();
9692
9693        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
9694                mOnAttachStateChangeListeners;
9695        if (listeners != null && listeners.size() > 0) {
9696            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
9697            // perform the dispatching. The iterator is a safe guard against listeners that
9698            // could mutate the list by calling the various add/remove methods. This prevents
9699            // the array from being modified while we iterate it.
9700            for (OnAttachStateChangeListener listener : listeners) {
9701                listener.onViewAttachedToWindow(this);
9702            }
9703        }
9704
9705        int vis = info.mWindowVisibility;
9706        if (vis != GONE) {
9707            onWindowVisibilityChanged(vis);
9708        }
9709        if ((mPrivateFlags&DRAWABLE_STATE_DIRTY) != 0) {
9710            // If nobody has evaluated the drawable state yet, then do it now.
9711            refreshDrawableState();
9712        }
9713    }
9714
9715    void dispatchDetachedFromWindow() {
9716        AttachInfo info = mAttachInfo;
9717        if (info != null) {
9718            int vis = info.mWindowVisibility;
9719            if (vis != GONE) {
9720                onWindowVisibilityChanged(GONE);
9721            }
9722        }
9723
9724        onDetachedFromWindow();
9725
9726        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
9727                mOnAttachStateChangeListeners;
9728        if (listeners != null && listeners.size() > 0) {
9729            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
9730            // perform the dispatching. The iterator is a safe guard against listeners that
9731            // could mutate the list by calling the various add/remove methods. This prevents
9732            // the array from being modified while we iterate it.
9733            for (OnAttachStateChangeListener listener : listeners) {
9734                listener.onViewDetachedFromWindow(this);
9735            }
9736        }
9737
9738        if ((mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0) {
9739            mAttachInfo.mScrollContainers.remove(this);
9740            mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
9741        }
9742
9743        mAttachInfo = null;
9744    }
9745
9746    /**
9747     * Store this view hierarchy's frozen state into the given container.
9748     *
9749     * @param container The SparseArray in which to save the view's state.
9750     *
9751     * @see #restoreHierarchyState(android.util.SparseArray)
9752     * @see #dispatchSaveInstanceState(android.util.SparseArray)
9753     * @see #onSaveInstanceState()
9754     */
9755    public void saveHierarchyState(SparseArray<Parcelable> container) {
9756        dispatchSaveInstanceState(container);
9757    }
9758
9759    /**
9760     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
9761     * this view and its children. May be overridden to modify how freezing happens to a
9762     * view's children; for example, some views may want to not store state for their children.
9763     *
9764     * @param container The SparseArray in which to save the view's state.
9765     *
9766     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
9767     * @see #saveHierarchyState(android.util.SparseArray)
9768     * @see #onSaveInstanceState()
9769     */
9770    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
9771        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
9772            mPrivateFlags &= ~SAVE_STATE_CALLED;
9773            Parcelable state = onSaveInstanceState();
9774            if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
9775                throw new IllegalStateException(
9776                        "Derived class did not call super.onSaveInstanceState()");
9777            }
9778            if (state != null) {
9779                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
9780                // + ": " + state);
9781                container.put(mID, state);
9782            }
9783        }
9784    }
9785
9786    /**
9787     * Hook allowing a view to generate a representation of its internal state
9788     * that can later be used to create a new instance with that same state.
9789     * This state should only contain information that is not persistent or can
9790     * not be reconstructed later. For example, you will never store your
9791     * current position on screen because that will be computed again when a
9792     * new instance of the view is placed in its view hierarchy.
9793     * <p>
9794     * Some examples of things you may store here: the current cursor position
9795     * in a text view (but usually not the text itself since that is stored in a
9796     * content provider or other persistent storage), the currently selected
9797     * item in a list view.
9798     *
9799     * @return Returns a Parcelable object containing the view's current dynamic
9800     *         state, or null if there is nothing interesting to save. The
9801     *         default implementation returns null.
9802     * @see #onRestoreInstanceState(android.os.Parcelable)
9803     * @see #saveHierarchyState(android.util.SparseArray)
9804     * @see #dispatchSaveInstanceState(android.util.SparseArray)
9805     * @see #setSaveEnabled(boolean)
9806     */
9807    protected Parcelable onSaveInstanceState() {
9808        mPrivateFlags |= SAVE_STATE_CALLED;
9809        return BaseSavedState.EMPTY_STATE;
9810    }
9811
9812    /**
9813     * Restore this view hierarchy's frozen state from the given container.
9814     *
9815     * @param container The SparseArray which holds previously frozen states.
9816     *
9817     * @see #saveHierarchyState(android.util.SparseArray)
9818     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
9819     * @see #onRestoreInstanceState(android.os.Parcelable)
9820     */
9821    public void restoreHierarchyState(SparseArray<Parcelable> container) {
9822        dispatchRestoreInstanceState(container);
9823    }
9824
9825    /**
9826     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
9827     * state for this view and its children. May be overridden to modify how restoring
9828     * happens to a view's children; for example, some views may want to not store state
9829     * for their children.
9830     *
9831     * @param container The SparseArray which holds previously saved state.
9832     *
9833     * @see #dispatchSaveInstanceState(android.util.SparseArray)
9834     * @see #restoreHierarchyState(android.util.SparseArray)
9835     * @see #onRestoreInstanceState(android.os.Parcelable)
9836     */
9837    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
9838        if (mID != NO_ID) {
9839            Parcelable state = container.get(mID);
9840            if (state != null) {
9841                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
9842                // + ": " + state);
9843                mPrivateFlags &= ~SAVE_STATE_CALLED;
9844                onRestoreInstanceState(state);
9845                if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
9846                    throw new IllegalStateException(
9847                            "Derived class did not call super.onRestoreInstanceState()");
9848                }
9849            }
9850        }
9851    }
9852
9853    /**
9854     * Hook allowing a view to re-apply a representation of its internal state that had previously
9855     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
9856     * null state.
9857     *
9858     * @param state The frozen state that had previously been returned by
9859     *        {@link #onSaveInstanceState}.
9860     *
9861     * @see #onSaveInstanceState()
9862     * @see #restoreHierarchyState(android.util.SparseArray)
9863     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
9864     */
9865    protected void onRestoreInstanceState(Parcelable state) {
9866        mPrivateFlags |= SAVE_STATE_CALLED;
9867        if (state != BaseSavedState.EMPTY_STATE && state != null) {
9868            throw new IllegalArgumentException("Wrong state class, expecting View State but "
9869                    + "received " + state.getClass().toString() + " instead. This usually happens "
9870                    + "when two views of different type have the same id in the same hierarchy. "
9871                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
9872                    + "other views do not use the same id.");
9873        }
9874    }
9875
9876    /**
9877     * <p>Return the time at which the drawing of the view hierarchy started.</p>
9878     *
9879     * @return the drawing start time in milliseconds
9880     */
9881    public long getDrawingTime() {
9882        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
9883    }
9884
9885    /**
9886     * <p>Enables or disables the duplication of the parent's state into this view. When
9887     * duplication is enabled, this view gets its drawable state from its parent rather
9888     * than from its own internal properties.</p>
9889     *
9890     * <p>Note: in the current implementation, setting this property to true after the
9891     * view was added to a ViewGroup might have no effect at all. This property should
9892     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
9893     *
9894     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
9895     * property is enabled, an exception will be thrown.</p>
9896     *
9897     * <p>Note: if the child view uses and updates additionnal states which are unknown to the
9898     * parent, these states should not be affected by this method.</p>
9899     *
9900     * @param enabled True to enable duplication of the parent's drawable state, false
9901     *                to disable it.
9902     *
9903     * @see #getDrawableState()
9904     * @see #isDuplicateParentStateEnabled()
9905     */
9906    public void setDuplicateParentStateEnabled(boolean enabled) {
9907        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
9908    }
9909
9910    /**
9911     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
9912     *
9913     * @return True if this view's drawable state is duplicated from the parent,
9914     *         false otherwise
9915     *
9916     * @see #getDrawableState()
9917     * @see #setDuplicateParentStateEnabled(boolean)
9918     */
9919    public boolean isDuplicateParentStateEnabled() {
9920        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
9921    }
9922
9923    /**
9924     * <p>Specifies the type of layer backing this view. The layer can be
9925     * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
9926     * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
9927     *
9928     * <p>A layer is associated with an optional {@link android.graphics.Paint}
9929     * instance that controls how the layer is composed on screen. The following
9930     * properties of the paint are taken into account when composing the layer:</p>
9931     * <ul>
9932     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
9933     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
9934     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
9935     * </ul>
9936     *
9937     * <p>If this view has an alpha value set to < 1.0 by calling
9938     * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
9939     * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
9940     * equivalent to setting a hardware layer on this view and providing a paint with
9941     * the desired alpha value.<p>
9942     *
9943     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
9944     * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
9945     * for more information on when and how to use layers.</p>
9946     *
9947     * @param layerType The ype of layer to use with this view, must be one of
9948     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
9949     *        {@link #LAYER_TYPE_HARDWARE}
9950     * @param paint The paint used to compose the layer. This argument is optional
9951     *        and can be null. It is ignored when the layer type is
9952     *        {@link #LAYER_TYPE_NONE}
9953     *
9954     * @see #getLayerType()
9955     * @see #LAYER_TYPE_NONE
9956     * @see #LAYER_TYPE_SOFTWARE
9957     * @see #LAYER_TYPE_HARDWARE
9958     * @see #setAlpha(float)
9959     *
9960     * @attr ref android.R.styleable#View_layerType
9961     */
9962    public void setLayerType(int layerType, Paint paint) {
9963        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
9964            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
9965                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
9966        }
9967
9968        if (layerType == mLayerType) {
9969            if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
9970                mLayerPaint = paint == null ? new Paint() : paint;
9971                invalidateParentCaches();
9972                invalidate(true);
9973            }
9974            return;
9975        }
9976
9977        // Destroy any previous software drawing cache if needed
9978        switch (mLayerType) {
9979            case LAYER_TYPE_HARDWARE:
9980                destroyLayer();
9981                // fall through - unaccelerated views may use software layer mechanism instead
9982            case LAYER_TYPE_SOFTWARE:
9983                destroyDrawingCache();
9984                break;
9985            default:
9986                break;
9987        }
9988
9989        mLayerType = layerType;
9990        final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
9991        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
9992        mLocalDirtyRect = layerDisabled ? null : new Rect();
9993
9994        invalidateParentCaches();
9995        invalidate(true);
9996    }
9997
9998    /**
9999     * Indicates whether this view has a static layer. A view with layer type
10000     * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
10001     * dynamic.
10002     */
10003    boolean hasStaticLayer() {
10004        return mLayerType == LAYER_TYPE_NONE;
10005    }
10006
10007    /**
10008     * Indicates what type of layer is currently associated with this view. By default
10009     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
10010     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
10011     * for more information on the different types of layers.
10012     *
10013     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
10014     *         {@link #LAYER_TYPE_HARDWARE}
10015     *
10016     * @see #setLayerType(int, android.graphics.Paint)
10017     * @see #buildLayer()
10018     * @see #LAYER_TYPE_NONE
10019     * @see #LAYER_TYPE_SOFTWARE
10020     * @see #LAYER_TYPE_HARDWARE
10021     */
10022    public int getLayerType() {
10023        return mLayerType;
10024    }
10025
10026    /**
10027     * Forces this view's layer to be created and this view to be rendered
10028     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
10029     * invoking this method will have no effect.
10030     *
10031     * This method can for instance be used to render a view into its layer before
10032     * starting an animation. If this view is complex, rendering into the layer
10033     * before starting the animation will avoid skipping frames.
10034     *
10035     * @throws IllegalStateException If this view is not attached to a window
10036     *
10037     * @see #setLayerType(int, android.graphics.Paint)
10038     */
10039    public void buildLayer() {
10040        if (mLayerType == LAYER_TYPE_NONE) return;
10041
10042        if (mAttachInfo == null) {
10043            throw new IllegalStateException("This view must be attached to a window first");
10044        }
10045
10046        switch (mLayerType) {
10047            case LAYER_TYPE_HARDWARE:
10048                getHardwareLayer();
10049                break;
10050            case LAYER_TYPE_SOFTWARE:
10051                buildDrawingCache(true);
10052                break;
10053        }
10054    }
10055
10056    /**
10057     * <p>Returns a hardware layer that can be used to draw this view again
10058     * without executing its draw method.</p>
10059     *
10060     * @return A HardwareLayer ready to render, or null if an error occurred.
10061     */
10062    HardwareLayer getHardwareLayer() {
10063        if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
10064                !mAttachInfo.mHardwareRenderer.isEnabled()) {
10065            return null;
10066        }
10067
10068        final int width = mRight - mLeft;
10069        final int height = mBottom - mTop;
10070
10071        if (width == 0 || height == 0) {
10072            return null;
10073        }
10074
10075        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
10076            if (mHardwareLayer == null) {
10077                mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
10078                        width, height, isOpaque());
10079                mLocalDirtyRect.setEmpty();
10080            } else if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
10081                mHardwareLayer.resize(width, height);
10082                mLocalDirtyRect.setEmpty();
10083            }
10084
10085            HardwareCanvas currentCanvas = mAttachInfo.mHardwareCanvas;
10086            final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas);
10087            mAttachInfo.mHardwareCanvas = canvas;
10088            try {
10089                canvas.setViewport(width, height);
10090                canvas.onPreDraw(mLocalDirtyRect);
10091                mLocalDirtyRect.setEmpty();
10092
10093                final int restoreCount = canvas.save();
10094
10095                computeScroll();
10096                canvas.translate(-mScrollX, -mScrollY);
10097
10098                mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10099
10100                // Fast path for layouts with no backgrounds
10101                if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10102                    mPrivateFlags &= ~DIRTY_MASK;
10103                    dispatchDraw(canvas);
10104                } else {
10105                    draw(canvas);
10106                }
10107
10108                canvas.restoreToCount(restoreCount);
10109            } finally {
10110                canvas.onPostDraw();
10111                mHardwareLayer.end(currentCanvas);
10112                mAttachInfo.mHardwareCanvas = currentCanvas;
10113            }
10114        }
10115
10116        return mHardwareLayer;
10117    }
10118
10119    boolean destroyLayer() {
10120        if (mHardwareLayer != null) {
10121            mHardwareLayer.destroy();
10122            mHardwareLayer = null;
10123            return true;
10124        }
10125        return false;
10126    }
10127
10128    /**
10129     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
10130     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
10131     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
10132     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
10133     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
10134     * null.</p>
10135     *
10136     * <p>Enabling the drawing cache is similar to
10137     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
10138     * acceleration is turned off. When hardware acceleration is turned on, enabling the
10139     * drawing cache has no effect on rendering because the system uses a different mechanism
10140     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
10141     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
10142     * for information on how to enable software and hardware layers.</p>
10143     *
10144     * <p>This API can be used to manually generate
10145     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
10146     * {@link #getDrawingCache()}.</p>
10147     *
10148     * @param enabled true to enable the drawing cache, false otherwise
10149     *
10150     * @see #isDrawingCacheEnabled()
10151     * @see #getDrawingCache()
10152     * @see #buildDrawingCache()
10153     * @see #setLayerType(int, android.graphics.Paint)
10154     */
10155    public void setDrawingCacheEnabled(boolean enabled) {
10156        mCachingFailed = false;
10157        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
10158    }
10159
10160    /**
10161     * <p>Indicates whether the drawing cache is enabled for this view.</p>
10162     *
10163     * @return true if the drawing cache is enabled
10164     *
10165     * @see #setDrawingCacheEnabled(boolean)
10166     * @see #getDrawingCache()
10167     */
10168    @ViewDebug.ExportedProperty(category = "drawing")
10169    public boolean isDrawingCacheEnabled() {
10170        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
10171    }
10172
10173    /**
10174     * Debugging utility which recursively outputs the dirty state of a view and its
10175     * descendants.
10176     *
10177     * @hide
10178     */
10179    @SuppressWarnings({"UnusedDeclaration"})
10180    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
10181        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.DIRTY_MASK) +
10182                ") DRAWN(" + (mPrivateFlags & DRAWN) + ")" + " CACHE_VALID(" +
10183                (mPrivateFlags & View.DRAWING_CACHE_VALID) +
10184                ") INVALIDATED(" + (mPrivateFlags & INVALIDATED) + ")");
10185        if (clear) {
10186            mPrivateFlags &= clearMask;
10187        }
10188        if (this instanceof ViewGroup) {
10189            ViewGroup parent = (ViewGroup) this;
10190            final int count = parent.getChildCount();
10191            for (int i = 0; i < count; i++) {
10192                final View child = parent.getChildAt(i);
10193                child.outputDirtyFlags(indent + "  ", clear, clearMask);
10194            }
10195        }
10196    }
10197
10198    /**
10199     * This method is used by ViewGroup to cause its children to restore or recreate their
10200     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
10201     * to recreate its own display list, which would happen if it went through the normal
10202     * draw/dispatchDraw mechanisms.
10203     *
10204     * @hide
10205     */
10206    protected void dispatchGetDisplayList() {}
10207
10208    /**
10209     * A view that is not attached or hardware accelerated cannot create a display list.
10210     * This method checks these conditions and returns the appropriate result.
10211     *
10212     * @return true if view has the ability to create a display list, false otherwise.
10213     *
10214     * @hide
10215     */
10216    public boolean canHaveDisplayList() {
10217        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
10218    }
10219
10220    /**
10221     * <p>Returns a display list that can be used to draw this view again
10222     * without executing its draw method.</p>
10223     *
10224     * @return A DisplayList ready to replay, or null if caching is not enabled.
10225     *
10226     * @hide
10227     */
10228    public DisplayList getDisplayList() {
10229        if (!canHaveDisplayList()) {
10230            return null;
10231        }
10232
10233        if (((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
10234                mDisplayList == null || !mDisplayList.isValid() ||
10235                mRecreateDisplayList)) {
10236            // Don't need to recreate the display list, just need to tell our
10237            // children to restore/recreate theirs
10238            if (mDisplayList != null && mDisplayList.isValid() &&
10239                    !mRecreateDisplayList) {
10240                mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10241                mPrivateFlags &= ~DIRTY_MASK;
10242                dispatchGetDisplayList();
10243
10244                return mDisplayList;
10245            }
10246
10247            // If we got here, we're recreating it. Mark it as such to ensure that
10248            // we copy in child display lists into ours in drawChild()
10249            mRecreateDisplayList = true;
10250            if (mDisplayList == null) {
10251                mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList();
10252                // If we're creating a new display list, make sure our parent gets invalidated
10253                // since they will need to recreate their display list to account for this
10254                // new child display list.
10255                invalidateParentCaches();
10256            }
10257
10258            final HardwareCanvas canvas = mDisplayList.start();
10259            int restoreCount = 0;
10260            try {
10261                int width = mRight - mLeft;
10262                int height = mBottom - mTop;
10263
10264                canvas.setViewport(width, height);
10265                // The dirty rect should always be null for a display list
10266                canvas.onPreDraw(null);
10267
10268                computeScroll();
10269
10270                restoreCount = canvas.save();
10271                canvas.translate(-mScrollX, -mScrollY);
10272                mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10273                mPrivateFlags &= ~DIRTY_MASK;
10274
10275                // Fast path for layouts with no backgrounds
10276                if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10277                    dispatchDraw(canvas);
10278                } else {
10279                    draw(canvas);
10280                }
10281            } finally {
10282                canvas.restoreToCount(restoreCount);
10283                canvas.onPostDraw();
10284
10285                mDisplayList.end();
10286            }
10287        } else {
10288            mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10289            mPrivateFlags &= ~DIRTY_MASK;
10290        }
10291
10292        return mDisplayList;
10293    }
10294
10295    /**
10296     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
10297     *
10298     * @return A non-scaled bitmap representing this view or null if cache is disabled.
10299     *
10300     * @see #getDrawingCache(boolean)
10301     */
10302    public Bitmap getDrawingCache() {
10303        return getDrawingCache(false);
10304    }
10305
10306    /**
10307     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
10308     * is null when caching is disabled. If caching is enabled and the cache is not ready,
10309     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
10310     * draw from the cache when the cache is enabled. To benefit from the cache, you must
10311     * request the drawing cache by calling this method and draw it on screen if the
10312     * returned bitmap is not null.</p>
10313     *
10314     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
10315     * this method will create a bitmap of the same size as this view. Because this bitmap
10316     * will be drawn scaled by the parent ViewGroup, the result on screen might show
10317     * scaling artifacts. To avoid such artifacts, you should call this method by setting
10318     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
10319     * size than the view. This implies that your application must be able to handle this
10320     * size.</p>
10321     *
10322     * @param autoScale Indicates whether the generated bitmap should be scaled based on
10323     *        the current density of the screen when the application is in compatibility
10324     *        mode.
10325     *
10326     * @return A bitmap representing this view or null if cache is disabled.
10327     *
10328     * @see #setDrawingCacheEnabled(boolean)
10329     * @see #isDrawingCacheEnabled()
10330     * @see #buildDrawingCache(boolean)
10331     * @see #destroyDrawingCache()
10332     */
10333    public Bitmap getDrawingCache(boolean autoScale) {
10334        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
10335            return null;
10336        }
10337        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
10338            buildDrawingCache(autoScale);
10339        }
10340        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
10341    }
10342
10343    /**
10344     * <p>Frees the resources used by the drawing cache. If you call
10345     * {@link #buildDrawingCache()} manually without calling
10346     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
10347     * should cleanup the cache with this method afterwards.</p>
10348     *
10349     * @see #setDrawingCacheEnabled(boolean)
10350     * @see #buildDrawingCache()
10351     * @see #getDrawingCache()
10352     */
10353    public void destroyDrawingCache() {
10354        if (mDrawingCache != null) {
10355            mDrawingCache.recycle();
10356            mDrawingCache = null;
10357        }
10358        if (mUnscaledDrawingCache != null) {
10359            mUnscaledDrawingCache.recycle();
10360            mUnscaledDrawingCache = null;
10361        }
10362    }
10363
10364    /**
10365     * Setting a solid background color for the drawing cache's bitmaps will improve
10366     * performance and memory usage. Note, though that this should only be used if this
10367     * view will always be drawn on top of a solid color.
10368     *
10369     * @param color The background color to use for the drawing cache's bitmap
10370     *
10371     * @see #setDrawingCacheEnabled(boolean)
10372     * @see #buildDrawingCache()
10373     * @see #getDrawingCache()
10374     */
10375    public void setDrawingCacheBackgroundColor(int color) {
10376        if (color != mDrawingCacheBackgroundColor) {
10377            mDrawingCacheBackgroundColor = color;
10378            mPrivateFlags &= ~DRAWING_CACHE_VALID;
10379        }
10380    }
10381
10382    /**
10383     * @see #setDrawingCacheBackgroundColor(int)
10384     *
10385     * @return The background color to used for the drawing cache's bitmap
10386     */
10387    public int getDrawingCacheBackgroundColor() {
10388        return mDrawingCacheBackgroundColor;
10389    }
10390
10391    /**
10392     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
10393     *
10394     * @see #buildDrawingCache(boolean)
10395     */
10396    public void buildDrawingCache() {
10397        buildDrawingCache(false);
10398    }
10399
10400    /**
10401     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
10402     *
10403     * <p>If you call {@link #buildDrawingCache()} manually without calling
10404     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
10405     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
10406     *
10407     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
10408     * this method will create a bitmap of the same size as this view. Because this bitmap
10409     * will be drawn scaled by the parent ViewGroup, the result on screen might show
10410     * scaling artifacts. To avoid such artifacts, you should call this method by setting
10411     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
10412     * size than the view. This implies that your application must be able to handle this
10413     * size.</p>
10414     *
10415     * <p>You should avoid calling this method when hardware acceleration is enabled. If
10416     * you do not need the drawing cache bitmap, calling this method will increase memory
10417     * usage and cause the view to be rendered in software once, thus negatively impacting
10418     * performance.</p>
10419     *
10420     * @see #getDrawingCache()
10421     * @see #destroyDrawingCache()
10422     */
10423    public void buildDrawingCache(boolean autoScale) {
10424        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
10425                mDrawingCache == null : mUnscaledDrawingCache == null)) {
10426            mCachingFailed = false;
10427
10428            if (ViewDebug.TRACE_HIERARCHY) {
10429                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
10430            }
10431
10432            int width = mRight - mLeft;
10433            int height = mBottom - mTop;
10434
10435            final AttachInfo attachInfo = mAttachInfo;
10436            final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
10437
10438            if (autoScale && scalingRequired) {
10439                width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
10440                height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
10441            }
10442
10443            final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
10444            final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
10445            final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
10446
10447            if (width <= 0 || height <= 0 ||
10448                     // Projected bitmap size in bytes
10449                    (width * height * (opaque && !use32BitCache ? 2 : 4) >
10450                            ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
10451                destroyDrawingCache();
10452                mCachingFailed = true;
10453                return;
10454            }
10455
10456            boolean clear = true;
10457            Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
10458
10459            if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
10460                Bitmap.Config quality;
10461                if (!opaque) {
10462                    // Never pick ARGB_4444 because it looks awful
10463                    // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
10464                    switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
10465                        case DRAWING_CACHE_QUALITY_AUTO:
10466                            quality = Bitmap.Config.ARGB_8888;
10467                            break;
10468                        case DRAWING_CACHE_QUALITY_LOW:
10469                            quality = Bitmap.Config.ARGB_8888;
10470                            break;
10471                        case DRAWING_CACHE_QUALITY_HIGH:
10472                            quality = Bitmap.Config.ARGB_8888;
10473                            break;
10474                        default:
10475                            quality = Bitmap.Config.ARGB_8888;
10476                            break;
10477                    }
10478                } else {
10479                    // Optimization for translucent windows
10480                    // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
10481                    quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
10482                }
10483
10484                // Try to cleanup memory
10485                if (bitmap != null) bitmap.recycle();
10486
10487                try {
10488                    bitmap = Bitmap.createBitmap(width, height, quality);
10489                    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
10490                    if (autoScale) {
10491                        mDrawingCache = bitmap;
10492                    } else {
10493                        mUnscaledDrawingCache = bitmap;
10494                    }
10495                    if (opaque && use32BitCache) bitmap.setHasAlpha(false);
10496                } catch (OutOfMemoryError e) {
10497                    // If there is not enough memory to create the bitmap cache, just
10498                    // ignore the issue as bitmap caches are not required to draw the
10499                    // view hierarchy
10500                    if (autoScale) {
10501                        mDrawingCache = null;
10502                    } else {
10503                        mUnscaledDrawingCache = null;
10504                    }
10505                    mCachingFailed = true;
10506                    return;
10507                }
10508
10509                clear = drawingCacheBackgroundColor != 0;
10510            }
10511
10512            Canvas canvas;
10513            if (attachInfo != null) {
10514                canvas = attachInfo.mCanvas;
10515                if (canvas == null) {
10516                    canvas = new Canvas();
10517                }
10518                canvas.setBitmap(bitmap);
10519                // Temporarily clobber the cached Canvas in case one of our children
10520                // is also using a drawing cache. Without this, the children would
10521                // steal the canvas by attaching their own bitmap to it and bad, bad
10522                // thing would happen (invisible views, corrupted drawings, etc.)
10523                attachInfo.mCanvas = null;
10524            } else {
10525                // This case should hopefully never or seldom happen
10526                canvas = new Canvas(bitmap);
10527            }
10528
10529            if (clear) {
10530                bitmap.eraseColor(drawingCacheBackgroundColor);
10531            }
10532
10533            computeScroll();
10534            final int restoreCount = canvas.save();
10535
10536            if (autoScale && scalingRequired) {
10537                final float scale = attachInfo.mApplicationScale;
10538                canvas.scale(scale, scale);
10539            }
10540
10541            canvas.translate(-mScrollX, -mScrollY);
10542
10543            mPrivateFlags |= DRAWN;
10544            if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
10545                    mLayerType != LAYER_TYPE_NONE) {
10546                mPrivateFlags |= DRAWING_CACHE_VALID;
10547            }
10548
10549            // Fast path for layouts with no backgrounds
10550            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10551                if (ViewDebug.TRACE_HIERARCHY) {
10552                    ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
10553                }
10554                mPrivateFlags &= ~DIRTY_MASK;
10555                dispatchDraw(canvas);
10556            } else {
10557                draw(canvas);
10558            }
10559
10560            canvas.restoreToCount(restoreCount);
10561            canvas.setBitmap(null);
10562
10563            if (attachInfo != null) {
10564                // Restore the cached Canvas for our siblings
10565                attachInfo.mCanvas = canvas;
10566            }
10567        }
10568    }
10569
10570    /**
10571     * Create a snapshot of the view into a bitmap.  We should probably make
10572     * some form of this public, but should think about the API.
10573     */
10574    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
10575        int width = mRight - mLeft;
10576        int height = mBottom - mTop;
10577
10578        final AttachInfo attachInfo = mAttachInfo;
10579        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
10580        width = (int) ((width * scale) + 0.5f);
10581        height = (int) ((height * scale) + 0.5f);
10582
10583        Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
10584        if (bitmap == null) {
10585            throw new OutOfMemoryError();
10586        }
10587
10588        Resources resources = getResources();
10589        if (resources != null) {
10590            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
10591        }
10592
10593        Canvas canvas;
10594        if (attachInfo != null) {
10595            canvas = attachInfo.mCanvas;
10596            if (canvas == null) {
10597                canvas = new Canvas();
10598            }
10599            canvas.setBitmap(bitmap);
10600            // Temporarily clobber the cached Canvas in case one of our children
10601            // is also using a drawing cache. Without this, the children would
10602            // steal the canvas by attaching their own bitmap to it and bad, bad
10603            // things would happen (invisible views, corrupted drawings, etc.)
10604            attachInfo.mCanvas = null;
10605        } else {
10606            // This case should hopefully never or seldom happen
10607            canvas = new Canvas(bitmap);
10608        }
10609
10610        if ((backgroundColor & 0xff000000) != 0) {
10611            bitmap.eraseColor(backgroundColor);
10612        }
10613
10614        computeScroll();
10615        final int restoreCount = canvas.save();
10616        canvas.scale(scale, scale);
10617        canvas.translate(-mScrollX, -mScrollY);
10618
10619        // Temporarily remove the dirty mask
10620        int flags = mPrivateFlags;
10621        mPrivateFlags &= ~DIRTY_MASK;
10622
10623        // Fast path for layouts with no backgrounds
10624        if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10625            dispatchDraw(canvas);
10626        } else {
10627            draw(canvas);
10628        }
10629
10630        mPrivateFlags = flags;
10631
10632        canvas.restoreToCount(restoreCount);
10633        canvas.setBitmap(null);
10634
10635        if (attachInfo != null) {
10636            // Restore the cached Canvas for our siblings
10637            attachInfo.mCanvas = canvas;
10638        }
10639
10640        return bitmap;
10641    }
10642
10643    /**
10644     * Indicates whether this View is currently in edit mode. A View is usually
10645     * in edit mode when displayed within a developer tool. For instance, if
10646     * this View is being drawn by a visual user interface builder, this method
10647     * should return true.
10648     *
10649     * Subclasses should check the return value of this method to provide
10650     * different behaviors if their normal behavior might interfere with the
10651     * host environment. For instance: the class spawns a thread in its
10652     * constructor, the drawing code relies on device-specific features, etc.
10653     *
10654     * This method is usually checked in the drawing code of custom widgets.
10655     *
10656     * @return True if this View is in edit mode, false otherwise.
10657     */
10658    public boolean isInEditMode() {
10659        return false;
10660    }
10661
10662    /**
10663     * If the View draws content inside its padding and enables fading edges,
10664     * it needs to support padding offsets. Padding offsets are added to the
10665     * fading edges to extend the length of the fade so that it covers pixels
10666     * drawn inside the padding.
10667     *
10668     * Subclasses of this class should override this method if they need
10669     * to draw content inside the padding.
10670     *
10671     * @return True if padding offset must be applied, false otherwise.
10672     *
10673     * @see #getLeftPaddingOffset()
10674     * @see #getRightPaddingOffset()
10675     * @see #getTopPaddingOffset()
10676     * @see #getBottomPaddingOffset()
10677     *
10678     * @since CURRENT
10679     */
10680    protected boolean isPaddingOffsetRequired() {
10681        return false;
10682    }
10683
10684    /**
10685     * Amount by which to extend the left fading region. Called only when
10686     * {@link #isPaddingOffsetRequired()} returns true.
10687     *
10688     * @return The left padding offset in pixels.
10689     *
10690     * @see #isPaddingOffsetRequired()
10691     *
10692     * @since CURRENT
10693     */
10694    protected int getLeftPaddingOffset() {
10695        return 0;
10696    }
10697
10698    /**
10699     * Amount by which to extend the right fading region. Called only when
10700     * {@link #isPaddingOffsetRequired()} returns true.
10701     *
10702     * @return The right padding offset in pixels.
10703     *
10704     * @see #isPaddingOffsetRequired()
10705     *
10706     * @since CURRENT
10707     */
10708    protected int getRightPaddingOffset() {
10709        return 0;
10710    }
10711
10712    /**
10713     * Amount by which to extend the top fading region. Called only when
10714     * {@link #isPaddingOffsetRequired()} returns true.
10715     *
10716     * @return The top padding offset in pixels.
10717     *
10718     * @see #isPaddingOffsetRequired()
10719     *
10720     * @since CURRENT
10721     */
10722    protected int getTopPaddingOffset() {
10723        return 0;
10724    }
10725
10726    /**
10727     * Amount by which to extend the bottom fading region. Called only when
10728     * {@link #isPaddingOffsetRequired()} returns true.
10729     *
10730     * @return The bottom padding offset in pixels.
10731     *
10732     * @see #isPaddingOffsetRequired()
10733     *
10734     * @since CURRENT
10735     */
10736    protected int getBottomPaddingOffset() {
10737        return 0;
10738    }
10739
10740    /**
10741     * @hide
10742     * @param offsetRequired
10743     */
10744    protected int getFadeTop(boolean offsetRequired) {
10745        int top = mPaddingTop;
10746        if (offsetRequired) top += getTopPaddingOffset();
10747        return top;
10748    }
10749
10750    /**
10751     * @hide
10752     * @param offsetRequired
10753     */
10754    protected int getFadeHeight(boolean offsetRequired) {
10755        int padding = mPaddingTop;
10756        if (offsetRequired) padding += getTopPaddingOffset();
10757        return mBottom - mTop - mPaddingBottom - padding;
10758    }
10759
10760    /**
10761     * <p>Indicates whether this view is attached to an hardware accelerated
10762     * window or not.</p>
10763     *
10764     * <p>Even if this method returns true, it does not mean that every call
10765     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
10766     * accelerated {@link android.graphics.Canvas}. For instance, if this view
10767     * is drawn onto an offscren {@link android.graphics.Bitmap} and its
10768     * window is hardware accelerated,
10769     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
10770     * return false, and this method will return true.</p>
10771     *
10772     * @return True if the view is attached to a window and the window is
10773     *         hardware accelerated; false in any other case.
10774     */
10775    public boolean isHardwareAccelerated() {
10776        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
10777    }
10778
10779    /**
10780     * Manually render this view (and all of its children) to the given Canvas.
10781     * The view must have already done a full layout before this function is
10782     * called.  When implementing a view, implement
10783     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
10784     * If you do need to override this method, call the superclass version.
10785     *
10786     * @param canvas The Canvas to which the View is rendered.
10787     */
10788    public void draw(Canvas canvas) {
10789        if (ViewDebug.TRACE_HIERARCHY) {
10790            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
10791        }
10792
10793        final int privateFlags = mPrivateFlags;
10794        final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
10795                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
10796        mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
10797
10798        /*
10799         * Draw traversal performs several drawing steps which must be executed
10800         * in the appropriate order:
10801         *
10802         *      1. Draw the background
10803         *      2. If necessary, save the canvas' layers to prepare for fading
10804         *      3. Draw view's content
10805         *      4. Draw children
10806         *      5. If necessary, draw the fading edges and restore layers
10807         *      6. Draw decorations (scrollbars for instance)
10808         */
10809
10810        // Step 1, draw the background, if needed
10811        int saveCount;
10812
10813        if (!dirtyOpaque) {
10814            final Drawable background = mBGDrawable;
10815            if (background != null) {
10816                final int scrollX = mScrollX;
10817                final int scrollY = mScrollY;
10818
10819                if (mBackgroundSizeChanged) {
10820                    background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
10821                    mBackgroundSizeChanged = false;
10822                }
10823
10824                if ((scrollX | scrollY) == 0) {
10825                    background.draw(canvas);
10826                } else {
10827                    canvas.translate(scrollX, scrollY);
10828                    background.draw(canvas);
10829                    canvas.translate(-scrollX, -scrollY);
10830                }
10831            }
10832        }
10833
10834        // skip step 2 & 5 if possible (common case)
10835        final int viewFlags = mViewFlags;
10836        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
10837        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
10838        if (!verticalEdges && !horizontalEdges) {
10839            // Step 3, draw the content
10840            if (!dirtyOpaque) onDraw(canvas);
10841
10842            // Step 4, draw the children
10843            dispatchDraw(canvas);
10844
10845            // Step 6, draw decorations (scrollbars)
10846            onDrawScrollBars(canvas);
10847
10848            // we're done...
10849            return;
10850        }
10851
10852        /*
10853         * Here we do the full fledged routine...
10854         * (this is an uncommon case where speed matters less,
10855         * this is why we repeat some of the tests that have been
10856         * done above)
10857         */
10858
10859        boolean drawTop = false;
10860        boolean drawBottom = false;
10861        boolean drawLeft = false;
10862        boolean drawRight = false;
10863
10864        float topFadeStrength = 0.0f;
10865        float bottomFadeStrength = 0.0f;
10866        float leftFadeStrength = 0.0f;
10867        float rightFadeStrength = 0.0f;
10868
10869        // Step 2, save the canvas' layers
10870        int paddingLeft = mPaddingLeft;
10871
10872        final boolean offsetRequired = isPaddingOffsetRequired();
10873        if (offsetRequired) {
10874            paddingLeft += getLeftPaddingOffset();
10875        }
10876
10877        int left = mScrollX + paddingLeft;
10878        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
10879        int top = mScrollY + getFadeTop(offsetRequired);
10880        int bottom = top + getFadeHeight(offsetRequired);
10881
10882        if (offsetRequired) {
10883            right += getRightPaddingOffset();
10884            bottom += getBottomPaddingOffset();
10885        }
10886
10887        final ScrollabilityCache scrollabilityCache = mScrollCache;
10888        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
10889        int length = (int) fadeHeight;
10890
10891        // clip the fade length if top and bottom fades overlap
10892        // overlapping fades produce odd-looking artifacts
10893        if (verticalEdges && (top + length > bottom - length)) {
10894            length = (bottom - top) / 2;
10895        }
10896
10897        // also clip horizontal fades if necessary
10898        if (horizontalEdges && (left + length > right - length)) {
10899            length = (right - left) / 2;
10900        }
10901
10902        if (verticalEdges) {
10903            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
10904            drawTop = topFadeStrength * fadeHeight > 1.0f;
10905            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
10906            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
10907        }
10908
10909        if (horizontalEdges) {
10910            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
10911            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
10912            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
10913            drawRight = rightFadeStrength * fadeHeight > 1.0f;
10914        }
10915
10916        saveCount = canvas.getSaveCount();
10917
10918        int solidColor = getSolidColor();
10919        if (solidColor == 0) {
10920            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
10921
10922            if (drawTop) {
10923                canvas.saveLayer(left, top, right, top + length, null, flags);
10924            }
10925
10926            if (drawBottom) {
10927                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
10928            }
10929
10930            if (drawLeft) {
10931                canvas.saveLayer(left, top, left + length, bottom, null, flags);
10932            }
10933
10934            if (drawRight) {
10935                canvas.saveLayer(right - length, top, right, bottom, null, flags);
10936            }
10937        } else {
10938            scrollabilityCache.setFadeColor(solidColor);
10939        }
10940
10941        // Step 3, draw the content
10942        if (!dirtyOpaque) onDraw(canvas);
10943
10944        // Step 4, draw the children
10945        dispatchDraw(canvas);
10946
10947        // Step 5, draw the fade effect and restore layers
10948        final Paint p = scrollabilityCache.paint;
10949        final Matrix matrix = scrollabilityCache.matrix;
10950        final Shader fade = scrollabilityCache.shader;
10951
10952        if (drawTop) {
10953            matrix.setScale(1, fadeHeight * topFadeStrength);
10954            matrix.postTranslate(left, top);
10955            fade.setLocalMatrix(matrix);
10956            canvas.drawRect(left, top, right, top + length, p);
10957        }
10958
10959        if (drawBottom) {
10960            matrix.setScale(1, fadeHeight * bottomFadeStrength);
10961            matrix.postRotate(180);
10962            matrix.postTranslate(left, bottom);
10963            fade.setLocalMatrix(matrix);
10964            canvas.drawRect(left, bottom - length, right, bottom, p);
10965        }
10966
10967        if (drawLeft) {
10968            matrix.setScale(1, fadeHeight * leftFadeStrength);
10969            matrix.postRotate(-90);
10970            matrix.postTranslate(left, top);
10971            fade.setLocalMatrix(matrix);
10972            canvas.drawRect(left, top, left + length, bottom, p);
10973        }
10974
10975        if (drawRight) {
10976            matrix.setScale(1, fadeHeight * rightFadeStrength);
10977            matrix.postRotate(90);
10978            matrix.postTranslate(right, top);
10979            fade.setLocalMatrix(matrix);
10980            canvas.drawRect(right - length, top, right, bottom, p);
10981        }
10982
10983        canvas.restoreToCount(saveCount);
10984
10985        // Step 6, draw decorations (scrollbars)
10986        onDrawScrollBars(canvas);
10987    }
10988
10989    /**
10990     * Override this if your view is known to always be drawn on top of a solid color background,
10991     * and needs to draw fading edges. Returning a non-zero color enables the view system to
10992     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
10993     * should be set to 0xFF.
10994     *
10995     * @see #setVerticalFadingEdgeEnabled(boolean)
10996     * @see #setHorizontalFadingEdgeEnabled(boolean)
10997     *
10998     * @return The known solid color background for this view, or 0 if the color may vary
10999     */
11000    @ViewDebug.ExportedProperty(category = "drawing")
11001    public int getSolidColor() {
11002        return 0;
11003    }
11004
11005    /**
11006     * Build a human readable string representation of the specified view flags.
11007     *
11008     * @param flags the view flags to convert to a string
11009     * @return a String representing the supplied flags
11010     */
11011    private static String printFlags(int flags) {
11012        String output = "";
11013        int numFlags = 0;
11014        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
11015            output += "TAKES_FOCUS";
11016            numFlags++;
11017        }
11018
11019        switch (flags & VISIBILITY_MASK) {
11020        case INVISIBLE:
11021            if (numFlags > 0) {
11022                output += " ";
11023            }
11024            output += "INVISIBLE";
11025            // USELESS HERE numFlags++;
11026            break;
11027        case GONE:
11028            if (numFlags > 0) {
11029                output += " ";
11030            }
11031            output += "GONE";
11032            // USELESS HERE numFlags++;
11033            break;
11034        default:
11035            break;
11036        }
11037        return output;
11038    }
11039
11040    /**
11041     * Build a human readable string representation of the specified private
11042     * view flags.
11043     *
11044     * @param privateFlags the private view flags to convert to a string
11045     * @return a String representing the supplied flags
11046     */
11047    private static String printPrivateFlags(int privateFlags) {
11048        String output = "";
11049        int numFlags = 0;
11050
11051        if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
11052            output += "WANTS_FOCUS";
11053            numFlags++;
11054        }
11055
11056        if ((privateFlags & FOCUSED) == FOCUSED) {
11057            if (numFlags > 0) {
11058                output += " ";
11059            }
11060            output += "FOCUSED";
11061            numFlags++;
11062        }
11063
11064        if ((privateFlags & SELECTED) == SELECTED) {
11065            if (numFlags > 0) {
11066                output += " ";
11067            }
11068            output += "SELECTED";
11069            numFlags++;
11070        }
11071
11072        if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
11073            if (numFlags > 0) {
11074                output += " ";
11075            }
11076            output += "IS_ROOT_NAMESPACE";
11077            numFlags++;
11078        }
11079
11080        if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
11081            if (numFlags > 0) {
11082                output += " ";
11083            }
11084            output += "HAS_BOUNDS";
11085            numFlags++;
11086        }
11087
11088        if ((privateFlags & DRAWN) == DRAWN) {
11089            if (numFlags > 0) {
11090                output += " ";
11091            }
11092            output += "DRAWN";
11093            // USELESS HERE numFlags++;
11094        }
11095        return output;
11096    }
11097
11098    /**
11099     * <p>Indicates whether or not this view's layout will be requested during
11100     * the next hierarchy layout pass.</p>
11101     *
11102     * @return true if the layout will be forced during next layout pass
11103     */
11104    public boolean isLayoutRequested() {
11105        return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
11106    }
11107
11108    /**
11109     * Assign a size and position to a view and all of its
11110     * descendants
11111     *
11112     * <p>This is the second phase of the layout mechanism.
11113     * (The first is measuring). In this phase, each parent calls
11114     * layout on all of its children to position them.
11115     * This is typically done using the child measurements
11116     * that were stored in the measure pass().</p>
11117     *
11118     * <p>Derived classes should not override this method.
11119     * Derived classes with children should override
11120     * onLayout. In that method, they should
11121     * call layout on each of their children.</p>
11122     *
11123     * @param l Left position, relative to parent
11124     * @param t Top position, relative to parent
11125     * @param r Right position, relative to parent
11126     * @param b Bottom position, relative to parent
11127     */
11128    @SuppressWarnings({"unchecked"})
11129    public void layout(int l, int t, int r, int b) {
11130        int oldL = mLeft;
11131        int oldT = mTop;
11132        int oldB = mBottom;
11133        int oldR = mRight;
11134        boolean changed = setFrame(l, t, r, b);
11135        if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
11136            if (ViewDebug.TRACE_HIERARCHY) {
11137                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
11138            }
11139
11140            onLayout(changed, l, t, r, b);
11141            mPrivateFlags &= ~LAYOUT_REQUIRED;
11142
11143            if (mOnLayoutChangeListeners != null) {
11144                ArrayList<OnLayoutChangeListener> listenersCopy =
11145                        (ArrayList<OnLayoutChangeListener>) mOnLayoutChangeListeners.clone();
11146                int numListeners = listenersCopy.size();
11147                for (int i = 0; i < numListeners; ++i) {
11148                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
11149                }
11150            }
11151        }
11152        mPrivateFlags &= ~FORCE_LAYOUT;
11153    }
11154
11155    /**
11156     * Called from layout when this view should
11157     * assign a size and position to each of its children.
11158     *
11159     * Derived classes with children should override
11160     * this method and call layout on each of
11161     * their children.
11162     * @param changed This is a new size or position for this view
11163     * @param left Left position, relative to parent
11164     * @param top Top position, relative to parent
11165     * @param right Right position, relative to parent
11166     * @param bottom Bottom position, relative to parent
11167     */
11168    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
11169    }
11170
11171    /**
11172     * Assign a size and position to this view.
11173     *
11174     * This is called from layout.
11175     *
11176     * @param left Left position, relative to parent
11177     * @param top Top position, relative to parent
11178     * @param right Right position, relative to parent
11179     * @param bottom Bottom position, relative to parent
11180     * @return true if the new size and position are different than the
11181     *         previous ones
11182     * {@hide}
11183     */
11184    protected boolean setFrame(int left, int top, int right, int bottom) {
11185        boolean changed = false;
11186
11187        if (DBG) {
11188            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
11189                    + right + "," + bottom + ")");
11190        }
11191
11192        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
11193            changed = true;
11194
11195            // Remember our drawn bit
11196            int drawn = mPrivateFlags & DRAWN;
11197
11198            int oldWidth = mRight - mLeft;
11199            int oldHeight = mBottom - mTop;
11200            int newWidth = right - left;
11201            int newHeight = bottom - top;
11202            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
11203
11204            // Invalidate our old position
11205            invalidate(sizeChanged);
11206
11207            mLeft = left;
11208            mTop = top;
11209            mRight = right;
11210            mBottom = bottom;
11211
11212            mPrivateFlags |= HAS_BOUNDS;
11213
11214
11215            if (sizeChanged) {
11216                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
11217                    // A change in dimension means an auto-centered pivot point changes, too
11218                    if (mTransformationInfo != null) {
11219                        mTransformationInfo.mMatrixDirty = true;
11220                    }
11221                }
11222                onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
11223            }
11224
11225            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
11226                // If we are visible, force the DRAWN bit to on so that
11227                // this invalidate will go through (at least to our parent).
11228                // This is because someone may have invalidated this view
11229                // before this call to setFrame came in, thereby clearing
11230                // the DRAWN bit.
11231                mPrivateFlags |= DRAWN;
11232                invalidate(sizeChanged);
11233                // parent display list may need to be recreated based on a change in the bounds
11234                // of any child
11235                invalidateParentCaches();
11236            }
11237
11238            // Reset drawn bit to original value (invalidate turns it off)
11239            mPrivateFlags |= drawn;
11240
11241            mBackgroundSizeChanged = true;
11242        }
11243        return changed;
11244    }
11245
11246    /**
11247     * Finalize inflating a view from XML.  This is called as the last phase
11248     * of inflation, after all child views have been added.
11249     *
11250     * <p>Even if the subclass overrides onFinishInflate, they should always be
11251     * sure to call the super method, so that we get called.
11252     */
11253    protected void onFinishInflate() {
11254    }
11255
11256    /**
11257     * Returns the resources associated with this view.
11258     *
11259     * @return Resources object.
11260     */
11261    public Resources getResources() {
11262        return mResources;
11263    }
11264
11265    /**
11266     * Invalidates the specified Drawable.
11267     *
11268     * @param drawable the drawable to invalidate
11269     */
11270    public void invalidateDrawable(Drawable drawable) {
11271        if (verifyDrawable(drawable)) {
11272            final Rect dirty = drawable.getBounds();
11273            final int scrollX = mScrollX;
11274            final int scrollY = mScrollY;
11275
11276            invalidate(dirty.left + scrollX, dirty.top + scrollY,
11277                    dirty.right + scrollX, dirty.bottom + scrollY);
11278        }
11279    }
11280
11281    /**
11282     * Schedules an action on a drawable to occur at a specified time.
11283     *
11284     * @param who the recipient of the action
11285     * @param what the action to run on the drawable
11286     * @param when the time at which the action must occur. Uses the
11287     *        {@link SystemClock#uptimeMillis} timebase.
11288     */
11289    public void scheduleDrawable(Drawable who, Runnable what, long when) {
11290        if (verifyDrawable(who) && what != null && mAttachInfo != null) {
11291            mAttachInfo.mHandler.postAtTime(what, who, when);
11292        }
11293    }
11294
11295    /**
11296     * Cancels a scheduled action on a drawable.
11297     *
11298     * @param who the recipient of the action
11299     * @param what the action to cancel
11300     */
11301    public void unscheduleDrawable(Drawable who, Runnable what) {
11302        if (verifyDrawable(who) && what != null && mAttachInfo != null) {
11303            mAttachInfo.mHandler.removeCallbacks(what, who);
11304        }
11305    }
11306
11307    /**
11308     * Unschedule any events associated with the given Drawable.  This can be
11309     * used when selecting a new Drawable into a view, so that the previous
11310     * one is completely unscheduled.
11311     *
11312     * @param who The Drawable to unschedule.
11313     *
11314     * @see #drawableStateChanged
11315     */
11316    public void unscheduleDrawable(Drawable who) {
11317        if (mAttachInfo != null) {
11318            mAttachInfo.mHandler.removeCallbacksAndMessages(who);
11319        }
11320    }
11321
11322    /**
11323    * Return the layout direction of a given Drawable.
11324    *
11325    * @param who the Drawable to query
11326    *
11327    * @hide
11328    */
11329    public int getResolvedLayoutDirection(Drawable who) {
11330        return (who == mBGDrawable) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT;
11331    }
11332
11333    /**
11334     * If your view subclass is displaying its own Drawable objects, it should
11335     * override this function and return true for any Drawable it is
11336     * displaying.  This allows animations for those drawables to be
11337     * scheduled.
11338     *
11339     * <p>Be sure to call through to the super class when overriding this
11340     * function.
11341     *
11342     * @param who The Drawable to verify.  Return true if it is one you are
11343     *            displaying, else return the result of calling through to the
11344     *            super class.
11345     *
11346     * @return boolean If true than the Drawable is being displayed in the
11347     *         view; else false and it is not allowed to animate.
11348     *
11349     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
11350     * @see #drawableStateChanged()
11351     */
11352    protected boolean verifyDrawable(Drawable who) {
11353        return who == mBGDrawable;
11354    }
11355
11356    /**
11357     * This function is called whenever the state of the view changes in such
11358     * a way that it impacts the state of drawables being shown.
11359     *
11360     * <p>Be sure to call through to the superclass when overriding this
11361     * function.
11362     *
11363     * @see Drawable#setState(int[])
11364     */
11365    protected void drawableStateChanged() {
11366        Drawable d = mBGDrawable;
11367        if (d != null && d.isStateful()) {
11368            d.setState(getDrawableState());
11369        }
11370    }
11371
11372    /**
11373     * Call this to force a view to update its drawable state. This will cause
11374     * drawableStateChanged to be called on this view. Views that are interested
11375     * in the new state should call getDrawableState.
11376     *
11377     * @see #drawableStateChanged
11378     * @see #getDrawableState
11379     */
11380    public void refreshDrawableState() {
11381        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
11382        drawableStateChanged();
11383
11384        ViewParent parent = mParent;
11385        if (parent != null) {
11386            parent.childDrawableStateChanged(this);
11387        }
11388    }
11389
11390    /**
11391     * Return an array of resource IDs of the drawable states representing the
11392     * current state of the view.
11393     *
11394     * @return The current drawable state
11395     *
11396     * @see Drawable#setState(int[])
11397     * @see #drawableStateChanged()
11398     * @see #onCreateDrawableState(int)
11399     */
11400    public final int[] getDrawableState() {
11401        if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
11402            return mDrawableState;
11403        } else {
11404            mDrawableState = onCreateDrawableState(0);
11405            mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
11406            return mDrawableState;
11407        }
11408    }
11409
11410    /**
11411     * Generate the new {@link android.graphics.drawable.Drawable} state for
11412     * this view. This is called by the view
11413     * system when the cached Drawable state is determined to be invalid.  To
11414     * retrieve the current state, you should use {@link #getDrawableState}.
11415     *
11416     * @param extraSpace if non-zero, this is the number of extra entries you
11417     * would like in the returned array in which you can place your own
11418     * states.
11419     *
11420     * @return Returns an array holding the current {@link Drawable} state of
11421     * the view.
11422     *
11423     * @see #mergeDrawableStates(int[], int[])
11424     */
11425    protected int[] onCreateDrawableState(int extraSpace) {
11426        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
11427                mParent instanceof View) {
11428            return ((View) mParent).onCreateDrawableState(extraSpace);
11429        }
11430
11431        int[] drawableState;
11432
11433        int privateFlags = mPrivateFlags;
11434
11435        int viewStateIndex = 0;
11436        if ((privateFlags & PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
11437        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
11438        if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
11439        if ((privateFlags & SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
11440        if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
11441        if ((privateFlags & ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
11442        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
11443                HardwareRenderer.isAvailable()) {
11444            // This is set if HW acceleration is requested, even if the current
11445            // process doesn't allow it.  This is just to allow app preview
11446            // windows to better match their app.
11447            viewStateIndex |= VIEW_STATE_ACCELERATED;
11448        }
11449        if ((privateFlags & HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
11450
11451        final int privateFlags2 = mPrivateFlags2;
11452        if ((privateFlags2 & DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
11453        if ((privateFlags2 & DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
11454
11455        drawableState = VIEW_STATE_SETS[viewStateIndex];
11456
11457        //noinspection ConstantIfStatement
11458        if (false) {
11459            Log.i("View", "drawableStateIndex=" + viewStateIndex);
11460            Log.i("View", toString()
11461                    + " pressed=" + ((privateFlags & PRESSED) != 0)
11462                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
11463                    + " fo=" + hasFocus()
11464                    + " sl=" + ((privateFlags & SELECTED) != 0)
11465                    + " wf=" + hasWindowFocus()
11466                    + ": " + Arrays.toString(drawableState));
11467        }
11468
11469        if (extraSpace == 0) {
11470            return drawableState;
11471        }
11472
11473        final int[] fullState;
11474        if (drawableState != null) {
11475            fullState = new int[drawableState.length + extraSpace];
11476            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
11477        } else {
11478            fullState = new int[extraSpace];
11479        }
11480
11481        return fullState;
11482    }
11483
11484    /**
11485     * Merge your own state values in <var>additionalState</var> into the base
11486     * state values <var>baseState</var> that were returned by
11487     * {@link #onCreateDrawableState(int)}.
11488     *
11489     * @param baseState The base state values returned by
11490     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
11491     * own additional state values.
11492     *
11493     * @param additionalState The additional state values you would like
11494     * added to <var>baseState</var>; this array is not modified.
11495     *
11496     * @return As a convenience, the <var>baseState</var> array you originally
11497     * passed into the function is returned.
11498     *
11499     * @see #onCreateDrawableState(int)
11500     */
11501    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
11502        final int N = baseState.length;
11503        int i = N - 1;
11504        while (i >= 0 && baseState[i] == 0) {
11505            i--;
11506        }
11507        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
11508        return baseState;
11509    }
11510
11511    /**
11512     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
11513     * on all Drawable objects associated with this view.
11514     */
11515    public void jumpDrawablesToCurrentState() {
11516        if (mBGDrawable != null) {
11517            mBGDrawable.jumpToCurrentState();
11518        }
11519    }
11520
11521    /**
11522     * Sets the background color for this view.
11523     * @param color the color of the background
11524     */
11525    @RemotableViewMethod
11526    public void setBackgroundColor(int color) {
11527        if (mBGDrawable instanceof ColorDrawable) {
11528            ((ColorDrawable) mBGDrawable).setColor(color);
11529        } else {
11530            setBackgroundDrawable(new ColorDrawable(color));
11531        }
11532    }
11533
11534    /**
11535     * Set the background to a given resource. The resource should refer to
11536     * a Drawable object or 0 to remove the background.
11537     * @param resid The identifier of the resource.
11538     * @attr ref android.R.styleable#View_background
11539     */
11540    @RemotableViewMethod
11541    public void setBackgroundResource(int resid) {
11542        if (resid != 0 && resid == mBackgroundResource) {
11543            return;
11544        }
11545
11546        Drawable d= null;
11547        if (resid != 0) {
11548            d = mResources.getDrawable(resid);
11549        }
11550        setBackgroundDrawable(d);
11551
11552        mBackgroundResource = resid;
11553    }
11554
11555    /**
11556     * Set the background to a given Drawable, or remove the background. If the
11557     * background has padding, this View's padding is set to the background's
11558     * padding. However, when a background is removed, this View's padding isn't
11559     * touched. If setting the padding is desired, please use
11560     * {@link #setPadding(int, int, int, int)}.
11561     *
11562     * @param d The Drawable to use as the background, or null to remove the
11563     *        background
11564     */
11565    public void setBackgroundDrawable(Drawable d) {
11566        if (d == mBGDrawable) {
11567            return;
11568        }
11569
11570        boolean requestLayout = false;
11571
11572        mBackgroundResource = 0;
11573
11574        /*
11575         * Regardless of whether we're setting a new background or not, we want
11576         * to clear the previous drawable.
11577         */
11578        if (mBGDrawable != null) {
11579            mBGDrawable.setCallback(null);
11580            unscheduleDrawable(mBGDrawable);
11581        }
11582
11583        if (d != null) {
11584            Rect padding = sThreadLocal.get();
11585            if (padding == null) {
11586                padding = new Rect();
11587                sThreadLocal.set(padding);
11588            }
11589            if (d.getPadding(padding)) {
11590                switch (d.getResolvedLayoutDirectionSelf()) {
11591                    case LAYOUT_DIRECTION_RTL:
11592                        setPadding(padding.right, padding.top, padding.left, padding.bottom);
11593                        break;
11594                    case LAYOUT_DIRECTION_LTR:
11595                    default:
11596                        setPadding(padding.left, padding.top, padding.right, padding.bottom);
11597                }
11598            }
11599
11600            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
11601            // if it has a different minimum size, we should layout again
11602            if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
11603                    mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
11604                requestLayout = true;
11605            }
11606
11607            d.setCallback(this);
11608            if (d.isStateful()) {
11609                d.setState(getDrawableState());
11610            }
11611            d.setVisible(getVisibility() == VISIBLE, false);
11612            mBGDrawable = d;
11613
11614            if ((mPrivateFlags & SKIP_DRAW) != 0) {
11615                mPrivateFlags &= ~SKIP_DRAW;
11616                mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
11617                requestLayout = true;
11618            }
11619        } else {
11620            /* Remove the background */
11621            mBGDrawable = null;
11622
11623            if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
11624                /*
11625                 * This view ONLY drew the background before and we're removing
11626                 * the background, so now it won't draw anything
11627                 * (hence we SKIP_DRAW)
11628                 */
11629                mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
11630                mPrivateFlags |= SKIP_DRAW;
11631            }
11632
11633            /*
11634             * When the background is set, we try to apply its padding to this
11635             * View. When the background is removed, we don't touch this View's
11636             * padding. This is noted in the Javadocs. Hence, we don't need to
11637             * requestLayout(), the invalidate() below is sufficient.
11638             */
11639
11640            // The old background's minimum size could have affected this
11641            // View's layout, so let's requestLayout
11642            requestLayout = true;
11643        }
11644
11645        computeOpaqueFlags();
11646
11647        if (requestLayout) {
11648            requestLayout();
11649        }
11650
11651        mBackgroundSizeChanged = true;
11652        invalidate(true);
11653    }
11654
11655    /**
11656     * Gets the background drawable
11657     * @return The drawable used as the background for this view, if any.
11658     */
11659    public Drawable getBackground() {
11660        return mBGDrawable;
11661    }
11662
11663    /**
11664     * Sets the padding. The view may add on the space required to display
11665     * the scrollbars, depending on the style and visibility of the scrollbars.
11666     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
11667     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
11668     * from the values set in this call.
11669     *
11670     * @attr ref android.R.styleable#View_padding
11671     * @attr ref android.R.styleable#View_paddingBottom
11672     * @attr ref android.R.styleable#View_paddingLeft
11673     * @attr ref android.R.styleable#View_paddingRight
11674     * @attr ref android.R.styleable#View_paddingTop
11675     * @param left the left padding in pixels
11676     * @param top the top padding in pixels
11677     * @param right the right padding in pixels
11678     * @param bottom the bottom padding in pixels
11679     */
11680    public void setPadding(int left, int top, int right, int bottom) {
11681        boolean changed = false;
11682
11683        mUserPaddingRelative = false;
11684
11685        mUserPaddingLeft = left;
11686        mUserPaddingRight = right;
11687        mUserPaddingBottom = bottom;
11688
11689        final int viewFlags = mViewFlags;
11690
11691        // Common case is there are no scroll bars.
11692        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
11693            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
11694                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
11695                        ? 0 : getVerticalScrollbarWidth();
11696                switch (mVerticalScrollbarPosition) {
11697                    case SCROLLBAR_POSITION_DEFAULT:
11698                        if (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
11699                            left += offset;
11700                        } else {
11701                            right += offset;
11702                        }
11703                        break;
11704                    case SCROLLBAR_POSITION_RIGHT:
11705                        right += offset;
11706                        break;
11707                    case SCROLLBAR_POSITION_LEFT:
11708                        left += offset;
11709                        break;
11710                }
11711            }
11712            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
11713                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
11714                        ? 0 : getHorizontalScrollbarHeight();
11715            }
11716        }
11717
11718        if (mPaddingLeft != left) {
11719            changed = true;
11720            mPaddingLeft = left;
11721        }
11722        if (mPaddingTop != top) {
11723            changed = true;
11724            mPaddingTop = top;
11725        }
11726        if (mPaddingRight != right) {
11727            changed = true;
11728            mPaddingRight = right;
11729        }
11730        if (mPaddingBottom != bottom) {
11731            changed = true;
11732            mPaddingBottom = bottom;
11733        }
11734
11735        if (changed) {
11736            requestLayout();
11737        }
11738    }
11739
11740    /**
11741     * Sets the relative padding. The view may add on the space required to display
11742     * the scrollbars, depending on the style and visibility of the scrollbars.
11743     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
11744     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
11745     * from the values set in this call.
11746     *
11747     * @attr ref android.R.styleable#View_padding
11748     * @attr ref android.R.styleable#View_paddingBottom
11749     * @attr ref android.R.styleable#View_paddingStart
11750     * @attr ref android.R.styleable#View_paddingEnd
11751     * @attr ref android.R.styleable#View_paddingTop
11752     * @param start the start padding in pixels
11753     * @param top the top padding in pixels
11754     * @param end the end padding in pixels
11755     * @param bottom the bottom padding in pixels
11756     *
11757     * @hide
11758     */
11759    public void setPaddingRelative(int start, int top, int end, int bottom) {
11760        mUserPaddingRelative = true;
11761
11762        mUserPaddingStart = start;
11763        mUserPaddingEnd = end;
11764
11765        switch(getResolvedLayoutDirection()) {
11766            case LAYOUT_DIRECTION_RTL:
11767                setPadding(end, top, start, bottom);
11768                break;
11769            case LAYOUT_DIRECTION_LTR:
11770            default:
11771                setPadding(start, top, end, bottom);
11772        }
11773    }
11774
11775    /**
11776     * Returns the top padding of this view.
11777     *
11778     * @return the top padding in pixels
11779     */
11780    public int getPaddingTop() {
11781        return mPaddingTop;
11782    }
11783
11784    /**
11785     * Returns the bottom padding of this view. If there are inset and enabled
11786     * scrollbars, this value may include the space required to display the
11787     * scrollbars as well.
11788     *
11789     * @return the bottom padding in pixels
11790     */
11791    public int getPaddingBottom() {
11792        return mPaddingBottom;
11793    }
11794
11795    /**
11796     * Returns the left padding of this view. If there are inset and enabled
11797     * scrollbars, this value may include the space required to display the
11798     * scrollbars as well.
11799     *
11800     * @return the left padding in pixels
11801     */
11802    public int getPaddingLeft() {
11803        return mPaddingLeft;
11804    }
11805
11806    /**
11807     * Returns the start padding of this view. If there are inset and enabled
11808     * scrollbars, this value may include the space required to display the
11809     * scrollbars as well.
11810     *
11811     * @return the start padding in pixels
11812     *
11813     * @hide
11814     */
11815    public int getPaddingStart() {
11816        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
11817                mPaddingRight : mPaddingLeft;
11818    }
11819
11820    /**
11821     * Returns the right padding of this view. If there are inset and enabled
11822     * scrollbars, this value may include the space required to display the
11823     * scrollbars as well.
11824     *
11825     * @return the right padding in pixels
11826     */
11827    public int getPaddingRight() {
11828        return mPaddingRight;
11829    }
11830
11831    /**
11832     * Returns the end padding of this view. If there are inset and enabled
11833     * scrollbars, this value may include the space required to display the
11834     * scrollbars as well.
11835     *
11836     * @return the end padding in pixels
11837     *
11838     * @hide
11839     */
11840    public int getPaddingEnd() {
11841        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
11842                mPaddingLeft : mPaddingRight;
11843    }
11844
11845    /**
11846     * Return if the padding as been set thru relative values
11847     * {@link #setPaddingRelative(int, int, int, int)} or thru
11848     * @attr ref android.R.styleable#View_paddingStart or
11849     * @attr ref android.R.styleable#View_paddingEnd
11850     *
11851     * @return true if the padding is relative or false if it is not.
11852     *
11853     * @hide
11854     */
11855    public boolean isPaddingRelative() {
11856        return mUserPaddingRelative;
11857    }
11858
11859    /**
11860     * Changes the selection state of this view. A view can be selected or not.
11861     * Note that selection is not the same as focus. Views are typically
11862     * selected in the context of an AdapterView like ListView or GridView;
11863     * the selected view is the view that is highlighted.
11864     *
11865     * @param selected true if the view must be selected, false otherwise
11866     */
11867    public void setSelected(boolean selected) {
11868        if (((mPrivateFlags & SELECTED) != 0) != selected) {
11869            mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
11870            if (!selected) resetPressedState();
11871            invalidate(true);
11872            refreshDrawableState();
11873            dispatchSetSelected(selected);
11874        }
11875    }
11876
11877    /**
11878     * Dispatch setSelected to all of this View's children.
11879     *
11880     * @see #setSelected(boolean)
11881     *
11882     * @param selected The new selected state
11883     */
11884    protected void dispatchSetSelected(boolean selected) {
11885    }
11886
11887    /**
11888     * Indicates the selection state of this view.
11889     *
11890     * @return true if the view is selected, false otherwise
11891     */
11892    @ViewDebug.ExportedProperty
11893    public boolean isSelected() {
11894        return (mPrivateFlags & SELECTED) != 0;
11895    }
11896
11897    /**
11898     * Changes the activated state of this view. A view can be activated or not.
11899     * Note that activation is not the same as selection.  Selection is
11900     * a transient property, representing the view (hierarchy) the user is
11901     * currently interacting with.  Activation is a longer-term state that the
11902     * user can move views in and out of.  For example, in a list view with
11903     * single or multiple selection enabled, the views in the current selection
11904     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
11905     * here.)  The activated state is propagated down to children of the view it
11906     * is set on.
11907     *
11908     * @param activated true if the view must be activated, false otherwise
11909     */
11910    public void setActivated(boolean activated) {
11911        if (((mPrivateFlags & ACTIVATED) != 0) != activated) {
11912            mPrivateFlags = (mPrivateFlags & ~ACTIVATED) | (activated ? ACTIVATED : 0);
11913            invalidate(true);
11914            refreshDrawableState();
11915            dispatchSetActivated(activated);
11916        }
11917    }
11918
11919    /**
11920     * Dispatch setActivated to all of this View's children.
11921     *
11922     * @see #setActivated(boolean)
11923     *
11924     * @param activated The new activated state
11925     */
11926    protected void dispatchSetActivated(boolean activated) {
11927    }
11928
11929    /**
11930     * Indicates the activation state of this view.
11931     *
11932     * @return true if the view is activated, false otherwise
11933     */
11934    @ViewDebug.ExportedProperty
11935    public boolean isActivated() {
11936        return (mPrivateFlags & ACTIVATED) != 0;
11937    }
11938
11939    /**
11940     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
11941     * observer can be used to get notifications when global events, like
11942     * layout, happen.
11943     *
11944     * The returned ViewTreeObserver observer is not guaranteed to remain
11945     * valid for the lifetime of this View. If the caller of this method keeps
11946     * a long-lived reference to ViewTreeObserver, it should always check for
11947     * the return value of {@link ViewTreeObserver#isAlive()}.
11948     *
11949     * @return The ViewTreeObserver for this view's hierarchy.
11950     */
11951    public ViewTreeObserver getViewTreeObserver() {
11952        if (mAttachInfo != null) {
11953            return mAttachInfo.mTreeObserver;
11954        }
11955        if (mFloatingTreeObserver == null) {
11956            mFloatingTreeObserver = new ViewTreeObserver();
11957        }
11958        return mFloatingTreeObserver;
11959    }
11960
11961    /**
11962     * <p>Finds the topmost view in the current view hierarchy.</p>
11963     *
11964     * @return the topmost view containing this view
11965     */
11966    public View getRootView() {
11967        if (mAttachInfo != null) {
11968            final View v = mAttachInfo.mRootView;
11969            if (v != null) {
11970                return v;
11971            }
11972        }
11973
11974        View parent = this;
11975
11976        while (parent.mParent != null && parent.mParent instanceof View) {
11977            parent = (View) parent.mParent;
11978        }
11979
11980        return parent;
11981    }
11982
11983    /**
11984     * <p>Computes the coordinates of this view on the screen. The argument
11985     * must be an array of two integers. After the method returns, the array
11986     * contains the x and y location in that order.</p>
11987     *
11988     * @param location an array of two integers in which to hold the coordinates
11989     */
11990    public void getLocationOnScreen(int[] location) {
11991        getLocationInWindow(location);
11992
11993        final AttachInfo info = mAttachInfo;
11994        if (info != null) {
11995            location[0] += info.mWindowLeft;
11996            location[1] += info.mWindowTop;
11997        }
11998    }
11999
12000    /**
12001     * <p>Computes the coordinates of this view in its window. The argument
12002     * must be an array of two integers. After the method returns, the array
12003     * contains the x and y location in that order.</p>
12004     *
12005     * @param location an array of two integers in which to hold the coordinates
12006     */
12007    public void getLocationInWindow(int[] location) {
12008        if (location == null || location.length < 2) {
12009            throw new IllegalArgumentException("location must be an array of "
12010                    + "two integers");
12011        }
12012
12013        location[0] = mLeft;
12014        location[1] = mTop;
12015        if (mTransformationInfo != null) {
12016            location[0] += (int) (mTransformationInfo.mTranslationX + 0.5f);
12017            location[1] += (int) (mTransformationInfo.mTranslationY + 0.5f);
12018        }
12019
12020        ViewParent viewParent = mParent;
12021        while (viewParent instanceof View) {
12022            final View view = (View)viewParent;
12023            location[0] += view.mLeft - view.mScrollX;
12024            location[1] += view.mTop - view.mScrollY;
12025            if (view.mTransformationInfo != null) {
12026                location[0] += (int) (view.mTransformationInfo.mTranslationX + 0.5f);
12027                location[1] += (int) (view.mTransformationInfo.mTranslationY + 0.5f);
12028            }
12029            viewParent = view.mParent;
12030        }
12031
12032        if (viewParent instanceof ViewRootImpl) {
12033            // *cough*
12034            final ViewRootImpl vr = (ViewRootImpl)viewParent;
12035            location[1] -= vr.mCurScrollY;
12036        }
12037    }
12038
12039    /**
12040     * {@hide}
12041     * @param id the id of the view to be found
12042     * @return the view of the specified id, null if cannot be found
12043     */
12044    protected View findViewTraversal(int id) {
12045        if (id == mID) {
12046            return this;
12047        }
12048        return null;
12049    }
12050
12051    /**
12052     * {@hide}
12053     * @param tag the tag of the view to be found
12054     * @return the view of specified tag, null if cannot be found
12055     */
12056    protected View findViewWithTagTraversal(Object tag) {
12057        if (tag != null && tag.equals(mTag)) {
12058            return this;
12059        }
12060        return null;
12061    }
12062
12063    /**
12064     * {@hide}
12065     * @param predicate The predicate to evaluate.
12066     * @param childToSkip If not null, ignores this child during the recursive traversal.
12067     * @return The first view that matches the predicate or null.
12068     */
12069    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
12070        if (predicate.apply(this)) {
12071            return this;
12072        }
12073        return null;
12074    }
12075
12076    /**
12077     * Look for a child view with the given id.  If this view has the given
12078     * id, return this view.
12079     *
12080     * @param id The id to search for.
12081     * @return The view that has the given id in the hierarchy or null
12082     */
12083    public final View findViewById(int id) {
12084        if (id < 0) {
12085            return null;
12086        }
12087        return findViewTraversal(id);
12088    }
12089
12090    /**
12091     * Finds a view by its unuque and stable accessibility id.
12092     *
12093     * @param accessibilityId The searched accessibility id.
12094     * @return The found view.
12095     */
12096    final View findViewByAccessibilityId(int accessibilityId) {
12097        if (accessibilityId < 0) {
12098            return null;
12099        }
12100        return findViewByAccessibilityIdTraversal(accessibilityId);
12101    }
12102
12103    /**
12104     * Performs the traversal to find a view by its unuque and stable accessibility id.
12105     *
12106     * <strong>Note:</strong>This method does not stop at the root namespace
12107     * boundary since the user can touch the screen at an arbitrary location
12108     * potentially crossing the root namespace bounday which will send an
12109     * accessibility event to accessibility services and they should be able
12110     * to obtain the event source. Also accessibility ids are guaranteed to be
12111     * unique in the window.
12112     *
12113     * @param accessibilityId The accessibility id.
12114     * @return The found view.
12115     */
12116    View findViewByAccessibilityIdTraversal(int accessibilityId) {
12117        if (getAccessibilityViewId() == accessibilityId) {
12118            return this;
12119        }
12120        return null;
12121    }
12122
12123    /**
12124     * Look for a child view with the given tag.  If this view has the given
12125     * tag, return this view.
12126     *
12127     * @param tag The tag to search for, using "tag.equals(getTag())".
12128     * @return The View that has the given tag in the hierarchy or null
12129     */
12130    public final View findViewWithTag(Object tag) {
12131        if (tag == null) {
12132            return null;
12133        }
12134        return findViewWithTagTraversal(tag);
12135    }
12136
12137    /**
12138     * {@hide}
12139     * Look for a child view that matches the specified predicate.
12140     * If this view matches the predicate, return this view.
12141     *
12142     * @param predicate The predicate to evaluate.
12143     * @return The first view that matches the predicate or null.
12144     */
12145    public final View findViewByPredicate(Predicate<View> predicate) {
12146        return findViewByPredicateTraversal(predicate, null);
12147    }
12148
12149    /**
12150     * {@hide}
12151     * Look for a child view that matches the specified predicate,
12152     * starting with the specified view and its descendents and then
12153     * recusively searching the ancestors and siblings of that view
12154     * until this view is reached.
12155     *
12156     * This method is useful in cases where the predicate does not match
12157     * a single unique view (perhaps multiple views use the same id)
12158     * and we are trying to find the view that is "closest" in scope to the
12159     * starting view.
12160     *
12161     * @param start The view to start from.
12162     * @param predicate The predicate to evaluate.
12163     * @return The first view that matches the predicate or null.
12164     */
12165    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
12166        View childToSkip = null;
12167        for (;;) {
12168            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
12169            if (view != null || start == this) {
12170                return view;
12171            }
12172
12173            ViewParent parent = start.getParent();
12174            if (parent == null || !(parent instanceof View)) {
12175                return null;
12176            }
12177
12178            childToSkip = start;
12179            start = (View) parent;
12180        }
12181    }
12182
12183    /**
12184     * Sets the identifier for this view. The identifier does not have to be
12185     * unique in this view's hierarchy. The identifier should be a positive
12186     * number.
12187     *
12188     * @see #NO_ID
12189     * @see #getId()
12190     * @see #findViewById(int)
12191     *
12192     * @param id a number used to identify the view
12193     *
12194     * @attr ref android.R.styleable#View_id
12195     */
12196    public void setId(int id) {
12197        mID = id;
12198    }
12199
12200    /**
12201     * {@hide}
12202     *
12203     * @param isRoot true if the view belongs to the root namespace, false
12204     *        otherwise
12205     */
12206    public void setIsRootNamespace(boolean isRoot) {
12207        if (isRoot) {
12208            mPrivateFlags |= IS_ROOT_NAMESPACE;
12209        } else {
12210            mPrivateFlags &= ~IS_ROOT_NAMESPACE;
12211        }
12212    }
12213
12214    /**
12215     * {@hide}
12216     *
12217     * @return true if the view belongs to the root namespace, false otherwise
12218     */
12219    public boolean isRootNamespace() {
12220        return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
12221    }
12222
12223    /**
12224     * Returns this view's identifier.
12225     *
12226     * @return a positive integer used to identify the view or {@link #NO_ID}
12227     *         if the view has no ID
12228     *
12229     * @see #setId(int)
12230     * @see #findViewById(int)
12231     * @attr ref android.R.styleable#View_id
12232     */
12233    @ViewDebug.CapturedViewProperty
12234    public int getId() {
12235        return mID;
12236    }
12237
12238    /**
12239     * Returns this view's tag.
12240     *
12241     * @return the Object stored in this view as a tag
12242     *
12243     * @see #setTag(Object)
12244     * @see #getTag(int)
12245     */
12246    @ViewDebug.ExportedProperty
12247    public Object getTag() {
12248        return mTag;
12249    }
12250
12251    /**
12252     * Sets the tag associated with this view. A tag can be used to mark
12253     * a view in its hierarchy and does not have to be unique within the
12254     * hierarchy. Tags can also be used to store data within a view without
12255     * resorting to another data structure.
12256     *
12257     * @param tag an Object to tag the view with
12258     *
12259     * @see #getTag()
12260     * @see #setTag(int, Object)
12261     */
12262    public void setTag(final Object tag) {
12263        mTag = tag;
12264    }
12265
12266    /**
12267     * Returns the tag associated with this view and the specified key.
12268     *
12269     * @param key The key identifying the tag
12270     *
12271     * @return the Object stored in this view as a tag
12272     *
12273     * @see #setTag(int, Object)
12274     * @see #getTag()
12275     */
12276    public Object getTag(int key) {
12277        if (mKeyedTags != null) return mKeyedTags.get(key);
12278        return null;
12279    }
12280
12281    /**
12282     * Sets a tag associated with this view and a key. A tag can be used
12283     * to mark a view in its hierarchy and does not have to be unique within
12284     * the hierarchy. Tags can also be used to store data within a view
12285     * without resorting to another data structure.
12286     *
12287     * The specified key should be an id declared in the resources of the
12288     * application to ensure it is unique (see the <a
12289     * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
12290     * Keys identified as belonging to
12291     * the Android framework or not associated with any package will cause
12292     * an {@link IllegalArgumentException} to be thrown.
12293     *
12294     * @param key The key identifying the tag
12295     * @param tag An Object to tag the view with
12296     *
12297     * @throws IllegalArgumentException If they specified key is not valid
12298     *
12299     * @see #setTag(Object)
12300     * @see #getTag(int)
12301     */
12302    public void setTag(int key, final Object tag) {
12303        // If the package id is 0x00 or 0x01, it's either an undefined package
12304        // or a framework id
12305        if ((key >>> 24) < 2) {
12306            throw new IllegalArgumentException("The key must be an application-specific "
12307                    + "resource id.");
12308        }
12309
12310        setKeyedTag(key, tag);
12311    }
12312
12313    /**
12314     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
12315     * framework id.
12316     *
12317     * @hide
12318     */
12319    public void setTagInternal(int key, Object tag) {
12320        if ((key >>> 24) != 0x1) {
12321            throw new IllegalArgumentException("The key must be a framework-specific "
12322                    + "resource id.");
12323        }
12324
12325        setKeyedTag(key, tag);
12326    }
12327
12328    private void setKeyedTag(int key, Object tag) {
12329        if (mKeyedTags == null) {
12330            mKeyedTags = new SparseArray<Object>();
12331        }
12332
12333        mKeyedTags.put(key, tag);
12334    }
12335
12336    /**
12337     * @param consistency The type of consistency. See ViewDebug for more information.
12338     *
12339     * @hide
12340     */
12341    protected boolean dispatchConsistencyCheck(int consistency) {
12342        return onConsistencyCheck(consistency);
12343    }
12344
12345    /**
12346     * Method that subclasses should implement to check their consistency. The type of
12347     * consistency check is indicated by the bit field passed as a parameter.
12348     *
12349     * @param consistency The type of consistency. See ViewDebug for more information.
12350     *
12351     * @throws IllegalStateException if the view is in an inconsistent state.
12352     *
12353     * @hide
12354     */
12355    protected boolean onConsistencyCheck(int consistency) {
12356        boolean result = true;
12357
12358        final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
12359        final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0;
12360
12361        if (checkLayout) {
12362            if (getParent() == null) {
12363                result = false;
12364                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
12365                        "View " + this + " does not have a parent.");
12366            }
12367
12368            if (mAttachInfo == null) {
12369                result = false;
12370                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
12371                        "View " + this + " is not attached to a window.");
12372            }
12373        }
12374
12375        if (checkDrawing) {
12376            // Do not check the DIRTY/DRAWN flags because views can call invalidate()
12377            // from their draw() method
12378
12379            if ((mPrivateFlags & DRAWN) != DRAWN &&
12380                    (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
12381                result = false;
12382                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
12383                        "View " + this + " was invalidated but its drawing cache is valid.");
12384            }
12385        }
12386
12387        return result;
12388    }
12389
12390    /**
12391     * Prints information about this view in the log output, with the tag
12392     * {@link #VIEW_LOG_TAG}.
12393     *
12394     * @hide
12395     */
12396    public void debug() {
12397        debug(0);
12398    }
12399
12400    /**
12401     * Prints information about this view in the log output, with the tag
12402     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
12403     * indentation defined by the <code>depth</code>.
12404     *
12405     * @param depth the indentation level
12406     *
12407     * @hide
12408     */
12409    protected void debug(int depth) {
12410        String output = debugIndent(depth - 1);
12411
12412        output += "+ " + this;
12413        int id = getId();
12414        if (id != -1) {
12415            output += " (id=" + id + ")";
12416        }
12417        Object tag = getTag();
12418        if (tag != null) {
12419            output += " (tag=" + tag + ")";
12420        }
12421        Log.d(VIEW_LOG_TAG, output);
12422
12423        if ((mPrivateFlags & FOCUSED) != 0) {
12424            output = debugIndent(depth) + " FOCUSED";
12425            Log.d(VIEW_LOG_TAG, output);
12426        }
12427
12428        output = debugIndent(depth);
12429        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
12430                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
12431                + "} ";
12432        Log.d(VIEW_LOG_TAG, output);
12433
12434        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
12435                || mPaddingBottom != 0) {
12436            output = debugIndent(depth);
12437            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
12438                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
12439            Log.d(VIEW_LOG_TAG, output);
12440        }
12441
12442        output = debugIndent(depth);
12443        output += "mMeasureWidth=" + mMeasuredWidth +
12444                " mMeasureHeight=" + mMeasuredHeight;
12445        Log.d(VIEW_LOG_TAG, output);
12446
12447        output = debugIndent(depth);
12448        if (mLayoutParams == null) {
12449            output += "BAD! no layout params";
12450        } else {
12451            output = mLayoutParams.debug(output);
12452        }
12453        Log.d(VIEW_LOG_TAG, output);
12454
12455        output = debugIndent(depth);
12456        output += "flags={";
12457        output += View.printFlags(mViewFlags);
12458        output += "}";
12459        Log.d(VIEW_LOG_TAG, output);
12460
12461        output = debugIndent(depth);
12462        output += "privateFlags={";
12463        output += View.printPrivateFlags(mPrivateFlags);
12464        output += "}";
12465        Log.d(VIEW_LOG_TAG, output);
12466    }
12467
12468    /**
12469     * Creates an string of whitespaces used for indentation.
12470     *
12471     * @param depth the indentation level
12472     * @return a String containing (depth * 2 + 3) * 2 white spaces
12473     *
12474     * @hide
12475     */
12476    protected static String debugIndent(int depth) {
12477        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
12478        for (int i = 0; i < (depth * 2) + 3; i++) {
12479            spaces.append(' ').append(' ');
12480        }
12481        return spaces.toString();
12482    }
12483
12484    /**
12485     * <p>Return the offset of the widget's text baseline from the widget's top
12486     * boundary. If this widget does not support baseline alignment, this
12487     * method returns -1. </p>
12488     *
12489     * @return the offset of the baseline within the widget's bounds or -1
12490     *         if baseline alignment is not supported
12491     */
12492    @ViewDebug.ExportedProperty(category = "layout")
12493    public int getBaseline() {
12494        return -1;
12495    }
12496
12497    /**
12498     * Call this when something has changed which has invalidated the
12499     * layout of this view. This will schedule a layout pass of the view
12500     * tree.
12501     */
12502    public void requestLayout() {
12503        if (ViewDebug.TRACE_HIERARCHY) {
12504            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT);
12505        }
12506
12507        mPrivateFlags |= FORCE_LAYOUT;
12508        mPrivateFlags |= INVALIDATED;
12509
12510        if (mParent != null) {
12511            if (mLayoutParams != null) {
12512                mLayoutParams.resolveWithDirection(getResolvedLayoutDirection());
12513            }
12514            if (!mParent.isLayoutRequested()) {
12515                mParent.requestLayout();
12516            }
12517        }
12518    }
12519
12520    /**
12521     * Forces this view to be laid out during the next layout pass.
12522     * This method does not call requestLayout() or forceLayout()
12523     * on the parent.
12524     */
12525    public void forceLayout() {
12526        mPrivateFlags |= FORCE_LAYOUT;
12527        mPrivateFlags |= INVALIDATED;
12528    }
12529
12530    /**
12531     * <p>
12532     * This is called to find out how big a view should be. The parent
12533     * supplies constraint information in the width and height parameters.
12534     * </p>
12535     *
12536     * <p>
12537     * The actual mesurement work of a view is performed in
12538     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
12539     * {@link #onMeasure(int, int)} can and must be overriden by subclasses.
12540     * </p>
12541     *
12542     *
12543     * @param widthMeasureSpec Horizontal space requirements as imposed by the
12544     *        parent
12545     * @param heightMeasureSpec Vertical space requirements as imposed by the
12546     *        parent
12547     *
12548     * @see #onMeasure(int, int)
12549     */
12550    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
12551        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
12552                widthMeasureSpec != mOldWidthMeasureSpec ||
12553                heightMeasureSpec != mOldHeightMeasureSpec) {
12554
12555            // first clears the measured dimension flag
12556            mPrivateFlags &= ~MEASURED_DIMENSION_SET;
12557
12558            if (ViewDebug.TRACE_HIERARCHY) {
12559                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
12560            }
12561
12562            // measure ourselves, this should set the measured dimension flag back
12563            onMeasure(widthMeasureSpec, heightMeasureSpec);
12564
12565            // flag not set, setMeasuredDimension() was not invoked, we raise
12566            // an exception to warn the developer
12567            if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
12568                throw new IllegalStateException("onMeasure() did not set the"
12569                        + " measured dimension by calling"
12570                        + " setMeasuredDimension()");
12571            }
12572
12573            mPrivateFlags |= LAYOUT_REQUIRED;
12574        }
12575
12576        mOldWidthMeasureSpec = widthMeasureSpec;
12577        mOldHeightMeasureSpec = heightMeasureSpec;
12578    }
12579
12580    /**
12581     * <p>
12582     * Measure the view and its content to determine the measured width and the
12583     * measured height. This method is invoked by {@link #measure(int, int)} and
12584     * should be overriden by subclasses to provide accurate and efficient
12585     * measurement of their contents.
12586     * </p>
12587     *
12588     * <p>
12589     * <strong>CONTRACT:</strong> When overriding this method, you
12590     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
12591     * measured width and height of this view. Failure to do so will trigger an
12592     * <code>IllegalStateException</code>, thrown by
12593     * {@link #measure(int, int)}. Calling the superclass'
12594     * {@link #onMeasure(int, int)} is a valid use.
12595     * </p>
12596     *
12597     * <p>
12598     * The base class implementation of measure defaults to the background size,
12599     * unless a larger size is allowed by the MeasureSpec. Subclasses should
12600     * override {@link #onMeasure(int, int)} to provide better measurements of
12601     * their content.
12602     * </p>
12603     *
12604     * <p>
12605     * If this method is overridden, it is the subclass's responsibility to make
12606     * sure the measured height and width are at least the view's minimum height
12607     * and width ({@link #getSuggestedMinimumHeight()} and
12608     * {@link #getSuggestedMinimumWidth()}).
12609     * </p>
12610     *
12611     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
12612     *                         The requirements are encoded with
12613     *                         {@link android.view.View.MeasureSpec}.
12614     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
12615     *                         The requirements are encoded with
12616     *                         {@link android.view.View.MeasureSpec}.
12617     *
12618     * @see #getMeasuredWidth()
12619     * @see #getMeasuredHeight()
12620     * @see #setMeasuredDimension(int, int)
12621     * @see #getSuggestedMinimumHeight()
12622     * @see #getSuggestedMinimumWidth()
12623     * @see android.view.View.MeasureSpec#getMode(int)
12624     * @see android.view.View.MeasureSpec#getSize(int)
12625     */
12626    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
12627        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
12628                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
12629    }
12630
12631    /**
12632     * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
12633     * measured width and measured height. Failing to do so will trigger an
12634     * exception at measurement time.</p>
12635     *
12636     * @param measuredWidth The measured width of this view.  May be a complex
12637     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
12638     * {@link #MEASURED_STATE_TOO_SMALL}.
12639     * @param measuredHeight The measured height of this view.  May be a complex
12640     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
12641     * {@link #MEASURED_STATE_TOO_SMALL}.
12642     */
12643    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
12644        mMeasuredWidth = measuredWidth;
12645        mMeasuredHeight = measuredHeight;
12646
12647        mPrivateFlags |= MEASURED_DIMENSION_SET;
12648    }
12649
12650    /**
12651     * Merge two states as returned by {@link #getMeasuredState()}.
12652     * @param curState The current state as returned from a view or the result
12653     * of combining multiple views.
12654     * @param newState The new view state to combine.
12655     * @return Returns a new integer reflecting the combination of the two
12656     * states.
12657     */
12658    public static int combineMeasuredStates(int curState, int newState) {
12659        return curState | newState;
12660    }
12661
12662    /**
12663     * Version of {@link #resolveSizeAndState(int, int, int)}
12664     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
12665     */
12666    public static int resolveSize(int size, int measureSpec) {
12667        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
12668    }
12669
12670    /**
12671     * Utility to reconcile a desired size and state, with constraints imposed
12672     * by a MeasureSpec.  Will take the desired size, unless a different size
12673     * is imposed by the constraints.  The returned value is a compound integer,
12674     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
12675     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
12676     * size is smaller than the size the view wants to be.
12677     *
12678     * @param size How big the view wants to be
12679     * @param measureSpec Constraints imposed by the parent
12680     * @return Size information bit mask as defined by
12681     * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
12682     */
12683    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
12684        int result = size;
12685        int specMode = MeasureSpec.getMode(measureSpec);
12686        int specSize =  MeasureSpec.getSize(measureSpec);
12687        switch (specMode) {
12688        case MeasureSpec.UNSPECIFIED:
12689            result = size;
12690            break;
12691        case MeasureSpec.AT_MOST:
12692            if (specSize < size) {
12693                result = specSize | MEASURED_STATE_TOO_SMALL;
12694            } else {
12695                result = size;
12696            }
12697            break;
12698        case MeasureSpec.EXACTLY:
12699            result = specSize;
12700            break;
12701        }
12702        return result | (childMeasuredState&MEASURED_STATE_MASK);
12703    }
12704
12705    /**
12706     * Utility to return a default size. Uses the supplied size if the
12707     * MeasureSpec imposed no constraints. Will get larger if allowed
12708     * by the MeasureSpec.
12709     *
12710     * @param size Default size for this view
12711     * @param measureSpec Constraints imposed by the parent
12712     * @return The size this view should be.
12713     */
12714    public static int getDefaultSize(int size, int measureSpec) {
12715        int result = size;
12716        int specMode = MeasureSpec.getMode(measureSpec);
12717        int specSize = MeasureSpec.getSize(measureSpec);
12718
12719        switch (specMode) {
12720        case MeasureSpec.UNSPECIFIED:
12721            result = size;
12722            break;
12723        case MeasureSpec.AT_MOST:
12724        case MeasureSpec.EXACTLY:
12725            result = specSize;
12726            break;
12727        }
12728        return result;
12729    }
12730
12731    /**
12732     * Returns the suggested minimum height that the view should use. This
12733     * returns the maximum of the view's minimum height
12734     * and the background's minimum height
12735     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
12736     * <p>
12737     * When being used in {@link #onMeasure(int, int)}, the caller should still
12738     * ensure the returned height is within the requirements of the parent.
12739     *
12740     * @return The suggested minimum height of the view.
12741     */
12742    protected int getSuggestedMinimumHeight() {
12743        int suggestedMinHeight = mMinHeight;
12744
12745        if (mBGDrawable != null) {
12746            final int bgMinHeight = mBGDrawable.getMinimumHeight();
12747            if (suggestedMinHeight < bgMinHeight) {
12748                suggestedMinHeight = bgMinHeight;
12749            }
12750        }
12751
12752        return suggestedMinHeight;
12753    }
12754
12755    /**
12756     * Returns the suggested minimum width that the view should use. This
12757     * returns the maximum of the view's minimum width)
12758     * and the background's minimum width
12759     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
12760     * <p>
12761     * When being used in {@link #onMeasure(int, int)}, the caller should still
12762     * ensure the returned width is within the requirements of the parent.
12763     *
12764     * @return The suggested minimum width of the view.
12765     */
12766    protected int getSuggestedMinimumWidth() {
12767        int suggestedMinWidth = mMinWidth;
12768
12769        if (mBGDrawable != null) {
12770            final int bgMinWidth = mBGDrawable.getMinimumWidth();
12771            if (suggestedMinWidth < bgMinWidth) {
12772                suggestedMinWidth = bgMinWidth;
12773            }
12774        }
12775
12776        return suggestedMinWidth;
12777    }
12778
12779    /**
12780     * Sets the minimum height of the view. It is not guaranteed the view will
12781     * be able to achieve this minimum height (for example, if its parent layout
12782     * constrains it with less available height).
12783     *
12784     * @param minHeight The minimum height the view will try to be.
12785     */
12786    public void setMinimumHeight(int minHeight) {
12787        mMinHeight = minHeight;
12788    }
12789
12790    /**
12791     * Sets the minimum width of the view. It is not guaranteed the view will
12792     * be able to achieve this minimum width (for example, if its parent layout
12793     * constrains it with less available width).
12794     *
12795     * @param minWidth The minimum width the view will try to be.
12796     */
12797    public void setMinimumWidth(int minWidth) {
12798        mMinWidth = minWidth;
12799    }
12800
12801    /**
12802     * Get the animation currently associated with this view.
12803     *
12804     * @return The animation that is currently playing or
12805     *         scheduled to play for this view.
12806     */
12807    public Animation getAnimation() {
12808        return mCurrentAnimation;
12809    }
12810
12811    /**
12812     * Start the specified animation now.
12813     *
12814     * @param animation the animation to start now
12815     */
12816    public void startAnimation(Animation animation) {
12817        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
12818        setAnimation(animation);
12819        invalidateParentCaches();
12820        invalidate(true);
12821    }
12822
12823    /**
12824     * Cancels any animations for this view.
12825     */
12826    public void clearAnimation() {
12827        if (mCurrentAnimation != null) {
12828            mCurrentAnimation.detach();
12829        }
12830        mCurrentAnimation = null;
12831        invalidateParentIfNeeded();
12832    }
12833
12834    /**
12835     * Sets the next animation to play for this view.
12836     * If you want the animation to play immediately, use
12837     * startAnimation. This method provides allows fine-grained
12838     * control over the start time and invalidation, but you
12839     * must make sure that 1) the animation has a start time set, and
12840     * 2) the view will be invalidated when the animation is supposed to
12841     * start.
12842     *
12843     * @param animation The next animation, or null.
12844     */
12845    public void setAnimation(Animation animation) {
12846        mCurrentAnimation = animation;
12847        if (animation != null) {
12848            animation.reset();
12849        }
12850    }
12851
12852    /**
12853     * Invoked by a parent ViewGroup to notify the start of the animation
12854     * currently associated with this view. If you override this method,
12855     * always call super.onAnimationStart();
12856     *
12857     * @see #setAnimation(android.view.animation.Animation)
12858     * @see #getAnimation()
12859     */
12860    protected void onAnimationStart() {
12861        mPrivateFlags |= ANIMATION_STARTED;
12862    }
12863
12864    /**
12865     * Invoked by a parent ViewGroup to notify the end of the animation
12866     * currently associated with this view. If you override this method,
12867     * always call super.onAnimationEnd();
12868     *
12869     * @see #setAnimation(android.view.animation.Animation)
12870     * @see #getAnimation()
12871     */
12872    protected void onAnimationEnd() {
12873        mPrivateFlags &= ~ANIMATION_STARTED;
12874    }
12875
12876    /**
12877     * Invoked if there is a Transform that involves alpha. Subclass that can
12878     * draw themselves with the specified alpha should return true, and then
12879     * respect that alpha when their onDraw() is called. If this returns false
12880     * then the view may be redirected to draw into an offscreen buffer to
12881     * fulfill the request, which will look fine, but may be slower than if the
12882     * subclass handles it internally. The default implementation returns false.
12883     *
12884     * @param alpha The alpha (0..255) to apply to the view's drawing
12885     * @return true if the view can draw with the specified alpha.
12886     */
12887    protected boolean onSetAlpha(int alpha) {
12888        return false;
12889    }
12890
12891    /**
12892     * This is used by the RootView to perform an optimization when
12893     * the view hierarchy contains one or several SurfaceView.
12894     * SurfaceView is always considered transparent, but its children are not,
12895     * therefore all View objects remove themselves from the global transparent
12896     * region (passed as a parameter to this function).
12897     *
12898     * @param region The transparent region for this ViewAncestor (window).
12899     *
12900     * @return Returns true if the effective visibility of the view at this
12901     * point is opaque, regardless of the transparent region; returns false
12902     * if it is possible for underlying windows to be seen behind the view.
12903     *
12904     * {@hide}
12905     */
12906    public boolean gatherTransparentRegion(Region region) {
12907        final AttachInfo attachInfo = mAttachInfo;
12908        if (region != null && attachInfo != null) {
12909            final int pflags = mPrivateFlags;
12910            if ((pflags & SKIP_DRAW) == 0) {
12911                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
12912                // remove it from the transparent region.
12913                final int[] location = attachInfo.mTransparentLocation;
12914                getLocationInWindow(location);
12915                region.op(location[0], location[1], location[0] + mRight - mLeft,
12916                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
12917            } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) {
12918                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
12919                // exists, so we remove the background drawable's non-transparent
12920                // parts from this transparent region.
12921                applyDrawableToTransparentRegion(mBGDrawable, region);
12922            }
12923        }
12924        return true;
12925    }
12926
12927    /**
12928     * Play a sound effect for this view.
12929     *
12930     * <p>The framework will play sound effects for some built in actions, such as
12931     * clicking, but you may wish to play these effects in your widget,
12932     * for instance, for internal navigation.
12933     *
12934     * <p>The sound effect will only be played if sound effects are enabled by the user, and
12935     * {@link #isSoundEffectsEnabled()} is true.
12936     *
12937     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
12938     */
12939    public void playSoundEffect(int soundConstant) {
12940        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
12941            return;
12942        }
12943        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
12944    }
12945
12946    /**
12947     * BZZZTT!!1!
12948     *
12949     * <p>Provide haptic feedback to the user for this view.
12950     *
12951     * <p>The framework will provide haptic feedback for some built in actions,
12952     * such as long presses, but you may wish to provide feedback for your
12953     * own widget.
12954     *
12955     * <p>The feedback will only be performed if
12956     * {@link #isHapticFeedbackEnabled()} is true.
12957     *
12958     * @param feedbackConstant One of the constants defined in
12959     * {@link HapticFeedbackConstants}
12960     */
12961    public boolean performHapticFeedback(int feedbackConstant) {
12962        return performHapticFeedback(feedbackConstant, 0);
12963    }
12964
12965    /**
12966     * BZZZTT!!1!
12967     *
12968     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
12969     *
12970     * @param feedbackConstant One of the constants defined in
12971     * {@link HapticFeedbackConstants}
12972     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
12973     */
12974    public boolean performHapticFeedback(int feedbackConstant, int flags) {
12975        if (mAttachInfo == null) {
12976            return false;
12977        }
12978        //noinspection SimplifiableIfStatement
12979        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
12980                && !isHapticFeedbackEnabled()) {
12981            return false;
12982        }
12983        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
12984                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
12985    }
12986
12987    /**
12988     * Request that the visibility of the status bar be changed.
12989     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
12990     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
12991     */
12992    public void setSystemUiVisibility(int visibility) {
12993        if (visibility != mSystemUiVisibility) {
12994            mSystemUiVisibility = visibility;
12995            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
12996                mParent.recomputeViewAttributes(this);
12997            }
12998        }
12999    }
13000
13001    /**
13002     * Returns the status bar visibility that this view has requested.
13003     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
13004     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
13005     */
13006    public int getSystemUiVisibility() {
13007        return mSystemUiVisibility;
13008    }
13009
13010    /**
13011     * Set a listener to receive callbacks when the visibility of the system bar changes.
13012     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
13013     */
13014    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
13015        mOnSystemUiVisibilityChangeListener = l;
13016        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13017            mParent.recomputeViewAttributes(this);
13018        }
13019    }
13020
13021    /**
13022     */
13023    public void dispatchSystemUiVisibilityChanged(int visibility) {
13024        if (mOnSystemUiVisibilityChangeListener != null) {
13025            mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
13026                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
13027        }
13028    }
13029
13030    /**
13031     * Creates an image that the system displays during the drag and drop
13032     * operation. This is called a &quot;drag shadow&quot;. The default implementation
13033     * for a DragShadowBuilder based on a View returns an image that has exactly the same
13034     * appearance as the given View. The default also positions the center of the drag shadow
13035     * directly under the touch point. If no View is provided (the constructor with no parameters
13036     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
13037     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
13038     * default is an invisible drag shadow.
13039     * <p>
13040     * You are not required to use the View you provide to the constructor as the basis of the
13041     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
13042     * anything you want as the drag shadow.
13043     * </p>
13044     * <p>
13045     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
13046     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
13047     *  size and position of the drag shadow. It uses this data to construct a
13048     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
13049     *  so that your application can draw the shadow image in the Canvas.
13050     * </p>
13051     */
13052    public static class DragShadowBuilder {
13053        private final WeakReference<View> mView;
13054
13055        /**
13056         * Constructs a shadow image builder based on a View. By default, the resulting drag
13057         * shadow will have the same appearance and dimensions as the View, with the touch point
13058         * over the center of the View.
13059         * @param view A View. Any View in scope can be used.
13060         */
13061        public DragShadowBuilder(View view) {
13062            mView = new WeakReference<View>(view);
13063        }
13064
13065        /**
13066         * Construct a shadow builder object with no associated View.  This
13067         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
13068         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
13069         * to supply the drag shadow's dimensions and appearance without
13070         * reference to any View object. If they are not overridden, then the result is an
13071         * invisible drag shadow.
13072         */
13073        public DragShadowBuilder() {
13074            mView = new WeakReference<View>(null);
13075        }
13076
13077        /**
13078         * Returns the View object that had been passed to the
13079         * {@link #View.DragShadowBuilder(View)}
13080         * constructor.  If that View parameter was {@code null} or if the
13081         * {@link #View.DragShadowBuilder()}
13082         * constructor was used to instantiate the builder object, this method will return
13083         * null.
13084         *
13085         * @return The View object associate with this builder object.
13086         */
13087        @SuppressWarnings({"JavadocReference"})
13088        final public View getView() {
13089            return mView.get();
13090        }
13091
13092        /**
13093         * Provides the metrics for the shadow image. These include the dimensions of
13094         * the shadow image, and the point within that shadow that should
13095         * be centered under the touch location while dragging.
13096         * <p>
13097         * The default implementation sets the dimensions of the shadow to be the
13098         * same as the dimensions of the View itself and centers the shadow under
13099         * the touch point.
13100         * </p>
13101         *
13102         * @param shadowSize A {@link android.graphics.Point} containing the width and height
13103         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
13104         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
13105         * image.
13106         *
13107         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
13108         * shadow image that should be underneath the touch point during the drag and drop
13109         * operation. Your application must set {@link android.graphics.Point#x} to the
13110         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
13111         */
13112        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
13113            final View view = mView.get();
13114            if (view != null) {
13115                shadowSize.set(view.getWidth(), view.getHeight());
13116                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
13117            } else {
13118                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
13119            }
13120        }
13121
13122        /**
13123         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
13124         * based on the dimensions it received from the
13125         * {@link #onProvideShadowMetrics(Point, Point)} callback.
13126         *
13127         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
13128         */
13129        public void onDrawShadow(Canvas canvas) {
13130            final View view = mView.get();
13131            if (view != null) {
13132                view.draw(canvas);
13133            } else {
13134                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
13135            }
13136        }
13137    }
13138
13139    /**
13140     * Starts a drag and drop operation. When your application calls this method, it passes a
13141     * {@link android.view.View.DragShadowBuilder} object to the system. The
13142     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
13143     * to get metrics for the drag shadow, and then calls the object's
13144     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
13145     * <p>
13146     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
13147     *  drag events to all the View objects in your application that are currently visible. It does
13148     *  this either by calling the View object's drag listener (an implementation of
13149     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
13150     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
13151     *  Both are passed a {@link android.view.DragEvent} object that has a
13152     *  {@link android.view.DragEvent#getAction()} value of
13153     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
13154     * </p>
13155     * <p>
13156     * Your application can invoke startDrag() on any attached View object. The View object does not
13157     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
13158     * be related to the View the user selected for dragging.
13159     * </p>
13160     * @param data A {@link android.content.ClipData} object pointing to the data to be
13161     * transferred by the drag and drop operation.
13162     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
13163     * drag shadow.
13164     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
13165     * drop operation. This Object is put into every DragEvent object sent by the system during the
13166     * current drag.
13167     * <p>
13168     * myLocalState is a lightweight mechanism for the sending information from the dragged View
13169     * to the target Views. For example, it can contain flags that differentiate between a
13170     * a copy operation and a move operation.
13171     * </p>
13172     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
13173     * so the parameter should be set to 0.
13174     * @return {@code true} if the method completes successfully, or
13175     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
13176     * do a drag, and so no drag operation is in progress.
13177     */
13178    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
13179            Object myLocalState, int flags) {
13180        if (ViewDebug.DEBUG_DRAG) {
13181            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
13182        }
13183        boolean okay = false;
13184
13185        Point shadowSize = new Point();
13186        Point shadowTouchPoint = new Point();
13187        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
13188
13189        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
13190                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
13191            throw new IllegalStateException("Drag shadow dimensions must not be negative");
13192        }
13193
13194        if (ViewDebug.DEBUG_DRAG) {
13195            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
13196                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
13197        }
13198        Surface surface = new Surface();
13199        try {
13200            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
13201                    flags, shadowSize.x, shadowSize.y, surface);
13202            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
13203                    + " surface=" + surface);
13204            if (token != null) {
13205                Canvas canvas = surface.lockCanvas(null);
13206                try {
13207                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
13208                    shadowBuilder.onDrawShadow(canvas);
13209                } finally {
13210                    surface.unlockCanvasAndPost(canvas);
13211                }
13212
13213                final ViewRootImpl root = getViewRootImpl();
13214
13215                // Cache the local state object for delivery with DragEvents
13216                root.setLocalDragState(myLocalState);
13217
13218                // repurpose 'shadowSize' for the last touch point
13219                root.getLastTouchPoint(shadowSize);
13220
13221                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
13222                        shadowSize.x, shadowSize.y,
13223                        shadowTouchPoint.x, shadowTouchPoint.y, data);
13224                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
13225
13226                // Off and running!  Release our local surface instance; the drag
13227                // shadow surface is now managed by the system process.
13228                surface.release();
13229            }
13230        } catch (Exception e) {
13231            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
13232            surface.destroy();
13233        }
13234
13235        return okay;
13236    }
13237
13238    /**
13239     * Handles drag events sent by the system following a call to
13240     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
13241     *<p>
13242     * When the system calls this method, it passes a
13243     * {@link android.view.DragEvent} object. A call to
13244     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
13245     * in DragEvent. The method uses these to determine what is happening in the drag and drop
13246     * operation.
13247     * @param event The {@link android.view.DragEvent} sent by the system.
13248     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
13249     * in DragEvent, indicating the type of drag event represented by this object.
13250     * @return {@code true} if the method was successful, otherwise {@code false}.
13251     * <p>
13252     *  The method should return {@code true} in response to an action type of
13253     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
13254     *  operation.
13255     * </p>
13256     * <p>
13257     *  The method should also return {@code true} in response to an action type of
13258     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
13259     *  {@code false} if it didn't.
13260     * </p>
13261     */
13262    public boolean onDragEvent(DragEvent event) {
13263        return false;
13264    }
13265
13266    /**
13267     * Detects if this View is enabled and has a drag event listener.
13268     * If both are true, then it calls the drag event listener with the
13269     * {@link android.view.DragEvent} it received. If the drag event listener returns
13270     * {@code true}, then dispatchDragEvent() returns {@code true}.
13271     * <p>
13272     * For all other cases, the method calls the
13273     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
13274     * method and returns its result.
13275     * </p>
13276     * <p>
13277     * This ensures that a drag event is always consumed, even if the View does not have a drag
13278     * event listener. However, if the View has a listener and the listener returns true, then
13279     * onDragEvent() is not called.
13280     * </p>
13281     */
13282    public boolean dispatchDragEvent(DragEvent event) {
13283        //noinspection SimplifiableIfStatement
13284        if (mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
13285                && mOnDragListener.onDrag(this, event)) {
13286            return true;
13287        }
13288        return onDragEvent(event);
13289    }
13290
13291    boolean canAcceptDrag() {
13292        return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
13293    }
13294
13295    /**
13296     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
13297     * it is ever exposed at all.
13298     * @hide
13299     */
13300    public void onCloseSystemDialogs(String reason) {
13301    }
13302
13303    /**
13304     * Given a Drawable whose bounds have been set to draw into this view,
13305     * update a Region being computed for
13306     * {@link #gatherTransparentRegion(android.graphics.Region)} so
13307     * that any non-transparent parts of the Drawable are removed from the
13308     * given transparent region.
13309     *
13310     * @param dr The Drawable whose transparency is to be applied to the region.
13311     * @param region A Region holding the current transparency information,
13312     * where any parts of the region that are set are considered to be
13313     * transparent.  On return, this region will be modified to have the
13314     * transparency information reduced by the corresponding parts of the
13315     * Drawable that are not transparent.
13316     * {@hide}
13317     */
13318    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
13319        if (DBG) {
13320            Log.i("View", "Getting transparent region for: " + this);
13321        }
13322        final Region r = dr.getTransparentRegion();
13323        final Rect db = dr.getBounds();
13324        final AttachInfo attachInfo = mAttachInfo;
13325        if (r != null && attachInfo != null) {
13326            final int w = getRight()-getLeft();
13327            final int h = getBottom()-getTop();
13328            if (db.left > 0) {
13329                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
13330                r.op(0, 0, db.left, h, Region.Op.UNION);
13331            }
13332            if (db.right < w) {
13333                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
13334                r.op(db.right, 0, w, h, Region.Op.UNION);
13335            }
13336            if (db.top > 0) {
13337                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
13338                r.op(0, 0, w, db.top, Region.Op.UNION);
13339            }
13340            if (db.bottom < h) {
13341                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
13342                r.op(0, db.bottom, w, h, Region.Op.UNION);
13343            }
13344            final int[] location = attachInfo.mTransparentLocation;
13345            getLocationInWindow(location);
13346            r.translate(location[0], location[1]);
13347            region.op(r, Region.Op.INTERSECT);
13348        } else {
13349            region.op(db, Region.Op.DIFFERENCE);
13350        }
13351    }
13352
13353    private void checkForLongClick(int delayOffset) {
13354        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
13355            mHasPerformedLongPress = false;
13356
13357            if (mPendingCheckForLongPress == null) {
13358                mPendingCheckForLongPress = new CheckForLongPress();
13359            }
13360            mPendingCheckForLongPress.rememberWindowAttachCount();
13361            postDelayed(mPendingCheckForLongPress,
13362                    ViewConfiguration.getLongPressTimeout() - delayOffset);
13363        }
13364    }
13365
13366    /**
13367     * Inflate a view from an XML resource.  This convenience method wraps the {@link
13368     * LayoutInflater} class, which provides a full range of options for view inflation.
13369     *
13370     * @param context The Context object for your activity or application.
13371     * @param resource The resource ID to inflate
13372     * @param root A view group that will be the parent.  Used to properly inflate the
13373     * layout_* parameters.
13374     * @see LayoutInflater
13375     */
13376    public static View inflate(Context context, int resource, ViewGroup root) {
13377        LayoutInflater factory = LayoutInflater.from(context);
13378        return factory.inflate(resource, root);
13379    }
13380
13381    /**
13382     * Scroll the view with standard behavior for scrolling beyond the normal
13383     * content boundaries. Views that call this method should override
13384     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
13385     * results of an over-scroll operation.
13386     *
13387     * Views can use this method to handle any touch or fling-based scrolling.
13388     *
13389     * @param deltaX Change in X in pixels
13390     * @param deltaY Change in Y in pixels
13391     * @param scrollX Current X scroll value in pixels before applying deltaX
13392     * @param scrollY Current Y scroll value in pixels before applying deltaY
13393     * @param scrollRangeX Maximum content scroll range along the X axis
13394     * @param scrollRangeY Maximum content scroll range along the Y axis
13395     * @param maxOverScrollX Number of pixels to overscroll by in either direction
13396     *          along the X axis.
13397     * @param maxOverScrollY Number of pixels to overscroll by in either direction
13398     *          along the Y axis.
13399     * @param isTouchEvent true if this scroll operation is the result of a touch event.
13400     * @return true if scrolling was clamped to an over-scroll boundary along either
13401     *          axis, false otherwise.
13402     */
13403    @SuppressWarnings({"UnusedParameters"})
13404    protected boolean overScrollBy(int deltaX, int deltaY,
13405            int scrollX, int scrollY,
13406            int scrollRangeX, int scrollRangeY,
13407            int maxOverScrollX, int maxOverScrollY,
13408            boolean isTouchEvent) {
13409        final int overScrollMode = mOverScrollMode;
13410        final boolean canScrollHorizontal =
13411                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
13412        final boolean canScrollVertical =
13413                computeVerticalScrollRange() > computeVerticalScrollExtent();
13414        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
13415                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
13416        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
13417                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
13418
13419        int newScrollX = scrollX + deltaX;
13420        if (!overScrollHorizontal) {
13421            maxOverScrollX = 0;
13422        }
13423
13424        int newScrollY = scrollY + deltaY;
13425        if (!overScrollVertical) {
13426            maxOverScrollY = 0;
13427        }
13428
13429        // Clamp values if at the limits and record
13430        final int left = -maxOverScrollX;
13431        final int right = maxOverScrollX + scrollRangeX;
13432        final int top = -maxOverScrollY;
13433        final int bottom = maxOverScrollY + scrollRangeY;
13434
13435        boolean clampedX = false;
13436        if (newScrollX > right) {
13437            newScrollX = right;
13438            clampedX = true;
13439        } else if (newScrollX < left) {
13440            newScrollX = left;
13441            clampedX = true;
13442        }
13443
13444        boolean clampedY = false;
13445        if (newScrollY > bottom) {
13446            newScrollY = bottom;
13447            clampedY = true;
13448        } else if (newScrollY < top) {
13449            newScrollY = top;
13450            clampedY = true;
13451        }
13452
13453        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
13454
13455        return clampedX || clampedY;
13456    }
13457
13458    /**
13459     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
13460     * respond to the results of an over-scroll operation.
13461     *
13462     * @param scrollX New X scroll value in pixels
13463     * @param scrollY New Y scroll value in pixels
13464     * @param clampedX True if scrollX was clamped to an over-scroll boundary
13465     * @param clampedY True if scrollY was clamped to an over-scroll boundary
13466     */
13467    protected void onOverScrolled(int scrollX, int scrollY,
13468            boolean clampedX, boolean clampedY) {
13469        // Intentionally empty.
13470    }
13471
13472    /**
13473     * Returns the over-scroll mode for this view. The result will be
13474     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
13475     * (allow over-scrolling only if the view content is larger than the container),
13476     * or {@link #OVER_SCROLL_NEVER}.
13477     *
13478     * @return This view's over-scroll mode.
13479     */
13480    public int getOverScrollMode() {
13481        return mOverScrollMode;
13482    }
13483
13484    /**
13485     * Set the over-scroll mode for this view. Valid over-scroll modes are
13486     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
13487     * (allow over-scrolling only if the view content is larger than the container),
13488     * or {@link #OVER_SCROLL_NEVER}.
13489     *
13490     * Setting the over-scroll mode of a view will have an effect only if the
13491     * view is capable of scrolling.
13492     *
13493     * @param overScrollMode The new over-scroll mode for this view.
13494     */
13495    public void setOverScrollMode(int overScrollMode) {
13496        if (overScrollMode != OVER_SCROLL_ALWAYS &&
13497                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
13498                overScrollMode != OVER_SCROLL_NEVER) {
13499            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
13500        }
13501        mOverScrollMode = overScrollMode;
13502    }
13503
13504    /**
13505     * Gets a scale factor that determines the distance the view should scroll
13506     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
13507     * @return The vertical scroll scale factor.
13508     * @hide
13509     */
13510    protected float getVerticalScrollFactor() {
13511        if (mVerticalScrollFactor == 0) {
13512            TypedValue outValue = new TypedValue();
13513            if (!mContext.getTheme().resolveAttribute(
13514                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
13515                throw new IllegalStateException(
13516                        "Expected theme to define listPreferredItemHeight.");
13517            }
13518            mVerticalScrollFactor = outValue.getDimension(
13519                    mContext.getResources().getDisplayMetrics());
13520        }
13521        return mVerticalScrollFactor;
13522    }
13523
13524    /**
13525     * Gets a scale factor that determines the distance the view should scroll
13526     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
13527     * @return The horizontal scroll scale factor.
13528     * @hide
13529     */
13530    protected float getHorizontalScrollFactor() {
13531        // TODO: Should use something else.
13532        return getVerticalScrollFactor();
13533    }
13534
13535    /**
13536     * Return the value specifying the text direction or policy that was set with
13537     * {@link #setTextDirection(int)}.
13538     *
13539     * @return the defined text direction. It can be one of:
13540     *
13541     * {@link #TEXT_DIRECTION_INHERIT},
13542     * {@link #TEXT_DIRECTION_FIRST_STRONG}
13543     * {@link #TEXT_DIRECTION_ANY_RTL},
13544     * {@link #TEXT_DIRECTION_LTR},
13545     * {@link #TEXT_DIRECTION_RTL},
13546     *
13547     * @hide
13548     */
13549    public int getTextDirection() {
13550        return mTextDirection;
13551    }
13552
13553    /**
13554     * Set the text direction.
13555     *
13556     * @param textDirection the direction to set. Should be one of:
13557     *
13558     * {@link #TEXT_DIRECTION_INHERIT},
13559     * {@link #TEXT_DIRECTION_FIRST_STRONG}
13560     * {@link #TEXT_DIRECTION_ANY_RTL},
13561     * {@link #TEXT_DIRECTION_LTR},
13562     * {@link #TEXT_DIRECTION_RTL},
13563     *
13564     * @hide
13565     */
13566    public void setTextDirection(int textDirection) {
13567        if (textDirection != mTextDirection) {
13568            mTextDirection = textDirection;
13569            resetResolvedTextDirection();
13570            requestLayout();
13571        }
13572    }
13573
13574    /**
13575     * Return the resolved text direction.
13576     *
13577     * @return the resolved text direction. Return one of:
13578     *
13579     * {@link #TEXT_DIRECTION_FIRST_STRONG}
13580     * {@link #TEXT_DIRECTION_ANY_RTL},
13581     * {@link #TEXT_DIRECTION_LTR},
13582     * {@link #TEXT_DIRECTION_RTL},
13583     *
13584     * @hide
13585     */
13586    public int getResolvedTextDirection() {
13587        if (mResolvedTextDirection == TEXT_DIRECTION_INHERIT) {
13588            resolveTextDirection();
13589        }
13590        return mResolvedTextDirection;
13591    }
13592
13593    /**
13594     * Resolve the text direction.
13595     *
13596     * @hide
13597     */
13598    protected void resolveTextDirection() {
13599        if (mTextDirection != TEXT_DIRECTION_INHERIT) {
13600            mResolvedTextDirection = mTextDirection;
13601            return;
13602        }
13603        if (mParent != null && mParent instanceof ViewGroup) {
13604            mResolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
13605            return;
13606        }
13607        mResolvedTextDirection = TEXT_DIRECTION_FIRST_STRONG;
13608    }
13609
13610    /**
13611     * Reset resolved text direction. Will be resolved during a call to getResolvedTextDirection().
13612     *
13613     * @hide
13614     */
13615    protected void resetResolvedTextDirection() {
13616        mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
13617    }
13618
13619    //
13620    // Properties
13621    //
13622    /**
13623     * A Property wrapper around the <code>alpha</code> functionality handled by the
13624     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
13625     */
13626    public static Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
13627        @Override
13628        public void setValue(View object, float value) {
13629            object.setAlpha(value);
13630        }
13631
13632        @Override
13633        public Float get(View object) {
13634            return object.getAlpha();
13635        }
13636    };
13637
13638    /**
13639     * A Property wrapper around the <code>translationX</code> functionality handled by the
13640     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
13641     */
13642    public static Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
13643        @Override
13644        public void setValue(View object, float value) {
13645            object.setTranslationX(value);
13646        }
13647
13648                @Override
13649        public Float get(View object) {
13650            return object.getTranslationX();
13651        }
13652    };
13653
13654    /**
13655     * A Property wrapper around the <code>translationY</code> functionality handled by the
13656     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
13657     */
13658    public static Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
13659        @Override
13660        public void setValue(View object, float value) {
13661            object.setTranslationY(value);
13662        }
13663
13664        @Override
13665        public Float get(View object) {
13666            return object.getTranslationY();
13667        }
13668    };
13669
13670    /**
13671     * A Property wrapper around the <code>x</code> functionality handled by the
13672     * {@link View#setX(float)} and {@link View#getX()} methods.
13673     */
13674    public static Property<View, Float> X = new FloatProperty<View>("x") {
13675        @Override
13676        public void setValue(View object, float value) {
13677            object.setX(value);
13678        }
13679
13680        @Override
13681        public Float get(View object) {
13682            return object.getX();
13683        }
13684    };
13685
13686    /**
13687     * A Property wrapper around the <code>y</code> functionality handled by the
13688     * {@link View#setY(float)} and {@link View#getY()} methods.
13689     */
13690    public static Property<View, Float> Y = new FloatProperty<View>("y") {
13691        @Override
13692        public void setValue(View object, float value) {
13693            object.setY(value);
13694        }
13695
13696        @Override
13697        public Float get(View object) {
13698            return object.getY();
13699        }
13700    };
13701
13702    /**
13703     * A Property wrapper around the <code>rotation</code> functionality handled by the
13704     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
13705     */
13706    public static Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
13707        @Override
13708        public void setValue(View object, float value) {
13709            object.setRotation(value);
13710        }
13711
13712        @Override
13713        public Float get(View object) {
13714            return object.getRotation();
13715        }
13716    };
13717
13718    /**
13719     * A Property wrapper around the <code>rotationX</code> functionality handled by the
13720     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
13721     */
13722    public static Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
13723        @Override
13724        public void setValue(View object, float value) {
13725            object.setRotationX(value);
13726        }
13727
13728        @Override
13729        public Float get(View object) {
13730            return object.getRotationX();
13731        }
13732    };
13733
13734    /**
13735     * A Property wrapper around the <code>rotationY</code> functionality handled by the
13736     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
13737     */
13738    public static Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
13739        @Override
13740        public void setValue(View object, float value) {
13741            object.setRotationY(value);
13742        }
13743
13744        @Override
13745        public Float get(View object) {
13746            return object.getRotationY();
13747        }
13748    };
13749
13750    /**
13751     * A Property wrapper around the <code>scaleX</code> functionality handled by the
13752     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
13753     */
13754    public static Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
13755        @Override
13756        public void setValue(View object, float value) {
13757            object.setScaleX(value);
13758        }
13759
13760        @Override
13761        public Float get(View object) {
13762            return object.getScaleX();
13763        }
13764    };
13765
13766    /**
13767     * A Property wrapper around the <code>scaleY</code> functionality handled by the
13768     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
13769     */
13770    public static Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
13771        @Override
13772        public void setValue(View object, float value) {
13773            object.setScaleY(value);
13774        }
13775
13776        @Override
13777        public Float get(View object) {
13778            return object.getScaleY();
13779        }
13780    };
13781
13782    /**
13783     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
13784     * Each MeasureSpec represents a requirement for either the width or the height.
13785     * A MeasureSpec is comprised of a size and a mode. There are three possible
13786     * modes:
13787     * <dl>
13788     * <dt>UNSPECIFIED</dt>
13789     * <dd>
13790     * The parent has not imposed any constraint on the child. It can be whatever size
13791     * it wants.
13792     * </dd>
13793     *
13794     * <dt>EXACTLY</dt>
13795     * <dd>
13796     * The parent has determined an exact size for the child. The child is going to be
13797     * given those bounds regardless of how big it wants to be.
13798     * </dd>
13799     *
13800     * <dt>AT_MOST</dt>
13801     * <dd>
13802     * The child can be as large as it wants up to the specified size.
13803     * </dd>
13804     * </dl>
13805     *
13806     * MeasureSpecs are implemented as ints to reduce object allocation. This class
13807     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
13808     */
13809    public static class MeasureSpec {
13810        private static final int MODE_SHIFT = 30;
13811        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
13812
13813        /**
13814         * Measure specification mode: The parent has not imposed any constraint
13815         * on the child. It can be whatever size it wants.
13816         */
13817        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
13818
13819        /**
13820         * Measure specification mode: The parent has determined an exact size
13821         * for the child. The child is going to be given those bounds regardless
13822         * of how big it wants to be.
13823         */
13824        public static final int EXACTLY     = 1 << MODE_SHIFT;
13825
13826        /**
13827         * Measure specification mode: The child can be as large as it wants up
13828         * to the specified size.
13829         */
13830        public static final int AT_MOST     = 2 << MODE_SHIFT;
13831
13832        /**
13833         * Creates a measure specification based on the supplied size and mode.
13834         *
13835         * The mode must always be one of the following:
13836         * <ul>
13837         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
13838         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
13839         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
13840         * </ul>
13841         *
13842         * @param size the size of the measure specification
13843         * @param mode the mode of the measure specification
13844         * @return the measure specification based on size and mode
13845         */
13846        public static int makeMeasureSpec(int size, int mode) {
13847            return size + mode;
13848        }
13849
13850        /**
13851         * Extracts the mode from the supplied measure specification.
13852         *
13853         * @param measureSpec the measure specification to extract the mode from
13854         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
13855         *         {@link android.view.View.MeasureSpec#AT_MOST} or
13856         *         {@link android.view.View.MeasureSpec#EXACTLY}
13857         */
13858        public static int getMode(int measureSpec) {
13859            return (measureSpec & MODE_MASK);
13860        }
13861
13862        /**
13863         * Extracts the size from the supplied measure specification.
13864         *
13865         * @param measureSpec the measure specification to extract the size from
13866         * @return the size in pixels defined in the supplied measure specification
13867         */
13868        public static int getSize(int measureSpec) {
13869            return (measureSpec & ~MODE_MASK);
13870        }
13871
13872        /**
13873         * Returns a String representation of the specified measure
13874         * specification.
13875         *
13876         * @param measureSpec the measure specification to convert to a String
13877         * @return a String with the following format: "MeasureSpec: MODE SIZE"
13878         */
13879        public static String toString(int measureSpec) {
13880            int mode = getMode(measureSpec);
13881            int size = getSize(measureSpec);
13882
13883            StringBuilder sb = new StringBuilder("MeasureSpec: ");
13884
13885            if (mode == UNSPECIFIED)
13886                sb.append("UNSPECIFIED ");
13887            else if (mode == EXACTLY)
13888                sb.append("EXACTLY ");
13889            else if (mode == AT_MOST)
13890                sb.append("AT_MOST ");
13891            else
13892                sb.append(mode).append(" ");
13893
13894            sb.append(size);
13895            return sb.toString();
13896        }
13897    }
13898
13899    class CheckForLongPress implements Runnable {
13900
13901        private int mOriginalWindowAttachCount;
13902
13903        public void run() {
13904            if (isPressed() && (mParent != null)
13905                    && mOriginalWindowAttachCount == mWindowAttachCount) {
13906                if (performLongClick()) {
13907                    mHasPerformedLongPress = true;
13908                }
13909            }
13910        }
13911
13912        public void rememberWindowAttachCount() {
13913            mOriginalWindowAttachCount = mWindowAttachCount;
13914        }
13915    }
13916
13917    private final class CheckForTap implements Runnable {
13918        public void run() {
13919            mPrivateFlags &= ~PREPRESSED;
13920            mPrivateFlags |= PRESSED;
13921            refreshDrawableState();
13922            checkForLongClick(ViewConfiguration.getTapTimeout());
13923        }
13924    }
13925
13926    private final class PerformClick implements Runnable {
13927        public void run() {
13928            performClick();
13929        }
13930    }
13931
13932    /** @hide */
13933    public void hackTurnOffWindowResizeAnim(boolean off) {
13934        mAttachInfo.mTurnOffWindowResizeAnim = off;
13935    }
13936
13937    /**
13938     * This method returns a ViewPropertyAnimator object, which can be used to animate
13939     * specific properties on this View.
13940     *
13941     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
13942     */
13943    public ViewPropertyAnimator animate() {
13944        if (mAnimator == null) {
13945            mAnimator = new ViewPropertyAnimator(this);
13946        }
13947        return mAnimator;
13948    }
13949
13950    /**
13951     * Interface definition for a callback to be invoked when a key event is
13952     * dispatched to this view. The callback will be invoked before the key
13953     * event is given to the view.
13954     */
13955    public interface OnKeyListener {
13956        /**
13957         * Called when a key is dispatched to a view. This allows listeners to
13958         * get a chance to respond before the target view.
13959         *
13960         * @param v The view the key has been dispatched to.
13961         * @param keyCode The code for the physical key that was pressed
13962         * @param event The KeyEvent object containing full information about
13963         *        the event.
13964         * @return True if the listener has consumed the event, false otherwise.
13965         */
13966        boolean onKey(View v, int keyCode, KeyEvent event);
13967    }
13968
13969    /**
13970     * Interface definition for a callback to be invoked when a touch event is
13971     * dispatched to this view. The callback will be invoked before the touch
13972     * event is given to the view.
13973     */
13974    public interface OnTouchListener {
13975        /**
13976         * Called when a touch event is dispatched to a view. This allows listeners to
13977         * get a chance to respond before the target view.
13978         *
13979         * @param v The view the touch event has been dispatched to.
13980         * @param event The MotionEvent object containing full information about
13981         *        the event.
13982         * @return True if the listener has consumed the event, false otherwise.
13983         */
13984        boolean onTouch(View v, MotionEvent event);
13985    }
13986
13987    /**
13988     * Interface definition for a callback to be invoked when a hover event is
13989     * dispatched to this view. The callback will be invoked before the hover
13990     * event is given to the view.
13991     */
13992    public interface OnHoverListener {
13993        /**
13994         * Called when a hover event is dispatched to a view. This allows listeners to
13995         * get a chance to respond before the target view.
13996         *
13997         * @param v The view the hover event has been dispatched to.
13998         * @param event The MotionEvent object containing full information about
13999         *        the event.
14000         * @return True if the listener has consumed the event, false otherwise.
14001         */
14002        boolean onHover(View v, MotionEvent event);
14003    }
14004
14005    /**
14006     * Interface definition for a callback to be invoked when a generic motion event is
14007     * dispatched to this view. The callback will be invoked before the generic motion
14008     * event is given to the view.
14009     */
14010    public interface OnGenericMotionListener {
14011        /**
14012         * Called when a generic motion event 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 generic motion event has been dispatched to.
14016         * @param event The MotionEvent object containing full information about
14017         *        the event.
14018         * @return True if the listener has consumed the event, false otherwise.
14019         */
14020        boolean onGenericMotion(View v, MotionEvent event);
14021    }
14022
14023    /**
14024     * Interface definition for a callback to be invoked when a view has been clicked and held.
14025     */
14026    public interface OnLongClickListener {
14027        /**
14028         * Called when a view has been clicked and held.
14029         *
14030         * @param v The view that was clicked and held.
14031         *
14032         * @return true if the callback consumed the long click, false otherwise.
14033         */
14034        boolean onLongClick(View v);
14035    }
14036
14037    /**
14038     * Interface definition for a callback to be invoked when a drag is being dispatched
14039     * to this view.  The callback will be invoked before the hosting view's own
14040     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
14041     * onDrag(event) behavior, it should return 'false' from this callback.
14042     */
14043    public interface OnDragListener {
14044        /**
14045         * Called when a drag event is dispatched to a view. This allows listeners
14046         * to get a chance to override base View behavior.
14047         *
14048         * @param v The View that received the drag event.
14049         * @param event The {@link android.view.DragEvent} object for the drag event.
14050         * @return {@code true} if the drag event was handled successfully, or {@code false}
14051         * if the drag event was not handled. Note that {@code false} will trigger the View
14052         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
14053         */
14054        boolean onDrag(View v, DragEvent event);
14055    }
14056
14057    /**
14058     * Interface definition for a callback to be invoked when the focus state of
14059     * a view changed.
14060     */
14061    public interface OnFocusChangeListener {
14062        /**
14063         * Called when the focus state of a view has changed.
14064         *
14065         * @param v The view whose state has changed.
14066         * @param hasFocus The new focus state of v.
14067         */
14068        void onFocusChange(View v, boolean hasFocus);
14069    }
14070
14071    /**
14072     * Interface definition for a callback to be invoked when a view is clicked.
14073     */
14074    public interface OnClickListener {
14075        /**
14076         * Called when a view has been clicked.
14077         *
14078         * @param v The view that was clicked.
14079         */
14080        void onClick(View v);
14081    }
14082
14083    /**
14084     * Interface definition for a callback to be invoked when the context menu
14085     * for this view is being built.
14086     */
14087    public interface OnCreateContextMenuListener {
14088        /**
14089         * Called when the context menu for this view is being built. It is not
14090         * safe to hold onto the menu after this method returns.
14091         *
14092         * @param menu The context menu that is being built
14093         * @param v The view for which the context menu is being built
14094         * @param menuInfo Extra information about the item for which the
14095         *            context menu should be shown. This information will vary
14096         *            depending on the class of v.
14097         */
14098        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
14099    }
14100
14101    /**
14102     * Interface definition for a callback to be invoked when the status bar changes
14103     * visibility.
14104     *
14105     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
14106     */
14107    public interface OnSystemUiVisibilityChangeListener {
14108        /**
14109         * Called when the status bar changes visibility because of a call to
14110         * {@link View#setSystemUiVisibility(int)}.
14111         *
14112         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
14113         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
14114         */
14115        public void onSystemUiVisibilityChange(int visibility);
14116    }
14117
14118    /**
14119     * Interface definition for a callback to be invoked when this view is attached
14120     * or detached from its window.
14121     */
14122    public interface OnAttachStateChangeListener {
14123        /**
14124         * Called when the view is attached to a window.
14125         * @param v The view that was attached
14126         */
14127        public void onViewAttachedToWindow(View v);
14128        /**
14129         * Called when the view is detached from a window.
14130         * @param v The view that was detached
14131         */
14132        public void onViewDetachedFromWindow(View v);
14133    }
14134
14135    private final class UnsetPressedState implements Runnable {
14136        public void run() {
14137            setPressed(false);
14138        }
14139    }
14140
14141    /**
14142     * Base class for derived classes that want to save and restore their own
14143     * state in {@link android.view.View#onSaveInstanceState()}.
14144     */
14145    public static class BaseSavedState extends AbsSavedState {
14146        /**
14147         * Constructor used when reading from a parcel. Reads the state of the superclass.
14148         *
14149         * @param source
14150         */
14151        public BaseSavedState(Parcel source) {
14152            super(source);
14153        }
14154
14155        /**
14156         * Constructor called by derived classes when creating their SavedState objects
14157         *
14158         * @param superState The state of the superclass of this view
14159         */
14160        public BaseSavedState(Parcelable superState) {
14161            super(superState);
14162        }
14163
14164        public static final Parcelable.Creator<BaseSavedState> CREATOR =
14165                new Parcelable.Creator<BaseSavedState>() {
14166            public BaseSavedState createFromParcel(Parcel in) {
14167                return new BaseSavedState(in);
14168            }
14169
14170            public BaseSavedState[] newArray(int size) {
14171                return new BaseSavedState[size];
14172            }
14173        };
14174    }
14175
14176    /**
14177     * A set of information given to a view when it is attached to its parent
14178     * window.
14179     */
14180    static class AttachInfo {
14181        interface Callbacks {
14182            void playSoundEffect(int effectId);
14183            boolean performHapticFeedback(int effectId, boolean always);
14184        }
14185
14186        /**
14187         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
14188         * to a Handler. This class contains the target (View) to invalidate and
14189         * the coordinates of the dirty rectangle.
14190         *
14191         * For performance purposes, this class also implements a pool of up to
14192         * POOL_LIMIT objects that get reused. This reduces memory allocations
14193         * whenever possible.
14194         */
14195        static class InvalidateInfo implements Poolable<InvalidateInfo> {
14196            private static final int POOL_LIMIT = 10;
14197            private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
14198                    Pools.finitePool(new PoolableManager<InvalidateInfo>() {
14199                        public InvalidateInfo newInstance() {
14200                            return new InvalidateInfo();
14201                        }
14202
14203                        public void onAcquired(InvalidateInfo element) {
14204                        }
14205
14206                        public void onReleased(InvalidateInfo element) {
14207                            element.target = null;
14208                        }
14209                    }, POOL_LIMIT)
14210            );
14211
14212            private InvalidateInfo mNext;
14213            private boolean mIsPooled;
14214
14215            View target;
14216
14217            int left;
14218            int top;
14219            int right;
14220            int bottom;
14221
14222            public void setNextPoolable(InvalidateInfo element) {
14223                mNext = element;
14224            }
14225
14226            public InvalidateInfo getNextPoolable() {
14227                return mNext;
14228            }
14229
14230            static InvalidateInfo acquire() {
14231                return sPool.acquire();
14232            }
14233
14234            void release() {
14235                sPool.release(this);
14236            }
14237
14238            public boolean isPooled() {
14239                return mIsPooled;
14240            }
14241
14242            public void setPooled(boolean isPooled) {
14243                mIsPooled = isPooled;
14244            }
14245        }
14246
14247        final IWindowSession mSession;
14248
14249        final IWindow mWindow;
14250
14251        final IBinder mWindowToken;
14252
14253        final Callbacks mRootCallbacks;
14254
14255        HardwareCanvas mHardwareCanvas;
14256
14257        /**
14258         * The top view of the hierarchy.
14259         */
14260        View mRootView;
14261
14262        IBinder mPanelParentWindowToken;
14263        Surface mSurface;
14264
14265        boolean mHardwareAccelerated;
14266        boolean mHardwareAccelerationRequested;
14267        HardwareRenderer mHardwareRenderer;
14268
14269        /**
14270         * Scale factor used by the compatibility mode
14271         */
14272        float mApplicationScale;
14273
14274        /**
14275         * Indicates whether the application is in compatibility mode
14276         */
14277        boolean mScalingRequired;
14278
14279        /**
14280         * If set, ViewAncestor doesn't use its lame animation for when the window resizes.
14281         */
14282        boolean mTurnOffWindowResizeAnim;
14283
14284        /**
14285         * Left position of this view's window
14286         */
14287        int mWindowLeft;
14288
14289        /**
14290         * Top position of this view's window
14291         */
14292        int mWindowTop;
14293
14294        /**
14295         * Indicates whether views need to use 32-bit drawing caches
14296         */
14297        boolean mUse32BitDrawingCache;
14298
14299        /**
14300         * For windows that are full-screen but using insets to layout inside
14301         * of the screen decorations, these are the current insets for the
14302         * content of the window.
14303         */
14304        final Rect mContentInsets = new Rect();
14305
14306        /**
14307         * For windows that are full-screen but using insets to layout inside
14308         * of the screen decorations, these are the current insets for the
14309         * actual visible parts of the window.
14310         */
14311        final Rect mVisibleInsets = new Rect();
14312
14313        /**
14314         * The internal insets given by this window.  This value is
14315         * supplied by the client (through
14316         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
14317         * be given to the window manager when changed to be used in laying
14318         * out windows behind it.
14319         */
14320        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
14321                = new ViewTreeObserver.InternalInsetsInfo();
14322
14323        /**
14324         * All views in the window's hierarchy that serve as scroll containers,
14325         * used to determine if the window can be resized or must be panned
14326         * to adjust for a soft input area.
14327         */
14328        final ArrayList<View> mScrollContainers = new ArrayList<View>();
14329
14330        final KeyEvent.DispatcherState mKeyDispatchState
14331                = new KeyEvent.DispatcherState();
14332
14333        /**
14334         * Indicates whether the view's window currently has the focus.
14335         */
14336        boolean mHasWindowFocus;
14337
14338        /**
14339         * The current visibility of the window.
14340         */
14341        int mWindowVisibility;
14342
14343        /**
14344         * Indicates the time at which drawing started to occur.
14345         */
14346        long mDrawingTime;
14347
14348        /**
14349         * Indicates whether or not ignoring the DIRTY_MASK flags.
14350         */
14351        boolean mIgnoreDirtyState;
14352
14353        /**
14354         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
14355         * to avoid clearing that flag prematurely.
14356         */
14357        boolean mSetIgnoreDirtyState = false;
14358
14359        /**
14360         * Indicates whether the view's window is currently in touch mode.
14361         */
14362        boolean mInTouchMode;
14363
14364        /**
14365         * Indicates that ViewAncestor should trigger a global layout change
14366         * the next time it performs a traversal
14367         */
14368        boolean mRecomputeGlobalAttributes;
14369
14370        /**
14371         * Set during a traveral if any views want to keep the screen on.
14372         */
14373        boolean mKeepScreenOn;
14374
14375        /**
14376         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
14377         */
14378        int mSystemUiVisibility;
14379
14380        /**
14381         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
14382         * attached.
14383         */
14384        boolean mHasSystemUiListeners;
14385
14386        /**
14387         * Set if the visibility of any views has changed.
14388         */
14389        boolean mViewVisibilityChanged;
14390
14391        /**
14392         * Set to true if a view has been scrolled.
14393         */
14394        boolean mViewScrollChanged;
14395
14396        /**
14397         * Global to the view hierarchy used as a temporary for dealing with
14398         * x/y points in the transparent region computations.
14399         */
14400        final int[] mTransparentLocation = new int[2];
14401
14402        /**
14403         * Global to the view hierarchy used as a temporary for dealing with
14404         * x/y points in the ViewGroup.invalidateChild implementation.
14405         */
14406        final int[] mInvalidateChildLocation = new int[2];
14407
14408
14409        /**
14410         * Global to the view hierarchy used as a temporary for dealing with
14411         * x/y location when view is transformed.
14412         */
14413        final float[] mTmpTransformLocation = new float[2];
14414
14415        /**
14416         * The view tree observer used to dispatch global events like
14417         * layout, pre-draw, touch mode change, etc.
14418         */
14419        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
14420
14421        /**
14422         * A Canvas used by the view hierarchy to perform bitmap caching.
14423         */
14424        Canvas mCanvas;
14425
14426        /**
14427         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
14428         * handler can be used to pump events in the UI events queue.
14429         */
14430        final Handler mHandler;
14431
14432        /**
14433         * Identifier for messages requesting the view to be invalidated.
14434         * Such messages should be sent to {@link #mHandler}.
14435         */
14436        static final int INVALIDATE_MSG = 0x1;
14437
14438        /**
14439         * Identifier for messages requesting the view to invalidate a region.
14440         * Such messages should be sent to {@link #mHandler}.
14441         */
14442        static final int INVALIDATE_RECT_MSG = 0x2;
14443
14444        /**
14445         * Temporary for use in computing invalidate rectangles while
14446         * calling up the hierarchy.
14447         */
14448        final Rect mTmpInvalRect = new Rect();
14449
14450        /**
14451         * Temporary for use in computing hit areas with transformed views
14452         */
14453        final RectF mTmpTransformRect = new RectF();
14454
14455        /**
14456         * Temporary list for use in collecting focusable descendents of a view.
14457         */
14458        final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24);
14459
14460        /**
14461         * The id of the window for accessibility purposes.
14462         */
14463        int mAccessibilityWindowId = View.NO_ID;
14464
14465        /**
14466         * Creates a new set of attachment information with the specified
14467         * events handler and thread.
14468         *
14469         * @param handler the events handler the view must use
14470         */
14471        AttachInfo(IWindowSession session, IWindow window,
14472                Handler handler, Callbacks effectPlayer) {
14473            mSession = session;
14474            mWindow = window;
14475            mWindowToken = window.asBinder();
14476            mHandler = handler;
14477            mRootCallbacks = effectPlayer;
14478        }
14479    }
14480
14481    /**
14482     * <p>ScrollabilityCache holds various fields used by a View when scrolling
14483     * is supported. This avoids keeping too many unused fields in most
14484     * instances of View.</p>
14485     */
14486    private static class ScrollabilityCache implements Runnable {
14487
14488        /**
14489         * Scrollbars are not visible
14490         */
14491        public static final int OFF = 0;
14492
14493        /**
14494         * Scrollbars are visible
14495         */
14496        public static final int ON = 1;
14497
14498        /**
14499         * Scrollbars are fading away
14500         */
14501        public static final int FADING = 2;
14502
14503        public boolean fadeScrollBars;
14504
14505        public int fadingEdgeLength;
14506        public int scrollBarDefaultDelayBeforeFade;
14507        public int scrollBarFadeDuration;
14508
14509        public int scrollBarSize;
14510        public ScrollBarDrawable scrollBar;
14511        public float[] interpolatorValues;
14512        public View host;
14513
14514        public final Paint paint;
14515        public final Matrix matrix;
14516        public Shader shader;
14517
14518        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
14519
14520        private static final float[] OPAQUE = { 255 };
14521        private static final float[] TRANSPARENT = { 0.0f };
14522
14523        /**
14524         * When fading should start. This time moves into the future every time
14525         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
14526         */
14527        public long fadeStartTime;
14528
14529
14530        /**
14531         * The current state of the scrollbars: ON, OFF, or FADING
14532         */
14533        public int state = OFF;
14534
14535        private int mLastColor;
14536
14537        public ScrollabilityCache(ViewConfiguration configuration, View host) {
14538            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
14539            scrollBarSize = configuration.getScaledScrollBarSize();
14540            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
14541            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
14542
14543            paint = new Paint();
14544            matrix = new Matrix();
14545            // use use a height of 1, and then wack the matrix each time we
14546            // actually use it.
14547            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
14548
14549            paint.setShader(shader);
14550            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
14551            this.host = host;
14552        }
14553
14554        public void setFadeColor(int color) {
14555            if (color != 0 && color != mLastColor) {
14556                mLastColor = color;
14557                color |= 0xFF000000;
14558
14559                shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
14560                        color & 0x00FFFFFF, Shader.TileMode.CLAMP);
14561
14562                paint.setShader(shader);
14563                // Restore the default transfer mode (src_over)
14564                paint.setXfermode(null);
14565            }
14566        }
14567
14568        public void run() {
14569            long now = AnimationUtils.currentAnimationTimeMillis();
14570            if (now >= fadeStartTime) {
14571
14572                // the animation fades the scrollbars out by changing
14573                // the opacity (alpha) from fully opaque to fully
14574                // transparent
14575                int nextFrame = (int) now;
14576                int framesCount = 0;
14577
14578                Interpolator interpolator = scrollBarInterpolator;
14579
14580                // Start opaque
14581                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
14582
14583                // End transparent
14584                nextFrame += scrollBarFadeDuration;
14585                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
14586
14587                state = FADING;
14588
14589                // Kick off the fade animation
14590                host.invalidate(true);
14591            }
14592        }
14593    }
14594
14595    /**
14596     * Resuable callback for sending
14597     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
14598     */
14599    private class SendViewScrolledAccessibilityEvent implements Runnable {
14600        public volatile boolean mIsPending;
14601
14602        public void run() {
14603            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
14604            mIsPending = false;
14605        }
14606    }
14607
14608    /**
14609     * <p>
14610     * This class represents a delegate that can be registered in a {@link View}
14611     * to enhance accessibility support via composition rather via inheritance.
14612     * It is specifically targeted to widget developers that extend basic View
14613     * classes i.e. classes in package android.view, that would like their
14614     * applications to be backwards compatible.
14615     * </p>
14616     * <p>
14617     * A scenario in which a developer would like to use an accessibility delegate
14618     * is overriding a method introduced in a later API version then the minimal API
14619     * version supported by the application. For example, the method
14620     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
14621     * in API version 4 when the accessibility APIs were first introduced. If a
14622     * developer would like his application to run on API version 4 devices (assuming
14623     * all other APIs used by the application are version 4 or lower) and take advantage
14624     * of this method, instead of overriding the method which would break the application's
14625     * backwards compatibility, he can override the corresponding method in this
14626     * delegate and register the delegate in the target View if the API version of
14627     * the system is high enough i.e. the API version is same or higher to the API
14628     * version that introduced
14629     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
14630     * </p>
14631     * <p>
14632     * Here is an example implementation:
14633     * </p>
14634     * <code><pre><p>
14635     * if (Build.VERSION.SDK_INT >= 14) {
14636     *     // If the API version is equal of higher than the version in
14637     *     // which onInitializeAccessibilityNodeInfo was introduced we
14638     *     // register a delegate with a customized implementation.
14639     *     View view = findViewById(R.id.view_id);
14640     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
14641     *         public void onInitializeAccessibilityNodeInfo(View host,
14642     *                 AccessibilityNodeInfo info) {
14643     *             // Let the default implementation populate the info.
14644     *             super.onInitializeAccessibilityNodeInfo(host, info);
14645     *             // Set some other information.
14646     *             info.setEnabled(host.isEnabled());
14647     *         }
14648     *     });
14649     * }
14650     * </code></pre></p>
14651     * <p>
14652     * This delegate contains methods that correspond to the accessibility methods
14653     * in View. If a delegate has been specified the implementation in View hands
14654     * off handling to the corresponding method in this delegate. The default
14655     * implementation the delegate methods behaves exactly as the corresponding
14656     * method in View for the case of no accessibility delegate been set. Hence,
14657     * to customize the behavior of a View method, clients can override only the
14658     * corresponding delegate method without altering the behavior of the rest
14659     * accessibility related methods of the host view.
14660     * </p>
14661     */
14662    public static class AccessibilityDelegate {
14663
14664        /**
14665         * Sends an accessibility event of the given type. If accessibility is not
14666         * enabled this method has no effect.
14667         * <p>
14668         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
14669         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
14670         * been set.
14671         * </p>
14672         *
14673         * @param host The View hosting the delegate.
14674         * @param eventType The type of the event to send.
14675         *
14676         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
14677         */
14678        public void sendAccessibilityEvent(View host, int eventType) {
14679            host.sendAccessibilityEventInternal(eventType);
14680        }
14681
14682        /**
14683         * Sends an accessibility event. This method behaves exactly as
14684         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
14685         * empty {@link AccessibilityEvent} and does not perform a check whether
14686         * accessibility is enabled.
14687         * <p>
14688         * The default implementation behaves as
14689         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
14690         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
14691         * the case of no accessibility delegate been set.
14692         * </p>
14693         *
14694         * @param host The View hosting the delegate.
14695         * @param event The event to send.
14696         *
14697         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
14698         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
14699         */
14700        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
14701            host.sendAccessibilityEventUncheckedInternal(event);
14702        }
14703
14704        /**
14705         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
14706         * to its children for adding their text content to the event.
14707         * <p>
14708         * The default implementation behaves as
14709         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
14710         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
14711         * the case of no accessibility delegate been set.
14712         * </p>
14713         *
14714         * @param host The View hosting the delegate.
14715         * @param event The event.
14716         * @return True if the event population was completed.
14717         *
14718         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
14719         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
14720         */
14721        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
14722            return host.dispatchPopulateAccessibilityEventInternal(event);
14723        }
14724
14725        /**
14726         * Gives a chance to the host View to populate the accessibility event with its
14727         * text content.
14728         * <p>
14729         * The default implementation behaves as
14730         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
14731         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
14732         * the case of no accessibility delegate been set.
14733         * </p>
14734         *
14735         * @param host The View hosting the delegate.
14736         * @param event The accessibility event which to populate.
14737         *
14738         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
14739         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
14740         */
14741        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
14742            host.onPopulateAccessibilityEventInternal(event);
14743        }
14744
14745        /**
14746         * Initializes an {@link AccessibilityEvent} with information about the
14747         * the host View which is the event source.
14748         * <p>
14749         * The default implementation behaves as
14750         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
14751         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
14752         * the case of no accessibility delegate been set.
14753         * </p>
14754         *
14755         * @param host The View hosting the delegate.
14756         * @param event The event to initialize.
14757         *
14758         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
14759         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
14760         */
14761        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
14762            host.onInitializeAccessibilityEventInternal(event);
14763        }
14764
14765        /**
14766         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
14767         * <p>
14768         * The default implementation behaves as
14769         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
14770         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
14771         * the case of no accessibility delegate been set.
14772         * </p>
14773         *
14774         * @param host The View hosting the delegate.
14775         * @param info The instance to initialize.
14776         *
14777         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
14778         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
14779         */
14780        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
14781            host.onInitializeAccessibilityNodeInfoInternal(info);
14782        }
14783
14784        /**
14785         * Called when a child of the host View has requested sending an
14786         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
14787         * to augment the event.
14788         * <p>
14789         * The default implementation behaves as
14790         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
14791         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
14792         * the case of no accessibility delegate been set.
14793         * </p>
14794         *
14795         * @param host The View hosting the delegate.
14796         * @param child The child which requests sending the event.
14797         * @param event The event to be sent.
14798         * @return True if the event should be sent
14799         *
14800         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
14801         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
14802         */
14803        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
14804                AccessibilityEvent event) {
14805            return host.onRequestSendAccessibilityEventInternal(child, event);
14806        }
14807    }
14808}
14809