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