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