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