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