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