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