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