View.java revision 33e72aef05c75699c9180626dbaa00b06f86ad5b
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.graphics.RectF;
20import com.android.internal.R;
21import com.android.internal.view.menu.MenuBuilder;
22
23import android.content.Context;
24import android.content.res.Configuration;
25import android.content.res.Resources;
26import android.content.res.TypedArray;
27import android.graphics.Bitmap;
28import android.graphics.Canvas;
29import android.graphics.Interpolator;
30import android.graphics.LinearGradient;
31import android.graphics.Matrix;
32import android.graphics.Paint;
33import android.graphics.PixelFormat;
34import android.graphics.Point;
35import android.graphics.PorterDuff;
36import android.graphics.PorterDuffXfermode;
37import android.graphics.Rect;
38import android.graphics.Region;
39import android.graphics.Shader;
40import android.graphics.drawable.ColorDrawable;
41import android.graphics.drawable.Drawable;
42import android.os.Handler;
43import android.os.IBinder;
44import android.os.Message;
45import android.os.Parcel;
46import android.os.Parcelable;
47import android.os.RemoteException;
48import android.os.SystemClock;
49import android.os.SystemProperties;
50import android.util.AttributeSet;
51import android.util.Config;
52import android.util.EventLog;
53import android.util.Log;
54import android.util.Pool;
55import android.util.Poolable;
56import android.util.PoolableManager;
57import android.util.Pools;
58import android.util.SparseArray;
59import android.view.ContextMenu.ContextMenuInfo;
60import android.view.accessibility.AccessibilityEvent;
61import android.view.accessibility.AccessibilityEventSource;
62import android.view.accessibility.AccessibilityManager;
63import android.view.animation.Animation;
64import android.view.animation.AnimationUtils;
65import android.view.inputmethod.EditorInfo;
66import android.view.inputmethod.InputConnection;
67import android.view.inputmethod.InputMethodManager;
68import android.widget.ScrollBarDrawable;
69
70import java.lang.ref.SoftReference;
71import java.lang.reflect.InvocationTargetException;
72import java.lang.reflect.Method;
73import java.util.ArrayList;
74import java.util.Arrays;
75import java.util.WeakHashMap;
76
77/**
78 * <p>
79 * This class represents the basic building block for user interface components. A View
80 * occupies a rectangular area on the screen and is responsible for drawing and
81 * event handling. View is the base class for <em>widgets</em>, which are
82 * used to create interactive UI components (buttons, text fields, etc.). The
83 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
84 * are invisible containers that hold other Views (or other ViewGroups) and define
85 * their layout properties.
86 * </p>
87 *
88 * <div class="special">
89 * <p>For an introduction to using this class to develop your
90 * application's user interface, read the Developer Guide documentation on
91 * <strong><a href="{@docRoot}guide/topics/ui/index.html">User Interface</a></strong>. Special topics
92 * include:
93 * <br/><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a>
94 * <br/><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a>
95 * <br/><a href="{@docRoot}guide/topics/ui/layout-objects.html">Common Layout Objects</a>
96 * <br/><a href="{@docRoot}guide/topics/ui/binding.html">Binding to Data with AdapterView</a>
97 * <br/><a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a>
98 * <br/><a href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a>
99 * <br/><a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>
100 * <br/><a href="{@docRoot}guide/topics/ui/how-android-draws.html">How Android Draws Views</a>.
101 * </p>
102 * </div>
103 *
104 * <a name="Using"></a>
105 * <h3>Using Views</h3>
106 * <p>
107 * All of the views in a window are arranged in a single tree. You can add views
108 * either from code or by specifying a tree of views in one or more XML layout
109 * files. There are many specialized subclasses of views that act as controls or
110 * are capable of displaying text, images, or other content.
111 * </p>
112 * <p>
113 * Once you have created a tree of views, there are typically a few types of
114 * common operations you may wish to perform:
115 * <ul>
116 * <li><strong>Set properties:</strong> for example setting the text of a
117 * {@link android.widget.TextView}. The available properties and the methods
118 * that set them will vary among the different subclasses of views. Note that
119 * properties that are known at build time can be set in the XML layout
120 * files.</li>
121 * <li><strong>Set focus:</strong> The framework will handled moving focus in
122 * response to user input. To force focus to a specific view, call
123 * {@link #requestFocus}.</li>
124 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
125 * that will be notified when something interesting happens to the view. For
126 * example, all views will let you set a listener to be notified when the view
127 * gains or loses focus. You can register such a listener using
128 * {@link #setOnFocusChangeListener}. Other view subclasses offer more
129 * specialized listeners. For example, a Button exposes a listener to notify
130 * clients when the button is clicked.</li>
131 * <li><strong>Set visibility:</strong> You can hide or show views using
132 * {@link #setVisibility}.</li>
133 * </ul>
134 * </p>
135 * <p><em>
136 * Note: The Android framework is responsible for measuring, laying out and
137 * drawing views. You should not call methods that perform these actions on
138 * views yourself unless you are actually implementing a
139 * {@link android.view.ViewGroup}.
140 * </em></p>
141 *
142 * <a name="Lifecycle"></a>
143 * <h3>Implementing a Custom View</h3>
144 *
145 * <p>
146 * To implement a custom view, you will usually begin by providing overrides for
147 * some of the standard methods that the framework calls on all views. You do
148 * not need to override all of these methods. In fact, you can start by just
149 * overriding {@link #onDraw(android.graphics.Canvas)}.
150 * <table border="2" width="85%" align="center" cellpadding="5">
151 *     <thead>
152 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
153 *     </thead>
154 *
155 *     <tbody>
156 *     <tr>
157 *         <td rowspan="2">Creation</td>
158 *         <td>Constructors</td>
159 *         <td>There is a form of the constructor that are called when the view
160 *         is created from code and a form that is called when the view is
161 *         inflated from a layout file. The second form should parse and apply
162 *         any attributes defined in the layout file.
163 *         </td>
164 *     </tr>
165 *     <tr>
166 *         <td><code>{@link #onFinishInflate()}</code></td>
167 *         <td>Called after a view and all of its children has been inflated
168 *         from XML.</td>
169 *     </tr>
170 *
171 *     <tr>
172 *         <td rowspan="3">Layout</td>
173 *         <td><code>{@link #onMeasure}</code></td>
174 *         <td>Called to determine the size requirements for this view and all
175 *         of its children.
176 *         </td>
177 *     </tr>
178 *     <tr>
179 *         <td><code>{@link #onLayout}</code></td>
180 *         <td>Called when this view should assign a size and position to all
181 *         of its children.
182 *         </td>
183 *     </tr>
184 *     <tr>
185 *         <td><code>{@link #onSizeChanged}</code></td>
186 *         <td>Called when the size of this view has changed.
187 *         </td>
188 *     </tr>
189 *
190 *     <tr>
191 *         <td>Drawing</td>
192 *         <td><code>{@link #onDraw}</code></td>
193 *         <td>Called when the view should render its content.
194 *         </td>
195 *     </tr>
196 *
197 *     <tr>
198 *         <td rowspan="4">Event processing</td>
199 *         <td><code>{@link #onKeyDown}</code></td>
200 *         <td>Called when a new key event occurs.
201 *         </td>
202 *     </tr>
203 *     <tr>
204 *         <td><code>{@link #onKeyUp}</code></td>
205 *         <td>Called when a key up event occurs.
206 *         </td>
207 *     </tr>
208 *     <tr>
209 *         <td><code>{@link #onTrackballEvent}</code></td>
210 *         <td>Called when a trackball motion event occurs.
211 *         </td>
212 *     </tr>
213 *     <tr>
214 *         <td><code>{@link #onTouchEvent}</code></td>
215 *         <td>Called when a touch screen motion event occurs.
216 *         </td>
217 *     </tr>
218 *
219 *     <tr>
220 *         <td rowspan="2">Focus</td>
221 *         <td><code>{@link #onFocusChanged}</code></td>
222 *         <td>Called when the view gains or loses focus.
223 *         </td>
224 *     </tr>
225 *
226 *     <tr>
227 *         <td><code>{@link #onWindowFocusChanged}</code></td>
228 *         <td>Called when the window containing the view gains or loses focus.
229 *         </td>
230 *     </tr>
231 *
232 *     <tr>
233 *         <td rowspan="3">Attaching</td>
234 *         <td><code>{@link #onAttachedToWindow()}</code></td>
235 *         <td>Called when the view is attached to a window.
236 *         </td>
237 *     </tr>
238 *
239 *     <tr>
240 *         <td><code>{@link #onDetachedFromWindow}</code></td>
241 *         <td>Called when the view is detached from its window.
242 *         </td>
243 *     </tr>
244 *
245 *     <tr>
246 *         <td><code>{@link #onWindowVisibilityChanged}</code></td>
247 *         <td>Called when the visibility of the window containing the view
248 *         has changed.
249 *         </td>
250 *     </tr>
251 *     </tbody>
252 *
253 * </table>
254 * </p>
255 *
256 * <a name="IDs"></a>
257 * <h3>IDs</h3>
258 * Views may have an integer id associated with them. These ids are typically
259 * assigned in the layout XML files, and are used to find specific views within
260 * the view tree. A common pattern is to:
261 * <ul>
262 * <li>Define a Button in the layout file and assign it a unique ID.
263 * <pre>
264 * &lt;Button 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()} and {@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 *
546 * @attr ref android.R.styleable#View_background
547 * @attr ref android.R.styleable#View_clickable
548 * @attr ref android.R.styleable#View_contentDescription
549 * @attr ref android.R.styleable#View_drawingCacheQuality
550 * @attr ref android.R.styleable#View_duplicateParentState
551 * @attr ref android.R.styleable#View_id
552 * @attr ref android.R.styleable#View_fadingEdge
553 * @attr ref android.R.styleable#View_fadingEdgeLength
554 * @attr ref android.R.styleable#View_fitsSystemWindows
555 * @attr ref android.R.styleable#View_isScrollContainer
556 * @attr ref android.R.styleable#View_focusable
557 * @attr ref android.R.styleable#View_focusableInTouchMode
558 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
559 * @attr ref android.R.styleable#View_keepScreenOn
560 * @attr ref android.R.styleable#View_longClickable
561 * @attr ref android.R.styleable#View_minHeight
562 * @attr ref android.R.styleable#View_minWidth
563 * @attr ref android.R.styleable#View_nextFocusDown
564 * @attr ref android.R.styleable#View_nextFocusLeft
565 * @attr ref android.R.styleable#View_nextFocusRight
566 * @attr ref android.R.styleable#View_nextFocusUp
567 * @attr ref android.R.styleable#View_onClick
568 * @attr ref android.R.styleable#View_padding
569 * @attr ref android.R.styleable#View_paddingBottom
570 * @attr ref android.R.styleable#View_paddingLeft
571 * @attr ref android.R.styleable#View_paddingRight
572 * @attr ref android.R.styleable#View_paddingTop
573 * @attr ref android.R.styleable#View_saveEnabled
574 * @attr ref android.R.styleable#View_scrollX
575 * @attr ref android.R.styleable#View_scrollY
576 * @attr ref android.R.styleable#View_scrollbarSize
577 * @attr ref android.R.styleable#View_scrollbarStyle
578 * @attr ref android.R.styleable#View_scrollbars
579 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
580 * @attr ref android.R.styleable#View_scrollbarFadeDuration
581 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
582 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
583 * @attr ref android.R.styleable#View_scrollbarThumbVertical
584 * @attr ref android.R.styleable#View_scrollbarTrackVertical
585 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
586 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
587 * @attr ref android.R.styleable#View_soundEffectsEnabled
588 * @attr ref android.R.styleable#View_tag
589 * @attr ref android.R.styleable#View_visibility
590 *
591 * @see android.view.ViewGroup
592 */
593public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
594    private static final boolean DBG = false;
595
596    /**
597     * The logging tag used by this class with android.util.Log.
598     */
599    protected static final String VIEW_LOG_TAG = "View";
600
601    /**
602     * Used to mark a View that has no ID.
603     */
604    public static final int NO_ID = -1;
605
606    /**
607     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
608     * calling setFlags.
609     */
610    private static final int NOT_FOCUSABLE = 0x00000000;
611
612    /**
613     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
614     * setFlags.
615     */
616    private static final int FOCUSABLE = 0x00000001;
617
618    /**
619     * Mask for use with setFlags indicating bits used for focus.
620     */
621    private static final int FOCUSABLE_MASK = 0x00000001;
622
623    /**
624     * This view will adjust its padding to fit sytem windows (e.g. status bar)
625     */
626    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
627
628    /**
629     * This view is visible.  Use with {@link #setVisibility}.
630     */
631    public static final int VISIBLE = 0x00000000;
632
633    /**
634     * This view is invisible, but it still takes up space for layout purposes.
635     * Use with {@link #setVisibility}.
636     */
637    public static final int INVISIBLE = 0x00000004;
638
639    /**
640     * This view is invisible, and it doesn't take any space for layout
641     * purposes. Use with {@link #setVisibility}.
642     */
643    public static final int GONE = 0x00000008;
644
645    /**
646     * Mask for use with setFlags indicating bits used for visibility.
647     * {@hide}
648     */
649    static final int VISIBILITY_MASK = 0x0000000C;
650
651    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
652
653    /**
654     * This view is enabled. Intrepretation varies by subclass.
655     * Use with ENABLED_MASK when calling setFlags.
656     * {@hide}
657     */
658    static final int ENABLED = 0x00000000;
659
660    /**
661     * This view is disabled. Intrepretation varies by subclass.
662     * Use with ENABLED_MASK when calling setFlags.
663     * {@hide}
664     */
665    static final int DISABLED = 0x00000020;
666
667   /**
668    * Mask for use with setFlags indicating bits used for indicating whether
669    * this view is enabled
670    * {@hide}
671    */
672    static final int ENABLED_MASK = 0x00000020;
673
674    /**
675     * This view won't draw. {@link #onDraw} won't be called and further
676     * optimizations
677     * will be performed. It is okay to have this flag set and a background.
678     * Use with DRAW_MASK when calling setFlags.
679     * {@hide}
680     */
681    static final int WILL_NOT_DRAW = 0x00000080;
682
683    /**
684     * Mask for use with setFlags indicating bits used for indicating whether
685     * this view is will draw
686     * {@hide}
687     */
688    static final int DRAW_MASK = 0x00000080;
689
690    /**
691     * <p>This view doesn't show scrollbars.</p>
692     * {@hide}
693     */
694    static final int SCROLLBARS_NONE = 0x00000000;
695
696    /**
697     * <p>This view shows horizontal scrollbars.</p>
698     * {@hide}
699     */
700    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
701
702    /**
703     * <p>This view shows vertical scrollbars.</p>
704     * {@hide}
705     */
706    static final int SCROLLBARS_VERTICAL = 0x00000200;
707
708    /**
709     * <p>Mask for use with setFlags indicating bits used for indicating which
710     * scrollbars are enabled.</p>
711     * {@hide}
712     */
713    static final int SCROLLBARS_MASK = 0x00000300;
714
715    // note 0x00000400 and 0x00000800 are now available for next flags...
716
717    /**
718     * <p>This view doesn't show fading edges.</p>
719     * {@hide}
720     */
721    static final int FADING_EDGE_NONE = 0x00000000;
722
723    /**
724     * <p>This view shows horizontal fading edges.</p>
725     * {@hide}
726     */
727    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
728
729    /**
730     * <p>This view shows vertical fading edges.</p>
731     * {@hide}
732     */
733    static final int FADING_EDGE_VERTICAL = 0x00002000;
734
735    /**
736     * <p>Mask for use with setFlags indicating bits used for indicating which
737     * fading edges are enabled.</p>
738     * {@hide}
739     */
740    static final int FADING_EDGE_MASK = 0x00003000;
741
742    /**
743     * <p>Indicates this view can be clicked. When clickable, a View reacts
744     * to clicks by notifying the OnClickListener.<p>
745     * {@hide}
746     */
747    static final int CLICKABLE = 0x00004000;
748
749    /**
750     * <p>Indicates this view is caching its drawing into a bitmap.</p>
751     * {@hide}
752     */
753    static final int DRAWING_CACHE_ENABLED = 0x00008000;
754
755    /**
756     * <p>Indicates that no icicle should be saved for this view.<p>
757     * {@hide}
758     */
759    static final int SAVE_DISABLED = 0x000010000;
760
761    /**
762     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
763     * property.</p>
764     * {@hide}
765     */
766    static final int SAVE_DISABLED_MASK = 0x000010000;
767
768    /**
769     * <p>Indicates that no drawing cache should ever be created for this view.<p>
770     * {@hide}
771     */
772    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
773
774    /**
775     * <p>Indicates this view can take / keep focus when int touch mode.</p>
776     * {@hide}
777     */
778    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
779
780    /**
781     * <p>Enables low quality mode for the drawing cache.</p>
782     */
783    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
784
785    /**
786     * <p>Enables high quality mode for the drawing cache.</p>
787     */
788    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
789
790    /**
791     * <p>Enables automatic quality mode for the drawing cache.</p>
792     */
793    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
794
795    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
796            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
797    };
798
799    /**
800     * <p>Mask for use with setFlags indicating bits used for the cache
801     * quality property.</p>
802     * {@hide}
803     */
804    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
805
806    /**
807     * <p>
808     * Indicates this view can be long clicked. When long clickable, a View
809     * reacts to long clicks by notifying the OnLongClickListener or showing a
810     * context menu.
811     * </p>
812     * {@hide}
813     */
814    static final int LONG_CLICKABLE = 0x00200000;
815
816    /**
817     * <p>Indicates that this view gets its drawable states from its direct parent
818     * and ignores its original internal states.</p>
819     *
820     * @hide
821     */
822    static final int DUPLICATE_PARENT_STATE = 0x00400000;
823
824    /**
825     * The scrollbar style to display the scrollbars inside the content area,
826     * without increasing the padding. The scrollbars will be overlaid with
827     * translucency on the view's content.
828     */
829    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
830
831    /**
832     * The scrollbar style to display the scrollbars inside the padded area,
833     * increasing the padding of the view. The scrollbars will not overlap the
834     * content area of the view.
835     */
836    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
837
838    /**
839     * The scrollbar style to display the scrollbars at the edge of the view,
840     * without increasing the padding. The scrollbars will be overlaid with
841     * translucency.
842     */
843    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
844
845    /**
846     * The scrollbar style to display the scrollbars at the edge of the view,
847     * increasing the padding of the view. The scrollbars will only overlap the
848     * background, if any.
849     */
850    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
851
852    /**
853     * Mask to check if the scrollbar style is overlay or inset.
854     * {@hide}
855     */
856    static final int SCROLLBARS_INSET_MASK = 0x01000000;
857
858    /**
859     * Mask to check if the scrollbar style is inside or outside.
860     * {@hide}
861     */
862    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
863
864    /**
865     * Mask for scrollbar style.
866     * {@hide}
867     */
868    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
869
870    /**
871     * View flag indicating that the screen should remain on while the
872     * window containing this view is visible to the user.  This effectively
873     * takes care of automatically setting the WindowManager's
874     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
875     */
876    public static final int KEEP_SCREEN_ON = 0x04000000;
877
878    /**
879     * View flag indicating whether this view should have sound effects enabled
880     * for events such as clicking and touching.
881     */
882    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
883
884    /**
885     * View flag indicating whether this view should have haptic feedback
886     * enabled for events such as long presses.
887     */
888    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
889
890    /**
891     * <p>Indicates that the view hierarchy should stop saving state when
892     * it reaches this view.  If state saving is initiated immediately at
893     * the view, it will be allowed.
894     * {@hide}
895     */
896    static final int PARENT_SAVE_DISABLED = 0x20000000;
897
898    /**
899     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
900     * {@hide}
901     */
902    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
903
904    /**
905     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
906     * should add all focusable Views regardless if they are focusable in touch mode.
907     */
908    public static final int FOCUSABLES_ALL = 0x00000000;
909
910    /**
911     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
912     * should add only Views focusable in touch mode.
913     */
914    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
915
916    /**
917     * Use with {@link #focusSearch}. Move focus to the previous selectable
918     * item.
919     */
920    public static final int FOCUS_BACKWARD = 0x00000001;
921
922    /**
923     * Use with {@link #focusSearch}. Move focus to the next selectable
924     * item.
925     */
926    public static final int FOCUS_FORWARD = 0x00000002;
927
928    /**
929     * Use with {@link #focusSearch}. Move focus to the left.
930     */
931    public static final int FOCUS_LEFT = 0x00000011;
932
933    /**
934     * Use with {@link #focusSearch}. Move focus up.
935     */
936    public static final int FOCUS_UP = 0x00000021;
937
938    /**
939     * Use with {@link #focusSearch}. Move focus to the right.
940     */
941    public static final int FOCUS_RIGHT = 0x00000042;
942
943    /**
944     * Use with {@link #focusSearch}. Move focus down.
945     */
946    public static final int FOCUS_DOWN = 0x00000082;
947
948    /**
949     * Base View state sets
950     */
951    // Singles
952    /**
953     * Indicates the view has no states set. States are used with
954     * {@link android.graphics.drawable.Drawable} to change the drawing of the
955     * view depending on its state.
956     *
957     * @see android.graphics.drawable.Drawable
958     * @see #getDrawableState()
959     */
960    protected static final int[] EMPTY_STATE_SET = {};
961    /**
962     * Indicates the view is enabled. States are used with
963     * {@link android.graphics.drawable.Drawable} to change the drawing of the
964     * view depending on its state.
965     *
966     * @see android.graphics.drawable.Drawable
967     * @see #getDrawableState()
968     */
969    protected static final int[] ENABLED_STATE_SET = {R.attr.state_enabled};
970    /**
971     * Indicates the view is focused. States are used with
972     * {@link android.graphics.drawable.Drawable} to change the drawing of the
973     * view depending on its state.
974     *
975     * @see android.graphics.drawable.Drawable
976     * @see #getDrawableState()
977     */
978    protected static final int[] FOCUSED_STATE_SET = {R.attr.state_focused};
979    /**
980     * Indicates the view is selected. States are used with
981     * {@link android.graphics.drawable.Drawable} to change the drawing of the
982     * view depending on its state.
983     *
984     * @see android.graphics.drawable.Drawable
985     * @see #getDrawableState()
986     */
987    protected static final int[] SELECTED_STATE_SET = {R.attr.state_selected};
988    /**
989     * Indicates the view is pressed. States are used with
990     * {@link android.graphics.drawable.Drawable} to change the drawing of the
991     * view depending on its state.
992     *
993     * @see android.graphics.drawable.Drawable
994     * @see #getDrawableState()
995     * @hide
996     */
997    protected static final int[] PRESSED_STATE_SET = {R.attr.state_pressed};
998    /**
999     * Indicates the view's window has focus. States are used with
1000     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1001     * view depending on its state.
1002     *
1003     * @see android.graphics.drawable.Drawable
1004     * @see #getDrawableState()
1005     */
1006    protected static final int[] WINDOW_FOCUSED_STATE_SET =
1007            {R.attr.state_window_focused};
1008    // Doubles
1009    /**
1010     * Indicates the view is enabled and has the focus.
1011     *
1012     * @see #ENABLED_STATE_SET
1013     * @see #FOCUSED_STATE_SET
1014     */
1015    protected static final int[] ENABLED_FOCUSED_STATE_SET =
1016            stateSetUnion(ENABLED_STATE_SET, FOCUSED_STATE_SET);
1017    /**
1018     * Indicates the view is enabled and selected.
1019     *
1020     * @see #ENABLED_STATE_SET
1021     * @see #SELECTED_STATE_SET
1022     */
1023    protected static final int[] ENABLED_SELECTED_STATE_SET =
1024            stateSetUnion(ENABLED_STATE_SET, SELECTED_STATE_SET);
1025    /**
1026     * Indicates the view is enabled and that its window has focus.
1027     *
1028     * @see #ENABLED_STATE_SET
1029     * @see #WINDOW_FOCUSED_STATE_SET
1030     */
1031    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET =
1032            stateSetUnion(ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1033    /**
1034     * Indicates the view is focused and selected.
1035     *
1036     * @see #FOCUSED_STATE_SET
1037     * @see #SELECTED_STATE_SET
1038     */
1039    protected static final int[] FOCUSED_SELECTED_STATE_SET =
1040            stateSetUnion(FOCUSED_STATE_SET, SELECTED_STATE_SET);
1041    /**
1042     * Indicates the view has the focus and that its window has the focus.
1043     *
1044     * @see #FOCUSED_STATE_SET
1045     * @see #WINDOW_FOCUSED_STATE_SET
1046     */
1047    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET =
1048            stateSetUnion(FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1049    /**
1050     * Indicates the view is selected and that its window has the focus.
1051     *
1052     * @see #SELECTED_STATE_SET
1053     * @see #WINDOW_FOCUSED_STATE_SET
1054     */
1055    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET =
1056            stateSetUnion(SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1057    // Triples
1058    /**
1059     * Indicates the view is enabled, focused and selected.
1060     *
1061     * @see #ENABLED_STATE_SET
1062     * @see #FOCUSED_STATE_SET
1063     * @see #SELECTED_STATE_SET
1064     */
1065    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET =
1066            stateSetUnion(ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
1067    /**
1068     * Indicates the view is enabled, focused and its window has the focus.
1069     *
1070     * @see #ENABLED_STATE_SET
1071     * @see #FOCUSED_STATE_SET
1072     * @see #WINDOW_FOCUSED_STATE_SET
1073     */
1074    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET =
1075            stateSetUnion(ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1076    /**
1077     * Indicates the view is enabled, selected and its window has the focus.
1078     *
1079     * @see #ENABLED_STATE_SET
1080     * @see #SELECTED_STATE_SET
1081     * @see #WINDOW_FOCUSED_STATE_SET
1082     */
1083    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1084            stateSetUnion(ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1085    /**
1086     * Indicates the view is focused, selected and its window has the focus.
1087     *
1088     * @see #FOCUSED_STATE_SET
1089     * @see #SELECTED_STATE_SET
1090     * @see #WINDOW_FOCUSED_STATE_SET
1091     */
1092    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1093            stateSetUnion(FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1094    /**
1095     * Indicates the view is enabled, focused, selected and its window
1096     * has the focus.
1097     *
1098     * @see #ENABLED_STATE_SET
1099     * @see #FOCUSED_STATE_SET
1100     * @see #SELECTED_STATE_SET
1101     * @see #WINDOW_FOCUSED_STATE_SET
1102     */
1103    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1104            stateSetUnion(ENABLED_FOCUSED_SELECTED_STATE_SET,
1105                          WINDOW_FOCUSED_STATE_SET);
1106
1107    /**
1108     * Indicates the view is pressed and its window has the focus.
1109     *
1110     * @see #PRESSED_STATE_SET
1111     * @see #WINDOW_FOCUSED_STATE_SET
1112     */
1113    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET =
1114            stateSetUnion(PRESSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1115
1116    /**
1117     * Indicates the view is pressed and selected.
1118     *
1119     * @see #PRESSED_STATE_SET
1120     * @see #SELECTED_STATE_SET
1121     */
1122    protected static final int[] PRESSED_SELECTED_STATE_SET =
1123            stateSetUnion(PRESSED_STATE_SET, SELECTED_STATE_SET);
1124
1125    /**
1126     * Indicates the view is pressed, selected and its window has the focus.
1127     *
1128     * @see #PRESSED_STATE_SET
1129     * @see #SELECTED_STATE_SET
1130     * @see #WINDOW_FOCUSED_STATE_SET
1131     */
1132    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1133            stateSetUnion(PRESSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1134
1135    /**
1136     * Indicates the view is pressed and focused.
1137     *
1138     * @see #PRESSED_STATE_SET
1139     * @see #FOCUSED_STATE_SET
1140     */
1141    protected static final int[] PRESSED_FOCUSED_STATE_SET =
1142            stateSetUnion(PRESSED_STATE_SET, FOCUSED_STATE_SET);
1143
1144    /**
1145     * Indicates the view is pressed, focused and its window has the focus.
1146     *
1147     * @see #PRESSED_STATE_SET
1148     * @see #FOCUSED_STATE_SET
1149     * @see #WINDOW_FOCUSED_STATE_SET
1150     */
1151    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET =
1152            stateSetUnion(PRESSED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1153
1154    /**
1155     * Indicates the view is pressed, focused and selected.
1156     *
1157     * @see #PRESSED_STATE_SET
1158     * @see #SELECTED_STATE_SET
1159     * @see #FOCUSED_STATE_SET
1160     */
1161    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET =
1162            stateSetUnion(PRESSED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
1163
1164    /**
1165     * Indicates the view is pressed, focused, selected and its window has the focus.
1166     *
1167     * @see #PRESSED_STATE_SET
1168     * @see #FOCUSED_STATE_SET
1169     * @see #SELECTED_STATE_SET
1170     * @see #WINDOW_FOCUSED_STATE_SET
1171     */
1172    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1173            stateSetUnion(PRESSED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1174
1175    /**
1176     * Indicates the view is pressed and enabled.
1177     *
1178     * @see #PRESSED_STATE_SET
1179     * @see #ENABLED_STATE_SET
1180     */
1181    protected static final int[] PRESSED_ENABLED_STATE_SET =
1182            stateSetUnion(PRESSED_STATE_SET, ENABLED_STATE_SET);
1183
1184    /**
1185     * Indicates the view is pressed, enabled and its window has the focus.
1186     *
1187     * @see #PRESSED_STATE_SET
1188     * @see #ENABLED_STATE_SET
1189     * @see #WINDOW_FOCUSED_STATE_SET
1190     */
1191    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET =
1192            stateSetUnion(PRESSED_ENABLED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1193
1194    /**
1195     * Indicates the view is pressed, enabled and selected.
1196     *
1197     * @see #PRESSED_STATE_SET
1198     * @see #ENABLED_STATE_SET
1199     * @see #SELECTED_STATE_SET
1200     */
1201    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET =
1202            stateSetUnion(PRESSED_ENABLED_STATE_SET, SELECTED_STATE_SET);
1203
1204    /**
1205     * Indicates the view is pressed, enabled, selected and its window has the
1206     * focus.
1207     *
1208     * @see #PRESSED_STATE_SET
1209     * @see #ENABLED_STATE_SET
1210     * @see #SELECTED_STATE_SET
1211     * @see #WINDOW_FOCUSED_STATE_SET
1212     */
1213    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1214            stateSetUnion(PRESSED_ENABLED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1215
1216    /**
1217     * Indicates the view is pressed, enabled and focused.
1218     *
1219     * @see #PRESSED_STATE_SET
1220     * @see #ENABLED_STATE_SET
1221     * @see #FOCUSED_STATE_SET
1222     */
1223    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET =
1224            stateSetUnion(PRESSED_ENABLED_STATE_SET, FOCUSED_STATE_SET);
1225
1226    /**
1227     * Indicates the view is pressed, enabled, focused and its window has the
1228     * focus.
1229     *
1230     * @see #PRESSED_STATE_SET
1231     * @see #ENABLED_STATE_SET
1232     * @see #FOCUSED_STATE_SET
1233     * @see #WINDOW_FOCUSED_STATE_SET
1234     */
1235    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET =
1236            stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1237
1238    /**
1239     * Indicates the view is pressed, enabled, focused and selected.
1240     *
1241     * @see #PRESSED_STATE_SET
1242     * @see #ENABLED_STATE_SET
1243     * @see #SELECTED_STATE_SET
1244     * @see #FOCUSED_STATE_SET
1245     */
1246    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET =
1247            stateSetUnion(PRESSED_ENABLED_FOCUSED_STATE_SET, SELECTED_STATE_SET);
1248
1249    /**
1250     * Indicates the view is pressed, enabled, focused, selected and its window
1251     * has the focus.
1252     *
1253     * @see #PRESSED_STATE_SET
1254     * @see #ENABLED_STATE_SET
1255     * @see #SELECTED_STATE_SET
1256     * @see #FOCUSED_STATE_SET
1257     * @see #WINDOW_FOCUSED_STATE_SET
1258     */
1259    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET =
1260            stateSetUnion(PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET, WINDOW_FOCUSED_STATE_SET);
1261
1262    /**
1263     * The order here is very important to {@link #getDrawableState()}
1264     */
1265    private static final int[][] VIEW_STATE_SETS = {
1266        EMPTY_STATE_SET,                                           // 0 0 0 0 0
1267        WINDOW_FOCUSED_STATE_SET,                                  // 0 0 0 0 1
1268        SELECTED_STATE_SET,                                        // 0 0 0 1 0
1269        SELECTED_WINDOW_FOCUSED_STATE_SET,                         // 0 0 0 1 1
1270        FOCUSED_STATE_SET,                                         // 0 0 1 0 0
1271        FOCUSED_WINDOW_FOCUSED_STATE_SET,                          // 0 0 1 0 1
1272        FOCUSED_SELECTED_STATE_SET,                                // 0 0 1 1 0
1273        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,                 // 0 0 1 1 1
1274        ENABLED_STATE_SET,                                         // 0 1 0 0 0
1275        ENABLED_WINDOW_FOCUSED_STATE_SET,                          // 0 1 0 0 1
1276        ENABLED_SELECTED_STATE_SET,                                // 0 1 0 1 0
1277        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET,                 // 0 1 0 1 1
1278        ENABLED_FOCUSED_STATE_SET,                                 // 0 1 1 0 0
1279        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET,                  // 0 1 1 0 1
1280        ENABLED_FOCUSED_SELECTED_STATE_SET,                        // 0 1 1 1 0
1281        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,         // 0 1 1 1 1
1282        PRESSED_STATE_SET,                                         // 1 0 0 0 0
1283        PRESSED_WINDOW_FOCUSED_STATE_SET,                          // 1 0 0 0 1
1284        PRESSED_SELECTED_STATE_SET,                                // 1 0 0 1 0
1285        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET,                 // 1 0 0 1 1
1286        PRESSED_FOCUSED_STATE_SET,                                 // 1 0 1 0 0
1287        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET,                  // 1 0 1 0 1
1288        PRESSED_FOCUSED_SELECTED_STATE_SET,                        // 1 0 1 1 0
1289        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET,         // 1 0 1 1 1
1290        PRESSED_ENABLED_STATE_SET,                                 // 1 1 0 0 0
1291        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET,                  // 1 1 0 0 1
1292        PRESSED_ENABLED_SELECTED_STATE_SET,                        // 1 1 0 1 0
1293        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET,         // 1 1 0 1 1
1294        PRESSED_ENABLED_FOCUSED_STATE_SET,                         // 1 1 1 0 0
1295        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET,          // 1 1 1 0 1
1296        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET,                // 1 1 1 1 0
1297        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET, // 1 1 1 1 1
1298    };
1299
1300    /**
1301     * Used by views that contain lists of items. This state indicates that
1302     * the view is showing the last item.
1303     * @hide
1304     */
1305    protected static final int[] LAST_STATE_SET = {R.attr.state_last};
1306    /**
1307     * Used by views that contain lists of items. This state indicates that
1308     * the view is showing the first item.
1309     * @hide
1310     */
1311    protected static final int[] FIRST_STATE_SET = {R.attr.state_first};
1312    /**
1313     * Used by views that contain lists of items. This state indicates that
1314     * the view is showing the middle item.
1315     * @hide
1316     */
1317    protected static final int[] MIDDLE_STATE_SET = {R.attr.state_middle};
1318    /**
1319     * Used by views that contain lists of items. This state indicates that
1320     * the view is showing only one item.
1321     * @hide
1322     */
1323    protected static final int[] SINGLE_STATE_SET = {R.attr.state_single};
1324    /**
1325     * Used by views that contain lists of items. This state indicates that
1326     * the view is pressed and showing the last item.
1327     * @hide
1328     */
1329    protected static final int[] PRESSED_LAST_STATE_SET = {R.attr.state_last, R.attr.state_pressed};
1330    /**
1331     * Used by views that contain lists of items. This state indicates that
1332     * the view is pressed and showing the first item.
1333     * @hide
1334     */
1335    protected static final int[] PRESSED_FIRST_STATE_SET = {R.attr.state_first, R.attr.state_pressed};
1336    /**
1337     * Used by views that contain lists of items. This state indicates that
1338     * the view is pressed and showing the middle item.
1339     * @hide
1340     */
1341    protected static final int[] PRESSED_MIDDLE_STATE_SET = {R.attr.state_middle, R.attr.state_pressed};
1342    /**
1343     * Used by views that contain lists of items. This state indicates that
1344     * the view is pressed and showing only one item.
1345     * @hide
1346     */
1347    protected static final int[] PRESSED_SINGLE_STATE_SET = {R.attr.state_single, R.attr.state_pressed};
1348
1349    /**
1350     * Temporary Rect currently for use in setBackground().  This will probably
1351     * be extended in the future to hold our own class with more than just
1352     * a Rect. :)
1353     */
1354    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1355
1356    /**
1357     * Map used to store views' tags.
1358     */
1359    private static WeakHashMap<View, SparseArray<Object>> sTags;
1360
1361    /**
1362     * Lock used to access sTags.
1363     */
1364    private static final Object sTagsLock = new Object();
1365
1366    /**
1367     * The animation currently associated with this view.
1368     * @hide
1369     */
1370    protected Animation mCurrentAnimation = null;
1371
1372    /**
1373     * Width as measured during measure pass.
1374     * {@hide}
1375     */
1376    @ViewDebug.ExportedProperty
1377    protected int mMeasuredWidth;
1378
1379    /**
1380     * Height as measured during measure pass.
1381     * {@hide}
1382     */
1383    @ViewDebug.ExportedProperty
1384    protected int mMeasuredHeight;
1385
1386    /**
1387     * The view's identifier.
1388     * {@hide}
1389     *
1390     * @see #setId(int)
1391     * @see #getId()
1392     */
1393    @ViewDebug.ExportedProperty(resolveId = true)
1394    int mID = NO_ID;
1395
1396    /**
1397     * The view's tag.
1398     * {@hide}
1399     *
1400     * @see #setTag(Object)
1401     * @see #getTag()
1402     */
1403    protected Object mTag;
1404
1405    // for mPrivateFlags:
1406    /** {@hide} */
1407    static final int WANTS_FOCUS                    = 0x00000001;
1408    /** {@hide} */
1409    static final int FOCUSED                        = 0x00000002;
1410    /** {@hide} */
1411    static final int SELECTED                       = 0x00000004;
1412    /** {@hide} */
1413    static final int IS_ROOT_NAMESPACE              = 0x00000008;
1414    /** {@hide} */
1415    static final int HAS_BOUNDS                     = 0x00000010;
1416    /** {@hide} */
1417    static final int DRAWN                          = 0x00000020;
1418    /**
1419     * When this flag is set, this view is running an animation on behalf of its
1420     * children and should therefore not cancel invalidate requests, even if they
1421     * lie outside of this view's bounds.
1422     *
1423     * {@hide}
1424     */
1425    static final int DRAW_ANIMATION                 = 0x00000040;
1426    /** {@hide} */
1427    static final int SKIP_DRAW                      = 0x00000080;
1428    /** {@hide} */
1429    static final int ONLY_DRAWS_BACKGROUND          = 0x00000100;
1430    /** {@hide} */
1431    static final int REQUEST_TRANSPARENT_REGIONS    = 0x00000200;
1432    /** {@hide} */
1433    static final int DRAWABLE_STATE_DIRTY           = 0x00000400;
1434    /** {@hide} */
1435    static final int MEASURED_DIMENSION_SET         = 0x00000800;
1436    /** {@hide} */
1437    static final int FORCE_LAYOUT                   = 0x00001000;
1438
1439    private static final int LAYOUT_REQUIRED        = 0x00002000;
1440
1441    private static final int PRESSED                = 0x00004000;
1442
1443    /** {@hide} */
1444    static final int DRAWING_CACHE_VALID            = 0x00008000;
1445    /**
1446     * Flag used to indicate that this view should be drawn once more (and only once
1447     * more) after its animation has completed.
1448     * {@hide}
1449     */
1450    static final int ANIMATION_STARTED              = 0x00010000;
1451
1452    private static final int SAVE_STATE_CALLED      = 0x00020000;
1453
1454    /**
1455     * Indicates that the View returned true when onSetAlpha() was called and that
1456     * the alpha must be restored.
1457     * {@hide}
1458     */
1459    static final int ALPHA_SET                      = 0x00040000;
1460
1461    /**
1462     * Set by {@link #setScrollContainer(boolean)}.
1463     */
1464    static final int SCROLL_CONTAINER               = 0x00080000;
1465
1466    /**
1467     * Set by {@link #setScrollContainer(boolean)}.
1468     */
1469    static final int SCROLL_CONTAINER_ADDED         = 0x00100000;
1470
1471    /**
1472     * View flag indicating whether this view was invalidated (fully or partially.)
1473     *
1474     * @hide
1475     */
1476    static final int DIRTY                          = 0x00200000;
1477
1478    /**
1479     * View flag indicating whether this view was invalidated by an opaque
1480     * invalidate request.
1481     *
1482     * @hide
1483     */
1484    static final int DIRTY_OPAQUE                   = 0x00400000;
1485
1486    /**
1487     * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
1488     *
1489     * @hide
1490     */
1491    static final int DIRTY_MASK                     = 0x00600000;
1492
1493    /**
1494     * Indicates whether the background is opaque.
1495     *
1496     * @hide
1497     */
1498    static final int OPAQUE_BACKGROUND              = 0x00800000;
1499
1500    /**
1501     * Indicates whether the scrollbars are opaque.
1502     *
1503     * @hide
1504     */
1505    static final int OPAQUE_SCROLLBARS              = 0x01000000;
1506
1507    /**
1508     * Indicates whether the view is opaque.
1509     *
1510     * @hide
1511     */
1512    static final int OPAQUE_MASK                    = 0x01800000;
1513
1514    /**
1515     * Indicates a prepressed state;
1516     * the short time between ACTION_DOWN and recognizing
1517     * a 'real' press. Prepressed is used to recognize quick taps
1518     * even when they are shorter than ViewConfiguration.getTapTimeout().
1519     *
1520     * @hide
1521     */
1522    private static final int PREPRESSED             = 0x02000000;
1523
1524    /**
1525     * Indicates whether the view is temporarily detached.
1526     *
1527     * @hide
1528     */
1529    static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
1530
1531    /**
1532     * Indicates that we should awaken scroll bars once attached
1533     *
1534     * @hide
1535     */
1536    private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1537
1538    /**
1539     * The parent this view is attached to.
1540     * {@hide}
1541     *
1542     * @see #getParent()
1543     */
1544    protected ViewParent mParent;
1545
1546    /**
1547     * {@hide}
1548     */
1549    AttachInfo mAttachInfo;
1550
1551    /**
1552     * {@hide}
1553     */
1554    @ViewDebug.ExportedProperty(flagMapping = {
1555        @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
1556                name = "FORCE_LAYOUT"),
1557        @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
1558                name = "LAYOUT_REQUIRED"),
1559        @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
1560            name = "DRAWING_CACHE_INVALID", outputIf = false),
1561        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
1562        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
1563        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
1564        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
1565    })
1566    int mPrivateFlags;
1567
1568    /**
1569     * Count of how many windows this view has been attached to.
1570     */
1571    int mWindowAttachCount;
1572
1573    /**
1574     * The layout parameters associated with this view and used by the parent
1575     * {@link android.view.ViewGroup} to determine how this view should be
1576     * laid out.
1577     * {@hide}
1578     */
1579    protected ViewGroup.LayoutParams mLayoutParams;
1580
1581    /**
1582     * The view flags hold various views states.
1583     * {@hide}
1584     */
1585    @ViewDebug.ExportedProperty
1586    int mViewFlags;
1587
1588    /**
1589     * The transform matrix for the View. This transform is calculated internally
1590     * based on the rotation, scaleX, and scaleY properties. The identity matrix
1591     * is used by default. Do *not* use this variable directly; instead call
1592     * getMatrix(), which will automatically recalculate the matrix if necessary
1593     * to get the correct matrix based on the latest rotation and scale properties.
1594     */
1595    private final Matrix mMatrix = new Matrix();
1596
1597    /**
1598     * The transform matrix for the View. This transform is calculated internally
1599     * based on the rotation, scaleX, and scaleY properties. The identity matrix
1600     * is used by default. Do *not* use this variable directly; instead call
1601     * getMatrix(), which will automatically recalculate the matrix if necessary
1602     * to get the correct matrix based on the latest rotation and scale properties.
1603     */
1604    private Matrix mInverseMatrix;
1605
1606    /**
1607     * An internal variable that tracks whether we need to recalculate the
1608     * transform matrix, based on whether the rotation or scaleX/Y properties
1609     * have changed since the matrix was last calculated.
1610     */
1611    private boolean mMatrixDirty = false;
1612
1613    /**
1614     * An internal variable that tracks whether we need to recalculate the
1615     * transform matrix, based on whether the rotation or scaleX/Y properties
1616     * have changed since the matrix was last calculated.
1617     */
1618    private boolean mInverseMatrixDirty = true;
1619
1620    /**
1621     * A variable that tracks whether we need to recalculate the
1622     * transform matrix, based on whether the rotation or scaleX/Y properties
1623     * have changed since the matrix was last calculated. This variable
1624     * is only valid after a call to getMatrix().
1625     */
1626    private boolean mMatrixIsIdentity = true;
1627
1628    /**
1629     * The degrees rotation around the pivot point.
1630     */
1631    @ViewDebug.ExportedProperty
1632    private float mRotation = 0f;
1633
1634    /**
1635     * The amount of scale in the x direction around the pivot point. A
1636     * value of 1 means no scaling is applied.
1637     */
1638    @ViewDebug.ExportedProperty
1639    private float mScaleX = 1f;
1640
1641    /**
1642     * The amount of scale in the y direction around the pivot point. A
1643     * value of 1 means no scaling is applied.
1644     */
1645    @ViewDebug.ExportedProperty
1646    private float mScaleY = 1f;
1647
1648    /**
1649     * The amount of scale in the x direction around the pivot point. A
1650     * value of 1 means no scaling is applied.
1651     */
1652    @ViewDebug.ExportedProperty
1653    private float mPivotX = 0f;
1654
1655    /**
1656     * The amount of scale in the y direction around the pivot point. A
1657     * value of 1 means no scaling is applied.
1658     */
1659    @ViewDebug.ExportedProperty
1660    private float mPivotY = 0f;
1661
1662    /**
1663     * The opacity of the View. This is a value from 0 to 1, where 0 means
1664     * completely transparent and 1 means completely opaque.
1665     */
1666    @ViewDebug.ExportedProperty
1667    private float mAlpha = 1f;
1668
1669    /**
1670     * The distance in pixels from the left edge of this view's parent
1671     * to the left edge of this view.
1672     * {@hide}
1673     */
1674    @ViewDebug.ExportedProperty
1675    protected int mLeft;
1676    /**
1677     * The distance in pixels from the left edge of this view's parent
1678     * to the right edge of this view.
1679     * {@hide}
1680     */
1681    @ViewDebug.ExportedProperty
1682    protected int mRight;
1683    /**
1684     * The distance in pixels from the top edge of this view's parent
1685     * to the top edge of this view.
1686     * {@hide}
1687     */
1688    @ViewDebug.ExportedProperty
1689    protected int mTop;
1690    /**
1691     * The distance in pixels from the top edge of this view's parent
1692     * to the bottom edge of this view.
1693     * {@hide}
1694     */
1695    @ViewDebug.ExportedProperty
1696    protected int mBottom;
1697
1698    /**
1699     * The offset, in pixels, by which the content of this view is scrolled
1700     * horizontally.
1701     * {@hide}
1702     */
1703    @ViewDebug.ExportedProperty
1704    protected int mScrollX;
1705    /**
1706     * The offset, in pixels, by which the content of this view is scrolled
1707     * vertically.
1708     * {@hide}
1709     */
1710    @ViewDebug.ExportedProperty
1711    protected int mScrollY;
1712
1713    /**
1714     * The left padding in pixels, that is the distance in pixels between the
1715     * left edge of this view and the left edge of its content.
1716     * {@hide}
1717     */
1718    @ViewDebug.ExportedProperty
1719    protected int mPaddingLeft;
1720    /**
1721     * The right padding in pixels, that is the distance in pixels between the
1722     * right edge of this view and the right edge of its content.
1723     * {@hide}
1724     */
1725    @ViewDebug.ExportedProperty
1726    protected int mPaddingRight;
1727    /**
1728     * The top padding in pixels, that is the distance in pixels between the
1729     * top edge of this view and the top edge of its content.
1730     * {@hide}
1731     */
1732    @ViewDebug.ExportedProperty
1733    protected int mPaddingTop;
1734    /**
1735     * The bottom padding in pixels, that is the distance in pixels between the
1736     * bottom edge of this view and the bottom edge of its content.
1737     * {@hide}
1738     */
1739    @ViewDebug.ExportedProperty
1740    protected int mPaddingBottom;
1741
1742    /**
1743     * Briefly describes the view and is primarily used for accessibility support.
1744     */
1745    private CharSequence mContentDescription;
1746
1747    /**
1748     * Cache the paddingRight set by the user to append to the scrollbar's size.
1749     */
1750    @ViewDebug.ExportedProperty
1751    int mUserPaddingRight;
1752
1753    /**
1754     * Cache the paddingBottom set by the user to append to the scrollbar's size.
1755     */
1756    @ViewDebug.ExportedProperty
1757    int mUserPaddingBottom;
1758
1759    /**
1760     * @hide
1761     */
1762    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
1763    /**
1764     * @hide
1765     */
1766    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
1767
1768    private Resources mResources = null;
1769
1770    private Drawable mBGDrawable;
1771
1772    private int mBackgroundResource;
1773    private boolean mBackgroundSizeChanged;
1774
1775    /**
1776     * Listener used to dispatch focus change events.
1777     * This field should be made private, so it is hidden from the SDK.
1778     * {@hide}
1779     */
1780    protected OnFocusChangeListener mOnFocusChangeListener;
1781
1782    /**
1783     * Listener used to dispatch click events.
1784     * This field should be made private, so it is hidden from the SDK.
1785     * {@hide}
1786     */
1787    protected OnClickListener mOnClickListener;
1788
1789    /**
1790     * Listener used to dispatch long click events.
1791     * This field should be made private, so it is hidden from the SDK.
1792     * {@hide}
1793     */
1794    protected OnLongClickListener mOnLongClickListener;
1795
1796    /**
1797     * Listener used to build the context menu.
1798     * This field should be made private, so it is hidden from the SDK.
1799     * {@hide}
1800     */
1801    protected OnCreateContextMenuListener mOnCreateContextMenuListener;
1802
1803    private OnKeyListener mOnKeyListener;
1804
1805    private OnTouchListener mOnTouchListener;
1806
1807    /**
1808     * The application environment this view lives in.
1809     * This field should be made private, so it is hidden from the SDK.
1810     * {@hide}
1811     */
1812    protected Context mContext;
1813
1814    private ScrollabilityCache mScrollCache;
1815
1816    private int[] mDrawableState = null;
1817
1818    private SoftReference<Bitmap> mDrawingCache;
1819    private SoftReference<Bitmap> mUnscaledDrawingCache;
1820
1821    /**
1822     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
1823     * the user may specify which view to go to next.
1824     */
1825    private int mNextFocusLeftId = View.NO_ID;
1826
1827    /**
1828     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
1829     * the user may specify which view to go to next.
1830     */
1831    private int mNextFocusRightId = View.NO_ID;
1832
1833    /**
1834     * When this view has focus and the next focus is {@link #FOCUS_UP},
1835     * the user may specify which view to go to next.
1836     */
1837    private int mNextFocusUpId = View.NO_ID;
1838
1839    /**
1840     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
1841     * the user may specify which view to go to next.
1842     */
1843    private int mNextFocusDownId = View.NO_ID;
1844
1845    private CheckForLongPress mPendingCheckForLongPress;
1846    private CheckForTap mPendingCheckForTap = null;
1847    private PerformClick mPerformClick;
1848
1849    private UnsetPressedState mUnsetPressedState;
1850
1851    /**
1852     * Whether the long press's action has been invoked.  The tap's action is invoked on the
1853     * up event while a long press is invoked as soon as the long press duration is reached, so
1854     * a long press could be performed before the tap is checked, in which case the tap's action
1855     * should not be invoked.
1856     */
1857    private boolean mHasPerformedLongPress;
1858
1859    /**
1860     * The minimum height of the view. We'll try our best to have the height
1861     * of this view to at least this amount.
1862     */
1863    @ViewDebug.ExportedProperty
1864    private int mMinHeight;
1865
1866    /**
1867     * The minimum width of the view. We'll try our best to have the width
1868     * of this view to at least this amount.
1869     */
1870    @ViewDebug.ExportedProperty
1871    private int mMinWidth;
1872
1873    /**
1874     * The delegate to handle touch events that are physically in this view
1875     * but should be handled by another view.
1876     */
1877    private TouchDelegate mTouchDelegate = null;
1878
1879    /**
1880     * Solid color to use as a background when creating the drawing cache. Enables
1881     * the cache to use 16 bit bitmaps instead of 32 bit.
1882     */
1883    private int mDrawingCacheBackgroundColor = 0;
1884
1885    /**
1886     * Special tree observer used when mAttachInfo is null.
1887     */
1888    private ViewTreeObserver mFloatingTreeObserver;
1889
1890    /**
1891     * Cache the touch slop from the context that created the view.
1892     */
1893    private int mTouchSlop;
1894
1895    // Used for debug only
1896    static long sInstanceCount = 0;
1897
1898    /**
1899     * Simple constructor to use when creating a view from code.
1900     *
1901     * @param context The Context the view is running in, through which it can
1902     *        access the current theme, resources, etc.
1903     */
1904    public View(Context context) {
1905        mContext = context;
1906        mResources = context != null ? context.getResources() : null;
1907        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
1908        // Used for debug only
1909        //++sInstanceCount;
1910        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
1911    }
1912
1913    /**
1914     * Constructor that is called when inflating a view from XML. This is called
1915     * when a view is being constructed from an XML file, supplying attributes
1916     * that were specified in the XML file. This version uses a default style of
1917     * 0, so the only attribute values applied are those in the Context's Theme
1918     * and the given AttributeSet.
1919     *
1920     * <p>
1921     * The method onFinishInflate() will be called after all children have been
1922     * added.
1923     *
1924     * @param context The Context the view is running in, through which it can
1925     *        access the current theme, resources, etc.
1926     * @param attrs The attributes of the XML tag that is inflating the view.
1927     * @see #View(Context, AttributeSet, int)
1928     */
1929    public View(Context context, AttributeSet attrs) {
1930        this(context, attrs, 0);
1931    }
1932
1933    /**
1934     * Perform inflation from XML and apply a class-specific base style. This
1935     * constructor of View allows subclasses to use their own base style when
1936     * they are inflating. For example, a Button class's constructor would call
1937     * this version of the super class constructor and supply
1938     * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
1939     * the theme's button style to modify all of the base view attributes (in
1940     * particular its background) as well as the Button class's attributes.
1941     *
1942     * @param context The Context the view is running in, through which it can
1943     *        access the current theme, resources, etc.
1944     * @param attrs The attributes of the XML tag that is inflating the view.
1945     * @param defStyle The default style to apply to this view. If 0, no style
1946     *        will be applied (beyond what is included in the theme). This may
1947     *        either be an attribute resource, whose value will be retrieved
1948     *        from the current theme, or an explicit style resource.
1949     * @see #View(Context, AttributeSet)
1950     */
1951    public View(Context context, AttributeSet attrs, int defStyle) {
1952        this(context);
1953
1954        TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
1955                defStyle, 0);
1956
1957        Drawable background = null;
1958
1959        int leftPadding = -1;
1960        int topPadding = -1;
1961        int rightPadding = -1;
1962        int bottomPadding = -1;
1963
1964        int padding = -1;
1965
1966        int viewFlagValues = 0;
1967        int viewFlagMasks = 0;
1968
1969        boolean setScrollContainer = false;
1970
1971        int x = 0;
1972        int y = 0;
1973
1974        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
1975
1976        final int N = a.getIndexCount();
1977        for (int i = 0; i < N; i++) {
1978            int attr = a.getIndex(i);
1979            switch (attr) {
1980                case com.android.internal.R.styleable.View_background:
1981                    background = a.getDrawable(attr);
1982                    break;
1983                case com.android.internal.R.styleable.View_padding:
1984                    padding = a.getDimensionPixelSize(attr, -1);
1985                    break;
1986                 case com.android.internal.R.styleable.View_paddingLeft:
1987                    leftPadding = a.getDimensionPixelSize(attr, -1);
1988                    break;
1989                case com.android.internal.R.styleable.View_paddingTop:
1990                    topPadding = a.getDimensionPixelSize(attr, -1);
1991                    break;
1992                case com.android.internal.R.styleable.View_paddingRight:
1993                    rightPadding = a.getDimensionPixelSize(attr, -1);
1994                    break;
1995                case com.android.internal.R.styleable.View_paddingBottom:
1996                    bottomPadding = a.getDimensionPixelSize(attr, -1);
1997                    break;
1998                case com.android.internal.R.styleable.View_scrollX:
1999                    x = a.getDimensionPixelOffset(attr, 0);
2000                    break;
2001                case com.android.internal.R.styleable.View_scrollY:
2002                    y = a.getDimensionPixelOffset(attr, 0);
2003                    break;
2004                case com.android.internal.R.styleable.View_id:
2005                    mID = a.getResourceId(attr, NO_ID);
2006                    break;
2007                case com.android.internal.R.styleable.View_tag:
2008                    mTag = a.getText(attr);
2009                    break;
2010                case com.android.internal.R.styleable.View_fitsSystemWindows:
2011                    if (a.getBoolean(attr, false)) {
2012                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
2013                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
2014                    }
2015                    break;
2016                case com.android.internal.R.styleable.View_focusable:
2017                    if (a.getBoolean(attr, false)) {
2018                        viewFlagValues |= FOCUSABLE;
2019                        viewFlagMasks |= FOCUSABLE_MASK;
2020                    }
2021                    break;
2022                case com.android.internal.R.styleable.View_focusableInTouchMode:
2023                    if (a.getBoolean(attr, false)) {
2024                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
2025                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
2026                    }
2027                    break;
2028                case com.android.internal.R.styleable.View_clickable:
2029                    if (a.getBoolean(attr, false)) {
2030                        viewFlagValues |= CLICKABLE;
2031                        viewFlagMasks |= CLICKABLE;
2032                    }
2033                    break;
2034                case com.android.internal.R.styleable.View_longClickable:
2035                    if (a.getBoolean(attr, false)) {
2036                        viewFlagValues |= LONG_CLICKABLE;
2037                        viewFlagMasks |= LONG_CLICKABLE;
2038                    }
2039                    break;
2040                case com.android.internal.R.styleable.View_saveEnabled:
2041                    if (!a.getBoolean(attr, true)) {
2042                        viewFlagValues |= SAVE_DISABLED;
2043                        viewFlagMasks |= SAVE_DISABLED_MASK;
2044                    }
2045                    break;
2046                case com.android.internal.R.styleable.View_duplicateParentState:
2047                    if (a.getBoolean(attr, false)) {
2048                        viewFlagValues |= DUPLICATE_PARENT_STATE;
2049                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
2050                    }
2051                    break;
2052                case com.android.internal.R.styleable.View_visibility:
2053                    final int visibility = a.getInt(attr, 0);
2054                    if (visibility != 0) {
2055                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
2056                        viewFlagMasks |= VISIBILITY_MASK;
2057                    }
2058                    break;
2059                case com.android.internal.R.styleable.View_drawingCacheQuality:
2060                    final int cacheQuality = a.getInt(attr, 0);
2061                    if (cacheQuality != 0) {
2062                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
2063                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
2064                    }
2065                    break;
2066                case com.android.internal.R.styleable.View_contentDescription:
2067                    mContentDescription = a.getString(attr);
2068                    break;
2069                case com.android.internal.R.styleable.View_soundEffectsEnabled:
2070                    if (!a.getBoolean(attr, true)) {
2071                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
2072                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
2073                    }
2074                    break;
2075                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
2076                    if (!a.getBoolean(attr, true)) {
2077                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
2078                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
2079                    }
2080                    break;
2081                case R.styleable.View_scrollbars:
2082                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
2083                    if (scrollbars != SCROLLBARS_NONE) {
2084                        viewFlagValues |= scrollbars;
2085                        viewFlagMasks |= SCROLLBARS_MASK;
2086                        initializeScrollbars(a);
2087                    }
2088                    break;
2089                case R.styleable.View_fadingEdge:
2090                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
2091                    if (fadingEdge != FADING_EDGE_NONE) {
2092                        viewFlagValues |= fadingEdge;
2093                        viewFlagMasks |= FADING_EDGE_MASK;
2094                        initializeFadingEdge(a);
2095                    }
2096                    break;
2097                case R.styleable.View_scrollbarStyle:
2098                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
2099                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
2100                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
2101                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
2102                    }
2103                    break;
2104                case R.styleable.View_isScrollContainer:
2105                    setScrollContainer = true;
2106                    if (a.getBoolean(attr, false)) {
2107                        setScrollContainer(true);
2108                    }
2109                    break;
2110                case com.android.internal.R.styleable.View_keepScreenOn:
2111                    if (a.getBoolean(attr, false)) {
2112                        viewFlagValues |= KEEP_SCREEN_ON;
2113                        viewFlagMasks |= KEEP_SCREEN_ON;
2114                    }
2115                    break;
2116                case R.styleable.View_nextFocusLeft:
2117                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
2118                    break;
2119                case R.styleable.View_nextFocusRight:
2120                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
2121                    break;
2122                case R.styleable.View_nextFocusUp:
2123                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
2124                    break;
2125                case R.styleable.View_nextFocusDown:
2126                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
2127                    break;
2128                case R.styleable.View_minWidth:
2129                    mMinWidth = a.getDimensionPixelSize(attr, 0);
2130                    break;
2131                case R.styleable.View_minHeight:
2132                    mMinHeight = a.getDimensionPixelSize(attr, 0);
2133                    break;
2134                case R.styleable.View_onClick:
2135                    if (context.isRestricted()) {
2136                        throw new IllegalStateException("The android:onClick attribute cannot "
2137                                + "be used within a restricted context");
2138                    }
2139
2140                    final String handlerName = a.getString(attr);
2141                    if (handlerName != null) {
2142                        setOnClickListener(new OnClickListener() {
2143                            private Method mHandler;
2144
2145                            public void onClick(View v) {
2146                                if (mHandler == null) {
2147                                    try {
2148                                        mHandler = getContext().getClass().getMethod(handlerName,
2149                                                View.class);
2150                                    } catch (NoSuchMethodException e) {
2151                                        int id = getId();
2152                                        String idText = id == NO_ID ? "" : " with id '"
2153                                                + getContext().getResources().getResourceEntryName(
2154                                                    id) + "'";
2155                                        throw new IllegalStateException("Could not find a method " +
2156                                                handlerName + "(View) in the activity "
2157                                                + getContext().getClass() + " for onClick handler"
2158                                                + " on view " + View.this.getClass() + idText, e);
2159                                    }
2160                                }
2161
2162                                try {
2163                                    mHandler.invoke(getContext(), View.this);
2164                                } catch (IllegalAccessException e) {
2165                                    throw new IllegalStateException("Could not execute non "
2166                                            + "public method of the activity", e);
2167                                } catch (InvocationTargetException e) {
2168                                    throw new IllegalStateException("Could not execute "
2169                                            + "method of the activity", e);
2170                                }
2171                            }
2172                        });
2173                    }
2174                    break;
2175            }
2176        }
2177
2178        if (background != null) {
2179            setBackgroundDrawable(background);
2180        }
2181
2182        if (padding >= 0) {
2183            leftPadding = padding;
2184            topPadding = padding;
2185            rightPadding = padding;
2186            bottomPadding = padding;
2187        }
2188
2189        // If the user specified the padding (either with android:padding or
2190        // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
2191        // use the default padding or the padding from the background drawable
2192        // (stored at this point in mPadding*)
2193        setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
2194                topPadding >= 0 ? topPadding : mPaddingTop,
2195                rightPadding >= 0 ? rightPadding : mPaddingRight,
2196                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
2197
2198        if (viewFlagMasks != 0) {
2199            setFlags(viewFlagValues, viewFlagMasks);
2200        }
2201
2202        // Needs to be called after mViewFlags is set
2203        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
2204            recomputePadding();
2205        }
2206
2207        if (x != 0 || y != 0) {
2208            scrollTo(x, y);
2209        }
2210
2211        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
2212            setScrollContainer(true);
2213        }
2214
2215        computeOpaqueFlags();
2216
2217        a.recycle();
2218    }
2219
2220    /**
2221     * Non-public constructor for use in testing
2222     */
2223    View() {
2224    }
2225
2226    // Used for debug only
2227    /*
2228    @Override
2229    protected void finalize() throws Throwable {
2230        super.finalize();
2231        --sInstanceCount;
2232    }
2233    */
2234
2235    /**
2236     * <p>
2237     * Initializes the fading edges from a given set of styled attributes. This
2238     * method should be called by subclasses that need fading edges and when an
2239     * instance of these subclasses is created programmatically rather than
2240     * being inflated from XML. This method is automatically called when the XML
2241     * is inflated.
2242     * </p>
2243     *
2244     * @param a the styled attributes set to initialize the fading edges from
2245     */
2246    protected void initializeFadingEdge(TypedArray a) {
2247        initScrollCache();
2248
2249        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
2250                R.styleable.View_fadingEdgeLength,
2251                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
2252    }
2253
2254    /**
2255     * Returns the size of the vertical faded edges used to indicate that more
2256     * content in this view is visible.
2257     *
2258     * @return The size in pixels of the vertical faded edge or 0 if vertical
2259     *         faded edges are not enabled for this view.
2260     * @attr ref android.R.styleable#View_fadingEdgeLength
2261     */
2262    public int getVerticalFadingEdgeLength() {
2263        if (isVerticalFadingEdgeEnabled()) {
2264            ScrollabilityCache cache = mScrollCache;
2265            if (cache != null) {
2266                return cache.fadingEdgeLength;
2267            }
2268        }
2269        return 0;
2270    }
2271
2272    /**
2273     * Set the size of the faded edge used to indicate that more content in this
2274     * view is available.  Will not change whether the fading edge is enabled; use
2275     * {@link #setVerticalFadingEdgeEnabled} or {@link #setHorizontalFadingEdgeEnabled}
2276     * to enable the fading edge for the vertical or horizontal fading edges.
2277     *
2278     * @param length The size in pixels of the faded edge used to indicate that more
2279     *        content in this view is visible.
2280     */
2281    public void setFadingEdgeLength(int length) {
2282        initScrollCache();
2283        mScrollCache.fadingEdgeLength = length;
2284    }
2285
2286    /**
2287     * Returns the size of the horizontal faded edges used to indicate that more
2288     * content in this view is visible.
2289     *
2290     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
2291     *         faded edges are not enabled for this view.
2292     * @attr ref android.R.styleable#View_fadingEdgeLength
2293     */
2294    public int getHorizontalFadingEdgeLength() {
2295        if (isHorizontalFadingEdgeEnabled()) {
2296            ScrollabilityCache cache = mScrollCache;
2297            if (cache != null) {
2298                return cache.fadingEdgeLength;
2299            }
2300        }
2301        return 0;
2302    }
2303
2304    /**
2305     * Returns the width of the vertical scrollbar.
2306     *
2307     * @return The width in pixels of the vertical scrollbar or 0 if there
2308     *         is no vertical scrollbar.
2309     */
2310    public int getVerticalScrollbarWidth() {
2311        ScrollabilityCache cache = mScrollCache;
2312        if (cache != null) {
2313            ScrollBarDrawable scrollBar = cache.scrollBar;
2314            if (scrollBar != null) {
2315                int size = scrollBar.getSize(true);
2316                if (size <= 0) {
2317                    size = cache.scrollBarSize;
2318                }
2319                return size;
2320            }
2321            return 0;
2322        }
2323        return 0;
2324    }
2325
2326    /**
2327     * Returns the height of the horizontal scrollbar.
2328     *
2329     * @return The height in pixels of the horizontal scrollbar or 0 if
2330     *         there is no horizontal scrollbar.
2331     */
2332    protected int getHorizontalScrollbarHeight() {
2333        ScrollabilityCache cache = mScrollCache;
2334        if (cache != null) {
2335            ScrollBarDrawable scrollBar = cache.scrollBar;
2336            if (scrollBar != null) {
2337                int size = scrollBar.getSize(false);
2338                if (size <= 0) {
2339                    size = cache.scrollBarSize;
2340                }
2341                return size;
2342            }
2343            return 0;
2344        }
2345        return 0;
2346    }
2347
2348    /**
2349     * <p>
2350     * Initializes the scrollbars from a given set of styled attributes. This
2351     * method should be called by subclasses that need scrollbars and when an
2352     * instance of these subclasses is created programmatically rather than
2353     * being inflated from XML. This method is automatically called when the XML
2354     * is inflated.
2355     * </p>
2356     *
2357     * @param a the styled attributes set to initialize the scrollbars from
2358     */
2359    protected void initializeScrollbars(TypedArray a) {
2360        initScrollCache();
2361
2362        final ScrollabilityCache scrollabilityCache = mScrollCache;
2363
2364        if (scrollabilityCache.scrollBar == null) {
2365            scrollabilityCache.scrollBar = new ScrollBarDrawable();
2366        }
2367
2368        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
2369
2370        if (!fadeScrollbars) {
2371            scrollabilityCache.state = ScrollabilityCache.ON;
2372        }
2373        scrollabilityCache.fadeScrollBars = fadeScrollbars;
2374
2375
2376        scrollabilityCache.scrollBarFadeDuration = a.getInt(
2377                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
2378                        .getScrollBarFadeDuration());
2379        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
2380                R.styleable.View_scrollbarDefaultDelayBeforeFade,
2381                ViewConfiguration.getScrollDefaultDelay());
2382
2383
2384        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
2385                com.android.internal.R.styleable.View_scrollbarSize,
2386                ViewConfiguration.get(mContext).getScaledScrollBarSize());
2387
2388        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
2389        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
2390
2391        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
2392        if (thumb != null) {
2393            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
2394        }
2395
2396        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
2397                false);
2398        if (alwaysDraw) {
2399            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
2400        }
2401
2402        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
2403        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
2404
2405        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
2406        if (thumb != null) {
2407            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
2408        }
2409
2410        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
2411                false);
2412        if (alwaysDraw) {
2413            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
2414        }
2415
2416        // Re-apply user/background padding so that scrollbar(s) get added
2417        recomputePadding();
2418    }
2419
2420    /**
2421     * <p>
2422     * Initalizes the scrollability cache if necessary.
2423     * </p>
2424     */
2425    private void initScrollCache() {
2426        if (mScrollCache == null) {
2427            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
2428        }
2429    }
2430
2431    /**
2432     * Register a callback to be invoked when focus of this view changed.
2433     *
2434     * @param l The callback that will run.
2435     */
2436    public void setOnFocusChangeListener(OnFocusChangeListener l) {
2437        mOnFocusChangeListener = l;
2438    }
2439
2440    /**
2441     * Returns the focus-change callback registered for this view.
2442     *
2443     * @return The callback, or null if one is not registered.
2444     */
2445    public OnFocusChangeListener getOnFocusChangeListener() {
2446        return mOnFocusChangeListener;
2447    }
2448
2449    /**
2450     * Register a callback to be invoked when this view is clicked. If this view is not
2451     * clickable, it becomes clickable.
2452     *
2453     * @param l The callback that will run
2454     *
2455     * @see #setClickable(boolean)
2456     */
2457    public void setOnClickListener(OnClickListener l) {
2458        if (!isClickable()) {
2459            setClickable(true);
2460        }
2461        mOnClickListener = l;
2462    }
2463
2464    /**
2465     * Register a callback to be invoked when this view is clicked and held. If this view is not
2466     * long clickable, it becomes long clickable.
2467     *
2468     * @param l The callback that will run
2469     *
2470     * @see #setLongClickable(boolean)
2471     */
2472    public void setOnLongClickListener(OnLongClickListener l) {
2473        if (!isLongClickable()) {
2474            setLongClickable(true);
2475        }
2476        mOnLongClickListener = l;
2477    }
2478
2479    /**
2480     * Register a callback to be invoked when the context menu for this view is
2481     * being built. If this view is not long clickable, it becomes long clickable.
2482     *
2483     * @param l The callback that will run
2484     *
2485     */
2486    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
2487        if (!isLongClickable()) {
2488            setLongClickable(true);
2489        }
2490        mOnCreateContextMenuListener = l;
2491    }
2492
2493    /**
2494     * Call this view's OnClickListener, if it is defined.
2495     *
2496     * @return True there was an assigned OnClickListener that was called, false
2497     *         otherwise is returned.
2498     */
2499    public boolean performClick() {
2500        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
2501
2502        if (mOnClickListener != null) {
2503            playSoundEffect(SoundEffectConstants.CLICK);
2504            mOnClickListener.onClick(this);
2505            return true;
2506        }
2507
2508        return false;
2509    }
2510
2511    /**
2512     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu
2513     * if the OnLongClickListener did not consume the event.
2514     *
2515     * @return True there was an assigned OnLongClickListener that was called, false
2516     *         otherwise is returned.
2517     */
2518    public boolean performLongClick() {
2519        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
2520
2521        boolean handled = false;
2522        if (mOnLongClickListener != null) {
2523            handled = mOnLongClickListener.onLongClick(View.this);
2524        }
2525        if (!handled) {
2526            handled = showContextMenu();
2527        }
2528        if (handled) {
2529            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
2530        }
2531        return handled;
2532    }
2533
2534    /**
2535     * Bring up the context menu for this view.
2536     *
2537     * @return Whether a context menu was displayed.
2538     */
2539    public boolean showContextMenu() {
2540        return getParent().showContextMenuForChild(this);
2541    }
2542
2543    /**
2544     * Register a callback to be invoked when a key is pressed in this view.
2545     * @param l the key listener to attach to this view
2546     */
2547    public void setOnKeyListener(OnKeyListener l) {
2548        mOnKeyListener = l;
2549    }
2550
2551    /**
2552     * Register a callback to be invoked when a touch event is sent to this view.
2553     * @param l the touch listener to attach to this view
2554     */
2555    public void setOnTouchListener(OnTouchListener l) {
2556        mOnTouchListener = l;
2557    }
2558
2559    /**
2560     * Give this view focus. This will cause {@link #onFocusChanged} to be called.
2561     *
2562     * Note: this does not check whether this {@link View} should get focus, it just
2563     * gives it focus no matter what.  It should only be called internally by framework
2564     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
2565     *
2566     * @param direction values are View.FOCUS_UP, View.FOCUS_DOWN,
2567     *        View.FOCUS_LEFT or View.FOCUS_RIGHT. This is the direction which
2568     *        focus moved when requestFocus() is called. It may not always
2569     *        apply, in which case use the default View.FOCUS_DOWN.
2570     * @param previouslyFocusedRect The rectangle of the view that had focus
2571     *        prior in this View's coordinate system.
2572     */
2573    void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
2574        if (DBG) {
2575            System.out.println(this + " requestFocus()");
2576        }
2577
2578        if ((mPrivateFlags & FOCUSED) == 0) {
2579            mPrivateFlags |= FOCUSED;
2580
2581            if (mParent != null) {
2582                mParent.requestChildFocus(this, this);
2583            }
2584
2585            onFocusChanged(true, direction, previouslyFocusedRect);
2586            refreshDrawableState();
2587        }
2588    }
2589
2590    /**
2591     * Request that a rectangle of this view be visible on the screen,
2592     * scrolling if necessary just enough.
2593     *
2594     * <p>A View should call this if it maintains some notion of which part
2595     * of its content is interesting.  For example, a text editing view
2596     * should call this when its cursor moves.
2597     *
2598     * @param rectangle The rectangle.
2599     * @return Whether any parent scrolled.
2600     */
2601    public boolean requestRectangleOnScreen(Rect rectangle) {
2602        return requestRectangleOnScreen(rectangle, false);
2603    }
2604
2605    /**
2606     * Request that a rectangle of this view be visible on the screen,
2607     * scrolling if necessary just enough.
2608     *
2609     * <p>A View should call this if it maintains some notion of which part
2610     * of its content is interesting.  For example, a text editing view
2611     * should call this when its cursor moves.
2612     *
2613     * <p>When <code>immediate</code> is set to true, scrolling will not be
2614     * animated.
2615     *
2616     * @param rectangle The rectangle.
2617     * @param immediate True to forbid animated scrolling, false otherwise
2618     * @return Whether any parent scrolled.
2619     */
2620    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
2621        View child = this;
2622        ViewParent parent = mParent;
2623        boolean scrolled = false;
2624        while (parent != null) {
2625            scrolled |= parent.requestChildRectangleOnScreen(child,
2626                    rectangle, immediate);
2627
2628            // offset rect so next call has the rectangle in the
2629            // coordinate system of its direct child.
2630            rectangle.offset(child.getLeft(), child.getTop());
2631            rectangle.offset(-child.getScrollX(), -child.getScrollY());
2632
2633            if (!(parent instanceof View)) {
2634                break;
2635            }
2636
2637            child = (View) parent;
2638            parent = child.getParent();
2639        }
2640        return scrolled;
2641    }
2642
2643    /**
2644     * Called when this view wants to give up focus. This will cause
2645     * {@link #onFocusChanged} to be called.
2646     */
2647    public void clearFocus() {
2648        if (DBG) {
2649            System.out.println(this + " clearFocus()");
2650        }
2651
2652        if ((mPrivateFlags & FOCUSED) != 0) {
2653            mPrivateFlags &= ~FOCUSED;
2654
2655            if (mParent != null) {
2656                mParent.clearChildFocus(this);
2657            }
2658
2659            onFocusChanged(false, 0, null);
2660            refreshDrawableState();
2661        }
2662    }
2663
2664    /**
2665     * Called to clear the focus of a view that is about to be removed.
2666     * Doesn't call clearChildFocus, which prevents this view from taking
2667     * focus again before it has been removed from the parent
2668     */
2669    void clearFocusForRemoval() {
2670        if ((mPrivateFlags & FOCUSED) != 0) {
2671            mPrivateFlags &= ~FOCUSED;
2672
2673            onFocusChanged(false, 0, null);
2674            refreshDrawableState();
2675        }
2676    }
2677
2678    /**
2679     * Called internally by the view system when a new view is getting focus.
2680     * This is what clears the old focus.
2681     */
2682    void unFocus() {
2683        if (DBG) {
2684            System.out.println(this + " unFocus()");
2685        }
2686
2687        if ((mPrivateFlags & FOCUSED) != 0) {
2688            mPrivateFlags &= ~FOCUSED;
2689
2690            onFocusChanged(false, 0, null);
2691            refreshDrawableState();
2692        }
2693    }
2694
2695    /**
2696     * Returns true if this view has focus iteself, or is the ancestor of the
2697     * view that has focus.
2698     *
2699     * @return True if this view has or contains focus, false otherwise.
2700     */
2701    @ViewDebug.ExportedProperty
2702    public boolean hasFocus() {
2703        return (mPrivateFlags & FOCUSED) != 0;
2704    }
2705
2706    /**
2707     * Returns true if this view is focusable or if it contains a reachable View
2708     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
2709     * is a View whose parents do not block descendants focus.
2710     *
2711     * Only {@link #VISIBLE} views are considered focusable.
2712     *
2713     * @return True if the view is focusable or if the view contains a focusable
2714     *         View, false otherwise.
2715     *
2716     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
2717     */
2718    public boolean hasFocusable() {
2719        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
2720    }
2721
2722    /**
2723     * Called by the view system when the focus state of this view changes.
2724     * When the focus change event is caused by directional navigation, direction
2725     * and previouslyFocusedRect provide insight into where the focus is coming from.
2726     * When overriding, be sure to call up through to the super class so that
2727     * the standard focus handling will occur.
2728     *
2729     * @param gainFocus True if the View has focus; false otherwise.
2730     * @param direction The direction focus has moved when requestFocus()
2731     *                  is called to give this view focus. Values are
2732     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT} or
2733     *                  {@link #FOCUS_RIGHT}. It may not always apply, in which
2734     *                  case use the default.
2735     * @param previouslyFocusedRect The rectangle, in this view's coordinate
2736     *        system, of the previously focused view.  If applicable, this will be
2737     *        passed in as finer grained information about where the focus is coming
2738     *        from (in addition to direction).  Will be <code>null</code> otherwise.
2739     */
2740    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
2741        if (gainFocus) {
2742            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
2743        }
2744
2745        InputMethodManager imm = InputMethodManager.peekInstance();
2746        if (!gainFocus) {
2747            if (isPressed()) {
2748                setPressed(false);
2749            }
2750            if (imm != null && mAttachInfo != null
2751                    && mAttachInfo.mHasWindowFocus) {
2752                imm.focusOut(this);
2753            }
2754            onFocusLost();
2755        } else if (imm != null && mAttachInfo != null
2756                && mAttachInfo.mHasWindowFocus) {
2757            imm.focusIn(this);
2758        }
2759
2760        invalidate();
2761        if (mOnFocusChangeListener != null) {
2762            mOnFocusChangeListener.onFocusChange(this, gainFocus);
2763        }
2764
2765        if (mAttachInfo != null) {
2766            mAttachInfo.mKeyDispatchState.reset(this);
2767        }
2768    }
2769
2770    /**
2771     * {@inheritDoc}
2772     */
2773    public void sendAccessibilityEvent(int eventType) {
2774        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
2775            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
2776        }
2777    }
2778
2779    /**
2780     * {@inheritDoc}
2781     */
2782    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
2783        event.setClassName(getClass().getName());
2784        event.setPackageName(getContext().getPackageName());
2785        event.setEnabled(isEnabled());
2786        event.setContentDescription(mContentDescription);
2787
2788        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
2789            ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
2790            getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
2791            event.setItemCount(focusablesTempList.size());
2792            event.setCurrentItemIndex(focusablesTempList.indexOf(this));
2793            focusablesTempList.clear();
2794        }
2795
2796        dispatchPopulateAccessibilityEvent(event);
2797
2798        AccessibilityManager.getInstance(mContext).sendAccessibilityEvent(event);
2799    }
2800
2801    /**
2802     * Dispatches an {@link AccessibilityEvent} to the {@link View} children
2803     * to be populated.
2804     *
2805     * @param event The event.
2806     *
2807     * @return True if the event population was completed.
2808     */
2809    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
2810        return false;
2811    }
2812
2813    /**
2814     * Gets the {@link View} description. It briefly describes the view and is
2815     * primarily used for accessibility support. Set this property to enable
2816     * better accessibility support for your application. This is especially
2817     * true for views that do not have textual representation (For example,
2818     * ImageButton).
2819     *
2820     * @return The content descriptiopn.
2821     *
2822     * @attr ref android.R.styleable#View_contentDescription
2823     */
2824    public CharSequence getContentDescription() {
2825        return mContentDescription;
2826    }
2827
2828    /**
2829     * Sets the {@link View} description. It briefly describes the view and is
2830     * primarily used for accessibility support. Set this property to enable
2831     * better accessibility support for your application. This is especially
2832     * true for views that do not have textual representation (For example,
2833     * ImageButton).
2834     *
2835     * @param contentDescription The content description.
2836     *
2837     * @attr ref android.R.styleable#View_contentDescription
2838     */
2839    public void setContentDescription(CharSequence contentDescription) {
2840        mContentDescription = contentDescription;
2841    }
2842
2843    /**
2844     * Invoked whenever this view loses focus, either by losing window focus or by losing
2845     * focus within its window. This method can be used to clear any state tied to the
2846     * focus. For instance, if a button is held pressed with the trackball and the window
2847     * loses focus, this method can be used to cancel the press.
2848     *
2849     * Subclasses of View overriding this method should always call super.onFocusLost().
2850     *
2851     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
2852     * @see #onWindowFocusChanged(boolean)
2853     *
2854     * @hide pending API council approval
2855     */
2856    protected void onFocusLost() {
2857        resetPressedState();
2858    }
2859
2860    private void resetPressedState() {
2861        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
2862            return;
2863        }
2864
2865        if (isPressed()) {
2866            setPressed(false);
2867
2868            if (!mHasPerformedLongPress) {
2869                removeLongPressCallback();
2870            }
2871        }
2872    }
2873
2874    /**
2875     * Returns true if this view has focus
2876     *
2877     * @return True if this view has focus, false otherwise.
2878     */
2879    @ViewDebug.ExportedProperty
2880    public boolean isFocused() {
2881        return (mPrivateFlags & FOCUSED) != 0;
2882    }
2883
2884    /**
2885     * Find the view in the hierarchy rooted at this view that currently has
2886     * focus.
2887     *
2888     * @return The view that currently has focus, or null if no focused view can
2889     *         be found.
2890     */
2891    public View findFocus() {
2892        return (mPrivateFlags & FOCUSED) != 0 ? this : null;
2893    }
2894
2895    /**
2896     * Change whether this view is one of the set of scrollable containers in
2897     * its window.  This will be used to determine whether the window can
2898     * resize or must pan when a soft input area is open -- scrollable
2899     * containers allow the window to use resize mode since the container
2900     * will appropriately shrink.
2901     */
2902    public void setScrollContainer(boolean isScrollContainer) {
2903        if (isScrollContainer) {
2904            if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
2905                mAttachInfo.mScrollContainers.add(this);
2906                mPrivateFlags |= SCROLL_CONTAINER_ADDED;
2907            }
2908            mPrivateFlags |= SCROLL_CONTAINER;
2909        } else {
2910            if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
2911                mAttachInfo.mScrollContainers.remove(this);
2912            }
2913            mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
2914        }
2915    }
2916
2917    /**
2918     * Returns the quality of the drawing cache.
2919     *
2920     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
2921     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
2922     *
2923     * @see #setDrawingCacheQuality(int)
2924     * @see #setDrawingCacheEnabled(boolean)
2925     * @see #isDrawingCacheEnabled()
2926     *
2927     * @attr ref android.R.styleable#View_drawingCacheQuality
2928     */
2929    public int getDrawingCacheQuality() {
2930        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
2931    }
2932
2933    /**
2934     * Set the drawing cache quality of this view. This value is used only when the
2935     * drawing cache is enabled
2936     *
2937     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
2938     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
2939     *
2940     * @see #getDrawingCacheQuality()
2941     * @see #setDrawingCacheEnabled(boolean)
2942     * @see #isDrawingCacheEnabled()
2943     *
2944     * @attr ref android.R.styleable#View_drawingCacheQuality
2945     */
2946    public void setDrawingCacheQuality(int quality) {
2947        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
2948    }
2949
2950    /**
2951     * Returns whether the screen should remain on, corresponding to the current
2952     * value of {@link #KEEP_SCREEN_ON}.
2953     *
2954     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
2955     *
2956     * @see #setKeepScreenOn(boolean)
2957     *
2958     * @attr ref android.R.styleable#View_keepScreenOn
2959     */
2960    public boolean getKeepScreenOn() {
2961        return (mViewFlags & KEEP_SCREEN_ON) != 0;
2962    }
2963
2964    /**
2965     * Controls whether the screen should remain on, modifying the
2966     * value of {@link #KEEP_SCREEN_ON}.
2967     *
2968     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
2969     *
2970     * @see #getKeepScreenOn()
2971     *
2972     * @attr ref android.R.styleable#View_keepScreenOn
2973     */
2974    public void setKeepScreenOn(boolean keepScreenOn) {
2975        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
2976    }
2977
2978    /**
2979     * @return The user specified next focus ID.
2980     *
2981     * @attr ref android.R.styleable#View_nextFocusLeft
2982     */
2983    public int getNextFocusLeftId() {
2984        return mNextFocusLeftId;
2985    }
2986
2987    /**
2988     * Set the id of the view to use for the next focus
2989     *
2990     * @param nextFocusLeftId
2991     *
2992     * @attr ref android.R.styleable#View_nextFocusLeft
2993     */
2994    public void setNextFocusLeftId(int nextFocusLeftId) {
2995        mNextFocusLeftId = nextFocusLeftId;
2996    }
2997
2998    /**
2999     * @return The user specified next focus ID.
3000     *
3001     * @attr ref android.R.styleable#View_nextFocusRight
3002     */
3003    public int getNextFocusRightId() {
3004        return mNextFocusRightId;
3005    }
3006
3007    /**
3008     * Set the id of the view to use for the next focus
3009     *
3010     * @param nextFocusRightId
3011     *
3012     * @attr ref android.R.styleable#View_nextFocusRight
3013     */
3014    public void setNextFocusRightId(int nextFocusRightId) {
3015        mNextFocusRightId = nextFocusRightId;
3016    }
3017
3018    /**
3019     * @return The user specified next focus ID.
3020     *
3021     * @attr ref android.R.styleable#View_nextFocusUp
3022     */
3023    public int getNextFocusUpId() {
3024        return mNextFocusUpId;
3025    }
3026
3027    /**
3028     * Set the id of the view to use for the next focus
3029     *
3030     * @param nextFocusUpId
3031     *
3032     * @attr ref android.R.styleable#View_nextFocusUp
3033     */
3034    public void setNextFocusUpId(int nextFocusUpId) {
3035        mNextFocusUpId = nextFocusUpId;
3036    }
3037
3038    /**
3039     * @return The user specified next focus ID.
3040     *
3041     * @attr ref android.R.styleable#View_nextFocusDown
3042     */
3043    public int getNextFocusDownId() {
3044        return mNextFocusDownId;
3045    }
3046
3047    /**
3048     * Set the id of the view to use for the next focus
3049     *
3050     * @param nextFocusDownId
3051     *
3052     * @attr ref android.R.styleable#View_nextFocusDown
3053     */
3054    public void setNextFocusDownId(int nextFocusDownId) {
3055        mNextFocusDownId = nextFocusDownId;
3056    }
3057
3058    /**
3059     * Returns the visibility of this view and all of its ancestors
3060     *
3061     * @return True if this view and all of its ancestors are {@link #VISIBLE}
3062     */
3063    public boolean isShown() {
3064        View current = this;
3065        //noinspection ConstantConditions
3066        do {
3067            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
3068                return false;
3069            }
3070            ViewParent parent = current.mParent;
3071            if (parent == null) {
3072                return false; // We are not attached to the view root
3073            }
3074            if (!(parent instanceof View)) {
3075                return true;
3076            }
3077            current = (View) parent;
3078        } while (current != null);
3079
3080        return false;
3081    }
3082
3083    /**
3084     * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag
3085     * is set
3086     *
3087     * @param insets Insets for system windows
3088     *
3089     * @return True if this view applied the insets, false otherwise
3090     */
3091    protected boolean fitSystemWindows(Rect insets) {
3092        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
3093            mPaddingLeft = insets.left;
3094            mPaddingTop = insets.top;
3095            mPaddingRight = insets.right;
3096            mPaddingBottom = insets.bottom;
3097            requestLayout();
3098            return true;
3099        }
3100        return false;
3101    }
3102
3103    /**
3104     * Determine if this view has the FITS_SYSTEM_WINDOWS flag set.
3105     * @return True if window has FITS_SYSTEM_WINDOWS set
3106     *
3107     * @hide
3108     */
3109    public boolean isFitsSystemWindowsFlagSet() {
3110        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
3111    }
3112
3113    /**
3114     * Returns the visibility status for this view.
3115     *
3116     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
3117     * @attr ref android.R.styleable#View_visibility
3118     */
3119    @ViewDebug.ExportedProperty(mapping = {
3120        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
3121        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
3122        @ViewDebug.IntToString(from = GONE,      to = "GONE")
3123    })
3124    public int getVisibility() {
3125        return mViewFlags & VISIBILITY_MASK;
3126    }
3127
3128    /**
3129     * Set the enabled state of this view.
3130     *
3131     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
3132     * @attr ref android.R.styleable#View_visibility
3133     */
3134    @RemotableViewMethod
3135    public void setVisibility(int visibility) {
3136        setFlags(visibility, VISIBILITY_MASK);
3137        if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
3138    }
3139
3140    /**
3141     * Returns the enabled status for this view. The interpretation of the
3142     * enabled state varies by subclass.
3143     *
3144     * @return True if this view is enabled, false otherwise.
3145     */
3146    @ViewDebug.ExportedProperty
3147    public boolean isEnabled() {
3148        return (mViewFlags & ENABLED_MASK) == ENABLED;
3149    }
3150
3151    /**
3152     * Set the enabled state of this view. The interpretation of the enabled
3153     * state varies by subclass.
3154     *
3155     * @param enabled True if this view is enabled, false otherwise.
3156     */
3157    @RemotableViewMethod
3158    public void setEnabled(boolean enabled) {
3159        if (enabled == isEnabled()) return;
3160
3161        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
3162
3163        /*
3164         * The View most likely has to change its appearance, so refresh
3165         * the drawable state.
3166         */
3167        refreshDrawableState();
3168
3169        // Invalidate too, since the default behavior for views is to be
3170        // be drawn at 50% alpha rather than to change the drawable.
3171        invalidate();
3172    }
3173
3174    /**
3175     * Set whether this view can receive the focus.
3176     *
3177     * Setting this to false will also ensure that this view is not focusable
3178     * in touch mode.
3179     *
3180     * @param focusable If true, this view can receive the focus.
3181     *
3182     * @see #setFocusableInTouchMode(boolean)
3183     * @attr ref android.R.styleable#View_focusable
3184     */
3185    public void setFocusable(boolean focusable) {
3186        if (!focusable) {
3187            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
3188        }
3189        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
3190    }
3191
3192    /**
3193     * Set whether this view can receive focus while in touch mode.
3194     *
3195     * Setting this to true will also ensure that this view is focusable.
3196     *
3197     * @param focusableInTouchMode If true, this view can receive the focus while
3198     *   in touch mode.
3199     *
3200     * @see #setFocusable(boolean)
3201     * @attr ref android.R.styleable#View_focusableInTouchMode
3202     */
3203    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
3204        // Focusable in touch mode should always be set before the focusable flag
3205        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
3206        // which, in touch mode, will not successfully request focus on this view
3207        // because the focusable in touch mode flag is not set
3208        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
3209        if (focusableInTouchMode) {
3210            setFlags(FOCUSABLE, FOCUSABLE_MASK);
3211        }
3212    }
3213
3214    /**
3215     * Set whether this view should have sound effects enabled for events such as
3216     * clicking and touching.
3217     *
3218     * <p>You may wish to disable sound effects for a view if you already play sounds,
3219     * for instance, a dial key that plays dtmf tones.
3220     *
3221     * @param soundEffectsEnabled whether sound effects are enabled for this view.
3222     * @see #isSoundEffectsEnabled()
3223     * @see #playSoundEffect(int)
3224     * @attr ref android.R.styleable#View_soundEffectsEnabled
3225     */
3226    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
3227        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
3228    }
3229
3230    /**
3231     * @return whether this view should have sound effects enabled for events such as
3232     *     clicking and touching.
3233     *
3234     * @see #setSoundEffectsEnabled(boolean)
3235     * @see #playSoundEffect(int)
3236     * @attr ref android.R.styleable#View_soundEffectsEnabled
3237     */
3238    @ViewDebug.ExportedProperty
3239    public boolean isSoundEffectsEnabled() {
3240        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
3241    }
3242
3243    /**
3244     * Set whether this view should have haptic feedback for events such as
3245     * long presses.
3246     *
3247     * <p>You may wish to disable haptic feedback if your view already controls
3248     * its own haptic feedback.
3249     *
3250     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
3251     * @see #isHapticFeedbackEnabled()
3252     * @see #performHapticFeedback(int)
3253     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
3254     */
3255    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
3256        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
3257    }
3258
3259    /**
3260     * @return whether this view should have haptic feedback enabled for events
3261     * long presses.
3262     *
3263     * @see #setHapticFeedbackEnabled(boolean)
3264     * @see #performHapticFeedback(int)
3265     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
3266     */
3267    @ViewDebug.ExportedProperty
3268    public boolean isHapticFeedbackEnabled() {
3269        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
3270    }
3271
3272    /**
3273     * If this view doesn't do any drawing on its own, set this flag to
3274     * allow further optimizations. By default, this flag is not set on
3275     * View, but could be set on some View subclasses such as ViewGroup.
3276     *
3277     * Typically, if you override {@link #onDraw} you should clear this flag.
3278     *
3279     * @param willNotDraw whether or not this View draw on its own
3280     */
3281    public void setWillNotDraw(boolean willNotDraw) {
3282        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
3283    }
3284
3285    /**
3286     * Returns whether or not this View draws on its own.
3287     *
3288     * @return true if this view has nothing to draw, false otherwise
3289     */
3290    @ViewDebug.ExportedProperty
3291    public boolean willNotDraw() {
3292        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
3293    }
3294
3295    /**
3296     * When a View's drawing cache is enabled, drawing is redirected to an
3297     * offscreen bitmap. Some views, like an ImageView, must be able to
3298     * bypass this mechanism if they already draw a single bitmap, to avoid
3299     * unnecessary usage of the memory.
3300     *
3301     * @param willNotCacheDrawing true if this view does not cache its
3302     *        drawing, false otherwise
3303     */
3304    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
3305        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
3306    }
3307
3308    /**
3309     * Returns whether or not this View can cache its drawing or not.
3310     *
3311     * @return true if this view does not cache its drawing, false otherwise
3312     */
3313    @ViewDebug.ExportedProperty
3314    public boolean willNotCacheDrawing() {
3315        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
3316    }
3317
3318    /**
3319     * Indicates whether this view reacts to click events or not.
3320     *
3321     * @return true if the view is clickable, false otherwise
3322     *
3323     * @see #setClickable(boolean)
3324     * @attr ref android.R.styleable#View_clickable
3325     */
3326    @ViewDebug.ExportedProperty
3327    public boolean isClickable() {
3328        return (mViewFlags & CLICKABLE) == CLICKABLE;
3329    }
3330
3331    /**
3332     * Enables or disables click events for this view. When a view
3333     * is clickable it will change its state to "pressed" on every click.
3334     * Subclasses should set the view clickable to visually react to
3335     * user's clicks.
3336     *
3337     * @param clickable true to make the view clickable, false otherwise
3338     *
3339     * @see #isClickable()
3340     * @attr ref android.R.styleable#View_clickable
3341     */
3342    public void setClickable(boolean clickable) {
3343        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
3344    }
3345
3346    /**
3347     * Indicates whether this view reacts to long click events or not.
3348     *
3349     * @return true if the view is long clickable, false otherwise
3350     *
3351     * @see #setLongClickable(boolean)
3352     * @attr ref android.R.styleable#View_longClickable
3353     */
3354    public boolean isLongClickable() {
3355        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
3356    }
3357
3358    /**
3359     * Enables or disables long click events for this view. When a view is long
3360     * clickable it reacts to the user holding down the button for a longer
3361     * duration than a tap. This event can either launch the listener or a
3362     * context menu.
3363     *
3364     * @param longClickable true to make the view long clickable, false otherwise
3365     * @see #isLongClickable()
3366     * @attr ref android.R.styleable#View_longClickable
3367     */
3368    public void setLongClickable(boolean longClickable) {
3369        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
3370    }
3371
3372    /**
3373     * Sets the pressed that for this view.
3374     *
3375     * @see #isClickable()
3376     * @see #setClickable(boolean)
3377     *
3378     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
3379     *        the View's internal state from a previously set "pressed" state.
3380     */
3381    public void setPressed(boolean pressed) {
3382        if (pressed) {
3383            mPrivateFlags |= PRESSED;
3384        } else {
3385            mPrivateFlags &= ~PRESSED;
3386        }
3387        refreshDrawableState();
3388        dispatchSetPressed(pressed);
3389    }
3390
3391    /**
3392     * Dispatch setPressed to all of this View's children.
3393     *
3394     * @see #setPressed(boolean)
3395     *
3396     * @param pressed The new pressed state
3397     */
3398    protected void dispatchSetPressed(boolean pressed) {
3399    }
3400
3401    /**
3402     * Indicates whether the view is currently in pressed state. Unless
3403     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
3404     * the pressed state.
3405     *
3406     * @see #setPressed
3407     * @see #isClickable()
3408     * @see #setClickable(boolean)
3409     *
3410     * @return true if the view is currently pressed, false otherwise
3411     */
3412    public boolean isPressed() {
3413        return (mPrivateFlags & PRESSED) == PRESSED;
3414    }
3415
3416    /**
3417     * Indicates whether this view will save its state (that is,
3418     * whether its {@link #onSaveInstanceState} method will be called).
3419     *
3420     * @return Returns true if the view state saving is enabled, else false.
3421     *
3422     * @see #setSaveEnabled(boolean)
3423     * @attr ref android.R.styleable#View_saveEnabled
3424     */
3425    public boolean isSaveEnabled() {
3426        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
3427    }
3428
3429    /**
3430     * Controls whether the saving of this view's state is
3431     * enabled (that is, whether its {@link #onSaveInstanceState} method
3432     * will be called).  Note that even if freezing is enabled, the
3433     * view still must have an id assigned to it (via {@link #setId setId()})
3434     * for its state to be saved.  This flag can only disable the
3435     * saving of this view; any child views may still have their state saved.
3436     *
3437     * @param enabled Set to false to <em>disable</em> state saving, or true
3438     * (the default) to allow it.
3439     *
3440     * @see #isSaveEnabled()
3441     * @see #setId(int)
3442     * @see #onSaveInstanceState()
3443     * @attr ref android.R.styleable#View_saveEnabled
3444     */
3445    public void setSaveEnabled(boolean enabled) {
3446        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
3447    }
3448
3449
3450    /**
3451     * Indicates whether the entire hierarchy under this view will save its
3452     * state when a state saving traversal occurs from its parent.  The default
3453     * is true; if false, these views will not be saved unless
3454     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
3455     *
3456     * @return Returns true if the view state saving from parent is enabled, else false.
3457     *
3458     * @see #setSaveFromParentEnabled(boolean)
3459     */
3460    public boolean isSaveFromParentEnabled() {
3461        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
3462    }
3463
3464    /**
3465     * Controls whether the entire hierarchy under this view will save its
3466     * state when a state saving traversal occurs from its parent.  The default
3467     * is true; if false, these views will not be saved unless
3468     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
3469     *
3470     * @param enabled Set to false to <em>disable</em> state saving, or true
3471     * (the default) to allow it.
3472     *
3473     * @see #isSaveFromParentEnabled()
3474     * @see #setId(int)
3475     * @see #onSaveInstanceState()
3476     */
3477    public void setSaveFromParentEnabled(boolean enabled) {
3478        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
3479    }
3480
3481
3482    /**
3483     * Returns whether this View is able to take focus.
3484     *
3485     * @return True if this view can take focus, or false otherwise.
3486     * @attr ref android.R.styleable#View_focusable
3487     */
3488    @ViewDebug.ExportedProperty
3489    public final boolean isFocusable() {
3490        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
3491    }
3492
3493    /**
3494     * When a view is focusable, it may not want to take focus when in touch mode.
3495     * For example, a button would like focus when the user is navigating via a D-pad
3496     * so that the user can click on it, but once the user starts touching the screen,
3497     * the button shouldn't take focus
3498     * @return Whether the view is focusable in touch mode.
3499     * @attr ref android.R.styleable#View_focusableInTouchMode
3500     */
3501    @ViewDebug.ExportedProperty
3502    public final boolean isFocusableInTouchMode() {
3503        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
3504    }
3505
3506    /**
3507     * Find the nearest view in the specified direction that can take focus.
3508     * This does not actually give focus to that view.
3509     *
3510     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
3511     *
3512     * @return The nearest focusable in the specified direction, or null if none
3513     *         can be found.
3514     */
3515    public View focusSearch(int direction) {
3516        if (mParent != null) {
3517            return mParent.focusSearch(this, direction);
3518        } else {
3519            return null;
3520        }
3521    }
3522
3523    /**
3524     * This method is the last chance for the focused view and its ancestors to
3525     * respond to an arrow key. This is called when the focused view did not
3526     * consume the key internally, nor could the view system find a new view in
3527     * the requested direction to give focus to.
3528     *
3529     * @param focused The currently focused view.
3530     * @param direction The direction focus wants to move. One of FOCUS_UP,
3531     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
3532     * @return True if the this view consumed this unhandled move.
3533     */
3534    public boolean dispatchUnhandledMove(View focused, int direction) {
3535        return false;
3536    }
3537
3538    /**
3539     * If a user manually specified the next view id for a particular direction,
3540     * use the root to look up the view.  Once a view is found, it is cached
3541     * for future lookups.
3542     * @param root The root view of the hierarchy containing this view.
3543     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
3544     * @return The user specified next view, or null if there is none.
3545     */
3546    View findUserSetNextFocus(View root, int direction) {
3547        switch (direction) {
3548            case FOCUS_LEFT:
3549                if (mNextFocusLeftId == View.NO_ID) return null;
3550                return findViewShouldExist(root, mNextFocusLeftId);
3551            case FOCUS_RIGHT:
3552                if (mNextFocusRightId == View.NO_ID) return null;
3553                return findViewShouldExist(root, mNextFocusRightId);
3554            case FOCUS_UP:
3555                if (mNextFocusUpId == View.NO_ID) return null;
3556                return findViewShouldExist(root, mNextFocusUpId);
3557            case FOCUS_DOWN:
3558                if (mNextFocusDownId == View.NO_ID) return null;
3559                return findViewShouldExist(root, mNextFocusDownId);
3560        }
3561        return null;
3562    }
3563
3564    private static View findViewShouldExist(View root, int childViewId) {
3565        View result = root.findViewById(childViewId);
3566        if (result == null) {
3567            Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
3568                    + "by user for id " + childViewId);
3569        }
3570        return result;
3571    }
3572
3573    /**
3574     * Find and return all focusable views that are descendants of this view,
3575     * possibly including this view if it is focusable itself.
3576     *
3577     * @param direction The direction of the focus
3578     * @return A list of focusable views
3579     */
3580    public ArrayList<View> getFocusables(int direction) {
3581        ArrayList<View> result = new ArrayList<View>(24);
3582        addFocusables(result, direction);
3583        return result;
3584    }
3585
3586    /**
3587     * Add any focusable views that are descendants of this view (possibly
3588     * including this view if it is focusable itself) to views.  If we are in touch mode,
3589     * only add views that are also focusable in touch mode.
3590     *
3591     * @param views Focusable views found so far
3592     * @param direction The direction of the focus
3593     */
3594    public void addFocusables(ArrayList<View> views, int direction) {
3595        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
3596    }
3597
3598    /**
3599     * Adds any focusable views that are descendants of this view (possibly
3600     * including this view if it is focusable itself) to views. This method
3601     * adds all focusable views regardless if we are in touch mode or
3602     * only views focusable in touch mode if we are in touch mode depending on
3603     * the focusable mode paramater.
3604     *
3605     * @param views Focusable views found so far or null if all we are interested is
3606     *        the number of focusables.
3607     * @param direction The direction of the focus.
3608     * @param focusableMode The type of focusables to be added.
3609     *
3610     * @see #FOCUSABLES_ALL
3611     * @see #FOCUSABLES_TOUCH_MODE
3612     */
3613    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
3614        if (!isFocusable()) {
3615            return;
3616        }
3617
3618        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE &&
3619                isInTouchMode() && !isFocusableInTouchMode()) {
3620            return;
3621        }
3622
3623        if (views != null) {
3624            views.add(this);
3625        }
3626    }
3627
3628    /**
3629     * Find and return all touchable views that are descendants of this view,
3630     * possibly including this view if it is touchable itself.
3631     *
3632     * @return A list of touchable views
3633     */
3634    public ArrayList<View> getTouchables() {
3635        ArrayList<View> result = new ArrayList<View>();
3636        addTouchables(result);
3637        return result;
3638    }
3639
3640    /**
3641     * Add any touchable views that are descendants of this view (possibly
3642     * including this view if it is touchable itself) to views.
3643     *
3644     * @param views Touchable views found so far
3645     */
3646    public void addTouchables(ArrayList<View> views) {
3647        final int viewFlags = mViewFlags;
3648
3649        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
3650                && (viewFlags & ENABLED_MASK) == ENABLED) {
3651            views.add(this);
3652        }
3653    }
3654
3655    /**
3656     * Call this to try to give focus to a specific view or to one of its
3657     * descendants.
3658     *
3659     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false),
3660     * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode})
3661     * while the device is in touch mode.
3662     *
3663     * See also {@link #focusSearch}, which is what you call to say that you
3664     * have focus, and you want your parent to look for the next one.
3665     *
3666     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
3667     * {@link #FOCUS_DOWN} and <code>null</code>.
3668     *
3669     * @return Whether this view or one of its descendants actually took focus.
3670     */
3671    public final boolean requestFocus() {
3672        return requestFocus(View.FOCUS_DOWN);
3673    }
3674
3675
3676    /**
3677     * Call this to try to give focus to a specific view or to one of its
3678     * descendants and give it a hint about what direction focus is heading.
3679     *
3680     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false),
3681     * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode})
3682     * while the device is in touch mode.
3683     *
3684     * See also {@link #focusSearch}, which is what you call to say that you
3685     * have focus, and you want your parent to look for the next one.
3686     *
3687     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
3688     * <code>null</code> set for the previously focused rectangle.
3689     *
3690     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
3691     * @return Whether this view or one of its descendants actually took focus.
3692     */
3693    public final boolean requestFocus(int direction) {
3694        return requestFocus(direction, null);
3695    }
3696
3697    /**
3698     * Call this to try to give focus to a specific view or to one of its descendants
3699     * and give it hints about the direction and a specific rectangle that the focus
3700     * is coming from.  The rectangle can help give larger views a finer grained hint
3701     * about where focus is coming from, and therefore, where to show selection, or
3702     * forward focus change internally.
3703     *
3704     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns false),
3705     * or if it is focusable and it is not focusable in touch mode ({@link #isFocusableInTouchMode})
3706     * while the device is in touch mode.
3707     *
3708     * A View will not take focus if it is not visible.
3709     *
3710     * A View will not take focus if one of its parents has {@link android.view.ViewGroup#getDescendantFocusability()}
3711     * equal to {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
3712     *
3713     * See also {@link #focusSearch}, which is what you call to say that you
3714     * have focus, and you want your parent to look for the next one.
3715     *
3716     * You may wish to override this method if your custom {@link View} has an internal
3717     * {@link View} that it wishes to forward the request to.
3718     *
3719     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
3720     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
3721     *        to give a finer grained hint about where focus is coming from.  May be null
3722     *        if there is no hint.
3723     * @return Whether this view or one of its descendants actually took focus.
3724     */
3725    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
3726        // need to be focusable
3727        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
3728                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
3729            return false;
3730        }
3731
3732        // need to be focusable in touch mode if in touch mode
3733        if (isInTouchMode() &&
3734                (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
3735            return false;
3736        }
3737
3738        // need to not have any parents blocking us
3739        if (hasAncestorThatBlocksDescendantFocus()) {
3740            return false;
3741        }
3742
3743        handleFocusGainInternal(direction, previouslyFocusedRect);
3744        return true;
3745    }
3746
3747    /**
3748     * Call this to try to give focus to a specific view or to one of its descendants. This is a
3749     * special variant of {@link #requestFocus() } that will allow views that are not focuable in
3750     * touch mode to request focus when they are touched.
3751     *
3752     * @return Whether this view or one of its descendants actually took focus.
3753     *
3754     * @see #isInTouchMode()
3755     *
3756     */
3757    public final boolean requestFocusFromTouch() {
3758        // Leave touch mode if we need to
3759        if (isInTouchMode()) {
3760            View root = getRootView();
3761            if (root != null) {
3762               ViewRoot viewRoot = (ViewRoot)root.getParent();
3763               if (viewRoot != null) {
3764                   viewRoot.ensureTouchMode(false);
3765               }
3766            }
3767        }
3768        return requestFocus(View.FOCUS_DOWN);
3769    }
3770
3771    /**
3772     * @return Whether any ancestor of this view blocks descendant focus.
3773     */
3774    private boolean hasAncestorThatBlocksDescendantFocus() {
3775        ViewParent ancestor = mParent;
3776        while (ancestor instanceof ViewGroup) {
3777            final ViewGroup vgAncestor = (ViewGroup) ancestor;
3778            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
3779                return true;
3780            } else {
3781                ancestor = vgAncestor.getParent();
3782            }
3783        }
3784        return false;
3785    }
3786
3787    /**
3788     * @hide
3789     */
3790    public void dispatchStartTemporaryDetach() {
3791        onStartTemporaryDetach();
3792    }
3793
3794    /**
3795     * This is called when a container is going to temporarily detach a child, with
3796     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
3797     * It will either be followed by {@link #onFinishTemporaryDetach()} or
3798     * {@link #onDetachedFromWindow()} when the container is done.
3799     */
3800    public void onStartTemporaryDetach() {
3801        removeUnsetPressCallback();
3802        mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
3803    }
3804
3805    /**
3806     * @hide
3807     */
3808    public void dispatchFinishTemporaryDetach() {
3809        onFinishTemporaryDetach();
3810    }
3811
3812    /**
3813     * Called after {@link #onStartTemporaryDetach} when the container is done
3814     * changing the view.
3815     */
3816    public void onFinishTemporaryDetach() {
3817    }
3818
3819    /**
3820     * capture information of this view for later analysis: developement only
3821     * check dynamic switch to make sure we only dump view
3822     * when ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW) is set
3823     */
3824    private static void captureViewInfo(String subTag, View v) {
3825        if (v == null || SystemProperties.getInt(ViewDebug.SYSTEM_PROPERTY_CAPTURE_VIEW, 0) == 0) {
3826            return;
3827        }
3828        ViewDebug.dumpCapturedView(subTag, v);
3829    }
3830
3831    /**
3832     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
3833     * for this view's window.  Returns null if the view is not currently attached
3834     * to the window.  Normally you will not need to use this directly, but
3835     * just use the standard high-level event callbacks like {@link #onKeyDown}.
3836     */
3837    public KeyEvent.DispatcherState getKeyDispatcherState() {
3838        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
3839    }
3840
3841    /**
3842     * Dispatch a key event before it is processed by any input method
3843     * associated with the view hierarchy.  This can be used to intercept
3844     * key events in special situations before the IME consumes them; a
3845     * typical example would be handling the BACK key to update the application's
3846     * UI instead of allowing the IME to see it and close itself.
3847     *
3848     * @param event The key event to be dispatched.
3849     * @return True if the event was handled, false otherwise.
3850     */
3851    public boolean dispatchKeyEventPreIme(KeyEvent event) {
3852        return onKeyPreIme(event.getKeyCode(), event);
3853    }
3854
3855    /**
3856     * Dispatch a key event to the next view on the focus path. This path runs
3857     * from the top of the view tree down to the currently focused view. If this
3858     * view has focus, it will dispatch to itself. Otherwise it will dispatch
3859     * the next node down the focus path. This method also fires any key
3860     * listeners.
3861     *
3862     * @param event The key event to be dispatched.
3863     * @return True if the event was handled, false otherwise.
3864     */
3865    public boolean dispatchKeyEvent(KeyEvent event) {
3866        // If any attached key listener a first crack at the event.
3867        //noinspection SimplifiableIfStatement
3868
3869        if (android.util.Config.LOGV) {
3870            captureViewInfo("captureViewKeyEvent", this);
3871        }
3872
3873        if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
3874                && mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
3875            return true;
3876        }
3877
3878        return event.dispatch(this, mAttachInfo != null
3879                ? mAttachInfo.mKeyDispatchState : null, this);
3880    }
3881
3882    /**
3883     * Dispatches a key shortcut event.
3884     *
3885     * @param event The key event to be dispatched.
3886     * @return True if the event was handled by the view, false otherwise.
3887     */
3888    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
3889        return onKeyShortcut(event.getKeyCode(), event);
3890    }
3891
3892    /**
3893     * Pass the touch screen motion event down to the target view, or this
3894     * view if it is the target.
3895     *
3896     * @param event The motion event to be dispatched.
3897     * @return True if the event was handled by the view, false otherwise.
3898     */
3899    public boolean dispatchTouchEvent(MotionEvent event) {
3900        if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
3901                mOnTouchListener.onTouch(this, event)) {
3902            return true;
3903        }
3904        return onTouchEvent(event);
3905    }
3906
3907    /**
3908     * Pass a trackball motion event down to the focused view.
3909     *
3910     * @param event The motion event to be dispatched.
3911     * @return True if the event was handled by the view, false otherwise.
3912     */
3913    public boolean dispatchTrackballEvent(MotionEvent event) {
3914        //Log.i("view", "view=" + this + ", " + event.toString());
3915        return onTrackballEvent(event);
3916    }
3917
3918    /**
3919     * Called when the window containing this view gains or loses window focus.
3920     * ViewGroups should override to route to their children.
3921     *
3922     * @param hasFocus True if the window containing this view now has focus,
3923     *        false otherwise.
3924     */
3925    public void dispatchWindowFocusChanged(boolean hasFocus) {
3926        onWindowFocusChanged(hasFocus);
3927    }
3928
3929    /**
3930     * Called when the window containing this view gains or loses focus.  Note
3931     * that this is separate from view focus: to receive key events, both
3932     * your view and its window must have focus.  If a window is displayed
3933     * on top of yours that takes input focus, then your own window will lose
3934     * focus but the view focus will remain unchanged.
3935     *
3936     * @param hasWindowFocus True if the window containing this view now has
3937     *        focus, false otherwise.
3938     */
3939    public void onWindowFocusChanged(boolean hasWindowFocus) {
3940        InputMethodManager imm = InputMethodManager.peekInstance();
3941        if (!hasWindowFocus) {
3942            if (isPressed()) {
3943                setPressed(false);
3944            }
3945            if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
3946                imm.focusOut(this);
3947            }
3948            removeLongPressCallback();
3949            onFocusLost();
3950        } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
3951            imm.focusIn(this);
3952        }
3953        refreshDrawableState();
3954    }
3955
3956    /**
3957     * Returns true if this view is in a window that currently has window focus.
3958     * Note that this is not the same as the view itself having focus.
3959     *
3960     * @return True if this view is in a window that currently has window focus.
3961     */
3962    public boolean hasWindowFocus() {
3963        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
3964    }
3965
3966    /**
3967     * Dispatch a view visibility change down the view hierarchy.
3968     * ViewGroups should override to route to their children.
3969     * @param changedView The view whose visibility changed. Could be 'this' or
3970     * an ancestor view.
3971     * @param visibility The new visibility of changedView: {@link #VISIBLE},
3972     * {@link #INVISIBLE} or {@link #GONE}.
3973     */
3974    protected void dispatchVisibilityChanged(View changedView, int visibility) {
3975        onVisibilityChanged(changedView, visibility);
3976    }
3977
3978    /**
3979     * Called when the visibility of the view or an ancestor of the view is changed.
3980     * @param changedView The view whose visibility changed. Could be 'this' or
3981     * an ancestor view.
3982     * @param visibility The new visibility of changedView: {@link #VISIBLE},
3983     * {@link #INVISIBLE} or {@link #GONE}.
3984     */
3985    protected void onVisibilityChanged(View changedView, int visibility) {
3986        if (visibility == VISIBLE) {
3987            if (mAttachInfo != null) {
3988                initialAwakenScrollBars();
3989            } else {
3990                mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
3991            }
3992        }
3993    }
3994
3995    /**
3996     * Dispatch a hint about whether this view is displayed. For instance, when
3997     * a View moves out of the screen, it might receives a display hint indicating
3998     * the view is not displayed. Applications should not <em>rely</em> on this hint
3999     * as there is no guarantee that they will receive one.
4000     *
4001     * @param hint A hint about whether or not this view is displayed:
4002     * {@link #VISIBLE} or {@link #INVISIBLE}.
4003     */
4004    public void dispatchDisplayHint(int hint) {
4005        onDisplayHint(hint);
4006    }
4007
4008    /**
4009     * Gives this view a hint about whether is displayed or not. For instance, when
4010     * a View moves out of the screen, it might receives a display hint indicating
4011     * the view is not displayed. Applications should not <em>rely</em> on this hint
4012     * as there is no guarantee that they will receive one.
4013     *
4014     * @param hint A hint about whether or not this view is displayed:
4015     * {@link #VISIBLE} or {@link #INVISIBLE}.
4016     */
4017    protected void onDisplayHint(int hint) {
4018    }
4019
4020    /**
4021     * Dispatch a window visibility change down the view hierarchy.
4022     * ViewGroups should override to route to their children.
4023     *
4024     * @param visibility The new visibility of the window.
4025     *
4026     * @see #onWindowVisibilityChanged
4027     */
4028    public void dispatchWindowVisibilityChanged(int visibility) {
4029        onWindowVisibilityChanged(visibility);
4030    }
4031
4032    /**
4033     * Called when the window containing has change its visibility
4034     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
4035     * that this tells you whether or not your window is being made visible
4036     * to the window manager; this does <em>not</em> tell you whether or not
4037     * your window is obscured by other windows on the screen, even if it
4038     * is itself visible.
4039     *
4040     * @param visibility The new visibility of the window.
4041     */
4042    protected void onWindowVisibilityChanged(int visibility) {
4043        if (visibility == VISIBLE) {
4044            initialAwakenScrollBars();
4045        }
4046    }
4047
4048    /**
4049     * Returns the current visibility of the window this view is attached to
4050     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
4051     *
4052     * @return Returns the current visibility of the view's window.
4053     */
4054    public int getWindowVisibility() {
4055        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
4056    }
4057
4058    /**
4059     * Retrieve the overall visible display size in which the window this view is
4060     * attached to has been positioned in.  This takes into account screen
4061     * decorations above the window, for both cases where the window itself
4062     * is being position inside of them or the window is being placed under
4063     * then and covered insets are used for the window to position its content
4064     * inside.  In effect, this tells you the available area where content can
4065     * be placed and remain visible to users.
4066     *
4067     * <p>This function requires an IPC back to the window manager to retrieve
4068     * the requested information, so should not be used in performance critical
4069     * code like drawing.
4070     *
4071     * @param outRect Filled in with the visible display frame.  If the view
4072     * is not attached to a window, this is simply the raw display size.
4073     */
4074    public void getWindowVisibleDisplayFrame(Rect outRect) {
4075        if (mAttachInfo != null) {
4076            try {
4077                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
4078            } catch (RemoteException e) {
4079                return;
4080            }
4081            // XXX This is really broken, and probably all needs to be done
4082            // in the window manager, and we need to know more about whether
4083            // we want the area behind or in front of the IME.
4084            final Rect insets = mAttachInfo.mVisibleInsets;
4085            outRect.left += insets.left;
4086            outRect.top += insets.top;
4087            outRect.right -= insets.right;
4088            outRect.bottom -= insets.bottom;
4089            return;
4090        }
4091        Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
4092        outRect.set(0, 0, d.getWidth(), d.getHeight());
4093    }
4094
4095    /**
4096     * Dispatch a notification about a resource configuration change down
4097     * the view hierarchy.
4098     * ViewGroups should override to route to their children.
4099     *
4100     * @param newConfig The new resource configuration.
4101     *
4102     * @see #onConfigurationChanged
4103     */
4104    public void dispatchConfigurationChanged(Configuration newConfig) {
4105        onConfigurationChanged(newConfig);
4106    }
4107
4108    /**
4109     * Called when the current configuration of the resources being used
4110     * by the application have changed.  You can use this to decide when
4111     * to reload resources that can changed based on orientation and other
4112     * configuration characterstics.  You only need to use this if you are
4113     * not relying on the normal {@link android.app.Activity} mechanism of
4114     * recreating the activity instance upon a configuration change.
4115     *
4116     * @param newConfig The new resource configuration.
4117     */
4118    protected void onConfigurationChanged(Configuration newConfig) {
4119    }
4120
4121    /**
4122     * Private function to aggregate all per-view attributes in to the view
4123     * root.
4124     */
4125    void dispatchCollectViewAttributes(int visibility) {
4126        performCollectViewAttributes(visibility);
4127    }
4128
4129    void performCollectViewAttributes(int visibility) {
4130        //noinspection PointlessBitwiseExpression
4131        if (((visibility | mViewFlags) & (VISIBILITY_MASK | KEEP_SCREEN_ON))
4132                == (VISIBLE | KEEP_SCREEN_ON)) {
4133            mAttachInfo.mKeepScreenOn = true;
4134        }
4135    }
4136
4137    void needGlobalAttributesUpdate(boolean force) {
4138        AttachInfo ai = mAttachInfo;
4139        if (ai != null) {
4140            if (ai.mKeepScreenOn || force) {
4141                ai.mRecomputeGlobalAttributes = true;
4142            }
4143        }
4144    }
4145
4146    /**
4147     * Returns whether the device is currently in touch mode.  Touch mode is entered
4148     * once the user begins interacting with the device by touch, and affects various
4149     * things like whether focus is always visible to the user.
4150     *
4151     * @return Whether the device is in touch mode.
4152     */
4153    @ViewDebug.ExportedProperty
4154    public boolean isInTouchMode() {
4155        if (mAttachInfo != null) {
4156            return mAttachInfo.mInTouchMode;
4157        } else {
4158            return ViewRoot.isInTouchMode();
4159        }
4160    }
4161
4162    /**
4163     * Returns the context the view is running in, through which it can
4164     * access the current theme, resources, etc.
4165     *
4166     * @return The view's Context.
4167     */
4168    @ViewDebug.CapturedViewProperty
4169    public final Context getContext() {
4170        return mContext;
4171    }
4172
4173    /**
4174     * Handle a key event before it is processed by any input method
4175     * associated with the view hierarchy.  This can be used to intercept
4176     * key events in special situations before the IME consumes them; a
4177     * typical example would be handling the BACK key to update the application's
4178     * UI instead of allowing the IME to see it and close itself.
4179     *
4180     * @param keyCode The value in event.getKeyCode().
4181     * @param event Description of the key event.
4182     * @return If you handled the event, return true. If you want to allow the
4183     *         event to be handled by the next receiver, return false.
4184     */
4185    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
4186        return false;
4187    }
4188
4189    /**
4190     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
4191     * KeyEvent.Callback.onKeyMultiple()}: perform press of the view
4192     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
4193     * is released, if the view is enabled and clickable.
4194     *
4195     * @param keyCode A key code that represents the button pressed, from
4196     *                {@link android.view.KeyEvent}.
4197     * @param event   The KeyEvent object that defines the button action.
4198     */
4199    public boolean onKeyDown(int keyCode, KeyEvent event) {
4200        boolean result = false;
4201
4202        switch (keyCode) {
4203            case KeyEvent.KEYCODE_DPAD_CENTER:
4204            case KeyEvent.KEYCODE_ENTER: {
4205                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
4206                    return true;
4207                }
4208                // Long clickable items don't necessarily have to be clickable
4209                if (((mViewFlags & CLICKABLE) == CLICKABLE ||
4210                        (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
4211                        (event.getRepeatCount() == 0)) {
4212                    setPressed(true);
4213                    if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
4214                        postCheckForLongClick(0);
4215                    }
4216                    return true;
4217                }
4218                break;
4219            }
4220        }
4221        return result;
4222    }
4223
4224    /**
4225     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
4226     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
4227     * the event).
4228     */
4229    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
4230        return false;
4231    }
4232
4233    /**
4234     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
4235     * KeyEvent.Callback.onKeyMultiple()}: perform clicking of the view
4236     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
4237     * {@link KeyEvent#KEYCODE_ENTER} is released.
4238     *
4239     * @param keyCode A key code that represents the button pressed, from
4240     *                {@link android.view.KeyEvent}.
4241     * @param event   The KeyEvent object that defines the button action.
4242     */
4243    public boolean onKeyUp(int keyCode, KeyEvent event) {
4244        boolean result = false;
4245
4246        switch (keyCode) {
4247            case KeyEvent.KEYCODE_DPAD_CENTER:
4248            case KeyEvent.KEYCODE_ENTER: {
4249                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
4250                    return true;
4251                }
4252                if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
4253                    setPressed(false);
4254
4255                    if (!mHasPerformedLongPress) {
4256                        // This is a tap, so remove the longpress check
4257                        removeLongPressCallback();
4258
4259                        result = performClick();
4260                    }
4261                }
4262                break;
4263            }
4264        }
4265        return result;
4266    }
4267
4268    /**
4269     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
4270     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
4271     * the event).
4272     *
4273     * @param keyCode     A key code that represents the button pressed, from
4274     *                    {@link android.view.KeyEvent}.
4275     * @param repeatCount The number of times the action was made.
4276     * @param event       The KeyEvent object that defines the button action.
4277     */
4278    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
4279        return false;
4280    }
4281
4282    /**
4283     * Called when an unhandled key shortcut event occurs.
4284     *
4285     * @param keyCode The value in event.getKeyCode().
4286     * @param event Description of the key event.
4287     * @return If you handled the event, return true. If you want to allow the
4288     *         event to be handled by the next receiver, return false.
4289     */
4290    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
4291        return false;
4292    }
4293
4294    /**
4295     * Check whether the called view is a text editor, in which case it
4296     * would make sense to automatically display a soft input window for
4297     * it.  Subclasses should override this if they implement
4298     * {@link #onCreateInputConnection(EditorInfo)} to return true if
4299     * a call on that method would return a non-null InputConnection, and
4300     * they are really a first-class editor that the user would normally
4301     * start typing on when the go into a window containing your view.
4302     *
4303     * <p>The default implementation always returns false.  This does
4304     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
4305     * will not be called or the user can not otherwise perform edits on your
4306     * view; it is just a hint to the system that this is not the primary
4307     * purpose of this view.
4308     *
4309     * @return Returns true if this view is a text editor, else false.
4310     */
4311    public boolean onCheckIsTextEditor() {
4312        return false;
4313    }
4314
4315    /**
4316     * Create a new InputConnection for an InputMethod to interact
4317     * with the view.  The default implementation returns null, since it doesn't
4318     * support input methods.  You can override this to implement such support.
4319     * This is only needed for views that take focus and text input.
4320     *
4321     * <p>When implementing this, you probably also want to implement
4322     * {@link #onCheckIsTextEditor()} to indicate you will return a
4323     * non-null InputConnection.
4324     *
4325     * @param outAttrs Fill in with attribute information about the connection.
4326     */
4327    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
4328        return null;
4329    }
4330
4331    /**
4332     * Called by the {@link android.view.inputmethod.InputMethodManager}
4333     * when a view who is not the current
4334     * input connection target is trying to make a call on the manager.  The
4335     * default implementation returns false; you can override this to return
4336     * true for certain views if you are performing InputConnection proxying
4337     * to them.
4338     * @param view The View that is making the InputMethodManager call.
4339     * @return Return true to allow the call, false to reject.
4340     */
4341    public boolean checkInputConnectionProxy(View view) {
4342        return false;
4343    }
4344
4345    /**
4346     * Show the context menu for this view. It is not safe to hold on to the
4347     * menu after returning from this method.
4348     *
4349     * @param menu The context menu to populate
4350     */
4351    public void createContextMenu(ContextMenu menu) {
4352        ContextMenuInfo menuInfo = getContextMenuInfo();
4353
4354        // Sets the current menu info so all items added to menu will have
4355        // my extra info set.
4356        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
4357
4358        onCreateContextMenu(menu);
4359        if (mOnCreateContextMenuListener != null) {
4360            mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
4361        }
4362
4363        // Clear the extra information so subsequent items that aren't mine don't
4364        // have my extra info.
4365        ((MenuBuilder)menu).setCurrentMenuInfo(null);
4366
4367        if (mParent != null) {
4368            mParent.createContextMenu(menu);
4369        }
4370    }
4371
4372    /**
4373     * Views should implement this if they have extra information to associate
4374     * with the context menu. The return result is supplied as a parameter to
4375     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
4376     * callback.
4377     *
4378     * @return Extra information about the item for which the context menu
4379     *         should be shown. This information will vary across different
4380     *         subclasses of View.
4381     */
4382    protected ContextMenuInfo getContextMenuInfo() {
4383        return null;
4384    }
4385
4386    /**
4387     * Views should implement this if the view itself is going to add items to
4388     * the context menu.
4389     *
4390     * @param menu the context menu to populate
4391     */
4392    protected void onCreateContextMenu(ContextMenu menu) {
4393    }
4394
4395    /**
4396     * Implement this method to handle trackball motion events.  The
4397     * <em>relative</em> movement of the trackball since the last event
4398     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
4399     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
4400     * that a movement of 1 corresponds to the user pressing one DPAD key (so
4401     * they will often be fractional values, representing the more fine-grained
4402     * movement information available from a trackball).
4403     *
4404     * @param event The motion event.
4405     * @return True if the event was handled, false otherwise.
4406     */
4407    public boolean onTrackballEvent(MotionEvent event) {
4408        return false;
4409    }
4410
4411    /**
4412     * Implement this method to handle touch screen motion events.
4413     *
4414     * @param event The motion event.
4415     * @return True if the event was handled, false otherwise.
4416     */
4417    public boolean onTouchEvent(MotionEvent event) {
4418        final int viewFlags = mViewFlags;
4419
4420        if ((viewFlags & ENABLED_MASK) == DISABLED) {
4421            // A disabled view that is clickable still consumes the touch
4422            // events, it just doesn't respond to them.
4423            return (((viewFlags & CLICKABLE) == CLICKABLE ||
4424                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
4425        }
4426
4427        if (mTouchDelegate != null) {
4428            if (mTouchDelegate.onTouchEvent(event)) {
4429                return true;
4430            }
4431        }
4432
4433        if (((viewFlags & CLICKABLE) == CLICKABLE ||
4434                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
4435            switch (event.getAction()) {
4436                case MotionEvent.ACTION_UP:
4437                    boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
4438                    if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
4439                        // take focus if we don't have it already and we should in
4440                        // touch mode.
4441                        boolean focusTaken = false;
4442                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
4443                            focusTaken = requestFocus();
4444                        }
4445
4446                        if (!mHasPerformedLongPress) {
4447                            // This is a tap, so remove the longpress check
4448                            removeLongPressCallback();
4449
4450                            // Only perform take click actions if we were in the pressed state
4451                            if (!focusTaken) {
4452                                // Use a Runnable and post this rather than calling
4453                                // performClick directly. This lets other visual state
4454                                // of the view update before click actions start.
4455                                if (mPerformClick == null) {
4456                                    mPerformClick = new PerformClick();
4457                                }
4458                                if (!post(mPerformClick)) {
4459                                    performClick();
4460                                }
4461                            }
4462                        }
4463
4464                        if (mUnsetPressedState == null) {
4465                            mUnsetPressedState = new UnsetPressedState();
4466                        }
4467
4468                        if (prepressed) {
4469                            mPrivateFlags |= PRESSED;
4470                            refreshDrawableState();
4471                            postDelayed(mUnsetPressedState,
4472                                    ViewConfiguration.getPressedStateDuration());
4473                        } else if (!post(mUnsetPressedState)) {
4474                            // If the post failed, unpress right now
4475                            mUnsetPressedState.run();
4476                        }
4477                        removeTapCallback();
4478                    }
4479                    break;
4480
4481                case MotionEvent.ACTION_DOWN:
4482                    if (mPendingCheckForTap == null) {
4483                        mPendingCheckForTap = new CheckForTap();
4484                    }
4485                    mPrivateFlags |= PREPRESSED;
4486                    mHasPerformedLongPress = false;
4487                    postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
4488                    break;
4489
4490                case MotionEvent.ACTION_CANCEL:
4491                    mPrivateFlags &= ~PRESSED;
4492                    refreshDrawableState();
4493                    removeTapCallback();
4494                    break;
4495
4496                case MotionEvent.ACTION_MOVE:
4497                    final int x = (int) event.getX();
4498                    final int y = (int) event.getY();
4499
4500                    // Be lenient about moving outside of buttons
4501                    if (!pointInView(x, y, mTouchSlop)) {
4502                        // Outside button
4503                        removeTapCallback();
4504                        if ((mPrivateFlags & PRESSED) != 0) {
4505                            // Remove any future long press/tap checks
4506                            removeLongPressCallback();
4507
4508                            // Need to switch from pressed to not pressed
4509                            mPrivateFlags &= ~PRESSED;
4510                            refreshDrawableState();
4511                        }
4512                    }
4513                    break;
4514            }
4515            return true;
4516        }
4517
4518        return false;
4519    }
4520
4521    /**
4522     * Remove the longpress detection timer.
4523     */
4524    private void removeLongPressCallback() {
4525        if (mPendingCheckForLongPress != null) {
4526          removeCallbacks(mPendingCheckForLongPress);
4527        }
4528    }
4529
4530    /**
4531     * Remove the prepress detection timer.
4532     */
4533    private void removeUnsetPressCallback() {
4534        if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
4535            setPressed(false);
4536            removeCallbacks(mUnsetPressedState);
4537        }
4538    }
4539
4540    /**
4541     * Remove the tap detection timer.
4542     */
4543    private void removeTapCallback() {
4544        if (mPendingCheckForTap != null) {
4545            mPrivateFlags &= ~PREPRESSED;
4546            removeCallbacks(mPendingCheckForTap);
4547        }
4548    }
4549
4550    /**
4551     * Cancels a pending long press.  Your subclass can use this if you
4552     * want the context menu to come up if the user presses and holds
4553     * at the same place, but you don't want it to come up if they press
4554     * and then move around enough to cause scrolling.
4555     */
4556    public void cancelLongPress() {
4557        removeLongPressCallback();
4558
4559        /*
4560         * The prepressed state handled by the tap callback is a display
4561         * construct, but the tap callback will post a long press callback
4562         * less its own timeout. Remove it here.
4563         */
4564        removeTapCallback();
4565    }
4566
4567    /**
4568     * Sets the TouchDelegate for this View.
4569     */
4570    public void setTouchDelegate(TouchDelegate delegate) {
4571        mTouchDelegate = delegate;
4572    }
4573
4574    /**
4575     * Gets the TouchDelegate for this View.
4576     */
4577    public TouchDelegate getTouchDelegate() {
4578        return mTouchDelegate;
4579    }
4580
4581    /**
4582     * Set flags controlling behavior of this view.
4583     *
4584     * @param flags Constant indicating the value which should be set
4585     * @param mask Constant indicating the bit range that should be changed
4586     */
4587    void setFlags(int flags, int mask) {
4588        int old = mViewFlags;
4589        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
4590
4591        int changed = mViewFlags ^ old;
4592        if (changed == 0) {
4593            return;
4594        }
4595        int privateFlags = mPrivateFlags;
4596
4597        /* Check if the FOCUSABLE bit has changed */
4598        if (((changed & FOCUSABLE_MASK) != 0) &&
4599                ((privateFlags & HAS_BOUNDS) !=0)) {
4600            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
4601                    && ((privateFlags & FOCUSED) != 0)) {
4602                /* Give up focus if we are no longer focusable */
4603                clearFocus();
4604            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
4605                    && ((privateFlags & FOCUSED) == 0)) {
4606                /*
4607                 * Tell the view system that we are now available to take focus
4608                 * if no one else already has it.
4609                 */
4610                if (mParent != null) mParent.focusableViewAvailable(this);
4611            }
4612        }
4613
4614        if ((flags & VISIBILITY_MASK) == VISIBLE) {
4615            if ((changed & VISIBILITY_MASK) != 0) {
4616                /*
4617                 * If this view is becoming visible, set the DRAWN flag so that
4618                 * the next invalidate() will not be skipped.
4619                 */
4620                mPrivateFlags |= DRAWN;
4621
4622                needGlobalAttributesUpdate(true);
4623
4624                // a view becoming visible is worth notifying the parent
4625                // about in case nothing has focus.  even if this specific view
4626                // isn't focusable, it may contain something that is, so let
4627                // the root view try to give this focus if nothing else does.
4628                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
4629                    mParent.focusableViewAvailable(this);
4630                }
4631            }
4632        }
4633
4634        /* Check if the GONE bit has changed */
4635        if ((changed & GONE) != 0) {
4636            needGlobalAttributesUpdate(false);
4637            requestLayout();
4638            invalidate();
4639
4640            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
4641                if (hasFocus()) clearFocus();
4642                destroyDrawingCache();
4643            }
4644            if (mAttachInfo != null) {
4645                mAttachInfo.mViewVisibilityChanged = true;
4646            }
4647        }
4648
4649        /* Check if the VISIBLE bit has changed */
4650        if ((changed & INVISIBLE) != 0) {
4651            needGlobalAttributesUpdate(false);
4652            invalidate();
4653
4654            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
4655                // root view becoming invisible shouldn't clear focus
4656                if (getRootView() != this) {
4657                    clearFocus();
4658                }
4659            }
4660            if (mAttachInfo != null) {
4661                mAttachInfo.mViewVisibilityChanged = true;
4662            }
4663        }
4664
4665        if ((changed & VISIBILITY_MASK) != 0) {
4666            dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
4667        }
4668
4669        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
4670            destroyDrawingCache();
4671        }
4672
4673        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
4674            destroyDrawingCache();
4675            mPrivateFlags &= ~DRAWING_CACHE_VALID;
4676        }
4677
4678        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
4679            destroyDrawingCache();
4680            mPrivateFlags &= ~DRAWING_CACHE_VALID;
4681        }
4682
4683        if ((changed & DRAW_MASK) != 0) {
4684            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
4685                if (mBGDrawable != null) {
4686                    mPrivateFlags &= ~SKIP_DRAW;
4687                    mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
4688                } else {
4689                    mPrivateFlags |= SKIP_DRAW;
4690                }
4691            } else {
4692                mPrivateFlags &= ~SKIP_DRAW;
4693            }
4694            requestLayout();
4695            invalidate();
4696        }
4697
4698        if ((changed & KEEP_SCREEN_ON) != 0) {
4699            if (mParent != null) {
4700                mParent.recomputeViewAttributes(this);
4701            }
4702        }
4703    }
4704
4705    /**
4706     * Change the view's z order in the tree, so it's on top of other sibling
4707     * views
4708     */
4709    public void bringToFront() {
4710        if (mParent != null) {
4711            mParent.bringChildToFront(this);
4712        }
4713    }
4714
4715    /**
4716     * This is called in response to an internal scroll in this view (i.e., the
4717     * view scrolled its own contents). This is typically as a result of
4718     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
4719     * called.
4720     *
4721     * @param l Current horizontal scroll origin.
4722     * @param t Current vertical scroll origin.
4723     * @param oldl Previous horizontal scroll origin.
4724     * @param oldt Previous vertical scroll origin.
4725     */
4726    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
4727        mBackgroundSizeChanged = true;
4728
4729        final AttachInfo ai = mAttachInfo;
4730        if (ai != null) {
4731            ai.mViewScrollChanged = true;
4732        }
4733    }
4734
4735    /**
4736     * This is called during layout when the size of this view has changed. If
4737     * you were just added to the view hierarchy, you're called with the old
4738     * values of 0.
4739     *
4740     * @param w Current width of this view.
4741     * @param h Current height of this view.
4742     * @param oldw Old width of this view.
4743     * @param oldh Old height of this view.
4744     */
4745    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
4746    }
4747
4748    /**
4749     * Called by draw to draw the child views. This may be overridden
4750     * by derived classes to gain control just before its children are drawn
4751     * (but after its own view has been drawn).
4752     * @param canvas the canvas on which to draw the view
4753     */
4754    protected void dispatchDraw(Canvas canvas) {
4755    }
4756
4757    /**
4758     * Gets the parent of this view. Note that the parent is a
4759     * ViewParent and not necessarily a View.
4760     *
4761     * @return Parent of this view.
4762     */
4763    public final ViewParent getParent() {
4764        return mParent;
4765    }
4766
4767    /**
4768     * Return the scrolled left position of this view. This is the left edge of
4769     * the displayed part of your view. You do not need to draw any pixels
4770     * farther left, since those are outside of the frame of your view on
4771     * screen.
4772     *
4773     * @return The left edge of the displayed part of your view, in pixels.
4774     */
4775    public final int getScrollX() {
4776        return mScrollX;
4777    }
4778
4779    /**
4780     * Return the scrolled top position of this view. This is the top edge of
4781     * the displayed part of your view. You do not need to draw any pixels above
4782     * it, since those are outside of the frame of your view on screen.
4783     *
4784     * @return The top edge of the displayed part of your view, in pixels.
4785     */
4786    public final int getScrollY() {
4787        return mScrollY;
4788    }
4789
4790    /**
4791     * Return the width of the your view.
4792     *
4793     * @return The width of your view, in pixels.
4794     */
4795    @ViewDebug.ExportedProperty
4796    public final int getWidth() {
4797        return mRight - mLeft;
4798    }
4799
4800    /**
4801     * Return the height of your view.
4802     *
4803     * @return The height of your view, in pixels.
4804     */
4805    @ViewDebug.ExportedProperty
4806    public final int getHeight() {
4807        return mBottom - mTop;
4808    }
4809
4810    /**
4811     * Return the visible drawing bounds of your view. Fills in the output
4812     * rectangle with the values from getScrollX(), getScrollY(),
4813     * getWidth(), and getHeight().
4814     *
4815     * @param outRect The (scrolled) drawing bounds of the view.
4816     */
4817    public void getDrawingRect(Rect outRect) {
4818        outRect.left = mScrollX;
4819        outRect.top = mScrollY;
4820        outRect.right = mScrollX + (mRight - mLeft);
4821        outRect.bottom = mScrollY + (mBottom - mTop);
4822    }
4823
4824    /**
4825     * The width of this view as measured in the most recent call to measure().
4826     * This should be used during measurement and layout calculations only. Use
4827     * {@link #getWidth()} to see how wide a view is after layout.
4828     *
4829     * @return The measured width of this view.
4830     */
4831    public final int getMeasuredWidth() {
4832        return mMeasuredWidth;
4833    }
4834
4835    /**
4836     * The height of this view as measured in the most recent call to measure().
4837     * This should be used during measurement and layout calculations only. Use
4838     * {@link #getHeight()} to see how tall a view is after layout.
4839     *
4840     * @return The measured height of this view.
4841     */
4842    public final int getMeasuredHeight() {
4843        return mMeasuredHeight;
4844    }
4845
4846    /**
4847     * The transform matrix of this view, which is calculated based on the current
4848     * roation, scale, and pivot properties.
4849     *
4850     * @see #getRotation()
4851     * @see #getScaleX()
4852     * @see #getScaleY()
4853     * @see #getPivotX()
4854     * @see #getPivotY()
4855     * @return The current transform matrix for the view
4856     */
4857    public Matrix getMatrix() {
4858        hasIdentityMatrix();
4859        return mMatrix;
4860    }
4861
4862    /**
4863     * Recomputes the transform matrix if necessary.
4864     *
4865     * @return True if the transform matrix is the identity matrix, false otherwise.
4866     */
4867    boolean hasIdentityMatrix() {
4868        if (mMatrixDirty) {
4869            // transform-related properties have changed since the last time someone
4870            // asked for the matrix; recalculate it with the current values
4871            mMatrix.reset();
4872            mMatrix.setRotate(mRotation, mPivotX, mPivotY);
4873            mMatrix.preScale(mScaleX, mScaleY, mPivotX, mPivotY);
4874            mMatrixDirty = false;
4875            mMatrixIsIdentity = mMatrix.isIdentity();
4876            mInverseMatrixDirty = true;
4877        }
4878        return mMatrixIsIdentity;
4879    }
4880
4881    /**
4882     * Utility method to retrieve the inverse of the current mMatrix property.
4883     * We cache the matrix to avoid recalculating it when transform properties
4884     * have not changed.
4885     *
4886     * @return The inverse of the current matrix of this view.
4887     */
4888    Matrix getInverseMatrix() {
4889        if (mInverseMatrixDirty) {
4890            if (mInverseMatrix == null) {
4891                mInverseMatrix = new Matrix();
4892            }
4893            mMatrix.invert(mInverseMatrix);
4894            mInverseMatrixDirty = false;
4895        }
4896        return mInverseMatrix;
4897    }
4898
4899    /**
4900     * The degrees that the view is rotated around the pivot point.
4901     *
4902     * @see #getPivotX()
4903     * @see #getPivotY()
4904     * @return The degrees of rotation.
4905     */
4906    public float getRotation() {
4907        return mRotation;
4908    }
4909
4910    /**
4911     * Sets the degrees that the view is rotated around the pivot point.
4912     *
4913     * @param rotation The degrees of rotation.
4914     * @see #getPivotX()
4915     * @see #getPivotY()
4916     */
4917    public void setRotation(float rotation) {
4918        if (mRotation != rotation) {
4919            // Double-invalidation is necessary to capture view's old and new areas
4920            invalidate();
4921            mRotation = rotation;
4922            mMatrixDirty = true;
4923            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
4924            invalidate();
4925        }
4926    }
4927
4928    /**
4929     * The amount that the view is scaled in x around the pivot point, as a proportion of
4930     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
4931     *
4932     * @default 1.0f
4933     * @see #getPivotX()
4934     * @see #getPivotY()
4935     * @return The scaling factor.
4936     */
4937    public float getScaleX() {
4938        return mScaleX;
4939    }
4940
4941    /**
4942     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
4943     * the view's unscaled width. A value of 1 means that no scaling is applied.
4944     *
4945     * @param scaleX The scaling factor.
4946     * @see #getPivotX()
4947     * @see #getPivotY()
4948     */
4949    public void setScaleX(float scaleX) {
4950        if (mScaleX != scaleX) {
4951            // Double-invalidation is necessary to capture view's old and new areas
4952            invalidate();
4953            mScaleX = scaleX;
4954            mMatrixDirty = true;
4955            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
4956            invalidate();
4957        }
4958    }
4959
4960    /**
4961     * The amount that the view is scaled in y around the pivot point, as a proportion of
4962     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
4963     *
4964     * @default 1.0f
4965     * @see #getPivotX()
4966     * @see #getPivotY()
4967     * @return The scaling factor.
4968     */
4969    public float getScaleY() {
4970        return mScaleY;
4971    }
4972
4973    /**
4974     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
4975     * the view's unscaled width. A value of 1 means that no scaling is applied.
4976     *
4977     * @param scaleY The scaling factor.
4978     * @see #getPivotX()
4979     * @see #getPivotY()
4980     */
4981    public void setScaleY(float scaleY) {
4982        if (mScaleY != scaleY) {
4983            // Double-invalidation is necessary to capture view's old and new areas
4984            invalidate();
4985            mScaleY = scaleY;
4986            mMatrixDirty = true;
4987            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
4988            invalidate();
4989        }
4990    }
4991
4992    /**
4993     * The x location of the point around which the view is {@link #setRotation(float) rotated}
4994     * and {@link #setScaleX(float) scaled}.
4995     *
4996     * @see #getRotation()
4997     * @see #getScaleX()
4998     * @see #getScaleY()
4999     * @see #getPivotY()
5000     * @return The x location of the pivot point.
5001     */
5002    public float getPivotX() {
5003        return mPivotX;
5004    }
5005
5006    /**
5007     * Sets the x location of the point around which the view is
5008     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
5009     *
5010     * @param pivotX The x location of the pivot point.
5011     * @see #getRotation()
5012     * @see #getScaleX()
5013     * @see #getScaleY()
5014     * @see #getPivotY()
5015     */
5016    public void setPivotX(float pivotX) {
5017        if (mPivotX != pivotX) {
5018            // Double-invalidation is necessary to capture view's old and new areas
5019            invalidate();
5020            mPivotX = pivotX;
5021            mMatrixDirty = true;
5022            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
5023            invalidate();
5024        }
5025    }
5026
5027    /**
5028     * The y location of the point around which the view is {@link #setRotation(float) rotated}
5029     * and {@link #setScaleY(float) scaled}.
5030     *
5031     * @see #getRotation()
5032     * @see #getScaleX()
5033     * @see #getScaleY()
5034     * @see #getPivotY()
5035     * @return The y location of the pivot point.
5036     */
5037    public float getPivotY() {
5038        return mPivotY;
5039    }
5040
5041    /**
5042     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
5043     * and {@link #setScaleY(float) scaled}.
5044     *
5045     * @param pivotY The y location of the pivot point.
5046     * @see #getRotation()
5047     * @see #getScaleX()
5048     * @see #getScaleY()
5049     * @see #getPivotY()
5050     */
5051    public void setPivotY(float pivotY) {
5052        if (mPivotY != pivotY) {
5053            // Double-invalidation is necessary to capture view's old and new areas
5054            invalidate();
5055            mPivotY = pivotY;
5056            mMatrixDirty = true;
5057            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
5058            invalidate();
5059        }
5060    }
5061
5062    /**
5063     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
5064     * completely transparent and 1 means the view is completely opaque.
5065     *
5066     * @default 1.0f
5067     * @return The opacity of the view.
5068     */
5069    public float getAlpha() {
5070        return mAlpha;
5071    }
5072
5073    /**
5074     * Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
5075     * completely transparent and 1 means the view is completely opaque.
5076     *
5077     * @param alpha The opacity of the view.
5078     */
5079    public void setAlpha(float alpha) {
5080        mAlpha = alpha;
5081        invalidate();
5082    }
5083
5084    /**
5085     * Top position of this view relative to its parent.
5086     *
5087     * @return The top of this view, in pixels.
5088     */
5089    @ViewDebug.CapturedViewProperty
5090    public final int getTop() {
5091        return mTop;
5092    }
5093
5094    /**
5095     * Sets the top position of this view relative to its parent.
5096     *
5097     * @param top The top of this view, in pixels.
5098     */
5099    public final void setTop(int top) {
5100        if (top != mTop) {
5101            if (hasIdentityMatrix()) {
5102                final ViewParent p = mParent;
5103                if (p != null && mAttachInfo != null) {
5104                    final int[] location = mAttachInfo.mInvalidateChildLocation;
5105                    final Rect r = mAttachInfo.mTmpInvalRect;
5106                    int minTop = Math.min(mTop, top);
5107                    location[0] = mLeft;
5108                    location[1] = minTop;
5109                    r.set(0, 0, mRight - mLeft, mBottom - minTop);
5110                    p.invalidateChildInParent(location, r);
5111                }
5112            } else {
5113                // Double-invalidation is necessary to capture view's old and new areas
5114                invalidate();
5115            }
5116
5117            mTop = top;
5118
5119            if (!mMatrixIsIdentity) {
5120                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
5121                invalidate();
5122            }
5123        }
5124    }
5125
5126    /**
5127     * Bottom position of this view relative to its parent.
5128     *
5129     * @return The bottom of this view, in pixels.
5130     */
5131    @ViewDebug.CapturedViewProperty
5132    public final int getBottom() {
5133        return mBottom;
5134    }
5135
5136    /**
5137     * Sets the bottom position of this view relative to its parent.
5138     *
5139     * @param bottom The bottom of this view, in pixels.
5140     */
5141    public final void setBottom(int bottom) {
5142        if (bottom != mBottom) {
5143            if (hasIdentityMatrix()) {
5144                final ViewParent p = mParent;
5145                if (p != null && mAttachInfo != null) {
5146                    final int[] location = mAttachInfo.mInvalidateChildLocation;
5147                    final Rect r = mAttachInfo.mTmpInvalRect;
5148                    int maxBottom = Math.max(mBottom, bottom);
5149                    location[0] = mLeft;
5150                    location[1] = mTop;
5151                    r.set(0, 0, mRight - mLeft, maxBottom - mTop);
5152                    p.invalidateChildInParent(location, r);
5153                }
5154            } else {
5155                // Double-invalidation is necessary to capture view's old and new areas
5156                invalidate();
5157            }
5158
5159            mBottom = bottom;
5160
5161            if (!mMatrixIsIdentity) {
5162                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
5163                invalidate();
5164            }
5165        }
5166    }
5167
5168    /**
5169     * Left position of this view relative to its parent.
5170     *
5171     * @return The left edge of this view, in pixels.
5172     */
5173    @ViewDebug.CapturedViewProperty
5174    public final int getLeft() {
5175        return mLeft;
5176    }
5177
5178    /**
5179     * Sets the left position of this view relative to its parent.
5180     *
5181     * @param left The bottom of this view, in pixels.
5182     */
5183    public final void setLeft(int left) {
5184        if (left != mLeft) {
5185            if (hasIdentityMatrix()) {
5186                final ViewParent p = mParent;
5187                if (p != null && mAttachInfo != null) {
5188                    final int[] location = mAttachInfo.mInvalidateChildLocation;
5189                    final Rect r = mAttachInfo.mTmpInvalRect;
5190                    int minLeft = Math.min(mLeft, left);
5191                    location[0] = minLeft;
5192                    location[1] = mTop;
5193                    r.set(0, 0, mRight - minLeft, mBottom - mTop);
5194                    p.invalidateChildInParent(location, r);
5195                }
5196            } else {
5197                // Double-invalidation is necessary to capture view's old and new areas
5198                invalidate();
5199            }
5200
5201            mLeft = left;
5202
5203            if (!mMatrixIsIdentity) {
5204                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
5205                invalidate();
5206            }
5207        }
5208    }
5209
5210    /**
5211     * Right position of this view relative to its parent.
5212     *
5213     * @return The right edge of this view, in pixels.
5214     */
5215    @ViewDebug.CapturedViewProperty
5216    public final int getRight() {
5217        return mRight;
5218    }
5219
5220    /**
5221     * Sets the right position of this view relative to its parent.
5222     *
5223     * @param right The bottom of this view, in pixels.
5224     */
5225    public final void setRight(int right) {
5226        if (right != mRight) {
5227            if (hasIdentityMatrix()) {
5228                final ViewParent p = mParent;
5229                if (p != null && mAttachInfo != null) {
5230                    final int[] location = mAttachInfo.mInvalidateChildLocation;
5231                    final Rect r = mAttachInfo.mTmpInvalRect;
5232                    int maxRight = Math.max(mRight, right);
5233                    location[0] = mLeft;
5234                    location[1] = mTop;
5235                    r.set(0, 0, maxRight - mLeft, mBottom - mTop);
5236                    p.invalidateChildInParent(location, r);
5237                }
5238            } else {
5239                // Double-invalidation is necessary to capture view's old and new areas
5240                invalidate();
5241            }
5242
5243            mRight = right;
5244
5245            if (!mMatrixIsIdentity) {
5246                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
5247                invalidate();
5248            }
5249        }
5250    }
5251
5252    /**
5253     * The horizontal location of this view relative to its parent. This value is equivalent to the
5254     * {@link #getLeft() left} property.
5255     *
5256     * @return The horizontal position of this view, in pixels.
5257     */
5258    public int getX() {
5259        return mLeft;
5260    }
5261
5262    /**
5263     * Sets the horizontal location of this view relative to its parent. Setting this value will
5264     * affect both the {@link #setLeft(int) left} and {@link #setRight(int) right} properties
5265     * of this view.
5266     *
5267     * @param x The horizontal position of this view, in pixels.
5268     */
5269    public void setX(int x) {
5270        offsetLeftAndRight(x - mLeft);
5271    }
5272
5273    /**
5274     * The vertical location of this view relative to its parent. This value is equivalent to the
5275     * {@link #getTop() left} property.
5276     *
5277     * @return The vertical position of this view, in pixels.
5278     */
5279    public int getY() {
5280        return mTop;
5281    }
5282
5283    /**
5284     * Sets the vertical location of this view relative to its parent. Setting this value will
5285     * affect both the {@link #setTop(int) left} and {@link #setBottom(int) right} properties
5286     * of this view.
5287     *
5288     * @param y The vertical position of this view, in pixels.
5289     */
5290    public void setY(int y) {
5291        offsetTopAndBottom(y - mTop);
5292    }
5293
5294    /**
5295     * Hit rectangle in parent's coordinates
5296     *
5297     * @param outRect The hit rectangle of the view.
5298     */
5299    public void getHitRect(Rect outRect) {
5300        if (hasIdentityMatrix() || mAttachInfo == null) {
5301            outRect.set(mLeft, mTop, mRight, mBottom);
5302        } else {
5303            Matrix m = getMatrix();
5304            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
5305            tmpRect.set(-mPivotX, -mPivotY, getWidth() - mPivotX, getHeight() - mPivotY);
5306            m.mapRect(tmpRect);
5307            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
5308                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
5309        }
5310    }
5311
5312    /**
5313     * This method detects whether the given event is inside the view and, if so,
5314     * handles it via the dispatchEvent(MotionEvent) method.
5315     *
5316     * @param ev The event that is being dispatched.
5317     * @param parentX The x location of the event in the parent's coordinates.
5318     * @param parentY The y location of the event in the parent's coordinates.
5319     * @return true if the event was inside this view, false otherwise.
5320     */
5321    boolean dispatchTouchEvent(MotionEvent ev, float parentX, float parentY) {
5322        float localX = parentX - mLeft;
5323        float localY = parentY - mTop;
5324        if (!hasIdentityMatrix() && mAttachInfo != null) {
5325            // non-identity matrix: transform the point into the view's coordinates
5326            final float[] localXY = mAttachInfo.mTmpTransformLocation;
5327            localXY[0] = localX;
5328            localXY[1] = localY;
5329            getInverseMatrix().mapPoints(localXY);
5330            localX = localXY[0];
5331            localY = localXY[1];
5332        }
5333        if (localX >= 0 && localY >= 0 && localX < (mRight - mLeft) && localY < (mBottom - mTop)) {
5334            // It would be safer to clone the event here but we don't for performance.
5335            // There are many subtle interactions in touch event dispatch; change at your own risk.
5336            mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
5337            ev.setLocation(localX, localY);
5338            return dispatchTouchEvent(ev);
5339        }
5340        return false;
5341    }
5342
5343    /**
5344     * Utility method to determine whether the given point, in local coordinates,
5345     * is inside the view, where the area of the view is expanded by the slop factor.
5346     * This method is called while processing touch-move events to determine if the event
5347     * is still within the view.
5348     */
5349    private boolean pointInView(float localX, float localY, float slop) {
5350        if (!hasIdentityMatrix() && mAttachInfo != null) {
5351            // non-identity matrix: transform the point into the view's coordinates
5352            final float[] localXY = mAttachInfo.mTmpTransformLocation;
5353            localXY[0] = localX;
5354            localXY[1] = localY;
5355            getInverseMatrix().mapPoints(localXY);
5356            localX = localXY[0];
5357            localY = localXY[1];
5358        }
5359        return localX > -slop && localY > -slop && localX < ((mRight - mLeft) + slop) &&
5360                localY < ((mBottom - mTop) + slop);
5361    }
5362
5363    /**
5364     * When a view has focus and the user navigates away from it, the next view is searched for
5365     * starting from the rectangle filled in by this method.
5366     *
5367     * By default, the rectange is the {@link #getDrawingRect})of the view.  However, if your
5368     * view maintains some idea of internal selection, such as a cursor, or a selected row
5369     * or column, you should override this method and fill in a more specific rectangle.
5370     *
5371     * @param r The rectangle to fill in, in this view's coordinates.
5372     */
5373    public void getFocusedRect(Rect r) {
5374        getDrawingRect(r);
5375    }
5376
5377    /**
5378     * If some part of this view is not clipped by any of its parents, then
5379     * return that area in r in global (root) coordinates. To convert r to local
5380     * coordinates, offset it by -globalOffset (e.g. r.offset(-globalOffset.x,
5381     * -globalOffset.y)) If the view is completely clipped or translated out,
5382     * return false.
5383     *
5384     * @param r If true is returned, r holds the global coordinates of the
5385     *        visible portion of this view.
5386     * @param globalOffset If true is returned, globalOffset holds the dx,dy
5387     *        between this view and its root. globalOffet may be null.
5388     * @return true if r is non-empty (i.e. part of the view is visible at the
5389     *         root level.
5390     */
5391    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
5392        int width = mRight - mLeft;
5393        int height = mBottom - mTop;
5394        if (width > 0 && height > 0) {
5395            r.set(0, 0, width, height);
5396            if (globalOffset != null) {
5397                globalOffset.set(-mScrollX, -mScrollY);
5398            }
5399            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
5400        }
5401        return false;
5402    }
5403
5404    public final boolean getGlobalVisibleRect(Rect r) {
5405        return getGlobalVisibleRect(r, null);
5406    }
5407
5408    public final boolean getLocalVisibleRect(Rect r) {
5409        Point offset = new Point();
5410        if (getGlobalVisibleRect(r, offset)) {
5411            r.offset(-offset.x, -offset.y); // make r local
5412            return true;
5413        }
5414        return false;
5415    }
5416
5417    /**
5418     * Offset this view's vertical location by the specified number of pixels.
5419     *
5420     * @param offset the number of pixels to offset the view by
5421     */
5422    public void offsetTopAndBottom(int offset) {
5423        if (offset != 0) {
5424            if (hasIdentityMatrix()) {
5425                final ViewParent p = mParent;
5426                if (p != null && mAttachInfo != null) {
5427                    final int[] location = mAttachInfo.mInvalidateChildLocation;
5428                    final Rect r = mAttachInfo.mTmpInvalRect;
5429                    int minTop = offset < 0 ? mTop + offset : mTop;
5430                    int maxBottom = offset < 0 ? mBottom : mBottom + offset;
5431                    location[0] = mLeft;
5432                    location[1] = minTop;
5433                    r.set(0, 0, mRight - mLeft, maxBottom - minTop);
5434                    p.invalidateChildInParent(location, r);
5435                }
5436            } else {
5437                invalidate();
5438            }
5439
5440            mTop += offset;
5441            mBottom += offset;
5442
5443            if (!mMatrixIsIdentity) {
5444                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
5445                invalidate();
5446            }
5447        }
5448    }
5449
5450    /**
5451     * Offset this view's horizontal location by the specified amount of pixels.
5452     *
5453     * @param offset the numer of pixels to offset the view by
5454     */
5455    public void offsetLeftAndRight(int offset) {
5456        if (offset != 0) {
5457            if (hasIdentityMatrix()) {
5458                final ViewParent p = mParent;
5459                if (p != null && mAttachInfo != null) {
5460                    final int[] location = mAttachInfo.mInvalidateChildLocation;
5461                    final Rect r = mAttachInfo.mTmpInvalRect;
5462                    int minLeft = offset < 0 ? mLeft + offset : mLeft;
5463                    int maxRight = offset < 0 ? mRight : mRight + offset;
5464                    location[0] = minLeft;
5465                    location[1] = mTop;
5466                    r.set(0, 0, maxRight - minLeft, mBottom - mTop);
5467                    p.invalidateChildInParent(location, r);
5468                }
5469            } else {
5470                invalidate();
5471            }
5472
5473            mLeft += offset;
5474            mRight += offset;
5475
5476            if (!mMatrixIsIdentity) {
5477                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
5478                invalidate();
5479            }
5480        }
5481    }
5482
5483    /**
5484     * Get the LayoutParams associated with this view. All views should have
5485     * layout parameters. These supply parameters to the <i>parent</i> of this
5486     * view specifying how it should be arranged. There are many subclasses of
5487     * ViewGroup.LayoutParams, and these correspond to the different subclasses
5488     * of ViewGroup that are responsible for arranging their children.
5489     * @return The LayoutParams associated with this view
5490     */
5491    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
5492    public ViewGroup.LayoutParams getLayoutParams() {
5493        return mLayoutParams;
5494    }
5495
5496    /**
5497     * Set the layout parameters associated with this view. These supply
5498     * parameters to the <i>parent</i> of this view specifying how it should be
5499     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
5500     * correspond to the different subclasses of ViewGroup that are responsible
5501     * for arranging their children.
5502     *
5503     * @param params the layout parameters for this view
5504     */
5505    public void setLayoutParams(ViewGroup.LayoutParams params) {
5506        if (params == null) {
5507            throw new NullPointerException("params == null");
5508        }
5509        mLayoutParams = params;
5510        requestLayout();
5511    }
5512
5513    /**
5514     * Set the scrolled position of your view. This will cause a call to
5515     * {@link #onScrollChanged(int, int, int, int)} and the view will be
5516     * invalidated.
5517     * @param x the x position to scroll to
5518     * @param y the y position to scroll to
5519     */
5520    public void scrollTo(int x, int y) {
5521        if (mScrollX != x || mScrollY != y) {
5522            int oldX = mScrollX;
5523            int oldY = mScrollY;
5524            mScrollX = x;
5525            mScrollY = y;
5526            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
5527            if (!awakenScrollBars()) {
5528                invalidate();
5529            }
5530        }
5531    }
5532
5533    /**
5534     * Move the scrolled position of your view. This will cause a call to
5535     * {@link #onScrollChanged(int, int, int, int)} and the view will be
5536     * invalidated.
5537     * @param x the amount of pixels to scroll by horizontally
5538     * @param y the amount of pixels to scroll by vertically
5539     */
5540    public void scrollBy(int x, int y) {
5541        scrollTo(mScrollX + x, mScrollY + y);
5542    }
5543
5544    /**
5545     * <p>Trigger the scrollbars to draw. When invoked this method starts an
5546     * animation to fade the scrollbars out after a default delay. If a subclass
5547     * provides animated scrolling, the start delay should equal the duration
5548     * of the scrolling animation.</p>
5549     *
5550     * <p>The animation starts only if at least one of the scrollbars is
5551     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
5552     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
5553     * this method returns true, and false otherwise. If the animation is
5554     * started, this method calls {@link #invalidate()}; in that case the
5555     * caller should not call {@link #invalidate()}.</p>
5556     *
5557     * <p>This method should be invoked every time a subclass directly updates
5558     * the scroll parameters.</p>
5559     *
5560     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
5561     * and {@link #scrollTo(int, int)}.</p>
5562     *
5563     * @return true if the animation is played, false otherwise
5564     *
5565     * @see #awakenScrollBars(int)
5566     * @see #scrollBy(int, int)
5567     * @see #scrollTo(int, int)
5568     * @see #isHorizontalScrollBarEnabled()
5569     * @see #isVerticalScrollBarEnabled()
5570     * @see #setHorizontalScrollBarEnabled(boolean)
5571     * @see #setVerticalScrollBarEnabled(boolean)
5572     */
5573    protected boolean awakenScrollBars() {
5574        return mScrollCache != null &&
5575                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
5576    }
5577
5578    /**
5579     * Trigger the scrollbars to draw.
5580     * This method differs from awakenScrollBars() only in its default duration.
5581     * initialAwakenScrollBars() will show the scroll bars for longer than
5582     * usual to give the user more of a chance to notice them.
5583     *
5584     * @return true if the animation is played, false otherwise.
5585     */
5586    private boolean initialAwakenScrollBars() {
5587        return mScrollCache != null &&
5588                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
5589    }
5590
5591    /**
5592     * <p>
5593     * Trigger the scrollbars to draw. When invoked this method starts an
5594     * animation to fade the scrollbars out after a fixed delay. If a subclass
5595     * provides animated scrolling, the start delay should equal the duration of
5596     * the scrolling animation.
5597     * </p>
5598     *
5599     * <p>
5600     * The animation starts only if at least one of the scrollbars is enabled,
5601     * as specified by {@link #isHorizontalScrollBarEnabled()} and
5602     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
5603     * this method returns true, and false otherwise. If the animation is
5604     * started, this method calls {@link #invalidate()}; in that case the caller
5605     * should not call {@link #invalidate()}.
5606     * </p>
5607     *
5608     * <p>
5609     * This method should be invoked everytime a subclass directly updates the
5610     * scroll parameters.
5611     * </p>
5612     *
5613     * @param startDelay the delay, in milliseconds, after which the animation
5614     *        should start; when the delay is 0, the animation starts
5615     *        immediately
5616     * @return true if the animation is played, false otherwise
5617     *
5618     * @see #scrollBy(int, int)
5619     * @see #scrollTo(int, int)
5620     * @see #isHorizontalScrollBarEnabled()
5621     * @see #isVerticalScrollBarEnabled()
5622     * @see #setHorizontalScrollBarEnabled(boolean)
5623     * @see #setVerticalScrollBarEnabled(boolean)
5624     */
5625    protected boolean awakenScrollBars(int startDelay) {
5626        return awakenScrollBars(startDelay, true);
5627    }
5628
5629    /**
5630     * <p>
5631     * Trigger the scrollbars to draw. When invoked this method starts an
5632     * animation to fade the scrollbars out after a fixed delay. If a subclass
5633     * provides animated scrolling, the start delay should equal the duration of
5634     * the scrolling animation.
5635     * </p>
5636     *
5637     * <p>
5638     * The animation starts only if at least one of the scrollbars is enabled,
5639     * as specified by {@link #isHorizontalScrollBarEnabled()} and
5640     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
5641     * this method returns true, and false otherwise. If the animation is
5642     * started, this method calls {@link #invalidate()} if the invalidate parameter
5643     * is set to true; in that case the caller
5644     * should not call {@link #invalidate()}.
5645     * </p>
5646     *
5647     * <p>
5648     * This method should be invoked everytime a subclass directly updates the
5649     * scroll parameters.
5650     * </p>
5651     *
5652     * @param startDelay the delay, in milliseconds, after which the animation
5653     *        should start; when the delay is 0, the animation starts
5654     *        immediately
5655     *
5656     * @param invalidate Wheter this method should call invalidate
5657     *
5658     * @return true if the animation is played, false otherwise
5659     *
5660     * @see #scrollBy(int, int)
5661     * @see #scrollTo(int, int)
5662     * @see #isHorizontalScrollBarEnabled()
5663     * @see #isVerticalScrollBarEnabled()
5664     * @see #setHorizontalScrollBarEnabled(boolean)
5665     * @see #setVerticalScrollBarEnabled(boolean)
5666     */
5667    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
5668        final ScrollabilityCache scrollCache = mScrollCache;
5669
5670        if (scrollCache == null || !scrollCache.fadeScrollBars) {
5671            return false;
5672        }
5673
5674        if (scrollCache.scrollBar == null) {
5675            scrollCache.scrollBar = new ScrollBarDrawable();
5676        }
5677
5678        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
5679
5680            if (invalidate) {
5681                // Invalidate to show the scrollbars
5682                invalidate();
5683            }
5684
5685            if (scrollCache.state == ScrollabilityCache.OFF) {
5686                // FIXME: this is copied from WindowManagerService.
5687                // We should get this value from the system when it
5688                // is possible to do so.
5689                final int KEY_REPEAT_FIRST_DELAY = 750;
5690                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
5691            }
5692
5693            // Tell mScrollCache when we should start fading. This may
5694            // extend the fade start time if one was already scheduled
5695            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
5696            scrollCache.fadeStartTime = fadeStartTime;
5697            scrollCache.state = ScrollabilityCache.ON;
5698
5699            // Schedule our fader to run, unscheduling any old ones first
5700            if (mAttachInfo != null) {
5701                mAttachInfo.mHandler.removeCallbacks(scrollCache);
5702                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
5703            }
5704
5705            return true;
5706        }
5707
5708        return false;
5709    }
5710
5711    /**
5712     * Mark the the area defined by dirty as needing to be drawn. If the view is
5713     * visible, {@link #onDraw} will be called at some point in the future.
5714     * This must be called from a UI thread. To call from a non-UI thread, call
5715     * {@link #postInvalidate()}.
5716     *
5717     * WARNING: This method is destructive to dirty.
5718     * @param dirty the rectangle representing the bounds of the dirty region
5719     */
5720    public void invalidate(Rect dirty) {
5721        if (ViewDebug.TRACE_HIERARCHY) {
5722            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
5723        }
5724
5725        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
5726            mPrivateFlags &= ~DRAWING_CACHE_VALID;
5727            final ViewParent p = mParent;
5728            final AttachInfo ai = mAttachInfo;
5729            if (p != null && ai != null) {
5730                final int scrollX = mScrollX;
5731                final int scrollY = mScrollY;
5732                final Rect r = ai.mTmpInvalRect;
5733                r.set(dirty.left - scrollX, dirty.top - scrollY,
5734                        dirty.right - scrollX, dirty.bottom - scrollY);
5735                mParent.invalidateChild(this, r);
5736            }
5737        }
5738    }
5739
5740    /**
5741     * Mark the the area defined by the rect (l,t,r,b) as needing to be drawn.
5742     * The coordinates of the dirty rect are relative to the view.
5743     * If the view is visible, {@link #onDraw} will be called at some point
5744     * in the future. This must be called from a UI thread. To call
5745     * from a non-UI thread, call {@link #postInvalidate()}.
5746     * @param l the left position of the dirty region
5747     * @param t the top position of the dirty region
5748     * @param r the right position of the dirty region
5749     * @param b the bottom position of the dirty region
5750     */
5751    public void invalidate(int l, int t, int r, int b) {
5752        if (ViewDebug.TRACE_HIERARCHY) {
5753            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
5754        }
5755
5756        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
5757            mPrivateFlags &= ~DRAWING_CACHE_VALID;
5758            final ViewParent p = mParent;
5759            final AttachInfo ai = mAttachInfo;
5760            if (p != null && ai != null && l < r && t < b) {
5761                final int scrollX = mScrollX;
5762                final int scrollY = mScrollY;
5763                final Rect tmpr = ai.mTmpInvalRect;
5764                tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
5765                p.invalidateChild(this, tmpr);
5766            }
5767        }
5768    }
5769
5770    /**
5771     * Invalidate the whole view. If the view is visible, {@link #onDraw} will
5772     * be called at some point in the future. This must be called from a
5773     * UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
5774     */
5775    public void invalidate() {
5776        if (ViewDebug.TRACE_HIERARCHY) {
5777            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
5778        }
5779
5780        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {
5781            mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;
5782            final ViewParent p = mParent;
5783            final AttachInfo ai = mAttachInfo;
5784            if (p != null && ai != null) {
5785                final Rect r = ai.mTmpInvalRect;
5786                r.set(0, 0, mRight - mLeft, mBottom - mTop);
5787                // Don't call invalidate -- we don't want to internally scroll
5788                // our own bounds
5789                p.invalidateChild(this, r);
5790            }
5791        }
5792    }
5793
5794    /**
5795     * Indicates whether this View is opaque. An opaque View guarantees that it will
5796     * draw all the pixels overlapping its bounds using a fully opaque color.
5797     *
5798     * Subclasses of View should override this method whenever possible to indicate
5799     * whether an instance is opaque. Opaque Views are treated in a special way by
5800     * the View hierarchy, possibly allowing it to perform optimizations during
5801     * invalidate/draw passes.
5802     *
5803     * @return True if this View is guaranteed to be fully opaque, false otherwise.
5804     */
5805    @ViewDebug.ExportedProperty
5806    public boolean isOpaque() {
5807        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK;
5808    }
5809
5810    private void computeOpaqueFlags() {
5811        // Opaque if:
5812        //   - Has a background
5813        //   - Background is opaque
5814        //   - Doesn't have scrollbars or scrollbars are inside overlay
5815
5816        if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
5817            mPrivateFlags |= OPAQUE_BACKGROUND;
5818        } else {
5819            mPrivateFlags &= ~OPAQUE_BACKGROUND;
5820        }
5821
5822        final int flags = mViewFlags;
5823        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
5824                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
5825            mPrivateFlags |= OPAQUE_SCROLLBARS;
5826        } else {
5827            mPrivateFlags &= ~OPAQUE_SCROLLBARS;
5828        }
5829    }
5830
5831    /**
5832     * @hide
5833     */
5834    protected boolean hasOpaqueScrollbars() {
5835        return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
5836    }
5837
5838    /**
5839     * @return A handler associated with the thread running the View. This
5840     * handler can be used to pump events in the UI events queue.
5841     */
5842    public Handler getHandler() {
5843        if (mAttachInfo != null) {
5844            return mAttachInfo.mHandler;
5845        }
5846        return null;
5847    }
5848
5849    /**
5850     * Causes the Runnable to be added to the message queue.
5851     * The runnable will be run on the user interface thread.
5852     *
5853     * @param action The Runnable that will be executed.
5854     *
5855     * @return Returns true if the Runnable was successfully placed in to the
5856     *         message queue.  Returns false on failure, usually because the
5857     *         looper processing the message queue is exiting.
5858     */
5859    public boolean post(Runnable action) {
5860        Handler handler;
5861        if (mAttachInfo != null) {
5862            handler = mAttachInfo.mHandler;
5863        } else {
5864            // Assume that post will succeed later
5865            ViewRoot.getRunQueue().post(action);
5866            return true;
5867        }
5868
5869        return handler.post(action);
5870    }
5871
5872    /**
5873     * Causes the Runnable to be added to the message queue, to be run
5874     * after the specified amount of time elapses.
5875     * The runnable will be run on the user interface thread.
5876     *
5877     * @param action The Runnable that will be executed.
5878     * @param delayMillis The delay (in milliseconds) until the Runnable
5879     *        will be executed.
5880     *
5881     * @return true if the Runnable was successfully placed in to the
5882     *         message queue.  Returns false on failure, usually because the
5883     *         looper processing the message queue is exiting.  Note that a
5884     *         result of true does not mean the Runnable will be processed --
5885     *         if the looper is quit before the delivery time of the message
5886     *         occurs then the message will be dropped.
5887     */
5888    public boolean postDelayed(Runnable action, long delayMillis) {
5889        Handler handler;
5890        if (mAttachInfo != null) {
5891            handler = mAttachInfo.mHandler;
5892        } else {
5893            // Assume that post will succeed later
5894            ViewRoot.getRunQueue().postDelayed(action, delayMillis);
5895            return true;
5896        }
5897
5898        return handler.postDelayed(action, delayMillis);
5899    }
5900
5901    /**
5902     * Removes the specified Runnable from the message queue.
5903     *
5904     * @param action The Runnable to remove from the message handling queue
5905     *
5906     * @return true if this view could ask the Handler to remove the Runnable,
5907     *         false otherwise. When the returned value is true, the Runnable
5908     *         may or may not have been actually removed from the message queue
5909     *         (for instance, if the Runnable was not in the queue already.)
5910     */
5911    public boolean removeCallbacks(Runnable action) {
5912        Handler handler;
5913        if (mAttachInfo != null) {
5914            handler = mAttachInfo.mHandler;
5915        } else {
5916            // Assume that post will succeed later
5917            ViewRoot.getRunQueue().removeCallbacks(action);
5918            return true;
5919        }
5920
5921        handler.removeCallbacks(action);
5922        return true;
5923    }
5924
5925    /**
5926     * Cause an invalidate to happen on a subsequent cycle through the event loop.
5927     * Use this to invalidate the View from a non-UI thread.
5928     *
5929     * @see #invalidate()
5930     */
5931    public void postInvalidate() {
5932        postInvalidateDelayed(0);
5933    }
5934
5935    /**
5936     * Cause an invalidate of the specified area to happen on a subsequent cycle
5937     * through the event loop. Use this to invalidate the View from a non-UI thread.
5938     *
5939     * @param left The left coordinate of the rectangle to invalidate.
5940     * @param top The top coordinate of the rectangle to invalidate.
5941     * @param right The right coordinate of the rectangle to invalidate.
5942     * @param bottom The bottom coordinate of the rectangle to invalidate.
5943     *
5944     * @see #invalidate(int, int, int, int)
5945     * @see #invalidate(Rect)
5946     */
5947    public void postInvalidate(int left, int top, int right, int bottom) {
5948        postInvalidateDelayed(0, left, top, right, bottom);
5949    }
5950
5951    /**
5952     * Cause an invalidate to happen on a subsequent cycle through the event
5953     * loop. Waits for the specified amount of time.
5954     *
5955     * @param delayMilliseconds the duration in milliseconds to delay the
5956     *         invalidation by
5957     */
5958    public void postInvalidateDelayed(long delayMilliseconds) {
5959        // We try only with the AttachInfo because there's no point in invalidating
5960        // if we are not attached to our window
5961        if (mAttachInfo != null) {
5962            Message msg = Message.obtain();
5963            msg.what = AttachInfo.INVALIDATE_MSG;
5964            msg.obj = this;
5965            mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
5966        }
5967    }
5968
5969    /**
5970     * Cause an invalidate of the specified area to happen on a subsequent cycle
5971     * through the event loop. Waits for the specified amount of time.
5972     *
5973     * @param delayMilliseconds the duration in milliseconds to delay the
5974     *         invalidation by
5975     * @param left The left coordinate of the rectangle to invalidate.
5976     * @param top The top coordinate of the rectangle to invalidate.
5977     * @param right The right coordinate of the rectangle to invalidate.
5978     * @param bottom The bottom coordinate of the rectangle to invalidate.
5979     */
5980    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
5981            int right, int bottom) {
5982
5983        // We try only with the AttachInfo because there's no point in invalidating
5984        // if we are not attached to our window
5985        if (mAttachInfo != null) {
5986            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
5987            info.target = this;
5988            info.left = left;
5989            info.top = top;
5990            info.right = right;
5991            info.bottom = bottom;
5992
5993            final Message msg = Message.obtain();
5994            msg.what = AttachInfo.INVALIDATE_RECT_MSG;
5995            msg.obj = info;
5996            mAttachInfo.mHandler.sendMessageDelayed(msg, delayMilliseconds);
5997        }
5998    }
5999
6000    /**
6001     * Called by a parent to request that a child update its values for mScrollX
6002     * and mScrollY if necessary. This will typically be done if the child is
6003     * animating a scroll using a {@link android.widget.Scroller Scroller}
6004     * object.
6005     */
6006    public void computeScroll() {
6007    }
6008
6009    /**
6010     * <p>Indicate whether the horizontal edges are faded when the view is
6011     * scrolled horizontally.</p>
6012     *
6013     * @return true if the horizontal edges should are faded on scroll, false
6014     *         otherwise
6015     *
6016     * @see #setHorizontalFadingEdgeEnabled(boolean)
6017     * @attr ref android.R.styleable#View_fadingEdge
6018     */
6019    public boolean isHorizontalFadingEdgeEnabled() {
6020        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
6021    }
6022
6023    /**
6024     * <p>Define whether the horizontal edges should be faded when this view
6025     * is scrolled horizontally.</p>
6026     *
6027     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
6028     *                                    be faded when the view is scrolled
6029     *                                    horizontally
6030     *
6031     * @see #isHorizontalFadingEdgeEnabled()
6032     * @attr ref android.R.styleable#View_fadingEdge
6033     */
6034    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
6035        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
6036            if (horizontalFadingEdgeEnabled) {
6037                initScrollCache();
6038            }
6039
6040            mViewFlags ^= FADING_EDGE_HORIZONTAL;
6041        }
6042    }
6043
6044    /**
6045     * <p>Indicate whether the vertical edges are faded when the view is
6046     * scrolled horizontally.</p>
6047     *
6048     * @return true if the vertical edges should are faded on scroll, false
6049     *         otherwise
6050     *
6051     * @see #setVerticalFadingEdgeEnabled(boolean)
6052     * @attr ref android.R.styleable#View_fadingEdge
6053     */
6054    public boolean isVerticalFadingEdgeEnabled() {
6055        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
6056    }
6057
6058    /**
6059     * <p>Define whether the vertical edges should be faded when this view
6060     * is scrolled vertically.</p>
6061     *
6062     * @param verticalFadingEdgeEnabled true if the vertical edges should
6063     *                                  be faded when the view is scrolled
6064     *                                  vertically
6065     *
6066     * @see #isVerticalFadingEdgeEnabled()
6067     * @attr ref android.R.styleable#View_fadingEdge
6068     */
6069    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
6070        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
6071            if (verticalFadingEdgeEnabled) {
6072                initScrollCache();
6073            }
6074
6075            mViewFlags ^= FADING_EDGE_VERTICAL;
6076        }
6077    }
6078
6079    /**
6080     * Returns the strength, or intensity, of the top faded edge. The strength is
6081     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
6082     * returns 0.0 or 1.0 but no value in between.
6083     *
6084     * Subclasses should override this method to provide a smoother fade transition
6085     * when scrolling occurs.
6086     *
6087     * @return the intensity of the top fade as a float between 0.0f and 1.0f
6088     */
6089    protected float getTopFadingEdgeStrength() {
6090        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
6091    }
6092
6093    /**
6094     * Returns the strength, or intensity, of the bottom faded edge. The strength is
6095     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
6096     * returns 0.0 or 1.0 but no value in between.
6097     *
6098     * Subclasses should override this method to provide a smoother fade transition
6099     * when scrolling occurs.
6100     *
6101     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
6102     */
6103    protected float getBottomFadingEdgeStrength() {
6104        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
6105                computeVerticalScrollRange() ? 1.0f : 0.0f;
6106    }
6107
6108    /**
6109     * Returns the strength, or intensity, of the left faded edge. The strength is
6110     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
6111     * returns 0.0 or 1.0 but no value in between.
6112     *
6113     * Subclasses should override this method to provide a smoother fade transition
6114     * when scrolling occurs.
6115     *
6116     * @return the intensity of the left fade as a float between 0.0f and 1.0f
6117     */
6118    protected float getLeftFadingEdgeStrength() {
6119        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
6120    }
6121
6122    /**
6123     * Returns the strength, or intensity, of the right faded edge. The strength is
6124     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
6125     * returns 0.0 or 1.0 but no value in between.
6126     *
6127     * Subclasses should override this method to provide a smoother fade transition
6128     * when scrolling occurs.
6129     *
6130     * @return the intensity of the right fade as a float between 0.0f and 1.0f
6131     */
6132    protected float getRightFadingEdgeStrength() {
6133        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
6134                computeHorizontalScrollRange() ? 1.0f : 0.0f;
6135    }
6136
6137    /**
6138     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
6139     * scrollbar is not drawn by default.</p>
6140     *
6141     * @return true if the horizontal scrollbar should be painted, false
6142     *         otherwise
6143     *
6144     * @see #setHorizontalScrollBarEnabled(boolean)
6145     */
6146    public boolean isHorizontalScrollBarEnabled() {
6147        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
6148    }
6149
6150    /**
6151     * <p>Define whether the horizontal scrollbar should be drawn or not. The
6152     * scrollbar is not drawn by default.</p>
6153     *
6154     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
6155     *                                   be painted
6156     *
6157     * @see #isHorizontalScrollBarEnabled()
6158     */
6159    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
6160        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
6161            mViewFlags ^= SCROLLBARS_HORIZONTAL;
6162            computeOpaqueFlags();
6163            recomputePadding();
6164        }
6165    }
6166
6167    /**
6168     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
6169     * scrollbar is not drawn by default.</p>
6170     *
6171     * @return true if the vertical scrollbar should be painted, false
6172     *         otherwise
6173     *
6174     * @see #setVerticalScrollBarEnabled(boolean)
6175     */
6176    public boolean isVerticalScrollBarEnabled() {
6177        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
6178    }
6179
6180    /**
6181     * <p>Define whether the vertical scrollbar should be drawn or not. The
6182     * scrollbar is not drawn by default.</p>
6183     *
6184     * @param verticalScrollBarEnabled true if the vertical scrollbar should
6185     *                                 be painted
6186     *
6187     * @see #isVerticalScrollBarEnabled()
6188     */
6189    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
6190        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
6191            mViewFlags ^= SCROLLBARS_VERTICAL;
6192            computeOpaqueFlags();
6193            recomputePadding();
6194        }
6195    }
6196
6197    private void recomputePadding() {
6198        setPadding(mPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
6199    }
6200
6201    /**
6202     * Define whether scrollbars will fade when the view is not scrolling.
6203     *
6204     * @param fadeScrollbars wheter to enable fading
6205     *
6206     */
6207    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
6208        initScrollCache();
6209        final ScrollabilityCache scrollabilityCache = mScrollCache;
6210        scrollabilityCache.fadeScrollBars = fadeScrollbars;
6211        if (fadeScrollbars) {
6212            scrollabilityCache.state = ScrollabilityCache.OFF;
6213        } else {
6214            scrollabilityCache.state = ScrollabilityCache.ON;
6215        }
6216    }
6217
6218    /**
6219     *
6220     * Returns true if scrollbars will fade when this view is not scrolling
6221     *
6222     * @return true if scrollbar fading is enabled
6223     */
6224    public boolean isScrollbarFadingEnabled() {
6225        return mScrollCache != null && mScrollCache.fadeScrollBars;
6226    }
6227
6228    /**
6229     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
6230     * inset. When inset, they add to the padding of the view. And the scrollbars
6231     * can be drawn inside the padding area or on the edge of the view. For example,
6232     * if a view has a background drawable and you want to draw the scrollbars
6233     * inside the padding specified by the drawable, you can use
6234     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
6235     * appear at the edge of the view, ignoring the padding, then you can use
6236     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
6237     * @param style the style of the scrollbars. Should be one of
6238     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
6239     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
6240     * @see #SCROLLBARS_INSIDE_OVERLAY
6241     * @see #SCROLLBARS_INSIDE_INSET
6242     * @see #SCROLLBARS_OUTSIDE_OVERLAY
6243     * @see #SCROLLBARS_OUTSIDE_INSET
6244     */
6245    public void setScrollBarStyle(int style) {
6246        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
6247            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
6248            computeOpaqueFlags();
6249            recomputePadding();
6250        }
6251    }
6252
6253    /**
6254     * <p>Returns the current scrollbar style.</p>
6255     * @return the current scrollbar style
6256     * @see #SCROLLBARS_INSIDE_OVERLAY
6257     * @see #SCROLLBARS_INSIDE_INSET
6258     * @see #SCROLLBARS_OUTSIDE_OVERLAY
6259     * @see #SCROLLBARS_OUTSIDE_INSET
6260     */
6261    public int getScrollBarStyle() {
6262        return mViewFlags & SCROLLBARS_STYLE_MASK;
6263    }
6264
6265    /**
6266     * <p>Compute the horizontal range that the horizontal scrollbar
6267     * represents.</p>
6268     *
6269     * <p>The range is expressed in arbitrary units that must be the same as the
6270     * units used by {@link #computeHorizontalScrollExtent()} and
6271     * {@link #computeHorizontalScrollOffset()}.</p>
6272     *
6273     * <p>The default range is the drawing width of this view.</p>
6274     *
6275     * @return the total horizontal range represented by the horizontal
6276     *         scrollbar
6277     *
6278     * @see #computeHorizontalScrollExtent()
6279     * @see #computeHorizontalScrollOffset()
6280     * @see android.widget.ScrollBarDrawable
6281     */
6282    protected int computeHorizontalScrollRange() {
6283        return getWidth();
6284    }
6285
6286    /**
6287     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
6288     * within the horizontal range. This value is used to compute the position
6289     * of the thumb within the scrollbar's track.</p>
6290     *
6291     * <p>The range is expressed in arbitrary units that must be the same as the
6292     * units used by {@link #computeHorizontalScrollRange()} and
6293     * {@link #computeHorizontalScrollExtent()}.</p>
6294     *
6295     * <p>The default offset is the scroll offset of this view.</p>
6296     *
6297     * @return the horizontal offset of the scrollbar's thumb
6298     *
6299     * @see #computeHorizontalScrollRange()
6300     * @see #computeHorizontalScrollExtent()
6301     * @see android.widget.ScrollBarDrawable
6302     */
6303    protected int computeHorizontalScrollOffset() {
6304        return mScrollX;
6305    }
6306
6307    /**
6308     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
6309     * within the horizontal range. This value is used to compute the length
6310     * of the thumb within the scrollbar's track.</p>
6311     *
6312     * <p>The range is expressed in arbitrary units that must be the same as the
6313     * units used by {@link #computeHorizontalScrollRange()} and
6314     * {@link #computeHorizontalScrollOffset()}.</p>
6315     *
6316     * <p>The default extent is the drawing width of this view.</p>
6317     *
6318     * @return the horizontal extent of the scrollbar's thumb
6319     *
6320     * @see #computeHorizontalScrollRange()
6321     * @see #computeHorizontalScrollOffset()
6322     * @see android.widget.ScrollBarDrawable
6323     */
6324    protected int computeHorizontalScrollExtent() {
6325        return getWidth();
6326    }
6327
6328    /**
6329     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
6330     *
6331     * <p>The range is expressed in arbitrary units that must be the same as the
6332     * units used by {@link #computeVerticalScrollExtent()} and
6333     * {@link #computeVerticalScrollOffset()}.</p>
6334     *
6335     * @return the total vertical range represented by the vertical scrollbar
6336     *
6337     * <p>The default range is the drawing height of this view.</p>
6338     *
6339     * @see #computeVerticalScrollExtent()
6340     * @see #computeVerticalScrollOffset()
6341     * @see android.widget.ScrollBarDrawable
6342     */
6343    protected int computeVerticalScrollRange() {
6344        return getHeight();
6345    }
6346
6347    /**
6348     * <p>Compute the vertical offset of the vertical scrollbar's thumb
6349     * within the horizontal range. This value is used to compute the position
6350     * of the thumb within the scrollbar's track.</p>
6351     *
6352     * <p>The range is expressed in arbitrary units that must be the same as the
6353     * units used by {@link #computeVerticalScrollRange()} and
6354     * {@link #computeVerticalScrollExtent()}.</p>
6355     *
6356     * <p>The default offset is the scroll offset of this view.</p>
6357     *
6358     * @return the vertical offset of the scrollbar's thumb
6359     *
6360     * @see #computeVerticalScrollRange()
6361     * @see #computeVerticalScrollExtent()
6362     * @see android.widget.ScrollBarDrawable
6363     */
6364    protected int computeVerticalScrollOffset() {
6365        return mScrollY;
6366    }
6367
6368    /**
6369     * <p>Compute the vertical extent of the horizontal scrollbar's thumb
6370     * within the vertical range. This value is used to compute the length
6371     * of the thumb within the scrollbar's track.</p>
6372     *
6373     * <p>The range is expressed in arbitrary units that must be the same as the
6374     * units used by {@link #computeVerticalScrollRange()} and
6375     * {@link #computeVerticalScrollOffset()}.</p>
6376     *
6377     * <p>The default extent is the drawing height of this view.</p>
6378     *
6379     * @return the vertical extent of the scrollbar's thumb
6380     *
6381     * @see #computeVerticalScrollRange()
6382     * @see #computeVerticalScrollOffset()
6383     * @see android.widget.ScrollBarDrawable
6384     */
6385    protected int computeVerticalScrollExtent() {
6386        return getHeight();
6387    }
6388
6389    /**
6390     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
6391     * scrollbars are painted only if they have been awakened first.</p>
6392     *
6393     * @param canvas the canvas on which to draw the scrollbars
6394     *
6395     * @see #awakenScrollBars(int)
6396     */
6397    protected final void onDrawScrollBars(Canvas canvas) {
6398        // scrollbars are drawn only when the animation is running
6399        final ScrollabilityCache cache = mScrollCache;
6400        if (cache != null) {
6401
6402            int state = cache.state;
6403
6404            if (state == ScrollabilityCache.OFF) {
6405                return;
6406            }
6407
6408            boolean invalidate = false;
6409
6410            if (state == ScrollabilityCache.FADING) {
6411                // We're fading -- get our fade interpolation
6412                if (cache.interpolatorValues == null) {
6413                    cache.interpolatorValues = new float[1];
6414                }
6415
6416                float[] values = cache.interpolatorValues;
6417
6418                // Stops the animation if we're done
6419                if (cache.scrollBarInterpolator.timeToValues(values) ==
6420                        Interpolator.Result.FREEZE_END) {
6421                    cache.state = ScrollabilityCache.OFF;
6422                } else {
6423                    cache.scrollBar.setAlpha(Math.round(values[0]));
6424                }
6425
6426                // This will make the scroll bars inval themselves after
6427                // drawing. We only want this when we're fading so that
6428                // we prevent excessive redraws
6429                invalidate = true;
6430            } else {
6431                // We're just on -- but we may have been fading before so
6432                // reset alpha
6433                cache.scrollBar.setAlpha(255);
6434            }
6435
6436
6437            final int viewFlags = mViewFlags;
6438
6439            final boolean drawHorizontalScrollBar =
6440                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
6441            final boolean drawVerticalScrollBar =
6442                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
6443                && !isVerticalScrollBarHidden();
6444
6445            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
6446                final int width = mRight - mLeft;
6447                final int height = mBottom - mTop;
6448
6449                final ScrollBarDrawable scrollBar = cache.scrollBar;
6450                int size = scrollBar.getSize(false);
6451                if (size <= 0) {
6452                    size = cache.scrollBarSize;
6453                }
6454
6455                final int scrollX = mScrollX;
6456                final int scrollY = mScrollY;
6457                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
6458
6459                int left, top, right, bottom;
6460
6461                if (drawHorizontalScrollBar) {
6462                    scrollBar.setParameters(computeHorizontalScrollRange(),
6463                                            computeHorizontalScrollOffset(),
6464                                            computeHorizontalScrollExtent(), false);
6465                    final int verticalScrollBarGap = drawVerticalScrollBar ?
6466                            getVerticalScrollbarWidth() : 0;
6467                    top = scrollY + height - size - (mUserPaddingBottom & inside);
6468                    left = scrollX + (mPaddingLeft & inside);
6469                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
6470                    bottom = top + size;
6471                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
6472                    if (invalidate) {
6473                        invalidate(left, top, right, bottom);
6474                    }
6475                }
6476
6477                if (drawVerticalScrollBar) {
6478                    scrollBar.setParameters(computeVerticalScrollRange(),
6479                                            computeVerticalScrollOffset(),
6480                                            computeVerticalScrollExtent(), true);
6481                    // TODO: Deal with RTL languages to position scrollbar on left
6482                    left = scrollX + width - size - (mUserPaddingRight & inside);
6483                    top = scrollY + (mPaddingTop & inside);
6484                    right = left + size;
6485                    bottom = scrollY + height - (mUserPaddingBottom & inside);
6486                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
6487                    if (invalidate) {
6488                        invalidate(left, top, right, bottom);
6489                    }
6490                }
6491            }
6492        }
6493    }
6494
6495    /**
6496     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
6497     * FastScroller is visible.
6498     * @return whether to temporarily hide the vertical scrollbar
6499     * @hide
6500     */
6501    protected boolean isVerticalScrollBarHidden() {
6502        return false;
6503    }
6504
6505    /**
6506     * <p>Draw the horizontal scrollbar if
6507     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
6508     *
6509     * @param canvas the canvas on which to draw the scrollbar
6510     * @param scrollBar the scrollbar's drawable
6511     *
6512     * @see #isHorizontalScrollBarEnabled()
6513     * @see #computeHorizontalScrollRange()
6514     * @see #computeHorizontalScrollExtent()
6515     * @see #computeHorizontalScrollOffset()
6516     * @see android.widget.ScrollBarDrawable
6517     * @hide
6518     */
6519    protected void onDrawHorizontalScrollBar(Canvas canvas,
6520                                             Drawable scrollBar,
6521                                             int l, int t, int r, int b) {
6522        scrollBar.setBounds(l, t, r, b);
6523        scrollBar.draw(canvas);
6524    }
6525
6526    /**
6527     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
6528     * returns true.</p>
6529     *
6530     * @param canvas the canvas on which to draw the scrollbar
6531     * @param scrollBar the scrollbar's drawable
6532     *
6533     * @see #isVerticalScrollBarEnabled()
6534     * @see #computeVerticalScrollRange()
6535     * @see #computeVerticalScrollExtent()
6536     * @see #computeVerticalScrollOffset()
6537     * @see android.widget.ScrollBarDrawable
6538     * @hide
6539     */
6540    protected void onDrawVerticalScrollBar(Canvas canvas,
6541                                           Drawable scrollBar,
6542                                           int l, int t, int r, int b) {
6543        scrollBar.setBounds(l, t, r, b);
6544        scrollBar.draw(canvas);
6545    }
6546
6547    /**
6548     * Implement this to do your drawing.
6549     *
6550     * @param canvas the canvas on which the background will be drawn
6551     */
6552    protected void onDraw(Canvas canvas) {
6553    }
6554
6555    /*
6556     * Caller is responsible for calling requestLayout if necessary.
6557     * (This allows addViewInLayout to not request a new layout.)
6558     */
6559    void assignParent(ViewParent parent) {
6560        if (mParent == null) {
6561            mParent = parent;
6562        } else if (parent == null) {
6563            mParent = null;
6564        } else {
6565            throw new RuntimeException("view " + this + " being added, but"
6566                    + " it already has a parent");
6567        }
6568    }
6569
6570    /**
6571     * This is called when the view is attached to a window.  At this point it
6572     * has a Surface and will start drawing.  Note that this function is
6573     * guaranteed to be called before {@link #onDraw}, however it may be called
6574     * any time before the first onDraw -- including before or after
6575     * {@link #onMeasure}.
6576     *
6577     * @see #onDetachedFromWindow()
6578     */
6579    protected void onAttachedToWindow() {
6580        if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
6581            mParent.requestTransparentRegion(this);
6582        }
6583        if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
6584            initialAwakenScrollBars();
6585            mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
6586        }
6587    }
6588
6589    /**
6590     * This is called when the view is detached from a window.  At this point it
6591     * no longer has a surface for drawing.
6592     *
6593     * @see #onAttachedToWindow()
6594     */
6595    protected void onDetachedFromWindow() {
6596        mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
6597        removeUnsetPressCallback();
6598        removeLongPressCallback();
6599        destroyDrawingCache();
6600    }
6601
6602    /**
6603     * @return The number of times this view has been attached to a window
6604     */
6605    protected int getWindowAttachCount() {
6606        return mWindowAttachCount;
6607    }
6608
6609    /**
6610     * Retrieve a unique token identifying the window this view is attached to.
6611     * @return Return the window's token for use in
6612     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
6613     */
6614    public IBinder getWindowToken() {
6615        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
6616    }
6617
6618    /**
6619     * Retrieve a unique token identifying the top-level "real" window of
6620     * the window that this view is attached to.  That is, this is like
6621     * {@link #getWindowToken}, except if the window this view in is a panel
6622     * window (attached to another containing window), then the token of
6623     * the containing window is returned instead.
6624     *
6625     * @return Returns the associated window token, either
6626     * {@link #getWindowToken()} or the containing window's token.
6627     */
6628    public IBinder getApplicationWindowToken() {
6629        AttachInfo ai = mAttachInfo;
6630        if (ai != null) {
6631            IBinder appWindowToken = ai.mPanelParentWindowToken;
6632            if (appWindowToken == null) {
6633                appWindowToken = ai.mWindowToken;
6634            }
6635            return appWindowToken;
6636        }
6637        return null;
6638    }
6639
6640    /**
6641     * Retrieve private session object this view hierarchy is using to
6642     * communicate with the window manager.
6643     * @return the session object to communicate with the window manager
6644     */
6645    /*package*/ IWindowSession getWindowSession() {
6646        return mAttachInfo != null ? mAttachInfo.mSession : null;
6647    }
6648
6649    /**
6650     * @param info the {@link android.view.View.AttachInfo} to associated with
6651     *        this view
6652     */
6653    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
6654        //System.out.println("Attached! " + this);
6655        mAttachInfo = info;
6656        mWindowAttachCount++;
6657        if (mFloatingTreeObserver != null) {
6658            info.mTreeObserver.merge(mFloatingTreeObserver);
6659            mFloatingTreeObserver = null;
6660        }
6661        if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
6662            mAttachInfo.mScrollContainers.add(this);
6663            mPrivateFlags |= SCROLL_CONTAINER_ADDED;
6664        }
6665        performCollectViewAttributes(visibility);
6666        onAttachedToWindow();
6667        int vis = info.mWindowVisibility;
6668        if (vis != GONE) {
6669            onWindowVisibilityChanged(vis);
6670        }
6671    }
6672
6673    void dispatchDetachedFromWindow() {
6674        //System.out.println("Detached! " + this);
6675        AttachInfo info = mAttachInfo;
6676        if (info != null) {
6677            int vis = info.mWindowVisibility;
6678            if (vis != GONE) {
6679                onWindowVisibilityChanged(GONE);
6680            }
6681        }
6682
6683        onDetachedFromWindow();
6684        if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
6685            mAttachInfo.mScrollContainers.remove(this);
6686            mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
6687        }
6688        mAttachInfo = null;
6689    }
6690
6691    /**
6692     * Store this view hierarchy's frozen state into the given container.
6693     *
6694     * @param container The SparseArray in which to save the view's state.
6695     *
6696     * @see #restoreHierarchyState
6697     * @see #dispatchSaveInstanceState
6698     * @see #onSaveInstanceState
6699     */
6700    public void saveHierarchyState(SparseArray<Parcelable> container) {
6701        dispatchSaveInstanceState(container);
6702    }
6703
6704    /**
6705     * Called by {@link #saveHierarchyState} to store the state for this view and its children.
6706     * May be overridden to modify how freezing happens to a view's children; for example, some
6707     * views may want to not store state for their children.
6708     *
6709     * @param container The SparseArray in which to save the view's state.
6710     *
6711     * @see #dispatchRestoreInstanceState
6712     * @see #saveHierarchyState
6713     * @see #onSaveInstanceState
6714     */
6715    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
6716        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
6717            mPrivateFlags &= ~SAVE_STATE_CALLED;
6718            Parcelable state = onSaveInstanceState();
6719            if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
6720                throw new IllegalStateException(
6721                        "Derived class did not call super.onSaveInstanceState()");
6722            }
6723            if (state != null) {
6724                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
6725                // + ": " + state);
6726                container.put(mID, state);
6727            }
6728        }
6729    }
6730
6731    /**
6732     * Hook allowing a view to generate a representation of its internal state
6733     * that can later be used to create a new instance with that same state.
6734     * This state should only contain information that is not persistent or can
6735     * not be reconstructed later. For example, you will never store your
6736     * current position on screen because that will be computed again when a
6737     * new instance of the view is placed in its view hierarchy.
6738     * <p>
6739     * Some examples of things you may store here: the current cursor position
6740     * in a text view (but usually not the text itself since that is stored in a
6741     * content provider or other persistent storage), the currently selected
6742     * item in a list view.
6743     *
6744     * @return Returns a Parcelable object containing the view's current dynamic
6745     *         state, or null if there is nothing interesting to save. The
6746     *         default implementation returns null.
6747     * @see #onRestoreInstanceState
6748     * @see #saveHierarchyState
6749     * @see #dispatchSaveInstanceState
6750     * @see #setSaveEnabled(boolean)
6751     */
6752    protected Parcelable onSaveInstanceState() {
6753        mPrivateFlags |= SAVE_STATE_CALLED;
6754        return BaseSavedState.EMPTY_STATE;
6755    }
6756
6757    /**
6758     * Restore this view hierarchy's frozen state from the given container.
6759     *
6760     * @param container The SparseArray which holds previously frozen states.
6761     *
6762     * @see #saveHierarchyState
6763     * @see #dispatchRestoreInstanceState
6764     * @see #onRestoreInstanceState
6765     */
6766    public void restoreHierarchyState(SparseArray<Parcelable> container) {
6767        dispatchRestoreInstanceState(container);
6768    }
6769
6770    /**
6771     * Called by {@link #restoreHierarchyState} to retrieve the state for this view and its
6772     * children. May be overridden to modify how restoreing happens to a view's children; for
6773     * example, some views may want to not store state for their children.
6774     *
6775     * @param container The SparseArray which holds previously saved state.
6776     *
6777     * @see #dispatchSaveInstanceState
6778     * @see #restoreHierarchyState
6779     * @see #onRestoreInstanceState
6780     */
6781    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
6782        if (mID != NO_ID) {
6783            Parcelable state = container.get(mID);
6784            if (state != null) {
6785                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
6786                // + ": " + state);
6787                mPrivateFlags &= ~SAVE_STATE_CALLED;
6788                onRestoreInstanceState(state);
6789                if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
6790                    throw new IllegalStateException(
6791                            "Derived class did not call super.onRestoreInstanceState()");
6792                }
6793            }
6794        }
6795    }
6796
6797    /**
6798     * Hook allowing a view to re-apply a representation of its internal state that had previously
6799     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
6800     * null state.
6801     *
6802     * @param state The frozen state that had previously been returned by
6803     *        {@link #onSaveInstanceState}.
6804     *
6805     * @see #onSaveInstanceState
6806     * @see #restoreHierarchyState
6807     * @see #dispatchRestoreInstanceState
6808     */
6809    protected void onRestoreInstanceState(Parcelable state) {
6810        mPrivateFlags |= SAVE_STATE_CALLED;
6811        if (state != BaseSavedState.EMPTY_STATE && state != null) {
6812            throw new IllegalArgumentException("Wrong state class, expecting View State but "
6813                    + "received " + state.getClass().toString() + " instead. This usually happens "
6814                    + "when two views of different type have the same id in the same hierarchy. "
6815                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
6816                    + "other views do not use the same id.");
6817        }
6818    }
6819
6820    /**
6821     * <p>Return the time at which the drawing of the view hierarchy started.</p>
6822     *
6823     * @return the drawing start time in milliseconds
6824     */
6825    public long getDrawingTime() {
6826        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
6827    }
6828
6829    /**
6830     * <p>Enables or disables the duplication of the parent's state into this view. When
6831     * duplication is enabled, this view gets its drawable state from its parent rather
6832     * than from its own internal properties.</p>
6833     *
6834     * <p>Note: in the current implementation, setting this property to true after the
6835     * view was added to a ViewGroup might have no effect at all. This property should
6836     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
6837     *
6838     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
6839     * property is enabled, an exception will be thrown.</p>
6840     *
6841     * @param enabled True to enable duplication of the parent's drawable state, false
6842     *                to disable it.
6843     *
6844     * @see #getDrawableState()
6845     * @see #isDuplicateParentStateEnabled()
6846     */
6847    public void setDuplicateParentStateEnabled(boolean enabled) {
6848        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
6849    }
6850
6851    /**
6852     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
6853     *
6854     * @return True if this view's drawable state is duplicated from the parent,
6855     *         false otherwise
6856     *
6857     * @see #getDrawableState()
6858     * @see #setDuplicateParentStateEnabled(boolean)
6859     */
6860    public boolean isDuplicateParentStateEnabled() {
6861        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
6862    }
6863
6864    /**
6865     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
6866     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
6867     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
6868     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
6869     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
6870     * null.</p>
6871     *
6872     * @param enabled true to enable the drawing cache, false otherwise
6873     *
6874     * @see #isDrawingCacheEnabled()
6875     * @see #getDrawingCache()
6876     * @see #buildDrawingCache()
6877     */
6878    public void setDrawingCacheEnabled(boolean enabled) {
6879        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
6880    }
6881
6882    /**
6883     * <p>Indicates whether the drawing cache is enabled for this view.</p>
6884     *
6885     * @return true if the drawing cache is enabled
6886     *
6887     * @see #setDrawingCacheEnabled(boolean)
6888     * @see #getDrawingCache()
6889     */
6890    @ViewDebug.ExportedProperty
6891    public boolean isDrawingCacheEnabled() {
6892        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
6893    }
6894
6895    /**
6896     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
6897     *
6898     * @return A non-scaled bitmap representing this view or null if cache is disabled.
6899     *
6900     * @see #getDrawingCache(boolean)
6901     */
6902    public Bitmap getDrawingCache() {
6903        return getDrawingCache(false);
6904    }
6905
6906    /**
6907     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
6908     * is null when caching is disabled. If caching is enabled and the cache is not ready,
6909     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
6910     * draw from the cache when the cache is enabled. To benefit from the cache, you must
6911     * request the drawing cache by calling this method and draw it on screen if the
6912     * returned bitmap is not null.</p>
6913     *
6914     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
6915     * this method will create a bitmap of the same size as this view. Because this bitmap
6916     * will be drawn scaled by the parent ViewGroup, the result on screen might show
6917     * scaling artifacts. To avoid such artifacts, you should call this method by setting
6918     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
6919     * size than the view. This implies that your application must be able to handle this
6920     * size.</p>
6921     *
6922     * @param autoScale Indicates whether the generated bitmap should be scaled based on
6923     *        the current density of the screen when the application is in compatibility
6924     *        mode.
6925     *
6926     * @return A bitmap representing this view or null if cache is disabled.
6927     *
6928     * @see #setDrawingCacheEnabled(boolean)
6929     * @see #isDrawingCacheEnabled()
6930     * @see #buildDrawingCache(boolean)
6931     * @see #destroyDrawingCache()
6932     */
6933    public Bitmap getDrawingCache(boolean autoScale) {
6934        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
6935            return null;
6936        }
6937        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
6938            buildDrawingCache(autoScale);
6939        }
6940        return autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :
6941                (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());
6942    }
6943
6944    /**
6945     * <p>Frees the resources used by the drawing cache. If you call
6946     * {@link #buildDrawingCache()} manually without calling
6947     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
6948     * should cleanup the cache with this method afterwards.</p>
6949     *
6950     * @see #setDrawingCacheEnabled(boolean)
6951     * @see #buildDrawingCache()
6952     * @see #getDrawingCache()
6953     */
6954    public void destroyDrawingCache() {
6955        if (mDrawingCache != null) {
6956            final Bitmap bitmap = mDrawingCache.get();
6957            if (bitmap != null) bitmap.recycle();
6958            mDrawingCache = null;
6959        }
6960        if (mUnscaledDrawingCache != null) {
6961            final Bitmap bitmap = mUnscaledDrawingCache.get();
6962            if (bitmap != null) bitmap.recycle();
6963            mUnscaledDrawingCache = null;
6964        }
6965    }
6966
6967    /**
6968     * Setting a solid background color for the drawing cache's bitmaps will improve
6969     * perfromance and memory usage. Note, though that this should only be used if this
6970     * view will always be drawn on top of a solid color.
6971     *
6972     * @param color The background color to use for the drawing cache's bitmap
6973     *
6974     * @see #setDrawingCacheEnabled(boolean)
6975     * @see #buildDrawingCache()
6976     * @see #getDrawingCache()
6977     */
6978    public void setDrawingCacheBackgroundColor(int color) {
6979        if (color != mDrawingCacheBackgroundColor) {
6980            mDrawingCacheBackgroundColor = color;
6981            mPrivateFlags &= ~DRAWING_CACHE_VALID;
6982        }
6983    }
6984
6985    /**
6986     * @see #setDrawingCacheBackgroundColor(int)
6987     *
6988     * @return The background color to used for the drawing cache's bitmap
6989     */
6990    public int getDrawingCacheBackgroundColor() {
6991        return mDrawingCacheBackgroundColor;
6992    }
6993
6994    /**
6995     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
6996     *
6997     * @see #buildDrawingCache(boolean)
6998     */
6999    public void buildDrawingCache() {
7000        buildDrawingCache(false);
7001    }
7002
7003    /**
7004     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
7005     *
7006     * <p>If you call {@link #buildDrawingCache()} manually without calling
7007     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
7008     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
7009     *
7010     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
7011     * this method will create a bitmap of the same size as this view. Because this bitmap
7012     * will be drawn scaled by the parent ViewGroup, the result on screen might show
7013     * scaling artifacts. To avoid such artifacts, you should call this method by setting
7014     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
7015     * size than the view. This implies that your application must be able to handle this
7016     * size.</p>
7017     *
7018     * @see #getDrawingCache()
7019     * @see #destroyDrawingCache()
7020     */
7021    public void buildDrawingCache(boolean autoScale) {
7022        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
7023                (mDrawingCache == null || mDrawingCache.get() == null) :
7024                (mUnscaledDrawingCache == null || mUnscaledDrawingCache.get() == null))) {
7025
7026            if (ViewDebug.TRACE_HIERARCHY) {
7027                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
7028            }
7029            if (Config.DEBUG && ViewDebug.profileDrawing) {
7030                EventLog.writeEvent(60002, hashCode());
7031            }
7032
7033            int width = mRight - mLeft;
7034            int height = mBottom - mTop;
7035
7036            final AttachInfo attachInfo = mAttachInfo;
7037            final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
7038
7039            if (autoScale && scalingRequired) {
7040                width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
7041                height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
7042            }
7043
7044            final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
7045            final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
7046            final boolean translucentWindow = attachInfo != null && attachInfo.mTranslucentWindow;
7047
7048            if (width <= 0 || height <= 0 ||
7049                     // Projected bitmap size in bytes
7050                    (width * height * (opaque && !translucentWindow ? 2 : 4) >
7051                            ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
7052                destroyDrawingCache();
7053                return;
7054            }
7055
7056            boolean clear = true;
7057            Bitmap bitmap = autoScale ? (mDrawingCache == null ? null : mDrawingCache.get()) :
7058                    (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get());
7059
7060            if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
7061                Bitmap.Config quality;
7062                if (!opaque) {
7063                    switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
7064                        case DRAWING_CACHE_QUALITY_AUTO:
7065                            quality = Bitmap.Config.ARGB_8888;
7066                            break;
7067                        case DRAWING_CACHE_QUALITY_LOW:
7068                            quality = Bitmap.Config.ARGB_4444;
7069                            break;
7070                        case DRAWING_CACHE_QUALITY_HIGH:
7071                            quality = Bitmap.Config.ARGB_8888;
7072                            break;
7073                        default:
7074                            quality = Bitmap.Config.ARGB_8888;
7075                            break;
7076                    }
7077                } else {
7078                    // Optimization for translucent windows
7079                    // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
7080                    quality = translucentWindow ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
7081                }
7082
7083                // Try to cleanup memory
7084                if (bitmap != null) bitmap.recycle();
7085
7086                try {
7087                    bitmap = Bitmap.createBitmap(width, height, quality);
7088                    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
7089                    if (autoScale) {
7090                        mDrawingCache = new SoftReference<Bitmap>(bitmap);
7091                    } else {
7092                        mUnscaledDrawingCache = new SoftReference<Bitmap>(bitmap);
7093                    }
7094                    if (opaque && translucentWindow) bitmap.setHasAlpha(false);
7095                } catch (OutOfMemoryError e) {
7096                    // If there is not enough memory to create the bitmap cache, just
7097                    // ignore the issue as bitmap caches are not required to draw the
7098                    // view hierarchy
7099                    if (autoScale) {
7100                        mDrawingCache = null;
7101                    } else {
7102                        mUnscaledDrawingCache = null;
7103                    }
7104                    return;
7105                }
7106
7107                clear = drawingCacheBackgroundColor != 0;
7108            }
7109
7110            Canvas canvas;
7111            if (attachInfo != null) {
7112                canvas = attachInfo.mCanvas;
7113                if (canvas == null) {
7114                    canvas = new Canvas();
7115                }
7116                canvas.setBitmap(bitmap);
7117                // Temporarily clobber the cached Canvas in case one of our children
7118                // is also using a drawing cache. Without this, the children would
7119                // steal the canvas by attaching their own bitmap to it and bad, bad
7120                // thing would happen (invisible views, corrupted drawings, etc.)
7121                attachInfo.mCanvas = null;
7122            } else {
7123                // This case should hopefully never or seldom happen
7124                canvas = new Canvas(bitmap);
7125            }
7126
7127            if (clear) {
7128                bitmap.eraseColor(drawingCacheBackgroundColor);
7129            }
7130
7131            computeScroll();
7132            final int restoreCount = canvas.save();
7133
7134            if (autoScale && scalingRequired) {
7135                final float scale = attachInfo.mApplicationScale;
7136                canvas.scale(scale, scale);
7137            }
7138
7139            canvas.translate(-mScrollX, -mScrollY);
7140
7141            mPrivateFlags |= DRAWN;
7142            mPrivateFlags |= DRAWING_CACHE_VALID;
7143
7144            // Fast path for layouts with no backgrounds
7145            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
7146                if (ViewDebug.TRACE_HIERARCHY) {
7147                    ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
7148                }
7149                mPrivateFlags &= ~DIRTY_MASK;
7150                dispatchDraw(canvas);
7151            } else {
7152                draw(canvas);
7153            }
7154
7155            canvas.restoreToCount(restoreCount);
7156
7157            if (attachInfo != null) {
7158                // Restore the cached Canvas for our siblings
7159                attachInfo.mCanvas = canvas;
7160            }
7161        }
7162    }
7163
7164    /**
7165     * Create a snapshot of the view into a bitmap.  We should probably make
7166     * some form of this public, but should think about the API.
7167     */
7168    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
7169        int width = mRight - mLeft;
7170        int height = mBottom - mTop;
7171
7172        final AttachInfo attachInfo = mAttachInfo;
7173        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
7174        width = (int) ((width * scale) + 0.5f);
7175        height = (int) ((height * scale) + 0.5f);
7176
7177        Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
7178        if (bitmap == null) {
7179            throw new OutOfMemoryError();
7180        }
7181
7182        bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
7183
7184        Canvas canvas;
7185        if (attachInfo != null) {
7186            canvas = attachInfo.mCanvas;
7187            if (canvas == null) {
7188                canvas = new Canvas();
7189            }
7190            canvas.setBitmap(bitmap);
7191            // Temporarily clobber the cached Canvas in case one of our children
7192            // is also using a drawing cache. Without this, the children would
7193            // steal the canvas by attaching their own bitmap to it and bad, bad
7194            // things would happen (invisible views, corrupted drawings, etc.)
7195            attachInfo.mCanvas = null;
7196        } else {
7197            // This case should hopefully never or seldom happen
7198            canvas = new Canvas(bitmap);
7199        }
7200
7201        if ((backgroundColor & 0xff000000) != 0) {
7202            bitmap.eraseColor(backgroundColor);
7203        }
7204
7205        computeScroll();
7206        final int restoreCount = canvas.save();
7207        canvas.scale(scale, scale);
7208        canvas.translate(-mScrollX, -mScrollY);
7209
7210        // Temporarily remove the dirty mask
7211        int flags = mPrivateFlags;
7212        mPrivateFlags &= ~DIRTY_MASK;
7213
7214        // Fast path for layouts with no backgrounds
7215        if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
7216            dispatchDraw(canvas);
7217        } else {
7218            draw(canvas);
7219        }
7220
7221        mPrivateFlags = flags;
7222
7223        canvas.restoreToCount(restoreCount);
7224
7225        if (attachInfo != null) {
7226            // Restore the cached Canvas for our siblings
7227            attachInfo.mCanvas = canvas;
7228        }
7229
7230        return bitmap;
7231    }
7232
7233    /**
7234     * Indicates whether this View is currently in edit mode. A View is usually
7235     * in edit mode when displayed within a developer tool. For instance, if
7236     * this View is being drawn by a visual user interface builder, this method
7237     * should return true.
7238     *
7239     * Subclasses should check the return value of this method to provide
7240     * different behaviors if their normal behavior might interfere with the
7241     * host environment. For instance: the class spawns a thread in its
7242     * constructor, the drawing code relies on device-specific features, etc.
7243     *
7244     * This method is usually checked in the drawing code of custom widgets.
7245     *
7246     * @return True if this View is in edit mode, false otherwise.
7247     */
7248    public boolean isInEditMode() {
7249        return false;
7250    }
7251
7252    /**
7253     * If the View draws content inside its padding and enables fading edges,
7254     * it needs to support padding offsets. Padding offsets are added to the
7255     * fading edges to extend the length of the fade so that it covers pixels
7256     * drawn inside the padding.
7257     *
7258     * Subclasses of this class should override this method if they need
7259     * to draw content inside the padding.
7260     *
7261     * @return True if padding offset must be applied, false otherwise.
7262     *
7263     * @see #getLeftPaddingOffset()
7264     * @see #getRightPaddingOffset()
7265     * @see #getTopPaddingOffset()
7266     * @see #getBottomPaddingOffset()
7267     *
7268     * @since CURRENT
7269     */
7270    protected boolean isPaddingOffsetRequired() {
7271        return false;
7272    }
7273
7274    /**
7275     * Amount by which to extend the left fading region. Called only when
7276     * {@link #isPaddingOffsetRequired()} returns true.
7277     *
7278     * @return The left padding offset in pixels.
7279     *
7280     * @see #isPaddingOffsetRequired()
7281     *
7282     * @since CURRENT
7283     */
7284    protected int getLeftPaddingOffset() {
7285        return 0;
7286    }
7287
7288    /**
7289     * Amount by which to extend the right fading region. Called only when
7290     * {@link #isPaddingOffsetRequired()} returns true.
7291     *
7292     * @return The right padding offset in pixels.
7293     *
7294     * @see #isPaddingOffsetRequired()
7295     *
7296     * @since CURRENT
7297     */
7298    protected int getRightPaddingOffset() {
7299        return 0;
7300    }
7301
7302    /**
7303     * Amount by which to extend the top fading region. Called only when
7304     * {@link #isPaddingOffsetRequired()} returns true.
7305     *
7306     * @return The top padding offset in pixels.
7307     *
7308     * @see #isPaddingOffsetRequired()
7309     *
7310     * @since CURRENT
7311     */
7312    protected int getTopPaddingOffset() {
7313        return 0;
7314    }
7315
7316    /**
7317     * Amount by which to extend the bottom fading region. Called only when
7318     * {@link #isPaddingOffsetRequired()} returns true.
7319     *
7320     * @return The bottom padding offset in pixels.
7321     *
7322     * @see #isPaddingOffsetRequired()
7323     *
7324     * @since CURRENT
7325     */
7326    protected int getBottomPaddingOffset() {
7327        return 0;
7328    }
7329
7330    /**
7331     * Manually render this view (and all of its children) to the given Canvas.
7332     * The view must have already done a full layout before this function is
7333     * called.  When implementing a view, do not override this method; instead,
7334     * you should implement {@link #onDraw}.
7335     *
7336     * @param canvas The Canvas to which the View is rendered.
7337     */
7338    public void draw(Canvas canvas) {
7339        if (ViewDebug.TRACE_HIERARCHY) {
7340            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
7341        }
7342
7343        final int privateFlags = mPrivateFlags;
7344        final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
7345                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
7346        mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
7347
7348        /*
7349         * Draw traversal performs several drawing steps which must be executed
7350         * in the appropriate order:
7351         *
7352         *      1. Draw the background
7353         *      2. If necessary, save the canvas' layers to prepare for fading
7354         *      3. Draw view's content
7355         *      4. Draw children
7356         *      5. If necessary, draw the fading edges and restore layers
7357         *      6. Draw decorations (scrollbars for instance)
7358         */
7359
7360        // Step 1, draw the background, if needed
7361        int saveCount;
7362
7363        if (!dirtyOpaque) {
7364            final Drawable background = mBGDrawable;
7365            if (background != null) {
7366                final int scrollX = mScrollX;
7367                final int scrollY = mScrollY;
7368
7369                if (mBackgroundSizeChanged) {
7370                    background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
7371                    mBackgroundSizeChanged = false;
7372                }
7373
7374                if ((scrollX | scrollY) == 0) {
7375                    background.draw(canvas);
7376                } else {
7377                    canvas.translate(scrollX, scrollY);
7378                    background.draw(canvas);
7379                    canvas.translate(-scrollX, -scrollY);
7380                }
7381            }
7382        }
7383
7384        // skip step 2 & 5 if possible (common case)
7385        final int viewFlags = mViewFlags;
7386        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
7387        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
7388        if (!verticalEdges && !horizontalEdges) {
7389            // Step 3, draw the content
7390            if (!dirtyOpaque) onDraw(canvas);
7391
7392            // Step 4, draw the children
7393            dispatchDraw(canvas);
7394
7395            // Step 6, draw decorations (scrollbars)
7396            onDrawScrollBars(canvas);
7397
7398            // we're done...
7399            return;
7400        }
7401
7402        /*
7403         * Here we do the full fledged routine...
7404         * (this is an uncommon case where speed matters less,
7405         * this is why we repeat some of the tests that have been
7406         * done above)
7407         */
7408
7409        boolean drawTop = false;
7410        boolean drawBottom = false;
7411        boolean drawLeft = false;
7412        boolean drawRight = false;
7413
7414        float topFadeStrength = 0.0f;
7415        float bottomFadeStrength = 0.0f;
7416        float leftFadeStrength = 0.0f;
7417        float rightFadeStrength = 0.0f;
7418
7419        // Step 2, save the canvas' layers
7420        int paddingLeft = mPaddingLeft;
7421        int paddingTop = mPaddingTop;
7422
7423        final boolean offsetRequired = isPaddingOffsetRequired();
7424        if (offsetRequired) {
7425            paddingLeft += getLeftPaddingOffset();
7426            paddingTop += getTopPaddingOffset();
7427        }
7428
7429        int left = mScrollX + paddingLeft;
7430        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
7431        int top = mScrollY + paddingTop;
7432        int bottom = top + mBottom - mTop - mPaddingBottom - paddingTop;
7433
7434        if (offsetRequired) {
7435            right += getRightPaddingOffset();
7436            bottom += getBottomPaddingOffset();
7437        }
7438
7439        final ScrollabilityCache scrollabilityCache = mScrollCache;
7440        int length = scrollabilityCache.fadingEdgeLength;
7441
7442        // clip the fade length if top and bottom fades overlap
7443        // overlapping fades produce odd-looking artifacts
7444        if (verticalEdges && (top + length > bottom - length)) {
7445            length = (bottom - top) / 2;
7446        }
7447
7448        // also clip horizontal fades if necessary
7449        if (horizontalEdges && (left + length > right - length)) {
7450            length = (right - left) / 2;
7451        }
7452
7453        if (verticalEdges) {
7454            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
7455            drawTop = topFadeStrength > 0.0f;
7456            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
7457            drawBottom = bottomFadeStrength > 0.0f;
7458        }
7459
7460        if (horizontalEdges) {
7461            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
7462            drawLeft = leftFadeStrength > 0.0f;
7463            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
7464            drawRight = rightFadeStrength > 0.0f;
7465        }
7466
7467        saveCount = canvas.getSaveCount();
7468
7469        int solidColor = getSolidColor();
7470        if (solidColor == 0) {
7471            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
7472
7473            if (drawTop) {
7474                canvas.saveLayer(left, top, right, top + length, null, flags);
7475            }
7476
7477            if (drawBottom) {
7478                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
7479            }
7480
7481            if (drawLeft) {
7482                canvas.saveLayer(left, top, left + length, bottom, null, flags);
7483            }
7484
7485            if (drawRight) {
7486                canvas.saveLayer(right - length, top, right, bottom, null, flags);
7487            }
7488        } else {
7489            scrollabilityCache.setFadeColor(solidColor);
7490        }
7491
7492        // Step 3, draw the content
7493        if (!dirtyOpaque) onDraw(canvas);
7494
7495        // Step 4, draw the children
7496        dispatchDraw(canvas);
7497
7498        // Step 5, draw the fade effect and restore layers
7499        final Paint p = scrollabilityCache.paint;
7500        final Matrix matrix = scrollabilityCache.matrix;
7501        final Shader fade = scrollabilityCache.shader;
7502        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
7503
7504        if (drawTop) {
7505            matrix.setScale(1, fadeHeight * topFadeStrength);
7506            matrix.postTranslate(left, top);
7507            fade.setLocalMatrix(matrix);
7508            canvas.drawRect(left, top, right, top + length, p);
7509        }
7510
7511        if (drawBottom) {
7512            matrix.setScale(1, fadeHeight * bottomFadeStrength);
7513            matrix.postRotate(180);
7514            matrix.postTranslate(left, bottom);
7515            fade.setLocalMatrix(matrix);
7516            canvas.drawRect(left, bottom - length, right, bottom, p);
7517        }
7518
7519        if (drawLeft) {
7520            matrix.setScale(1, fadeHeight * leftFadeStrength);
7521            matrix.postRotate(-90);
7522            matrix.postTranslate(left, top);
7523            fade.setLocalMatrix(matrix);
7524            canvas.drawRect(left, top, left + length, bottom, p);
7525        }
7526
7527        if (drawRight) {
7528            matrix.setScale(1, fadeHeight * rightFadeStrength);
7529            matrix.postRotate(90);
7530            matrix.postTranslate(right, top);
7531            fade.setLocalMatrix(matrix);
7532            canvas.drawRect(right - length, top, right, bottom, p);
7533        }
7534
7535        canvas.restoreToCount(saveCount);
7536
7537        // Step 6, draw decorations (scrollbars)
7538        onDrawScrollBars(canvas);
7539    }
7540
7541    /**
7542     * Override this if your view is known to always be drawn on top of a solid color background,
7543     * and needs to draw fading edges. Returning a non-zero color enables the view system to
7544     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
7545     * should be set to 0xFF.
7546     *
7547     * @see #setVerticalFadingEdgeEnabled
7548     * @see #setHorizontalFadingEdgeEnabled
7549     *
7550     * @return The known solid color background for this view, or 0 if the color may vary
7551     */
7552    public int getSolidColor() {
7553        return 0;
7554    }
7555
7556    /**
7557     * Build a human readable string representation of the specified view flags.
7558     *
7559     * @param flags the view flags to convert to a string
7560     * @return a String representing the supplied flags
7561     */
7562    private static String printFlags(int flags) {
7563        String output = "";
7564        int numFlags = 0;
7565        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
7566            output += "TAKES_FOCUS";
7567            numFlags++;
7568        }
7569
7570        switch (flags & VISIBILITY_MASK) {
7571        case INVISIBLE:
7572            if (numFlags > 0) {
7573                output += " ";
7574            }
7575            output += "INVISIBLE";
7576            // USELESS HERE numFlags++;
7577            break;
7578        case GONE:
7579            if (numFlags > 0) {
7580                output += " ";
7581            }
7582            output += "GONE";
7583            // USELESS HERE numFlags++;
7584            break;
7585        default:
7586            break;
7587        }
7588        return output;
7589    }
7590
7591    /**
7592     * Build a human readable string representation of the specified private
7593     * view flags.
7594     *
7595     * @param privateFlags the private view flags to convert to a string
7596     * @return a String representing the supplied flags
7597     */
7598    private static String printPrivateFlags(int privateFlags) {
7599        String output = "";
7600        int numFlags = 0;
7601
7602        if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
7603            output += "WANTS_FOCUS";
7604            numFlags++;
7605        }
7606
7607        if ((privateFlags & FOCUSED) == FOCUSED) {
7608            if (numFlags > 0) {
7609                output += " ";
7610            }
7611            output += "FOCUSED";
7612            numFlags++;
7613        }
7614
7615        if ((privateFlags & SELECTED) == SELECTED) {
7616            if (numFlags > 0) {
7617                output += " ";
7618            }
7619            output += "SELECTED";
7620            numFlags++;
7621        }
7622
7623        if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
7624            if (numFlags > 0) {
7625                output += " ";
7626            }
7627            output += "IS_ROOT_NAMESPACE";
7628            numFlags++;
7629        }
7630
7631        if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
7632            if (numFlags > 0) {
7633                output += " ";
7634            }
7635            output += "HAS_BOUNDS";
7636            numFlags++;
7637        }
7638
7639        if ((privateFlags & DRAWN) == DRAWN) {
7640            if (numFlags > 0) {
7641                output += " ";
7642            }
7643            output += "DRAWN";
7644            // USELESS HERE numFlags++;
7645        }
7646        return output;
7647    }
7648
7649    /**
7650     * <p>Indicates whether or not this view's layout will be requested during
7651     * the next hierarchy layout pass.</p>
7652     *
7653     * @return true if the layout will be forced during next layout pass
7654     */
7655    public boolean isLayoutRequested() {
7656        return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
7657    }
7658
7659    /**
7660     * Assign a size and position to a view and all of its
7661     * descendants
7662     *
7663     * <p>This is the second phase of the layout mechanism.
7664     * (The first is measuring). In this phase, each parent calls
7665     * layout on all of its children to position them.
7666     * This is typically done using the child measurements
7667     * that were stored in the measure pass().
7668     *
7669     * Derived classes with children should override
7670     * onLayout. In that method, they should
7671     * call layout on each of their their children.
7672     *
7673     * @param l Left position, relative to parent
7674     * @param t Top position, relative to parent
7675     * @param r Right position, relative to parent
7676     * @param b Bottom position, relative to parent
7677     */
7678    public final void layout(int l, int t, int r, int b) {
7679        boolean changed = setFrame(l, t, r, b);
7680        if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
7681            if (ViewDebug.TRACE_HIERARCHY) {
7682                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
7683            }
7684
7685            onLayout(changed, l, t, r, b);
7686            mPrivateFlags &= ~LAYOUT_REQUIRED;
7687        }
7688        mPrivateFlags &= ~FORCE_LAYOUT;
7689    }
7690
7691    /**
7692     * Called from layout when this view should
7693     * assign a size and position to each of its children.
7694     *
7695     * Derived classes with children should override
7696     * this method and call layout on each of
7697     * their their children.
7698     * @param changed This is a new size or position for this view
7699     * @param left Left position, relative to parent
7700     * @param top Top position, relative to parent
7701     * @param right Right position, relative to parent
7702     * @param bottom Bottom position, relative to parent
7703     */
7704    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
7705    }
7706
7707    /**
7708     * Assign a size and position to this view.
7709     *
7710     * This is called from layout.
7711     *
7712     * @param left Left position, relative to parent
7713     * @param top Top position, relative to parent
7714     * @param right Right position, relative to parent
7715     * @param bottom Bottom position, relative to parent
7716     * @return true if the new size and position are different than the
7717     *         previous ones
7718     * {@hide}
7719     */
7720    protected boolean setFrame(int left, int top, int right, int bottom) {
7721        boolean changed = false;
7722
7723        if (DBG) {
7724            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
7725                    + right + "," + bottom + ")");
7726        }
7727
7728        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
7729            changed = true;
7730
7731            // Remember our drawn bit
7732            int drawn = mPrivateFlags & DRAWN;
7733
7734            // Invalidate our old position
7735            invalidate();
7736
7737
7738            int oldWidth = mRight - mLeft;
7739            int oldHeight = mBottom - mTop;
7740
7741            mLeft = left;
7742            mTop = top;
7743            mRight = right;
7744            mBottom = bottom;
7745
7746            mPrivateFlags |= HAS_BOUNDS;
7747
7748            int newWidth = right - left;
7749            int newHeight = bottom - top;
7750
7751            if (newWidth != oldWidth || newHeight != oldHeight) {
7752                onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
7753            }
7754
7755            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
7756                // If we are visible, force the DRAWN bit to on so that
7757                // this invalidate will go through (at least to our parent).
7758                // This is because someone may have invalidated this view
7759                // before this call to setFrame came in, therby clearing
7760                // the DRAWN bit.
7761                mPrivateFlags |= DRAWN;
7762                invalidate();
7763            }
7764
7765            // Reset drawn bit to original value (invalidate turns it off)
7766            mPrivateFlags |= drawn;
7767
7768            mBackgroundSizeChanged = true;
7769        }
7770        return changed;
7771    }
7772
7773    /**
7774     * Finalize inflating a view from XML.  This is called as the last phase
7775     * of inflation, after all child views have been added.
7776     *
7777     * <p>Even if the subclass overrides onFinishInflate, they should always be
7778     * sure to call the super method, so that we get called.
7779     */
7780    protected void onFinishInflate() {
7781    }
7782
7783    /**
7784     * Returns the resources associated with this view.
7785     *
7786     * @return Resources object.
7787     */
7788    public Resources getResources() {
7789        return mResources;
7790    }
7791
7792    /**
7793     * Invalidates the specified Drawable.
7794     *
7795     * @param drawable the drawable to invalidate
7796     */
7797    public void invalidateDrawable(Drawable drawable) {
7798        if (verifyDrawable(drawable)) {
7799            final Rect dirty = drawable.getBounds();
7800            final int scrollX = mScrollX;
7801            final int scrollY = mScrollY;
7802
7803            invalidate(dirty.left + scrollX, dirty.top + scrollY,
7804                    dirty.right + scrollX, dirty.bottom + scrollY);
7805        }
7806    }
7807
7808    /**
7809     * Schedules an action on a drawable to occur at a specified time.
7810     *
7811     * @param who the recipient of the action
7812     * @param what the action to run on the drawable
7813     * @param when the time at which the action must occur. Uses the
7814     *        {@link SystemClock#uptimeMillis} timebase.
7815     */
7816    public void scheduleDrawable(Drawable who, Runnable what, long when) {
7817        if (verifyDrawable(who) && what != null && mAttachInfo != null) {
7818            mAttachInfo.mHandler.postAtTime(what, who, when);
7819        }
7820    }
7821
7822    /**
7823     * Cancels a scheduled action on a drawable.
7824     *
7825     * @param who the recipient of the action
7826     * @param what the action to cancel
7827     */
7828    public void unscheduleDrawable(Drawable who, Runnable what) {
7829        if (verifyDrawable(who) && what != null && mAttachInfo != null) {
7830            mAttachInfo.mHandler.removeCallbacks(what, who);
7831        }
7832    }
7833
7834    /**
7835     * Unschedule any events associated with the given Drawable.  This can be
7836     * used when selecting a new Drawable into a view, so that the previous
7837     * one is completely unscheduled.
7838     *
7839     * @param who The Drawable to unschedule.
7840     *
7841     * @see #drawableStateChanged
7842     */
7843    public void unscheduleDrawable(Drawable who) {
7844        if (mAttachInfo != null) {
7845            mAttachInfo.mHandler.removeCallbacksAndMessages(who);
7846        }
7847    }
7848
7849    /**
7850     * If your view subclass is displaying its own Drawable objects, it should
7851     * override this function and return true for any Drawable it is
7852     * displaying.  This allows animations for those drawables to be
7853     * scheduled.
7854     *
7855     * <p>Be sure to call through to the super class when overriding this
7856     * function.
7857     *
7858     * @param who The Drawable to verify.  Return true if it is one you are
7859     *            displaying, else return the result of calling through to the
7860     *            super class.
7861     *
7862     * @return boolean If true than the Drawable is being displayed in the
7863     *         view; else false and it is not allowed to animate.
7864     *
7865     * @see #unscheduleDrawable
7866     * @see #drawableStateChanged
7867     */
7868    protected boolean verifyDrawable(Drawable who) {
7869        return who == mBGDrawable;
7870    }
7871
7872    /**
7873     * This function is called whenever the state of the view changes in such
7874     * a way that it impacts the state of drawables being shown.
7875     *
7876     * <p>Be sure to call through to the superclass when overriding this
7877     * function.
7878     *
7879     * @see Drawable#setState
7880     */
7881    protected void drawableStateChanged() {
7882        Drawable d = mBGDrawable;
7883        if (d != null && d.isStateful()) {
7884            d.setState(getDrawableState());
7885        }
7886    }
7887
7888    /**
7889     * Call this to force a view to update its drawable state. This will cause
7890     * drawableStateChanged to be called on this view. Views that are interested
7891     * in the new state should call getDrawableState.
7892     *
7893     * @see #drawableStateChanged
7894     * @see #getDrawableState
7895     */
7896    public void refreshDrawableState() {
7897        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
7898        drawableStateChanged();
7899
7900        ViewParent parent = mParent;
7901        if (parent != null) {
7902            parent.childDrawableStateChanged(this);
7903        }
7904    }
7905
7906    /**
7907     * Return an array of resource IDs of the drawable states representing the
7908     * current state of the view.
7909     *
7910     * @return The current drawable state
7911     *
7912     * @see Drawable#setState
7913     * @see #drawableStateChanged
7914     * @see #onCreateDrawableState
7915     */
7916    public final int[] getDrawableState() {
7917        if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
7918            return mDrawableState;
7919        } else {
7920            mDrawableState = onCreateDrawableState(0);
7921            mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
7922            return mDrawableState;
7923        }
7924    }
7925
7926    /**
7927     * Generate the new {@link android.graphics.drawable.Drawable} state for
7928     * this view. This is called by the view
7929     * system when the cached Drawable state is determined to be invalid.  To
7930     * retrieve the current state, you should use {@link #getDrawableState}.
7931     *
7932     * @param extraSpace if non-zero, this is the number of extra entries you
7933     * would like in the returned array in which you can place your own
7934     * states.
7935     *
7936     * @return Returns an array holding the current {@link Drawable} state of
7937     * the view.
7938     *
7939     * @see #mergeDrawableStates
7940     */
7941    protected int[] onCreateDrawableState(int extraSpace) {
7942        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
7943                mParent instanceof View) {
7944            return ((View) mParent).onCreateDrawableState(extraSpace);
7945        }
7946
7947        int[] drawableState;
7948
7949        int privateFlags = mPrivateFlags;
7950
7951        int viewStateIndex = (((privateFlags & PRESSED) != 0) ? 1 : 0);
7952
7953        viewStateIndex = (viewStateIndex << 1)
7954                + (((mViewFlags & ENABLED_MASK) == ENABLED) ? 1 : 0);
7955
7956        viewStateIndex = (viewStateIndex << 1) + (isFocused() ? 1 : 0);
7957
7958        viewStateIndex = (viewStateIndex << 1)
7959                + (((privateFlags & SELECTED) != 0) ? 1 : 0);
7960
7961        final boolean hasWindowFocus = hasWindowFocus();
7962        viewStateIndex = (viewStateIndex << 1) + (hasWindowFocus ? 1 : 0);
7963
7964        drawableState = VIEW_STATE_SETS[viewStateIndex];
7965
7966        //noinspection ConstantIfStatement
7967        if (false) {
7968            Log.i("View", "drawableStateIndex=" + viewStateIndex);
7969            Log.i("View", toString()
7970                    + " pressed=" + ((privateFlags & PRESSED) != 0)
7971                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
7972                    + " fo=" + hasFocus()
7973                    + " sl=" + ((privateFlags & SELECTED) != 0)
7974                    + " wf=" + hasWindowFocus
7975                    + ": " + Arrays.toString(drawableState));
7976        }
7977
7978        if (extraSpace == 0) {
7979            return drawableState;
7980        }
7981
7982        final int[] fullState;
7983        if (drawableState != null) {
7984            fullState = new int[drawableState.length + extraSpace];
7985            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
7986        } else {
7987            fullState = new int[extraSpace];
7988        }
7989
7990        return fullState;
7991    }
7992
7993    /**
7994     * Merge your own state values in <var>additionalState</var> into the base
7995     * state values <var>baseState</var> that were returned by
7996     * {@link #onCreateDrawableState}.
7997     *
7998     * @param baseState The base state values returned by
7999     * {@link #onCreateDrawableState}, which will be modified to also hold your
8000     * own additional state values.
8001     *
8002     * @param additionalState The additional state values you would like
8003     * added to <var>baseState</var>; this array is not modified.
8004     *
8005     * @return As a convenience, the <var>baseState</var> array you originally
8006     * passed into the function is returned.
8007     *
8008     * @see #onCreateDrawableState
8009     */
8010    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
8011        final int N = baseState.length;
8012        int i = N - 1;
8013        while (i >= 0 && baseState[i] == 0) {
8014            i--;
8015        }
8016        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
8017        return baseState;
8018    }
8019
8020    /**
8021     * Sets the background color for this view.
8022     * @param color the color of the background
8023     */
8024    @RemotableViewMethod
8025    public void setBackgroundColor(int color) {
8026        setBackgroundDrawable(new ColorDrawable(color));
8027    }
8028
8029    /**
8030     * Set the background to a given resource. The resource should refer to
8031     * a Drawable object or 0 to remove the background.
8032     * @param resid The identifier of the resource.
8033     * @attr ref android.R.styleable#View_background
8034     */
8035    @RemotableViewMethod
8036    public void setBackgroundResource(int resid) {
8037        if (resid != 0 && resid == mBackgroundResource) {
8038            return;
8039        }
8040
8041        Drawable d= null;
8042        if (resid != 0) {
8043            d = mResources.getDrawable(resid);
8044        }
8045        setBackgroundDrawable(d);
8046
8047        mBackgroundResource = resid;
8048    }
8049
8050    /**
8051     * Set the background to a given Drawable, or remove the background. If the
8052     * background has padding, this View's padding is set to the background's
8053     * padding. However, when a background is removed, this View's padding isn't
8054     * touched. If setting the padding is desired, please use
8055     * {@link #setPadding(int, int, int, int)}.
8056     *
8057     * @param d The Drawable to use as the background, or null to remove the
8058     *        background
8059     */
8060    public void setBackgroundDrawable(Drawable d) {
8061        boolean requestLayout = false;
8062
8063        mBackgroundResource = 0;
8064
8065        /*
8066         * Regardless of whether we're setting a new background or not, we want
8067         * to clear the previous drawable.
8068         */
8069        if (mBGDrawable != null) {
8070            mBGDrawable.setCallback(null);
8071            unscheduleDrawable(mBGDrawable);
8072        }
8073
8074        if (d != null) {
8075            Rect padding = sThreadLocal.get();
8076            if (padding == null) {
8077                padding = new Rect();
8078                sThreadLocal.set(padding);
8079            }
8080            if (d.getPadding(padding)) {
8081                setPadding(padding.left, padding.top, padding.right, padding.bottom);
8082            }
8083
8084            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
8085            // if it has a different minimum size, we should layout again
8086            if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
8087                    mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
8088                requestLayout = true;
8089            }
8090
8091            d.setCallback(this);
8092            if (d.isStateful()) {
8093                d.setState(getDrawableState());
8094            }
8095            d.setVisible(getVisibility() == VISIBLE, false);
8096            mBGDrawable = d;
8097
8098            if ((mPrivateFlags & SKIP_DRAW) != 0) {
8099                mPrivateFlags &= ~SKIP_DRAW;
8100                mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
8101                requestLayout = true;
8102            }
8103        } else {
8104            /* Remove the background */
8105            mBGDrawable = null;
8106
8107            if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
8108                /*
8109                 * This view ONLY drew the background before and we're removing
8110                 * the background, so now it won't draw anything
8111                 * (hence we SKIP_DRAW)
8112                 */
8113                mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
8114                mPrivateFlags |= SKIP_DRAW;
8115            }
8116
8117            /*
8118             * When the background is set, we try to apply its padding to this
8119             * View. When the background is removed, we don't touch this View's
8120             * padding. This is noted in the Javadocs. Hence, we don't need to
8121             * requestLayout(), the invalidate() below is sufficient.
8122             */
8123
8124            // The old background's minimum size could have affected this
8125            // View's layout, so let's requestLayout
8126            requestLayout = true;
8127        }
8128
8129        computeOpaqueFlags();
8130
8131        if (requestLayout) {
8132            requestLayout();
8133        }
8134
8135        mBackgroundSizeChanged = true;
8136        invalidate();
8137    }
8138
8139    /**
8140     * Gets the background drawable
8141     * @return The drawable used as the background for this view, if any.
8142     */
8143    public Drawable getBackground() {
8144        return mBGDrawable;
8145    }
8146
8147    /**
8148     * Sets the padding. The view may add on the space required to display
8149     * the scrollbars, depending on the style and visibility of the scrollbars.
8150     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
8151     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
8152     * from the values set in this call.
8153     *
8154     * @attr ref android.R.styleable#View_padding
8155     * @attr ref android.R.styleable#View_paddingBottom
8156     * @attr ref android.R.styleable#View_paddingLeft
8157     * @attr ref android.R.styleable#View_paddingRight
8158     * @attr ref android.R.styleable#View_paddingTop
8159     * @param left the left padding in pixels
8160     * @param top the top padding in pixels
8161     * @param right the right padding in pixels
8162     * @param bottom the bottom padding in pixels
8163     */
8164    public void setPadding(int left, int top, int right, int bottom) {
8165        boolean changed = false;
8166
8167        mUserPaddingRight = right;
8168        mUserPaddingBottom = bottom;
8169
8170        final int viewFlags = mViewFlags;
8171
8172        // Common case is there are no scroll bars.
8173        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
8174            // TODO: Deal with RTL languages to adjust left padding instead of right.
8175            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
8176                right += (viewFlags & SCROLLBARS_INSET_MASK) == 0
8177                        ? 0 : getVerticalScrollbarWidth();
8178            }
8179            if ((viewFlags & SCROLLBARS_HORIZONTAL) == 0) {
8180                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
8181                        ? 0 : getHorizontalScrollbarHeight();
8182            }
8183        }
8184
8185        if (mPaddingLeft != left) {
8186            changed = true;
8187            mPaddingLeft = left;
8188        }
8189        if (mPaddingTop != top) {
8190            changed = true;
8191            mPaddingTop = top;
8192        }
8193        if (mPaddingRight != right) {
8194            changed = true;
8195            mPaddingRight = right;
8196        }
8197        if (mPaddingBottom != bottom) {
8198            changed = true;
8199            mPaddingBottom = bottom;
8200        }
8201
8202        if (changed) {
8203            requestLayout();
8204        }
8205    }
8206
8207    /**
8208     * Returns the top padding of this view.
8209     *
8210     * @return the top padding in pixels
8211     */
8212    public int getPaddingTop() {
8213        return mPaddingTop;
8214    }
8215
8216    /**
8217     * Returns the bottom padding of this view. If there are inset and enabled
8218     * scrollbars, this value may include the space required to display the
8219     * scrollbars as well.
8220     *
8221     * @return the bottom padding in pixels
8222     */
8223    public int getPaddingBottom() {
8224        return mPaddingBottom;
8225    }
8226
8227    /**
8228     * Returns the left padding of this view. If there are inset and enabled
8229     * scrollbars, this value may include the space required to display the
8230     * scrollbars as well.
8231     *
8232     * @return the left padding in pixels
8233     */
8234    public int getPaddingLeft() {
8235        return mPaddingLeft;
8236    }
8237
8238    /**
8239     * Returns the right padding of this view. If there are inset and enabled
8240     * scrollbars, this value may include the space required to display the
8241     * scrollbars as well.
8242     *
8243     * @return the right padding in pixels
8244     */
8245    public int getPaddingRight() {
8246        return mPaddingRight;
8247    }
8248
8249    /**
8250     * Changes the selection state of this view. A view can be selected or not.
8251     * Note that selection is not the same as focus. Views are typically
8252     * selected in the context of an AdapterView like ListView or GridView;
8253     * the selected view is the view that is highlighted.
8254     *
8255     * @param selected true if the view must be selected, false otherwise
8256     */
8257    public void setSelected(boolean selected) {
8258        if (((mPrivateFlags & SELECTED) != 0) != selected) {
8259            mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
8260            if (!selected) resetPressedState();
8261            invalidate();
8262            refreshDrawableState();
8263            dispatchSetSelected(selected);
8264        }
8265    }
8266
8267    /**
8268     * Dispatch setSelected to all of this View's children.
8269     *
8270     * @see #setSelected(boolean)
8271     *
8272     * @param selected The new selected state
8273     */
8274    protected void dispatchSetSelected(boolean selected) {
8275    }
8276
8277    /**
8278     * Indicates the selection state of this view.
8279     *
8280     * @return true if the view is selected, false otherwise
8281     */
8282    @ViewDebug.ExportedProperty
8283    public boolean isSelected() {
8284        return (mPrivateFlags & SELECTED) != 0;
8285    }
8286
8287    /**
8288     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
8289     * observer can be used to get notifications when global events, like
8290     * layout, happen.
8291     *
8292     * The returned ViewTreeObserver observer is not guaranteed to remain
8293     * valid for the lifetime of this View. If the caller of this method keeps
8294     * a long-lived reference to ViewTreeObserver, it should always check for
8295     * the return value of {@link ViewTreeObserver#isAlive()}.
8296     *
8297     * @return The ViewTreeObserver for this view's hierarchy.
8298     */
8299    public ViewTreeObserver getViewTreeObserver() {
8300        if (mAttachInfo != null) {
8301            return mAttachInfo.mTreeObserver;
8302        }
8303        if (mFloatingTreeObserver == null) {
8304            mFloatingTreeObserver = new ViewTreeObserver();
8305        }
8306        return mFloatingTreeObserver;
8307    }
8308
8309    /**
8310     * <p>Finds the topmost view in the current view hierarchy.</p>
8311     *
8312     * @return the topmost view containing this view
8313     */
8314    public View getRootView() {
8315        if (mAttachInfo != null) {
8316            final View v = mAttachInfo.mRootView;
8317            if (v != null) {
8318                return v;
8319            }
8320        }
8321
8322        View parent = this;
8323
8324        while (parent.mParent != null && parent.mParent instanceof View) {
8325            parent = (View) parent.mParent;
8326        }
8327
8328        return parent;
8329    }
8330
8331    /**
8332     * <p>Computes the coordinates of this view on the screen. The argument
8333     * must be an array of two integers. After the method returns, the array
8334     * contains the x and y location in that order.</p>
8335     *
8336     * @param location an array of two integers in which to hold the coordinates
8337     */
8338    public void getLocationOnScreen(int[] location) {
8339        getLocationInWindow(location);
8340
8341        final AttachInfo info = mAttachInfo;
8342        if (info != null) {
8343            location[0] += info.mWindowLeft;
8344            location[1] += info.mWindowTop;
8345        }
8346    }
8347
8348    /**
8349     * <p>Computes the coordinates of this view in its window. The argument
8350     * must be an array of two integers. After the method returns, the array
8351     * contains the x and y location in that order.</p>
8352     *
8353     * @param location an array of two integers in which to hold the coordinates
8354     */
8355    public void getLocationInWindow(int[] location) {
8356        if (location == null || location.length < 2) {
8357            throw new IllegalArgumentException("location must be an array of "
8358                    + "two integers");
8359        }
8360
8361        location[0] = mLeft;
8362        location[1] = mTop;
8363
8364        ViewParent viewParent = mParent;
8365        while (viewParent instanceof View) {
8366            final View view = (View)viewParent;
8367            location[0] += view.mLeft - view.mScrollX;
8368            location[1] += view.mTop - view.mScrollY;
8369            viewParent = view.mParent;
8370        }
8371
8372        if (viewParent instanceof ViewRoot) {
8373            // *cough*
8374            final ViewRoot vr = (ViewRoot)viewParent;
8375            location[1] -= vr.mCurScrollY;
8376        }
8377    }
8378
8379    /**
8380     * {@hide}
8381     * @param id the id of the view to be found
8382     * @return the view of the specified id, null if cannot be found
8383     */
8384    protected View findViewTraversal(int id) {
8385        if (id == mID) {
8386            return this;
8387        }
8388        return null;
8389    }
8390
8391    /**
8392     * {@hide}
8393     * @param tag the tag of the view to be found
8394     * @return the view of specified tag, null if cannot be found
8395     */
8396    protected View findViewWithTagTraversal(Object tag) {
8397        if (tag != null && tag.equals(mTag)) {
8398            return this;
8399        }
8400        return null;
8401    }
8402
8403    /**
8404     * Look for a child view with the given id.  If this view has the given
8405     * id, return this view.
8406     *
8407     * @param id The id to search for.
8408     * @return The view that has the given id in the hierarchy or null
8409     */
8410    public final View findViewById(int id) {
8411        if (id < 0) {
8412            return null;
8413        }
8414        return findViewTraversal(id);
8415    }
8416
8417    /**
8418     * Look for a child view with the given tag.  If this view has the given
8419     * tag, return this view.
8420     *
8421     * @param tag The tag to search for, using "tag.equals(getTag())".
8422     * @return The View that has the given tag in the hierarchy or null
8423     */
8424    public final View findViewWithTag(Object tag) {
8425        if (tag == null) {
8426            return null;
8427        }
8428        return findViewWithTagTraversal(tag);
8429    }
8430
8431    /**
8432     * Sets the identifier for this view. The identifier does not have to be
8433     * unique in this view's hierarchy. The identifier should be a positive
8434     * number.
8435     *
8436     * @see #NO_ID
8437     * @see #getId
8438     * @see #findViewById
8439     *
8440     * @param id a number used to identify the view
8441     *
8442     * @attr ref android.R.styleable#View_id
8443     */
8444    public void setId(int id) {
8445        mID = id;
8446    }
8447
8448    /**
8449     * {@hide}
8450     *
8451     * @param isRoot true if the view belongs to the root namespace, false
8452     *        otherwise
8453     */
8454    public void setIsRootNamespace(boolean isRoot) {
8455        if (isRoot) {
8456            mPrivateFlags |= IS_ROOT_NAMESPACE;
8457        } else {
8458            mPrivateFlags &= ~IS_ROOT_NAMESPACE;
8459        }
8460    }
8461
8462    /**
8463     * {@hide}
8464     *
8465     * @return true if the view belongs to the root namespace, false otherwise
8466     */
8467    public boolean isRootNamespace() {
8468        return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
8469    }
8470
8471    /**
8472     * Returns this view's identifier.
8473     *
8474     * @return a positive integer used to identify the view or {@link #NO_ID}
8475     *         if the view has no ID
8476     *
8477     * @see #setId
8478     * @see #findViewById
8479     * @attr ref android.R.styleable#View_id
8480     */
8481    @ViewDebug.CapturedViewProperty
8482    public int getId() {
8483        return mID;
8484    }
8485
8486    /**
8487     * Returns this view's tag.
8488     *
8489     * @return the Object stored in this view as a tag
8490     *
8491     * @see #setTag(Object)
8492     * @see #getTag(int)
8493     */
8494    @ViewDebug.ExportedProperty
8495    public Object getTag() {
8496        return mTag;
8497    }
8498
8499    /**
8500     * Sets the tag associated with this view. A tag can be used to mark
8501     * a view in its hierarchy and does not have to be unique within the
8502     * hierarchy. Tags can also be used to store data within a view without
8503     * resorting to another data structure.
8504     *
8505     * @param tag an Object to tag the view with
8506     *
8507     * @see #getTag()
8508     * @see #setTag(int, Object)
8509     */
8510    public void setTag(final Object tag) {
8511        mTag = tag;
8512    }
8513
8514    /**
8515     * Returns the tag associated with this view and the specified key.
8516     *
8517     * @param key The key identifying the tag
8518     *
8519     * @return the Object stored in this view as a tag
8520     *
8521     * @see #setTag(int, Object)
8522     * @see #getTag()
8523     */
8524    public Object getTag(int key) {
8525        SparseArray<Object> tags = null;
8526        synchronized (sTagsLock) {
8527            if (sTags != null) {
8528                tags = sTags.get(this);
8529            }
8530        }
8531
8532        if (tags != null) return tags.get(key);
8533        return null;
8534    }
8535
8536    /**
8537     * Sets a tag associated with this view and a key. A tag can be used
8538     * to mark a view in its hierarchy and does not have to be unique within
8539     * the hierarchy. Tags can also be used to store data within a view
8540     * without resorting to another data structure.
8541     *
8542     * The specified key should be an id declared in the resources of the
8543     * application to ensure it is unique (see the <a
8544     * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
8545     * Keys identified as belonging to
8546     * the Android framework or not associated with any package will cause
8547     * an {@link IllegalArgumentException} to be thrown.
8548     *
8549     * @param key The key identifying the tag
8550     * @param tag An Object to tag the view with
8551     *
8552     * @throws IllegalArgumentException If they specified key is not valid
8553     *
8554     * @see #setTag(Object)
8555     * @see #getTag(int)
8556     */
8557    public void setTag(int key, final Object tag) {
8558        // If the package id is 0x00 or 0x01, it's either an undefined package
8559        // or a framework id
8560        if ((key >>> 24) < 2) {
8561            throw new IllegalArgumentException("The key must be an application-specific "
8562                    + "resource id.");
8563        }
8564
8565        setTagInternal(this, key, tag);
8566    }
8567
8568    /**
8569     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
8570     * framework id.
8571     *
8572     * @hide
8573     */
8574    public void setTagInternal(int key, Object tag) {
8575        if ((key >>> 24) != 0x1) {
8576            throw new IllegalArgumentException("The key must be a framework-specific "
8577                    + "resource id.");
8578        }
8579
8580        setTagInternal(this, key, tag);
8581    }
8582
8583    private static void setTagInternal(View view, int key, Object tag) {
8584        SparseArray<Object> tags = null;
8585        synchronized (sTagsLock) {
8586            if (sTags == null) {
8587                sTags = new WeakHashMap<View, SparseArray<Object>>();
8588            } else {
8589                tags = sTags.get(view);
8590            }
8591        }
8592
8593        if (tags == null) {
8594            tags = new SparseArray<Object>(2);
8595            synchronized (sTagsLock) {
8596                sTags.put(view, tags);
8597            }
8598        }
8599
8600        tags.put(key, tag);
8601    }
8602
8603    /**
8604     * @param consistency The type of consistency. See ViewDebug for more information.
8605     *
8606     * @hide
8607     */
8608    protected boolean dispatchConsistencyCheck(int consistency) {
8609        return onConsistencyCheck(consistency);
8610    }
8611
8612    /**
8613     * Method that subclasses should implement to check their consistency. The type of
8614     * consistency check is indicated by the bit field passed as a parameter.
8615     *
8616     * @param consistency The type of consistency. See ViewDebug for more information.
8617     *
8618     * @throws IllegalStateException if the view is in an inconsistent state.
8619     *
8620     * @hide
8621     */
8622    protected boolean onConsistencyCheck(int consistency) {
8623        boolean result = true;
8624
8625        final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
8626        final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0;
8627
8628        if (checkLayout) {
8629            if (getParent() == null) {
8630                result = false;
8631                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
8632                        "View " + this + " does not have a parent.");
8633            }
8634
8635            if (mAttachInfo == null) {
8636                result = false;
8637                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
8638                        "View " + this + " is not attached to a window.");
8639            }
8640        }
8641
8642        if (checkDrawing) {
8643            // Do not check the DIRTY/DRAWN flags because views can call invalidate()
8644            // from their draw() method
8645
8646            if ((mPrivateFlags & DRAWN) != DRAWN &&
8647                    (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
8648                result = false;
8649                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
8650                        "View " + this + " was invalidated but its drawing cache is valid.");
8651            }
8652        }
8653
8654        return result;
8655    }
8656
8657    /**
8658     * Prints information about this view in the log output, with the tag
8659     * {@link #VIEW_LOG_TAG}.
8660     *
8661     * @hide
8662     */
8663    public void debug() {
8664        debug(0);
8665    }
8666
8667    /**
8668     * Prints information about this view in the log output, with the tag
8669     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
8670     * indentation defined by the <code>depth</code>.
8671     *
8672     * @param depth the indentation level
8673     *
8674     * @hide
8675     */
8676    protected void debug(int depth) {
8677        String output = debugIndent(depth - 1);
8678
8679        output += "+ " + this;
8680        int id = getId();
8681        if (id != -1) {
8682            output += " (id=" + id + ")";
8683        }
8684        Object tag = getTag();
8685        if (tag != null) {
8686            output += " (tag=" + tag + ")";
8687        }
8688        Log.d(VIEW_LOG_TAG, output);
8689
8690        if ((mPrivateFlags & FOCUSED) != 0) {
8691            output = debugIndent(depth) + " FOCUSED";
8692            Log.d(VIEW_LOG_TAG, output);
8693        }
8694
8695        output = debugIndent(depth);
8696        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
8697                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
8698                + "} ";
8699        Log.d(VIEW_LOG_TAG, output);
8700
8701        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
8702                || mPaddingBottom != 0) {
8703            output = debugIndent(depth);
8704            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
8705                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
8706            Log.d(VIEW_LOG_TAG, output);
8707        }
8708
8709        output = debugIndent(depth);
8710        output += "mMeasureWidth=" + mMeasuredWidth +
8711                " mMeasureHeight=" + mMeasuredHeight;
8712        Log.d(VIEW_LOG_TAG, output);
8713
8714        output = debugIndent(depth);
8715        if (mLayoutParams == null) {
8716            output += "BAD! no layout params";
8717        } else {
8718            output = mLayoutParams.debug(output);
8719        }
8720        Log.d(VIEW_LOG_TAG, output);
8721
8722        output = debugIndent(depth);
8723        output += "flags={";
8724        output += View.printFlags(mViewFlags);
8725        output += "}";
8726        Log.d(VIEW_LOG_TAG, output);
8727
8728        output = debugIndent(depth);
8729        output += "privateFlags={";
8730        output += View.printPrivateFlags(mPrivateFlags);
8731        output += "}";
8732        Log.d(VIEW_LOG_TAG, output);
8733    }
8734
8735    /**
8736     * Creates an string of whitespaces used for indentation.
8737     *
8738     * @param depth the indentation level
8739     * @return a String containing (depth * 2 + 3) * 2 white spaces
8740     *
8741     * @hide
8742     */
8743    protected static String debugIndent(int depth) {
8744        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
8745        for (int i = 0; i < (depth * 2) + 3; i++) {
8746            spaces.append(' ').append(' ');
8747        }
8748        return spaces.toString();
8749    }
8750
8751    /**
8752     * <p>Return the offset of the widget's text baseline from the widget's top
8753     * boundary. If this widget does not support baseline alignment, this
8754     * method returns -1. </p>
8755     *
8756     * @return the offset of the baseline within the widget's bounds or -1
8757     *         if baseline alignment is not supported
8758     */
8759    @ViewDebug.ExportedProperty
8760    public int getBaseline() {
8761        return -1;
8762    }
8763
8764    /**
8765     * Call this when something has changed which has invalidated the
8766     * layout of this view. This will schedule a layout pass of the view
8767     * tree.
8768     */
8769    public void requestLayout() {
8770        if (ViewDebug.TRACE_HIERARCHY) {
8771            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT);
8772        }
8773
8774        mPrivateFlags |= FORCE_LAYOUT;
8775
8776        if (mParent != null && !mParent.isLayoutRequested()) {
8777            mParent.requestLayout();
8778        }
8779    }
8780
8781    /**
8782     * Forces this view to be laid out during the next layout pass.
8783     * This method does not call requestLayout() or forceLayout()
8784     * on the parent.
8785     */
8786    public void forceLayout() {
8787        mPrivateFlags |= FORCE_LAYOUT;
8788    }
8789
8790    /**
8791     * <p>
8792     * This is called to find out how big a view should be. The parent
8793     * supplies constraint information in the width and height parameters.
8794     * </p>
8795     *
8796     * <p>
8797     * The actual mesurement work of a view is performed in
8798     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
8799     * {@link #onMeasure(int, int)} can and must be overriden by subclasses.
8800     * </p>
8801     *
8802     *
8803     * @param widthMeasureSpec Horizontal space requirements as imposed by the
8804     *        parent
8805     * @param heightMeasureSpec Vertical space requirements as imposed by the
8806     *        parent
8807     *
8808     * @see #onMeasure(int, int)
8809     */
8810    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
8811        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
8812                widthMeasureSpec != mOldWidthMeasureSpec ||
8813                heightMeasureSpec != mOldHeightMeasureSpec) {
8814
8815            // first clears the measured dimension flag
8816            mPrivateFlags &= ~MEASURED_DIMENSION_SET;
8817
8818            if (ViewDebug.TRACE_HIERARCHY) {
8819                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
8820            }
8821
8822            // measure ourselves, this should set the measured dimension flag back
8823            onMeasure(widthMeasureSpec, heightMeasureSpec);
8824
8825            // flag not set, setMeasuredDimension() was not invoked, we raise
8826            // an exception to warn the developer
8827            if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
8828                throw new IllegalStateException("onMeasure() did not set the"
8829                        + " measured dimension by calling"
8830                        + " setMeasuredDimension()");
8831            }
8832
8833            mPrivateFlags |= LAYOUT_REQUIRED;
8834        }
8835
8836        mOldWidthMeasureSpec = widthMeasureSpec;
8837        mOldHeightMeasureSpec = heightMeasureSpec;
8838    }
8839
8840    /**
8841     * <p>
8842     * Measure the view and its content to determine the measured width and the
8843     * measured height. This method is invoked by {@link #measure(int, int)} and
8844     * should be overriden by subclasses to provide accurate and efficient
8845     * measurement of their contents.
8846     * </p>
8847     *
8848     * <p>
8849     * <strong>CONTRACT:</strong> When overriding this method, you
8850     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
8851     * measured width and height of this view. Failure to do so will trigger an
8852     * <code>IllegalStateException</code>, thrown by
8853     * {@link #measure(int, int)}. Calling the superclass'
8854     * {@link #onMeasure(int, int)} is a valid use.
8855     * </p>
8856     *
8857     * <p>
8858     * The base class implementation of measure defaults to the background size,
8859     * unless a larger size is allowed by the MeasureSpec. Subclasses should
8860     * override {@link #onMeasure(int, int)} to provide better measurements of
8861     * their content.
8862     * </p>
8863     *
8864     * <p>
8865     * If this method is overridden, it is the subclass's responsibility to make
8866     * sure the measured height and width are at least the view's minimum height
8867     * and width ({@link #getSuggestedMinimumHeight()} and
8868     * {@link #getSuggestedMinimumWidth()}).
8869     * </p>
8870     *
8871     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
8872     *                         The requirements are encoded with
8873     *                         {@link android.view.View.MeasureSpec}.
8874     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
8875     *                         The requirements are encoded with
8876     *                         {@link android.view.View.MeasureSpec}.
8877     *
8878     * @see #getMeasuredWidth()
8879     * @see #getMeasuredHeight()
8880     * @see #setMeasuredDimension(int, int)
8881     * @see #getSuggestedMinimumHeight()
8882     * @see #getSuggestedMinimumWidth()
8883     * @see android.view.View.MeasureSpec#getMode(int)
8884     * @see android.view.View.MeasureSpec#getSize(int)
8885     */
8886    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
8887        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
8888                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
8889    }
8890
8891    /**
8892     * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
8893     * measured width and measured height. Failing to do so will trigger an
8894     * exception at measurement time.</p>
8895     *
8896     * @param measuredWidth the measured width of this view
8897     * @param measuredHeight the measured height of this view
8898     */
8899    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
8900        mMeasuredWidth = measuredWidth;
8901        mMeasuredHeight = measuredHeight;
8902
8903        mPrivateFlags |= MEASURED_DIMENSION_SET;
8904    }
8905
8906    /**
8907     * Utility to reconcile a desired size with constraints imposed by a MeasureSpec.
8908     * Will take the desired size, unless a different size is imposed by the constraints.
8909     *
8910     * @param size How big the view wants to be
8911     * @param measureSpec Constraints imposed by the parent
8912     * @return The size this view should be.
8913     */
8914    public static int resolveSize(int size, int measureSpec) {
8915        int result = size;
8916        int specMode = MeasureSpec.getMode(measureSpec);
8917        int specSize =  MeasureSpec.getSize(measureSpec);
8918        switch (specMode) {
8919        case MeasureSpec.UNSPECIFIED:
8920            result = size;
8921            break;
8922        case MeasureSpec.AT_MOST:
8923            result = Math.min(size, specSize);
8924            break;
8925        case MeasureSpec.EXACTLY:
8926            result = specSize;
8927            break;
8928        }
8929        return result;
8930    }
8931
8932    /**
8933     * Utility to return a default size. Uses the supplied size if the
8934     * MeasureSpec imposed no contraints. Will get larger if allowed
8935     * by the MeasureSpec.
8936     *
8937     * @param size Default size for this view
8938     * @param measureSpec Constraints imposed by the parent
8939     * @return The size this view should be.
8940     */
8941    public static int getDefaultSize(int size, int measureSpec) {
8942        int result = size;
8943        int specMode = MeasureSpec.getMode(measureSpec);
8944        int specSize =  MeasureSpec.getSize(measureSpec);
8945
8946        switch (specMode) {
8947        case MeasureSpec.UNSPECIFIED:
8948            result = size;
8949            break;
8950        case MeasureSpec.AT_MOST:
8951        case MeasureSpec.EXACTLY:
8952            result = specSize;
8953            break;
8954        }
8955        return result;
8956    }
8957
8958    /**
8959     * Returns the suggested minimum height that the view should use. This
8960     * returns the maximum of the view's minimum height
8961     * and the background's minimum height
8962     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
8963     * <p>
8964     * When being used in {@link #onMeasure(int, int)}, the caller should still
8965     * ensure the returned height is within the requirements of the parent.
8966     *
8967     * @return The suggested minimum height of the view.
8968     */
8969    protected int getSuggestedMinimumHeight() {
8970        int suggestedMinHeight = mMinHeight;
8971
8972        if (mBGDrawable != null) {
8973            final int bgMinHeight = mBGDrawable.getMinimumHeight();
8974            if (suggestedMinHeight < bgMinHeight) {
8975                suggestedMinHeight = bgMinHeight;
8976            }
8977        }
8978
8979        return suggestedMinHeight;
8980    }
8981
8982    /**
8983     * Returns the suggested minimum width that the view should use. This
8984     * returns the maximum of the view's minimum width)
8985     * and the background's minimum width
8986     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
8987     * <p>
8988     * When being used in {@link #onMeasure(int, int)}, the caller should still
8989     * ensure the returned width is within the requirements of the parent.
8990     *
8991     * @return The suggested minimum width of the view.
8992     */
8993    protected int getSuggestedMinimumWidth() {
8994        int suggestedMinWidth = mMinWidth;
8995
8996        if (mBGDrawable != null) {
8997            final int bgMinWidth = mBGDrawable.getMinimumWidth();
8998            if (suggestedMinWidth < bgMinWidth) {
8999                suggestedMinWidth = bgMinWidth;
9000            }
9001        }
9002
9003        return suggestedMinWidth;
9004    }
9005
9006    /**
9007     * Sets the minimum height of the view. It is not guaranteed the view will
9008     * be able to achieve this minimum height (for example, if its parent layout
9009     * constrains it with less available height).
9010     *
9011     * @param minHeight The minimum height the view will try to be.
9012     */
9013    public void setMinimumHeight(int minHeight) {
9014        mMinHeight = minHeight;
9015    }
9016
9017    /**
9018     * Sets the minimum width of the view. It is not guaranteed the view will
9019     * be able to achieve this minimum width (for example, if its parent layout
9020     * constrains it with less available width).
9021     *
9022     * @param minWidth The minimum width the view will try to be.
9023     */
9024    public void setMinimumWidth(int minWidth) {
9025        mMinWidth = minWidth;
9026    }
9027
9028    /**
9029     * Get the animation currently associated with this view.
9030     *
9031     * @return The animation that is currently playing or
9032     *         scheduled to play for this view.
9033     */
9034    public Animation getAnimation() {
9035        return mCurrentAnimation;
9036    }
9037
9038    /**
9039     * Start the specified animation now.
9040     *
9041     * @param animation the animation to start now
9042     */
9043    public void startAnimation(Animation animation) {
9044        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
9045        setAnimation(animation);
9046        invalidate();
9047    }
9048
9049    /**
9050     * Cancels any animations for this view.
9051     */
9052    public void clearAnimation() {
9053        if (mCurrentAnimation != null) {
9054            mCurrentAnimation.detach();
9055        }
9056        mCurrentAnimation = null;
9057    }
9058
9059    /**
9060     * Sets the next animation to play for this view.
9061     * If you want the animation to play immediately, use
9062     * startAnimation. This method provides allows fine-grained
9063     * control over the start time and invalidation, but you
9064     * must make sure that 1) the animation has a start time set, and
9065     * 2) the view will be invalidated when the animation is supposed to
9066     * start.
9067     *
9068     * @param animation The next animation, or null.
9069     */
9070    public void setAnimation(Animation animation) {
9071        mCurrentAnimation = animation;
9072        if (animation != null) {
9073            animation.reset();
9074        }
9075    }
9076
9077    /**
9078     * Invoked by a parent ViewGroup to notify the start of the animation
9079     * currently associated with this view. If you override this method,
9080     * always call super.onAnimationStart();
9081     *
9082     * @see #setAnimation(android.view.animation.Animation)
9083     * @see #getAnimation()
9084     */
9085    protected void onAnimationStart() {
9086        mPrivateFlags |= ANIMATION_STARTED;
9087    }
9088
9089    /**
9090     * Invoked by a parent ViewGroup to notify the end of the animation
9091     * currently associated with this view. If you override this method,
9092     * always call super.onAnimationEnd();
9093     *
9094     * @see #setAnimation(android.view.animation.Animation)
9095     * @see #getAnimation()
9096     */
9097    protected void onAnimationEnd() {
9098        mPrivateFlags &= ~ANIMATION_STARTED;
9099    }
9100
9101    /**
9102     * Invoked if there is a Transform that involves alpha. Subclass that can
9103     * draw themselves with the specified alpha should return true, and then
9104     * respect that alpha when their onDraw() is called. If this returns false
9105     * then the view may be redirected to draw into an offscreen buffer to
9106     * fulfill the request, which will look fine, but may be slower than if the
9107     * subclass handles it internally. The default implementation returns false.
9108     *
9109     * @param alpha The alpha (0..255) to apply to the view's drawing
9110     * @return true if the view can draw with the specified alpha.
9111     */
9112    protected boolean onSetAlpha(int alpha) {
9113        return false;
9114    }
9115
9116    /**
9117     * This is used by the RootView to perform an optimization when
9118     * the view hierarchy contains one or several SurfaceView.
9119     * SurfaceView is always considered transparent, but its children are not,
9120     * therefore all View objects remove themselves from the global transparent
9121     * region (passed as a parameter to this function).
9122     *
9123     * @param region The transparent region for this ViewRoot (window).
9124     *
9125     * @return Returns true if the effective visibility of the view at this
9126     * point is opaque, regardless of the transparent region; returns false
9127     * if it is possible for underlying windows to be seen behind the view.
9128     *
9129     * {@hide}
9130     */
9131    public boolean gatherTransparentRegion(Region region) {
9132        final AttachInfo attachInfo = mAttachInfo;
9133        if (region != null && attachInfo != null) {
9134            final int pflags = mPrivateFlags;
9135            if ((pflags & SKIP_DRAW) == 0) {
9136                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
9137                // remove it from the transparent region.
9138                final int[] location = attachInfo.mTransparentLocation;
9139                getLocationInWindow(location);
9140                region.op(location[0], location[1], location[0] + mRight - mLeft,
9141                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
9142            } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) {
9143                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
9144                // exists, so we remove the background drawable's non-transparent
9145                // parts from this transparent region.
9146                applyDrawableToTransparentRegion(mBGDrawable, region);
9147            }
9148        }
9149        return true;
9150    }
9151
9152    /**
9153     * Play a sound effect for this view.
9154     *
9155     * <p>The framework will play sound effects for some built in actions, such as
9156     * clicking, but you may wish to play these effects in your widget,
9157     * for instance, for internal navigation.
9158     *
9159     * <p>The sound effect will only be played if sound effects are enabled by the user, and
9160     * {@link #isSoundEffectsEnabled()} is true.
9161     *
9162     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
9163     */
9164    public void playSoundEffect(int soundConstant) {
9165        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
9166            return;
9167        }
9168        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
9169    }
9170
9171    /**
9172     * BZZZTT!!1!
9173     *
9174     * <p>Provide haptic feedback to the user for this view.
9175     *
9176     * <p>The framework will provide haptic feedback for some built in actions,
9177     * such as long presses, but you may wish to provide feedback for your
9178     * own widget.
9179     *
9180     * <p>The feedback will only be performed if
9181     * {@link #isHapticFeedbackEnabled()} is true.
9182     *
9183     * @param feedbackConstant One of the constants defined in
9184     * {@link HapticFeedbackConstants}
9185     */
9186    public boolean performHapticFeedback(int feedbackConstant) {
9187        return performHapticFeedback(feedbackConstant, 0);
9188    }
9189
9190    /**
9191     * BZZZTT!!1!
9192     *
9193     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
9194     *
9195     * @param feedbackConstant One of the constants defined in
9196     * {@link HapticFeedbackConstants}
9197     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
9198     */
9199    public boolean performHapticFeedback(int feedbackConstant, int flags) {
9200        if (mAttachInfo == null) {
9201            return false;
9202        }
9203        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
9204                && !isHapticFeedbackEnabled()) {
9205            return false;
9206        }
9207        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
9208                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
9209    }
9210
9211    /**
9212     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
9213     * it is ever exposed at all.
9214     * @hide
9215     */
9216    public void onCloseSystemDialogs(String reason) {
9217    }
9218
9219    /**
9220     * Given a Drawable whose bounds have been set to draw into this view,
9221     * update a Region being computed for {@link #gatherTransparentRegion} so
9222     * that any non-transparent parts of the Drawable are removed from the
9223     * given transparent region.
9224     *
9225     * @param dr The Drawable whose transparency is to be applied to the region.
9226     * @param region A Region holding the current transparency information,
9227     * where any parts of the region that are set are considered to be
9228     * transparent.  On return, this region will be modified to have the
9229     * transparency information reduced by the corresponding parts of the
9230     * Drawable that are not transparent.
9231     * {@hide}
9232     */
9233    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
9234        if (DBG) {
9235            Log.i("View", "Getting transparent region for: " + this);
9236        }
9237        final Region r = dr.getTransparentRegion();
9238        final Rect db = dr.getBounds();
9239        final AttachInfo attachInfo = mAttachInfo;
9240        if (r != null && attachInfo != null) {
9241            final int w = getRight()-getLeft();
9242            final int h = getBottom()-getTop();
9243            if (db.left > 0) {
9244                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
9245                r.op(0, 0, db.left, h, Region.Op.UNION);
9246            }
9247            if (db.right < w) {
9248                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
9249                r.op(db.right, 0, w, h, Region.Op.UNION);
9250            }
9251            if (db.top > 0) {
9252                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
9253                r.op(0, 0, w, db.top, Region.Op.UNION);
9254            }
9255            if (db.bottom < h) {
9256                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
9257                r.op(0, db.bottom, w, h, Region.Op.UNION);
9258            }
9259            final int[] location = attachInfo.mTransparentLocation;
9260            getLocationInWindow(location);
9261            r.translate(location[0], location[1]);
9262            region.op(r, Region.Op.INTERSECT);
9263        } else {
9264            region.op(db, Region.Op.DIFFERENCE);
9265        }
9266    }
9267
9268    private void postCheckForLongClick(int delayOffset) {
9269        mHasPerformedLongPress = false;
9270
9271        if (mPendingCheckForLongPress == null) {
9272            mPendingCheckForLongPress = new CheckForLongPress();
9273        }
9274        mPendingCheckForLongPress.rememberWindowAttachCount();
9275        postDelayed(mPendingCheckForLongPress,
9276                ViewConfiguration.getLongPressTimeout() - delayOffset);
9277    }
9278
9279    private static int[] stateSetUnion(final int[] stateSet1, final int[] stateSet2) {
9280        final int stateSet1Length = stateSet1.length;
9281        final int stateSet2Length = stateSet2.length;
9282        final int[] newSet = new int[stateSet1Length + stateSet2Length];
9283        int k = 0;
9284        int i = 0;
9285        int j = 0;
9286        // This is a merge of the two input state sets and assumes that the
9287        // input sets are sorted by the order imposed by ViewDrawableStates.
9288        for (int viewState : R.styleable.ViewDrawableStates) {
9289            if (i < stateSet1Length && stateSet1[i] == viewState) {
9290                newSet[k++] = viewState;
9291                i++;
9292            } else if (j < stateSet2Length && stateSet2[j] == viewState) {
9293                newSet[k++] = viewState;
9294                j++;
9295            }
9296            if (k > 1) {
9297                assert(newSet[k - 1] > newSet[k - 2]);
9298            }
9299        }
9300        return newSet;
9301    }
9302
9303    /**
9304     * Inflate a view from an XML resource.  This convenience method wraps the {@link
9305     * LayoutInflater} class, which provides a full range of options for view inflation.
9306     *
9307     * @param context The Context object for your activity or application.
9308     * @param resource The resource ID to inflate
9309     * @param root A view group that will be the parent.  Used to properly inflate the
9310     * layout_* parameters.
9311     * @see LayoutInflater
9312     */
9313    public static View inflate(Context context, int resource, ViewGroup root) {
9314        LayoutInflater factory = LayoutInflater.from(context);
9315        return factory.inflate(resource, root);
9316    }
9317
9318    /**
9319     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
9320     * Each MeasureSpec represents a requirement for either the width or the height.
9321     * A MeasureSpec is comprised of a size and a mode. There are three possible
9322     * modes:
9323     * <dl>
9324     * <dt>UNSPECIFIED</dt>
9325     * <dd>
9326     * The parent has not imposed any constraint on the child. It can be whatever size
9327     * it wants.
9328     * </dd>
9329     *
9330     * <dt>EXACTLY</dt>
9331     * <dd>
9332     * The parent has determined an exact size for the child. The child is going to be
9333     * given those bounds regardless of how big it wants to be.
9334     * </dd>
9335     *
9336     * <dt>AT_MOST</dt>
9337     * <dd>
9338     * The child can be as large as it wants up to the specified size.
9339     * </dd>
9340     * </dl>
9341     *
9342     * MeasureSpecs are implemented as ints to reduce object allocation. This class
9343     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
9344     */
9345    public static class MeasureSpec {
9346        private static final int MODE_SHIFT = 30;
9347        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
9348
9349        /**
9350         * Measure specification mode: The parent has not imposed any constraint
9351         * on the child. It can be whatever size it wants.
9352         */
9353        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
9354
9355        /**
9356         * Measure specification mode: The parent has determined an exact size
9357         * for the child. The child is going to be given those bounds regardless
9358         * of how big it wants to be.
9359         */
9360        public static final int EXACTLY     = 1 << MODE_SHIFT;
9361
9362        /**
9363         * Measure specification mode: The child can be as large as it wants up
9364         * to the specified size.
9365         */
9366        public static final int AT_MOST     = 2 << MODE_SHIFT;
9367
9368        /**
9369         * Creates a measure specification based on the supplied size and mode.
9370         *
9371         * The mode must always be one of the following:
9372         * <ul>
9373         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
9374         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
9375         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
9376         * </ul>
9377         *
9378         * @param size the size of the measure specification
9379         * @param mode the mode of the measure specification
9380         * @return the measure specification based on size and mode
9381         */
9382        public static int makeMeasureSpec(int size, int mode) {
9383            return size + mode;
9384        }
9385
9386        /**
9387         * Extracts the mode from the supplied measure specification.
9388         *
9389         * @param measureSpec the measure specification to extract the mode from
9390         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
9391         *         {@link android.view.View.MeasureSpec#AT_MOST} or
9392         *         {@link android.view.View.MeasureSpec#EXACTLY}
9393         */
9394        public static int getMode(int measureSpec) {
9395            return (measureSpec & MODE_MASK);
9396        }
9397
9398        /**
9399         * Extracts the size from the supplied measure specification.
9400         *
9401         * @param measureSpec the measure specification to extract the size from
9402         * @return the size in pixels defined in the supplied measure specification
9403         */
9404        public static int getSize(int measureSpec) {
9405            return (measureSpec & ~MODE_MASK);
9406        }
9407
9408        /**
9409         * Returns a String representation of the specified measure
9410         * specification.
9411         *
9412         * @param measureSpec the measure specification to convert to a String
9413         * @return a String with the following format: "MeasureSpec: MODE SIZE"
9414         */
9415        public static String toString(int measureSpec) {
9416            int mode = getMode(measureSpec);
9417            int size = getSize(measureSpec);
9418
9419            StringBuilder sb = new StringBuilder("MeasureSpec: ");
9420
9421            if (mode == UNSPECIFIED)
9422                sb.append("UNSPECIFIED ");
9423            else if (mode == EXACTLY)
9424                sb.append("EXACTLY ");
9425            else if (mode == AT_MOST)
9426                sb.append("AT_MOST ");
9427            else
9428                sb.append(mode).append(" ");
9429
9430            sb.append(size);
9431            return sb.toString();
9432        }
9433    }
9434
9435    class CheckForLongPress implements Runnable {
9436
9437        private int mOriginalWindowAttachCount;
9438
9439        public void run() {
9440            if (isPressed() && (mParent != null)
9441                    && mOriginalWindowAttachCount == mWindowAttachCount) {
9442                if (performLongClick()) {
9443                    mHasPerformedLongPress = true;
9444                }
9445            }
9446        }
9447
9448        public void rememberWindowAttachCount() {
9449            mOriginalWindowAttachCount = mWindowAttachCount;
9450        }
9451    }
9452
9453    private final class CheckForTap implements Runnable {
9454        public void run() {
9455            mPrivateFlags &= ~PREPRESSED;
9456            mPrivateFlags |= PRESSED;
9457            refreshDrawableState();
9458            if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
9459                postCheckForLongClick(ViewConfiguration.getTapTimeout());
9460            }
9461        }
9462    }
9463
9464    private final class PerformClick implements Runnable {
9465        public void run() {
9466            performClick();
9467        }
9468    }
9469
9470    /**
9471     * Interface definition for a callback to be invoked when a key event is
9472     * dispatched to this view. The callback will be invoked before the key
9473     * event is given to the view.
9474     */
9475    public interface OnKeyListener {
9476        /**
9477         * Called when a key is dispatched to a view. This allows listeners to
9478         * get a chance to respond before the target view.
9479         *
9480         * @param v The view the key has been dispatched to.
9481         * @param keyCode The code for the physical key that was pressed
9482         * @param event The KeyEvent object containing full information about
9483         *        the event.
9484         * @return True if the listener has consumed the event, false otherwise.
9485         */
9486        boolean onKey(View v, int keyCode, KeyEvent event);
9487    }
9488
9489    /**
9490     * Interface definition for a callback to be invoked when a touch event is
9491     * dispatched to this view. The callback will be invoked before the touch
9492     * event is given to the view.
9493     */
9494    public interface OnTouchListener {
9495        /**
9496         * Called when a touch event is dispatched to a view. This allows listeners to
9497         * get a chance to respond before the target view.
9498         *
9499         * @param v The view the touch event has been dispatched to.
9500         * @param event The MotionEvent object containing full information about
9501         *        the event.
9502         * @return True if the listener has consumed the event, false otherwise.
9503         */
9504        boolean onTouch(View v, MotionEvent event);
9505    }
9506
9507    /**
9508     * Interface definition for a callback to be invoked when a view has been clicked and held.
9509     */
9510    public interface OnLongClickListener {
9511        /**
9512         * Called when a view has been clicked and held.
9513         *
9514         * @param v The view that was clicked and held.
9515         *
9516         * return True if the callback consumed the long click, false otherwise
9517         */
9518        boolean onLongClick(View v);
9519    }
9520
9521    /**
9522     * Interface definition for a callback to be invoked when the focus state of
9523     * a view changed.
9524     */
9525    public interface OnFocusChangeListener {
9526        /**
9527         * Called when the focus state of a view has changed.
9528         *
9529         * @param v The view whose state has changed.
9530         * @param hasFocus The new focus state of v.
9531         */
9532        void onFocusChange(View v, boolean hasFocus);
9533    }
9534
9535    /**
9536     * Interface definition for a callback to be invoked when a view is clicked.
9537     */
9538    public interface OnClickListener {
9539        /**
9540         * Called when a view has been clicked.
9541         *
9542         * @param v The view that was clicked.
9543         */
9544        void onClick(View v);
9545    }
9546
9547    /**
9548     * Interface definition for a callback to be invoked when the context menu
9549     * for this view is being built.
9550     */
9551    public interface OnCreateContextMenuListener {
9552        /**
9553         * Called when the context menu for this view is being built. It is not
9554         * safe to hold onto the menu after this method returns.
9555         *
9556         * @param menu The context menu that is being built
9557         * @param v The view for which the context menu is being built
9558         * @param menuInfo Extra information about the item for which the
9559         *            context menu should be shown. This information will vary
9560         *            depending on the class of v.
9561         */
9562        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
9563    }
9564
9565    private final class UnsetPressedState implements Runnable {
9566        public void run() {
9567            setPressed(false);
9568        }
9569    }
9570
9571    /**
9572     * Base class for derived classes that want to save and restore their own
9573     * state in {@link android.view.View#onSaveInstanceState()}.
9574     */
9575    public static class BaseSavedState extends AbsSavedState {
9576        /**
9577         * Constructor used when reading from a parcel. Reads the state of the superclass.
9578         *
9579         * @param source
9580         */
9581        public BaseSavedState(Parcel source) {
9582            super(source);
9583        }
9584
9585        /**
9586         * Constructor called by derived classes when creating their SavedState objects
9587         *
9588         * @param superState The state of the superclass of this view
9589         */
9590        public BaseSavedState(Parcelable superState) {
9591            super(superState);
9592        }
9593
9594        public static final Parcelable.Creator<BaseSavedState> CREATOR =
9595                new Parcelable.Creator<BaseSavedState>() {
9596            public BaseSavedState createFromParcel(Parcel in) {
9597                return new BaseSavedState(in);
9598            }
9599
9600            public BaseSavedState[] newArray(int size) {
9601                return new BaseSavedState[size];
9602            }
9603        };
9604    }
9605
9606    /**
9607     * A set of information given to a view when it is attached to its parent
9608     * window.
9609     */
9610    static class AttachInfo {
9611        interface Callbacks {
9612            void playSoundEffect(int effectId);
9613            boolean performHapticFeedback(int effectId, boolean always);
9614        }
9615
9616        /**
9617         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
9618         * to a Handler. This class contains the target (View) to invalidate and
9619         * the coordinates of the dirty rectangle.
9620         *
9621         * For performance purposes, this class also implements a pool of up to
9622         * POOL_LIMIT objects that get reused. This reduces memory allocations
9623         * whenever possible.
9624         */
9625        static class InvalidateInfo implements Poolable<InvalidateInfo> {
9626            private static final int POOL_LIMIT = 10;
9627            private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
9628                    Pools.finitePool(new PoolableManager<InvalidateInfo>() {
9629                        public InvalidateInfo newInstance() {
9630                            return new InvalidateInfo();
9631                        }
9632
9633                        public void onAcquired(InvalidateInfo element) {
9634                        }
9635
9636                        public void onReleased(InvalidateInfo element) {
9637                        }
9638                    }, POOL_LIMIT)
9639            );
9640
9641            private InvalidateInfo mNext;
9642
9643            View target;
9644
9645            int left;
9646            int top;
9647            int right;
9648            int bottom;
9649
9650            public void setNextPoolable(InvalidateInfo element) {
9651                mNext = element;
9652            }
9653
9654            public InvalidateInfo getNextPoolable() {
9655                return mNext;
9656            }
9657
9658            static InvalidateInfo acquire() {
9659                return sPool.acquire();
9660            }
9661
9662            void release() {
9663                sPool.release(this);
9664            }
9665        }
9666
9667        final IWindowSession mSession;
9668
9669        final IWindow mWindow;
9670
9671        final IBinder mWindowToken;
9672
9673        final Callbacks mRootCallbacks;
9674
9675        /**
9676         * The top view of the hierarchy.
9677         */
9678        View mRootView;
9679
9680        IBinder mPanelParentWindowToken;
9681        Surface mSurface;
9682
9683        /**
9684         * Scale factor used by the compatibility mode
9685         */
9686        float mApplicationScale;
9687
9688        /**
9689         * Indicates whether the application is in compatibility mode
9690         */
9691        boolean mScalingRequired;
9692
9693        /**
9694         * Left position of this view's window
9695         */
9696        int mWindowLeft;
9697
9698        /**
9699         * Top position of this view's window
9700         */
9701        int mWindowTop;
9702
9703        /**
9704         * Indicates whether the window is translucent/transparent
9705         */
9706        boolean mTranslucentWindow;
9707
9708        /**
9709         * For windows that are full-screen but using insets to layout inside
9710         * of the screen decorations, these are the current insets for the
9711         * content of the window.
9712         */
9713        final Rect mContentInsets = new Rect();
9714
9715        /**
9716         * For windows that are full-screen but using insets to layout inside
9717         * of the screen decorations, these are the current insets for the
9718         * actual visible parts of the window.
9719         */
9720        final Rect mVisibleInsets = new Rect();
9721
9722        /**
9723         * The internal insets given by this window.  This value is
9724         * supplied by the client (through
9725         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
9726         * be given to the window manager when changed to be used in laying
9727         * out windows behind it.
9728         */
9729        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
9730                = new ViewTreeObserver.InternalInsetsInfo();
9731
9732        /**
9733         * All views in the window's hierarchy that serve as scroll containers,
9734         * used to determine if the window can be resized or must be panned
9735         * to adjust for a soft input area.
9736         */
9737        final ArrayList<View> mScrollContainers = new ArrayList<View>();
9738
9739        final KeyEvent.DispatcherState mKeyDispatchState
9740                = new KeyEvent.DispatcherState();
9741
9742        /**
9743         * Indicates whether the view's window currently has the focus.
9744         */
9745        boolean mHasWindowFocus;
9746
9747        /**
9748         * The current visibility of the window.
9749         */
9750        int mWindowVisibility;
9751
9752        /**
9753         * Indicates the time at which drawing started to occur.
9754         */
9755        long mDrawingTime;
9756
9757        /**
9758         * Indicates whether or not ignoring the DIRTY_MASK flags.
9759         */
9760        boolean mIgnoreDirtyState;
9761
9762        /**
9763         * Indicates whether the view's window is currently in touch mode.
9764         */
9765        boolean mInTouchMode;
9766
9767        /**
9768         * Indicates that ViewRoot should trigger a global layout change
9769         * the next time it performs a traversal
9770         */
9771        boolean mRecomputeGlobalAttributes;
9772
9773        /**
9774         * Set during a traveral if any views want to keep the screen on.
9775         */
9776        boolean mKeepScreenOn;
9777
9778        /**
9779         * Set if the visibility of any views has changed.
9780         */
9781        boolean mViewVisibilityChanged;
9782
9783        /**
9784         * Set to true if a view has been scrolled.
9785         */
9786        boolean mViewScrollChanged;
9787
9788        /**
9789         * Global to the view hierarchy used as a temporary for dealing with
9790         * x/y points in the transparent region computations.
9791         */
9792        final int[] mTransparentLocation = new int[2];
9793
9794        /**
9795         * Global to the view hierarchy used as a temporary for dealing with
9796         * x/y points in the ViewGroup.invalidateChild implementation.
9797         */
9798        final int[] mInvalidateChildLocation = new int[2];
9799
9800
9801        /**
9802         * Global to the view hierarchy used as a temporary for dealing with
9803         * x/y location when view is transformed.
9804         */
9805        final float[] mTmpTransformLocation = new float[2];
9806
9807        /**
9808         * The view tree observer used to dispatch global events like
9809         * layout, pre-draw, touch mode change, etc.
9810         */
9811        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
9812
9813        /**
9814         * A Canvas used by the view hierarchy to perform bitmap caching.
9815         */
9816        Canvas mCanvas;
9817
9818        /**
9819         * A Handler supplied by a view's {@link android.view.ViewRoot}. This
9820         * handler can be used to pump events in the UI events queue.
9821         */
9822        final Handler mHandler;
9823
9824        /**
9825         * Identifier for messages requesting the view to be invalidated.
9826         * Such messages should be sent to {@link #mHandler}.
9827         */
9828        static final int INVALIDATE_MSG = 0x1;
9829
9830        /**
9831         * Identifier for messages requesting the view to invalidate a region.
9832         * Such messages should be sent to {@link #mHandler}.
9833         */
9834        static final int INVALIDATE_RECT_MSG = 0x2;
9835
9836        /**
9837         * Temporary for use in computing invalidate rectangles while
9838         * calling up the hierarchy.
9839         */
9840        final Rect mTmpInvalRect = new Rect();
9841
9842        /**
9843         * Temporary for use in computing hit areas with transformed views
9844         */
9845        final RectF mTmpTransformRect = new RectF();
9846
9847        /**
9848         * Temporary for use in computing invalidation areas with transformed views
9849         */
9850        final float[] mTmpTransformBounds = new float[8];
9851
9852        /**
9853         * Temporary list for use in collecting focusable descendents of a view.
9854         */
9855        final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24);
9856
9857        /**
9858         * Creates a new set of attachment information with the specified
9859         * events handler and thread.
9860         *
9861         * @param handler the events handler the view must use
9862         */
9863        AttachInfo(IWindowSession session, IWindow window,
9864                Handler handler, Callbacks effectPlayer) {
9865            mSession = session;
9866            mWindow = window;
9867            mWindowToken = window.asBinder();
9868            mHandler = handler;
9869            mRootCallbacks = effectPlayer;
9870        }
9871    }
9872
9873    /**
9874     * <p>ScrollabilityCache holds various fields used by a View when scrolling
9875     * is supported. This avoids keeping too many unused fields in most
9876     * instances of View.</p>
9877     */
9878    private static class ScrollabilityCache implements Runnable {
9879
9880        /**
9881         * Scrollbars are not visible
9882         */
9883        public static final int OFF = 0;
9884
9885        /**
9886         * Scrollbars are visible
9887         */
9888        public static final int ON = 1;
9889
9890        /**
9891         * Scrollbars are fading away
9892         */
9893        public static final int FADING = 2;
9894
9895        public boolean fadeScrollBars;
9896
9897        public int fadingEdgeLength;
9898        public int scrollBarDefaultDelayBeforeFade;
9899        public int scrollBarFadeDuration;
9900
9901        public int scrollBarSize;
9902        public ScrollBarDrawable scrollBar;
9903        public float[] interpolatorValues;
9904        public View host;
9905
9906        public final Paint paint;
9907        public final Matrix matrix;
9908        public Shader shader;
9909
9910        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
9911
9912        private final float[] mOpaque = {255.0f};
9913        private final float[] mTransparent = {0.0f};
9914
9915        /**
9916         * When fading should start. This time moves into the future every time
9917         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
9918         */
9919        public long fadeStartTime;
9920
9921
9922        /**
9923         * The current state of the scrollbars: ON, OFF, or FADING
9924         */
9925        public int state = OFF;
9926
9927        private int mLastColor;
9928
9929        public ScrollabilityCache(ViewConfiguration configuration, View host) {
9930            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
9931            scrollBarSize = configuration.getScaledScrollBarSize();
9932            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
9933            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
9934
9935            paint = new Paint();
9936            matrix = new Matrix();
9937            // use use a height of 1, and then wack the matrix each time we
9938            // actually use it.
9939            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
9940
9941            paint.setShader(shader);
9942            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
9943            this.host = host;
9944        }
9945
9946        public void setFadeColor(int color) {
9947            if (color != 0 && color != mLastColor) {
9948                mLastColor = color;
9949                color |= 0xFF000000;
9950
9951                shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
9952                        color & 0x00FFFFFF, Shader.TileMode.CLAMP);
9953
9954                paint.setShader(shader);
9955                // Restore the default transfer mode (src_over)
9956                paint.setXfermode(null);
9957            }
9958        }
9959
9960        public void run() {
9961            long now = AnimationUtils.currentAnimationTimeMillis();
9962            if (now >= fadeStartTime) {
9963
9964                // the animation fades the scrollbars out by changing
9965                // the opacity (alpha) from fully opaque to fully
9966                // transparent
9967                int nextFrame = (int) now;
9968                int framesCount = 0;
9969
9970                Interpolator interpolator = scrollBarInterpolator;
9971
9972                // Start opaque
9973                interpolator.setKeyFrame(framesCount++, nextFrame, mOpaque);
9974
9975                // End transparent
9976                nextFrame += scrollBarFadeDuration;
9977                interpolator.setKeyFrame(framesCount, nextFrame, mTransparent);
9978
9979                state = FADING;
9980
9981                // Kick off the fade animation
9982                host.invalidate();
9983            }
9984        }
9985
9986    }
9987}
9988