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