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