View.java revision 035a1fcd5ea3ac0080bb74101cf2793ccb9aa689
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.content.ClipData;
20import android.content.Context;
21import android.content.res.Configuration;
22import android.content.res.Resources;
23import android.content.res.TypedArray;
24import android.graphics.Bitmap;
25import android.graphics.Camera;
26import android.graphics.Canvas;
27import android.graphics.Interpolator;
28import android.graphics.LinearGradient;
29import android.graphics.Matrix;
30import android.graphics.Paint;
31import android.graphics.PixelFormat;
32import android.graphics.Point;
33import android.graphics.PorterDuff;
34import android.graphics.PorterDuffXfermode;
35import android.graphics.Rect;
36import android.graphics.RectF;
37import android.graphics.Region;
38import android.graphics.Shader;
39import android.graphics.drawable.ColorDrawable;
40import android.graphics.drawable.Drawable;
41import android.os.Handler;
42import android.os.IBinder;
43import android.os.Message;
44import android.os.Parcel;
45import android.os.Parcelable;
46import android.os.RemoteException;
47import android.os.SystemClock;
48import android.text.TextUtils;
49import android.util.AttributeSet;
50import android.util.FloatProperty;
51import android.util.LocaleUtil;
52import android.util.Log;
53import android.util.Pool;
54import android.util.Poolable;
55import android.util.PoolableManager;
56import android.util.Pools;
57import android.util.Property;
58import android.util.SparseArray;
59import android.util.TypedValue;
60import android.view.ContextMenu.ContextMenuInfo;
61import android.view.accessibility.AccessibilityEvent;
62import android.view.accessibility.AccessibilityEventSource;
63import android.view.accessibility.AccessibilityManager;
64import android.view.accessibility.AccessibilityNodeInfo;
65import android.view.accessibility.AccessibilityNodeProvider;
66import android.view.animation.Animation;
67import android.view.animation.AnimationUtils;
68import android.view.animation.Transformation;
69import android.view.inputmethod.EditorInfo;
70import android.view.inputmethod.InputConnection;
71import android.view.inputmethod.InputMethodManager;
72import android.widget.ScrollBarDrawable;
73
74import static android.os.Build.VERSION_CODES.*;
75
76import com.android.internal.R;
77import com.android.internal.util.Predicate;
78import com.android.internal.view.menu.MenuBuilder;
79
80import java.lang.ref.WeakReference;
81import java.lang.reflect.InvocationTargetException;
82import java.lang.reflect.Method;
83import java.util.ArrayList;
84import java.util.Arrays;
85import java.util.Locale;
86import java.util.concurrent.CopyOnWriteArrayList;
87
88/**
89 * <p>
90 * This class represents the basic building block for user interface components. A View
91 * occupies a rectangular area on the screen and is responsible for drawing and
92 * event handling. View is the base class for <em>widgets</em>, which are
93 * used to create interactive UI components (buttons, text fields, etc.). The
94 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
95 * are invisible containers that hold other Views (or other ViewGroups) and define
96 * their layout properties.
97 * </p>
98 *
99 * <div class="special reference">
100 * <h3>Developer Guides</h3>
101 * <p>For information about using this class to develop your application's user interface,
102 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
103 * </div>
104 *
105 * <a name="Using"></a>
106 * <h3>Using Views</h3>
107 * <p>
108 * All of the views in a window are arranged in a single tree. You can add views
109 * either from code or by specifying a tree of views in one or more XML layout
110 * files. There are many specialized subclasses of views that act as controls or
111 * are capable of displaying text, images, or other content.
112 * </p>
113 * <p>
114 * Once you have created a tree of views, there are typically a few types of
115 * common operations you may wish to perform:
116 * <ul>
117 * <li><strong>Set properties:</strong> for example setting the text of a
118 * {@link android.widget.TextView}. The available properties and the methods
119 * that set them will vary among the different subclasses of views. Note that
120 * properties that are known at build time can be set in the XML layout
121 * files.</li>
122 * <li><strong>Set focus:</strong> The framework will handled moving focus in
123 * response to user input. To force focus to a specific view, call
124 * {@link #requestFocus}.</li>
125 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
126 * that will be notified when something interesting happens to the view. For
127 * example, all views will let you set a listener to be notified when the view
128 * gains or loses focus. You can register such a listener using
129 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
130 * Other view subclasses offer more specialized listeners. For example, a Button
131 * exposes a listener to notify clients when the button is clicked.</li>
132 * <li><strong>Set visibility:</strong> You can hide or show views using
133 * {@link #setVisibility(int)}.</li>
134 * </ul>
135 * </p>
136 * <p><em>
137 * Note: The Android framework is responsible for measuring, laying out and
138 * drawing views. You should not call methods that perform these actions on
139 * views yourself unless you are actually implementing a
140 * {@link android.view.ViewGroup}.
141 * </em></p>
142 *
143 * <a name="Lifecycle"></a>
144 * <h3>Implementing a Custom View</h3>
145 *
146 * <p>
147 * To implement a custom view, you will usually begin by providing overrides for
148 * some of the standard methods that the framework calls on all views. You do
149 * not need to override all of these methods. In fact, you can start by just
150 * overriding {@link #onDraw(android.graphics.Canvas)}.
151 * <table border="2" width="85%" align="center" cellpadding="5">
152 *     <thead>
153 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
154 *     </thead>
155 *
156 *     <tbody>
157 *     <tr>
158 *         <td rowspan="2">Creation</td>
159 *         <td>Constructors</td>
160 *         <td>There is a form of the constructor that are called when the view
161 *         is created from code and a form that is called when the view is
162 *         inflated from a layout file. The second form should parse and apply
163 *         any attributes defined in the layout file.
164 *         </td>
165 *     </tr>
166 *     <tr>
167 *         <td><code>{@link #onFinishInflate()}</code></td>
168 *         <td>Called after a view and all of its children has been inflated
169 *         from XML.</td>
170 *     </tr>
171 *
172 *     <tr>
173 *         <td rowspan="3">Layout</td>
174 *         <td><code>{@link #onMeasure(int, int)}</code></td>
175 *         <td>Called to determine the size requirements for this view and all
176 *         of its children.
177 *         </td>
178 *     </tr>
179 *     <tr>
180 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
181 *         <td>Called when this view should assign a size and position to all
182 *         of its children.
183 *         </td>
184 *     </tr>
185 *     <tr>
186 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
187 *         <td>Called when the size of this view has changed.
188 *         </td>
189 *     </tr>
190 *
191 *     <tr>
192 *         <td>Drawing</td>
193 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
194 *         <td>Called when the view should render its content.
195 *         </td>
196 *     </tr>
197 *
198 *     <tr>
199 *         <td rowspan="4">Event processing</td>
200 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
201 *         <td>Called when a new key event occurs.
202 *         </td>
203 *     </tr>
204 *     <tr>
205 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
206 *         <td>Called when a key up event occurs.
207 *         </td>
208 *     </tr>
209 *     <tr>
210 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
211 *         <td>Called when a trackball motion event occurs.
212 *         </td>
213 *     </tr>
214 *     <tr>
215 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
216 *         <td>Called when a touch screen motion event occurs.
217 *         </td>
218 *     </tr>
219 *
220 *     <tr>
221 *         <td rowspan="2">Focus</td>
222 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
223 *         <td>Called when the view gains or loses focus.
224 *         </td>
225 *     </tr>
226 *
227 *     <tr>
228 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
229 *         <td>Called when the window containing the view gains or loses focus.
230 *         </td>
231 *     </tr>
232 *
233 *     <tr>
234 *         <td rowspan="3">Attaching</td>
235 *         <td><code>{@link #onAttachedToWindow()}</code></td>
236 *         <td>Called when the view is attached to a window.
237 *         </td>
238 *     </tr>
239 *
240 *     <tr>
241 *         <td><code>{@link #onDetachedFromWindow}</code></td>
242 *         <td>Called when the view is detached from its window.
243 *         </td>
244 *     </tr>
245 *
246 *     <tr>
247 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
248 *         <td>Called when the visibility of the window containing the view
249 *         has changed.
250 *         </td>
251 *     </tr>
252 *     </tbody>
253 *
254 * </table>
255 * </p>
256 *
257 * <a name="IDs"></a>
258 * <h3>IDs</h3>
259 * Views may have an integer id associated with them. These ids are typically
260 * assigned in the layout XML files, and are used to find specific views within
261 * the view tree. A common pattern is to:
262 * <ul>
263 * <li>Define a Button in the layout file and assign it a unique ID.
264 * <pre>
265 * &lt;Button
266 *     android:id="@+id/my_button"
267 *     android:layout_width="wrap_content"
268 *     android:layout_height="wrap_content"
269 *     android:text="@string/my_button_text"/&gt;
270 * </pre></li>
271 * <li>From the onCreate method of an Activity, find the Button
272 * <pre class="prettyprint">
273 *      Button myButton = (Button) findViewById(R.id.my_button);
274 * </pre></li>
275 * </ul>
276 * <p>
277 * View IDs need not be unique throughout the tree, but it is good practice to
278 * ensure that they are at least unique within the part of the tree you are
279 * searching.
280 * </p>
281 *
282 * <a name="Position"></a>
283 * <h3>Position</h3>
284 * <p>
285 * The geometry of a view is that of a rectangle. A view has a location,
286 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
287 * two dimensions, expressed as a width and a height. The unit for location
288 * and dimensions is the pixel.
289 * </p>
290 *
291 * <p>
292 * It is possible to retrieve the location of a view by invoking the methods
293 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
294 * coordinate of the rectangle representing the view. The latter returns the
295 * top, or Y, coordinate of the rectangle representing the view. These methods
296 * both return the location of the view relative to its parent. For instance,
297 * when getLeft() returns 20, that means the view is located 20 pixels to the
298 * right of the left edge of its direct parent.
299 * </p>
300 *
301 * <p>
302 * In addition, several convenience methods are offered to avoid unnecessary
303 * computations, namely {@link #getRight()} and {@link #getBottom()}.
304 * These methods return the coordinates of the right and bottom edges of the
305 * rectangle representing the view. For instance, calling {@link #getRight()}
306 * is similar to the following computation: <code>getLeft() + getWidth()</code>
307 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
308 * </p>
309 *
310 * <a name="SizePaddingMargins"></a>
311 * <h3>Size, padding and margins</h3>
312 * <p>
313 * The size of a view is expressed with a width and a height. A view actually
314 * possess two pairs of width and height values.
315 * </p>
316 *
317 * <p>
318 * The first pair is known as <em>measured width</em> and
319 * <em>measured height</em>. These dimensions define how big a view wants to be
320 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
321 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
322 * and {@link #getMeasuredHeight()}.
323 * </p>
324 *
325 * <p>
326 * The second pair is simply known as <em>width</em> and <em>height</em>, or
327 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
328 * dimensions define the actual size of the view on screen, at drawing time and
329 * after layout. These values may, but do not have to, be different from the
330 * measured width and height. The width and height can be obtained by calling
331 * {@link #getWidth()} and {@link #getHeight()}.
332 * </p>
333 *
334 * <p>
335 * To measure its dimensions, a view takes into account its padding. The padding
336 * is expressed in pixels for the left, top, right and bottom parts of the view.
337 * Padding can be used to offset the content of the view by a specific amount of
338 * pixels. For instance, a left padding of 2 will push the view's content by
339 * 2 pixels to the right of the left edge. Padding can be set using the
340 * {@link #setPadding(int, int, int, int)} method and queried by calling
341 * {@link #getPaddingLeft()}, {@link #getPaddingTop()},
342 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}.
343 * </p>
344 *
345 * <p>
346 * Even though a view can define a padding, it does not provide any support for
347 * margins. However, view groups provide such a support. Refer to
348 * {@link android.view.ViewGroup} and
349 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
350 * </p>
351 *
352 * <a name="Layout"></a>
353 * <h3>Layout</h3>
354 * <p>
355 * Layout is a two pass process: a measure pass and a layout pass. The measuring
356 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
357 * of the view tree. Each view pushes dimension specifications down the tree
358 * during the recursion. At the end of the measure pass, every view has stored
359 * its measurements. The second pass happens in
360 * {@link #layout(int,int,int,int)} and is also top-down. During
361 * this pass each parent is responsible for positioning all of its children
362 * using the sizes computed in the measure pass.
363 * </p>
364 *
365 * <p>
366 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
367 * {@link #getMeasuredHeight()} values must be set, along with those for all of
368 * that view's descendants. A view's measured width and measured height values
369 * must respect the constraints imposed by the view's parents. This guarantees
370 * that at the end of the measure pass, all parents accept all of their
371 * children's measurements. A parent view may call measure() more than once on
372 * its children. For example, the parent may measure each child once with
373 * unspecified dimensions to find out how big they want to be, then call
374 * measure() on them again with actual numbers if the sum of all the children's
375 * unconstrained sizes is too big or too small.
376 * </p>
377 *
378 * <p>
379 * The measure pass uses two classes to communicate dimensions. The
380 * {@link MeasureSpec} class is used by views to tell their parents how they
381 * want to be measured and positioned. The base LayoutParams class just
382 * describes how big the view wants to be for both width and height. For each
383 * dimension, it can specify one of:
384 * <ul>
385 * <li> an exact number
386 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
387 * (minus padding)
388 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
389 * enclose its content (plus padding).
390 * </ul>
391 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
392 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
393 * an X and Y value.
394 * </p>
395 *
396 * <p>
397 * MeasureSpecs are used to push requirements down the tree from parent to
398 * child. A MeasureSpec can be in one of three modes:
399 * <ul>
400 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
401 * of a child view. For example, a LinearLayout may call measure() on its child
402 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
403 * tall the child view wants to be given a width of 240 pixels.
404 * <li>EXACTLY: This is used by the parent to impose an exact size on the
405 * child. The child must use this size, and guarantee that all of its
406 * descendants will fit within this size.
407 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
408 * child. The child must gurantee that it and all of its descendants will fit
409 * within this size.
410 * </ul>
411 * </p>
412 *
413 * <p>
414 * To intiate a layout, call {@link #requestLayout}. This method is typically
415 * called by a view on itself when it believes that is can no longer fit within
416 * its current bounds.
417 * </p>
418 *
419 * <a name="Drawing"></a>
420 * <h3>Drawing</h3>
421 * <p>
422 * Drawing is handled by walking the tree and rendering each view that
423 * intersects the invalid region. Because the tree is traversed in-order,
424 * this means that parents will draw before (i.e., behind) their children, with
425 * siblings drawn in the order they appear in the tree.
426 * If you set a background drawable for a View, then the View will draw it for you
427 * before calling back to its <code>onDraw()</code> method.
428 * </p>
429 *
430 * <p>
431 * Note that the framework will not draw views that are not in the invalid region.
432 * </p>
433 *
434 * <p>
435 * To force a view to draw, call {@link #invalidate()}.
436 * </p>
437 *
438 * <a name="EventHandlingThreading"></a>
439 * <h3>Event Handling and Threading</h3>
440 * <p>
441 * The basic cycle of a view is as follows:
442 * <ol>
443 * <li>An event comes in and is dispatched to the appropriate view. The view
444 * handles the event and notifies any listeners.</li>
445 * <li>If in the course of processing the event, the view's bounds may need
446 * to be changed, the view will call {@link #requestLayout()}.</li>
447 * <li>Similarly, if in the course of processing the event the view's appearance
448 * may need to be changed, the view will call {@link #invalidate()}.</li>
449 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
450 * the framework will take care of measuring, laying out, and drawing the tree
451 * as appropriate.</li>
452 * </ol>
453 * </p>
454 *
455 * <p><em>Note: The entire view tree is single threaded. You must always be on
456 * the UI thread when calling any method on any view.</em>
457 * If you are doing work on other threads and want to update the state of a view
458 * from that thread, you should use a {@link Handler}.
459 * </p>
460 *
461 * <a name="FocusHandling"></a>
462 * <h3>Focus Handling</h3>
463 * <p>
464 * The framework will handle routine focus movement in response to user input.
465 * This includes changing the focus as views are removed or hidden, or as new
466 * views become available. Views indicate their willingness to take focus
467 * through the {@link #isFocusable} method. To change whether a view can take
468 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
469 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
470 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
471 * </p>
472 * <p>
473 * Focus movement is based on an algorithm which finds the nearest neighbor in a
474 * given direction. In rare cases, the default algorithm may not match the
475 * intended behavior of the developer. In these situations, you can provide
476 * explicit overrides by using these XML attributes in the layout file:
477 * <pre>
478 * nextFocusDown
479 * nextFocusLeft
480 * nextFocusRight
481 * nextFocusUp
482 * </pre>
483 * </p>
484 *
485 *
486 * <p>
487 * To get a particular view to take focus, call {@link #requestFocus()}.
488 * </p>
489 *
490 * <a name="TouchMode"></a>
491 * <h3>Touch Mode</h3>
492 * <p>
493 * When a user is navigating a user interface via directional keys such as a D-pad, it is
494 * necessary to give focus to actionable items such as buttons so the user can see
495 * what will take input.  If the device has touch capabilities, however, and the user
496 * begins interacting with the interface by touching it, it is no longer necessary to
497 * always highlight, or give focus to, a particular view.  This motivates a mode
498 * for interaction named 'touch mode'.
499 * </p>
500 * <p>
501 * For a touch capable device, once the user touches the screen, the device
502 * will enter touch mode.  From this point onward, only views for which
503 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
504 * Other views that are touchable, like buttons, will not take focus when touched; they will
505 * only fire the on click listeners.
506 * </p>
507 * <p>
508 * Any time a user hits a directional key, such as a D-pad direction, the view device will
509 * exit touch mode, and find a view to take focus, so that the user may resume interacting
510 * with the user interface without touching the screen again.
511 * </p>
512 * <p>
513 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
514 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
515 * </p>
516 *
517 * <a name="Scrolling"></a>
518 * <h3>Scrolling</h3>
519 * <p>
520 * The framework provides basic support for views that wish to internally
521 * scroll their content. This includes keeping track of the X and Y scroll
522 * offset as well as mechanisms for drawing scrollbars. See
523 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
524 * {@link #awakenScrollBars()} for more details.
525 * </p>
526 *
527 * <a name="Tags"></a>
528 * <h3>Tags</h3>
529 * <p>
530 * Unlike IDs, tags are not used to identify views. Tags are essentially an
531 * extra piece of information that can be associated with a view. They are most
532 * often used as a convenience to store data related to views in the views
533 * themselves rather than by putting them in a separate structure.
534 * </p>
535 *
536 * <a name="Animation"></a>
537 * <h3>Animation</h3>
538 * <p>
539 * You can attach an {@link Animation} object to a view using
540 * {@link #setAnimation(Animation)} or
541 * {@link #startAnimation(Animation)}. The animation can alter the scale,
542 * rotation, translation and alpha of a view over time. If the animation is
543 * attached to a view that has children, the animation will affect the entire
544 * subtree rooted by that node. When an animation is started, the framework will
545 * take care of redrawing the appropriate views until the animation completes.
546 * </p>
547 * <p>
548 * Starting with Android 3.0, the preferred way of animating views is to use the
549 * {@link android.animation} package APIs.
550 * </p>
551 *
552 * <a name="Security"></a>
553 * <h3>Security</h3>
554 * <p>
555 * Sometimes it is essential that an application be able to verify that an action
556 * is being performed with the full knowledge and consent of the user, such as
557 * granting a permission request, making a purchase or clicking on an advertisement.
558 * Unfortunately, a malicious application could try to spoof the user into
559 * performing these actions, unaware, by concealing the intended purpose of the view.
560 * As a remedy, the framework offers a touch filtering mechanism that can be used to
561 * improve the security of views that provide access to sensitive functionality.
562 * </p><p>
563 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
564 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
565 * will discard touches that are received whenever the view's window is obscured by
566 * another visible window.  As a result, the view will not receive touches whenever a
567 * toast, dialog or other window appears above the view's window.
568 * </p><p>
569 * For more fine-grained control over security, consider overriding the
570 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
571 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
572 * </p>
573 *
574 * @attr ref android.R.styleable#View_alpha
575 * @attr ref android.R.styleable#View_background
576 * @attr ref android.R.styleable#View_clickable
577 * @attr ref android.R.styleable#View_contentDescription
578 * @attr ref android.R.styleable#View_drawingCacheQuality
579 * @attr ref android.R.styleable#View_duplicateParentState
580 * @attr ref android.R.styleable#View_id
581 * @attr ref android.R.styleable#View_requiresFadingEdge
582 * @attr ref android.R.styleable#View_fadingEdgeLength
583 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
584 * @attr ref android.R.styleable#View_fitsSystemWindows
585 * @attr ref android.R.styleable#View_isScrollContainer
586 * @attr ref android.R.styleable#View_focusable
587 * @attr ref android.R.styleable#View_focusableInTouchMode
588 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
589 * @attr ref android.R.styleable#View_keepScreenOn
590 * @attr ref android.R.styleable#View_layerType
591 * @attr ref android.R.styleable#View_longClickable
592 * @attr ref android.R.styleable#View_minHeight
593 * @attr ref android.R.styleable#View_minWidth
594 * @attr ref android.R.styleable#View_nextFocusDown
595 * @attr ref android.R.styleable#View_nextFocusLeft
596 * @attr ref android.R.styleable#View_nextFocusRight
597 * @attr ref android.R.styleable#View_nextFocusUp
598 * @attr ref android.R.styleable#View_onClick
599 * @attr ref android.R.styleable#View_padding
600 * @attr ref android.R.styleable#View_paddingBottom
601 * @attr ref android.R.styleable#View_paddingLeft
602 * @attr ref android.R.styleable#View_paddingRight
603 * @attr ref android.R.styleable#View_paddingTop
604 * @attr ref android.R.styleable#View_paddingStart
605 * @attr ref android.R.styleable#View_paddingEnd
606 * @attr ref android.R.styleable#View_saveEnabled
607 * @attr ref android.R.styleable#View_rotation
608 * @attr ref android.R.styleable#View_rotationX
609 * @attr ref android.R.styleable#View_rotationY
610 * @attr ref android.R.styleable#View_scaleX
611 * @attr ref android.R.styleable#View_scaleY
612 * @attr ref android.R.styleable#View_scrollX
613 * @attr ref android.R.styleable#View_scrollY
614 * @attr ref android.R.styleable#View_scrollbarSize
615 * @attr ref android.R.styleable#View_scrollbarStyle
616 * @attr ref android.R.styleable#View_scrollbars
617 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
618 * @attr ref android.R.styleable#View_scrollbarFadeDuration
619 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
620 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
621 * @attr ref android.R.styleable#View_scrollbarThumbVertical
622 * @attr ref android.R.styleable#View_scrollbarTrackVertical
623 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
624 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
625 * @attr ref android.R.styleable#View_soundEffectsEnabled
626 * @attr ref android.R.styleable#View_tag
627 * @attr ref android.R.styleable#View_transformPivotX
628 * @attr ref android.R.styleable#View_transformPivotY
629 * @attr ref android.R.styleable#View_translationX
630 * @attr ref android.R.styleable#View_translationY
631 * @attr ref android.R.styleable#View_visibility
632 *
633 * @see android.view.ViewGroup
634 */
635public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Callback,
636        AccessibilityEventSource {
637    private static final boolean DBG = false;
638
639    /**
640     * The logging tag used by this class with android.util.Log.
641     */
642    protected static final String VIEW_LOG_TAG = "View";
643
644    /**
645     * Used to mark a View that has no ID.
646     */
647    public static final int NO_ID = -1;
648
649    /**
650     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
651     * calling setFlags.
652     */
653    private static final int NOT_FOCUSABLE = 0x00000000;
654
655    /**
656     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
657     * setFlags.
658     */
659    private static final int FOCUSABLE = 0x00000001;
660
661    /**
662     * Mask for use with setFlags indicating bits used for focus.
663     */
664    private static final int FOCUSABLE_MASK = 0x00000001;
665
666    /**
667     * This view will adjust its padding to fit sytem windows (e.g. status bar)
668     */
669    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
670
671    /**
672     * This view is visible.
673     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
674     * android:visibility}.
675     */
676    public static final int VISIBLE = 0x00000000;
677
678    /**
679     * This view is invisible, but it still takes up space for layout purposes.
680     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
681     * android:visibility}.
682     */
683    public static final int INVISIBLE = 0x00000004;
684
685    /**
686     * This view is invisible, and it doesn't take any space for layout
687     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
688     * android:visibility}.
689     */
690    public static final int GONE = 0x00000008;
691
692    /**
693     * Mask for use with setFlags indicating bits used for visibility.
694     * {@hide}
695     */
696    static final int VISIBILITY_MASK = 0x0000000C;
697
698    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
699
700    /**
701     * This view is enabled. Intrepretation varies by subclass.
702     * Use with ENABLED_MASK when calling setFlags.
703     * {@hide}
704     */
705    static final int ENABLED = 0x00000000;
706
707    /**
708     * This view is disabled. Intrepretation varies by subclass.
709     * Use with ENABLED_MASK when calling setFlags.
710     * {@hide}
711     */
712    static final int DISABLED = 0x00000020;
713
714   /**
715    * Mask for use with setFlags indicating bits used for indicating whether
716    * this view is enabled
717    * {@hide}
718    */
719    static final int ENABLED_MASK = 0x00000020;
720
721    /**
722     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
723     * called and further optimizations will be performed. It is okay to have
724     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
725     * {@hide}
726     */
727    static final int WILL_NOT_DRAW = 0x00000080;
728
729    /**
730     * Mask for use with setFlags indicating bits used for indicating whether
731     * this view is will draw
732     * {@hide}
733     */
734    static final int DRAW_MASK = 0x00000080;
735
736    /**
737     * <p>This view doesn't show scrollbars.</p>
738     * {@hide}
739     */
740    static final int SCROLLBARS_NONE = 0x00000000;
741
742    /**
743     * <p>This view shows horizontal scrollbars.</p>
744     * {@hide}
745     */
746    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
747
748    /**
749     * <p>This view shows vertical scrollbars.</p>
750     * {@hide}
751     */
752    static final int SCROLLBARS_VERTICAL = 0x00000200;
753
754    /**
755     * <p>Mask for use with setFlags indicating bits used for indicating which
756     * scrollbars are enabled.</p>
757     * {@hide}
758     */
759    static final int SCROLLBARS_MASK = 0x00000300;
760
761    /**
762     * Indicates that the view should filter touches when its window is obscured.
763     * Refer to the class comments for more information about this security feature.
764     * {@hide}
765     */
766    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
767
768    // note flag value 0x00000800 is now available for next flags...
769
770    /**
771     * <p>This view doesn't show fading edges.</p>
772     * {@hide}
773     */
774    static final int FADING_EDGE_NONE = 0x00000000;
775
776    /**
777     * <p>This view shows horizontal fading edges.</p>
778     * {@hide}
779     */
780    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
781
782    /**
783     * <p>This view shows vertical fading edges.</p>
784     * {@hide}
785     */
786    static final int FADING_EDGE_VERTICAL = 0x00002000;
787
788    /**
789     * <p>Mask for use with setFlags indicating bits used for indicating which
790     * fading edges are enabled.</p>
791     * {@hide}
792     */
793    static final int FADING_EDGE_MASK = 0x00003000;
794
795    /**
796     * <p>Indicates this view can be clicked. When clickable, a View reacts
797     * to clicks by notifying the OnClickListener.<p>
798     * {@hide}
799     */
800    static final int CLICKABLE = 0x00004000;
801
802    /**
803     * <p>Indicates this view is caching its drawing into a bitmap.</p>
804     * {@hide}
805     */
806    static final int DRAWING_CACHE_ENABLED = 0x00008000;
807
808    /**
809     * <p>Indicates that no icicle should be saved for this view.<p>
810     * {@hide}
811     */
812    static final int SAVE_DISABLED = 0x000010000;
813
814    /**
815     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
816     * property.</p>
817     * {@hide}
818     */
819    static final int SAVE_DISABLED_MASK = 0x000010000;
820
821    /**
822     * <p>Indicates that no drawing cache should ever be created for this view.<p>
823     * {@hide}
824     */
825    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
826
827    /**
828     * <p>Indicates this view can take / keep focus when int touch mode.</p>
829     * {@hide}
830     */
831    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
832
833    /**
834     * <p>Enables low quality mode for the drawing cache.</p>
835     */
836    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
837
838    /**
839     * <p>Enables high quality mode for the drawing cache.</p>
840     */
841    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
842
843    /**
844     * <p>Enables automatic quality mode for the drawing cache.</p>
845     */
846    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
847
848    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
849            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
850    };
851
852    /**
853     * <p>Mask for use with setFlags indicating bits used for the cache
854     * quality property.</p>
855     * {@hide}
856     */
857    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
858
859    /**
860     * <p>
861     * Indicates this view can be long clicked. When long clickable, a View
862     * reacts to long clicks by notifying the OnLongClickListener or showing a
863     * context menu.
864     * </p>
865     * {@hide}
866     */
867    static final int LONG_CLICKABLE = 0x00200000;
868
869    /**
870     * <p>Indicates that this view gets its drawable states from its direct parent
871     * and ignores its original internal states.</p>
872     *
873     * @hide
874     */
875    static final int DUPLICATE_PARENT_STATE = 0x00400000;
876
877    /**
878     * The scrollbar style to display the scrollbars inside the content area,
879     * without increasing the padding. The scrollbars will be overlaid with
880     * translucency on the view's content.
881     */
882    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
883
884    /**
885     * The scrollbar style to display the scrollbars inside the padded area,
886     * increasing the padding of the view. The scrollbars will not overlap the
887     * content area of the view.
888     */
889    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
890
891    /**
892     * The scrollbar style to display the scrollbars at the edge of the view,
893     * without increasing the padding. The scrollbars will be overlaid with
894     * translucency.
895     */
896    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
897
898    /**
899     * The scrollbar style to display the scrollbars at the edge of the view,
900     * increasing the padding of the view. The scrollbars will only overlap the
901     * background, if any.
902     */
903    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
904
905    /**
906     * Mask to check if the scrollbar style is overlay or inset.
907     * {@hide}
908     */
909    static final int SCROLLBARS_INSET_MASK = 0x01000000;
910
911    /**
912     * Mask to check if the scrollbar style is inside or outside.
913     * {@hide}
914     */
915    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
916
917    /**
918     * Mask for scrollbar style.
919     * {@hide}
920     */
921    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
922
923    /**
924     * View flag indicating that the screen should remain on while the
925     * window containing this view is visible to the user.  This effectively
926     * takes care of automatically setting the WindowManager's
927     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
928     */
929    public static final int KEEP_SCREEN_ON = 0x04000000;
930
931    /**
932     * View flag indicating whether this view should have sound effects enabled
933     * for events such as clicking and touching.
934     */
935    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
936
937    /**
938     * View flag indicating whether this view should have haptic feedback
939     * enabled for events such as long presses.
940     */
941    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
942
943    /**
944     * <p>Indicates that the view hierarchy should stop saving state when
945     * it reaches this view.  If state saving is initiated immediately at
946     * the view, it will be allowed.
947     * {@hide}
948     */
949    static final int PARENT_SAVE_DISABLED = 0x20000000;
950
951    /**
952     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
953     * {@hide}
954     */
955    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
956
957    /**
958     * Horizontal direction of this view is from Left to Right.
959     * Use with {@link #setLayoutDirection}.
960     * {@hide}
961     */
962    public static final int LAYOUT_DIRECTION_LTR = 0x00000000;
963
964    /**
965     * Horizontal direction of this view is from Right to Left.
966     * Use with {@link #setLayoutDirection}.
967     * {@hide}
968     */
969    public static final int LAYOUT_DIRECTION_RTL = 0x40000000;
970
971    /**
972     * Horizontal direction of this view is inherited from its parent.
973     * Use with {@link #setLayoutDirection}.
974     * {@hide}
975     */
976    public static final int LAYOUT_DIRECTION_INHERIT = 0x80000000;
977
978    /**
979     * Horizontal direction of this view is from deduced from the default language
980     * script for the locale. Use with {@link #setLayoutDirection}.
981     * {@hide}
982     */
983    public static final int LAYOUT_DIRECTION_LOCALE = 0xC0000000;
984
985    /**
986     * Mask for use with setFlags indicating bits used for horizontalDirection.
987     * {@hide}
988     */
989    static final int LAYOUT_DIRECTION_MASK = 0xC0000000;
990
991    /*
992     * Array of horizontal direction flags for mapping attribute "horizontalDirection" to correct
993     * flag value.
994     * {@hide}
995     */
996    private static final int[] LAYOUT_DIRECTION_FLAGS = {LAYOUT_DIRECTION_LTR,
997        LAYOUT_DIRECTION_RTL, LAYOUT_DIRECTION_INHERIT, LAYOUT_DIRECTION_LOCALE};
998
999    /**
1000     * Default horizontalDirection.
1001     * {@hide}
1002     */
1003    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1004
1005    /**
1006     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1007     * should add all focusable Views regardless if they are focusable in touch mode.
1008     */
1009    public static final int FOCUSABLES_ALL = 0x00000000;
1010
1011    /**
1012     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1013     * should add only Views focusable in touch mode.
1014     */
1015    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1016
1017    /**
1018     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1019     * item.
1020     */
1021    public static final int FOCUS_BACKWARD = 0x00000001;
1022
1023    /**
1024     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1025     * item.
1026     */
1027    public static final int FOCUS_FORWARD = 0x00000002;
1028
1029    /**
1030     * Use with {@link #focusSearch(int)}. Move focus to the left.
1031     */
1032    public static final int FOCUS_LEFT = 0x00000011;
1033
1034    /**
1035     * Use with {@link #focusSearch(int)}. Move focus up.
1036     */
1037    public static final int FOCUS_UP = 0x00000021;
1038
1039    /**
1040     * Use with {@link #focusSearch(int)}. Move focus to the right.
1041     */
1042    public static final int FOCUS_RIGHT = 0x00000042;
1043
1044    /**
1045     * Use with {@link #focusSearch(int)}. Move focus down.
1046     */
1047    public static final int FOCUS_DOWN = 0x00000082;
1048
1049    /**
1050     * Bits of {@link #getMeasuredWidthAndState()} and
1051     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1052     */
1053    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1054
1055    /**
1056     * Bits of {@link #getMeasuredWidthAndState()} and
1057     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1058     */
1059    public static final int MEASURED_STATE_MASK = 0xff000000;
1060
1061    /**
1062     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1063     * for functions that combine both width and height into a single int,
1064     * such as {@link #getMeasuredState()} and the childState argument of
1065     * {@link #resolveSizeAndState(int, int, int)}.
1066     */
1067    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1068
1069    /**
1070     * Bit of {@link #getMeasuredWidthAndState()} and
1071     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1072     * is smaller that the space the view would like to have.
1073     */
1074    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1075
1076    /**
1077     * Base View state sets
1078     */
1079    // Singles
1080    /**
1081     * Indicates the view has no states set. States are used with
1082     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1083     * view depending on its state.
1084     *
1085     * @see android.graphics.drawable.Drawable
1086     * @see #getDrawableState()
1087     */
1088    protected static final int[] EMPTY_STATE_SET;
1089    /**
1090     * Indicates the view is enabled. States are used with
1091     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1092     * view depending on its state.
1093     *
1094     * @see android.graphics.drawable.Drawable
1095     * @see #getDrawableState()
1096     */
1097    protected static final int[] ENABLED_STATE_SET;
1098    /**
1099     * Indicates the view is focused. States are used with
1100     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1101     * view depending on its state.
1102     *
1103     * @see android.graphics.drawable.Drawable
1104     * @see #getDrawableState()
1105     */
1106    protected static final int[] FOCUSED_STATE_SET;
1107    /**
1108     * Indicates the view is selected. States are used with
1109     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1110     * view depending on its state.
1111     *
1112     * @see android.graphics.drawable.Drawable
1113     * @see #getDrawableState()
1114     */
1115    protected static final int[] SELECTED_STATE_SET;
1116    /**
1117     * Indicates the view is pressed. States are used with
1118     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1119     * view depending on its state.
1120     *
1121     * @see android.graphics.drawable.Drawable
1122     * @see #getDrawableState()
1123     * @hide
1124     */
1125    protected static final int[] PRESSED_STATE_SET;
1126    /**
1127     * Indicates the view's window has focus. States are used with
1128     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1129     * view depending on its state.
1130     *
1131     * @see android.graphics.drawable.Drawable
1132     * @see #getDrawableState()
1133     */
1134    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1135    // Doubles
1136    /**
1137     * Indicates the view is enabled and has the focus.
1138     *
1139     * @see #ENABLED_STATE_SET
1140     * @see #FOCUSED_STATE_SET
1141     */
1142    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1143    /**
1144     * Indicates the view is enabled and selected.
1145     *
1146     * @see #ENABLED_STATE_SET
1147     * @see #SELECTED_STATE_SET
1148     */
1149    protected static final int[] ENABLED_SELECTED_STATE_SET;
1150    /**
1151     * Indicates the view is enabled and that its window has focus.
1152     *
1153     * @see #ENABLED_STATE_SET
1154     * @see #WINDOW_FOCUSED_STATE_SET
1155     */
1156    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1157    /**
1158     * Indicates the view is focused and selected.
1159     *
1160     * @see #FOCUSED_STATE_SET
1161     * @see #SELECTED_STATE_SET
1162     */
1163    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1164    /**
1165     * Indicates the view has the focus and that its window has the focus.
1166     *
1167     * @see #FOCUSED_STATE_SET
1168     * @see #WINDOW_FOCUSED_STATE_SET
1169     */
1170    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1171    /**
1172     * Indicates the view is selected and that its window has the focus.
1173     *
1174     * @see #SELECTED_STATE_SET
1175     * @see #WINDOW_FOCUSED_STATE_SET
1176     */
1177    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1178    // Triples
1179    /**
1180     * Indicates the view is enabled, focused and selected.
1181     *
1182     * @see #ENABLED_STATE_SET
1183     * @see #FOCUSED_STATE_SET
1184     * @see #SELECTED_STATE_SET
1185     */
1186    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1187    /**
1188     * Indicates the view is enabled, focused and its window has the focus.
1189     *
1190     * @see #ENABLED_STATE_SET
1191     * @see #FOCUSED_STATE_SET
1192     * @see #WINDOW_FOCUSED_STATE_SET
1193     */
1194    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1195    /**
1196     * Indicates the view is enabled, selected and its window has the focus.
1197     *
1198     * @see #ENABLED_STATE_SET
1199     * @see #SELECTED_STATE_SET
1200     * @see #WINDOW_FOCUSED_STATE_SET
1201     */
1202    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1203    /**
1204     * Indicates the view is focused, selected and its window has the focus.
1205     *
1206     * @see #FOCUSED_STATE_SET
1207     * @see #SELECTED_STATE_SET
1208     * @see #WINDOW_FOCUSED_STATE_SET
1209     */
1210    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1211    /**
1212     * Indicates the view is enabled, focused, selected and its window
1213     * has the focus.
1214     *
1215     * @see #ENABLED_STATE_SET
1216     * @see #FOCUSED_STATE_SET
1217     * @see #SELECTED_STATE_SET
1218     * @see #WINDOW_FOCUSED_STATE_SET
1219     */
1220    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1221    /**
1222     * Indicates the view is pressed and its window has the focus.
1223     *
1224     * @see #PRESSED_STATE_SET
1225     * @see #WINDOW_FOCUSED_STATE_SET
1226     */
1227    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1228    /**
1229     * Indicates the view is pressed and selected.
1230     *
1231     * @see #PRESSED_STATE_SET
1232     * @see #SELECTED_STATE_SET
1233     */
1234    protected static final int[] PRESSED_SELECTED_STATE_SET;
1235    /**
1236     * Indicates the view is pressed, selected and its window has the focus.
1237     *
1238     * @see #PRESSED_STATE_SET
1239     * @see #SELECTED_STATE_SET
1240     * @see #WINDOW_FOCUSED_STATE_SET
1241     */
1242    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1243    /**
1244     * Indicates the view is pressed and focused.
1245     *
1246     * @see #PRESSED_STATE_SET
1247     * @see #FOCUSED_STATE_SET
1248     */
1249    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1250    /**
1251     * Indicates the view is pressed, focused and its window has the focus.
1252     *
1253     * @see #PRESSED_STATE_SET
1254     * @see #FOCUSED_STATE_SET
1255     * @see #WINDOW_FOCUSED_STATE_SET
1256     */
1257    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1258    /**
1259     * Indicates the view is pressed, focused and selected.
1260     *
1261     * @see #PRESSED_STATE_SET
1262     * @see #SELECTED_STATE_SET
1263     * @see #FOCUSED_STATE_SET
1264     */
1265    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1266    /**
1267     * Indicates the view is pressed, focused, selected and its window has the focus.
1268     *
1269     * @see #PRESSED_STATE_SET
1270     * @see #FOCUSED_STATE_SET
1271     * @see #SELECTED_STATE_SET
1272     * @see #WINDOW_FOCUSED_STATE_SET
1273     */
1274    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1275    /**
1276     * Indicates the view is pressed and enabled.
1277     *
1278     * @see #PRESSED_STATE_SET
1279     * @see #ENABLED_STATE_SET
1280     */
1281    protected static final int[] PRESSED_ENABLED_STATE_SET;
1282    /**
1283     * Indicates the view is pressed, enabled and its window has the focus.
1284     *
1285     * @see #PRESSED_STATE_SET
1286     * @see #ENABLED_STATE_SET
1287     * @see #WINDOW_FOCUSED_STATE_SET
1288     */
1289    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1290    /**
1291     * Indicates the view is pressed, enabled and selected.
1292     *
1293     * @see #PRESSED_STATE_SET
1294     * @see #ENABLED_STATE_SET
1295     * @see #SELECTED_STATE_SET
1296     */
1297    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1298    /**
1299     * Indicates the view is pressed, enabled, selected and its window has the
1300     * focus.
1301     *
1302     * @see #PRESSED_STATE_SET
1303     * @see #ENABLED_STATE_SET
1304     * @see #SELECTED_STATE_SET
1305     * @see #WINDOW_FOCUSED_STATE_SET
1306     */
1307    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1308    /**
1309     * Indicates the view is pressed, enabled and focused.
1310     *
1311     * @see #PRESSED_STATE_SET
1312     * @see #ENABLED_STATE_SET
1313     * @see #FOCUSED_STATE_SET
1314     */
1315    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1316    /**
1317     * Indicates the view is pressed, enabled, focused and its window has the
1318     * focus.
1319     *
1320     * @see #PRESSED_STATE_SET
1321     * @see #ENABLED_STATE_SET
1322     * @see #FOCUSED_STATE_SET
1323     * @see #WINDOW_FOCUSED_STATE_SET
1324     */
1325    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1326    /**
1327     * Indicates the view is pressed, enabled, focused and selected.
1328     *
1329     * @see #PRESSED_STATE_SET
1330     * @see #ENABLED_STATE_SET
1331     * @see #SELECTED_STATE_SET
1332     * @see #FOCUSED_STATE_SET
1333     */
1334    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1335    /**
1336     * Indicates the view is pressed, enabled, focused, selected and its window
1337     * has the focus.
1338     *
1339     * @see #PRESSED_STATE_SET
1340     * @see #ENABLED_STATE_SET
1341     * @see #SELECTED_STATE_SET
1342     * @see #FOCUSED_STATE_SET
1343     * @see #WINDOW_FOCUSED_STATE_SET
1344     */
1345    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1346
1347    /**
1348     * The order here is very important to {@link #getDrawableState()}
1349     */
1350    private static final int[][] VIEW_STATE_SETS;
1351
1352    static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1353    static final int VIEW_STATE_SELECTED = 1 << 1;
1354    static final int VIEW_STATE_FOCUSED = 1 << 2;
1355    static final int VIEW_STATE_ENABLED = 1 << 3;
1356    static final int VIEW_STATE_PRESSED = 1 << 4;
1357    static final int VIEW_STATE_ACTIVATED = 1 << 5;
1358    static final int VIEW_STATE_ACCELERATED = 1 << 6;
1359    static final int VIEW_STATE_HOVERED = 1 << 7;
1360    static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1361    static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
1362
1363    static final int[] VIEW_STATE_IDS = new int[] {
1364        R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
1365        R.attr.state_selected,          VIEW_STATE_SELECTED,
1366        R.attr.state_focused,           VIEW_STATE_FOCUSED,
1367        R.attr.state_enabled,           VIEW_STATE_ENABLED,
1368        R.attr.state_pressed,           VIEW_STATE_PRESSED,
1369        R.attr.state_activated,         VIEW_STATE_ACTIVATED,
1370        R.attr.state_accelerated,       VIEW_STATE_ACCELERATED,
1371        R.attr.state_hovered,           VIEW_STATE_HOVERED,
1372        R.attr.state_drag_can_accept,   VIEW_STATE_DRAG_CAN_ACCEPT,
1373        R.attr.state_drag_hovered,      VIEW_STATE_DRAG_HOVERED,
1374    };
1375
1376    static {
1377        if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1378            throw new IllegalStateException(
1379                    "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1380        }
1381        int[] orderedIds = new int[VIEW_STATE_IDS.length];
1382        for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
1383            int viewState = R.styleable.ViewDrawableStates[i];
1384            for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
1385                if (VIEW_STATE_IDS[j] == viewState) {
1386                    orderedIds[i * 2] = viewState;
1387                    orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
1388                }
1389            }
1390        }
1391        final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1392        VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1393        for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
1394            int numBits = Integer.bitCount(i);
1395            int[] set = new int[numBits];
1396            int pos = 0;
1397            for (int j = 0; j < orderedIds.length; j += 2) {
1398                if ((i & orderedIds[j+1]) != 0) {
1399                    set[pos++] = orderedIds[j];
1400                }
1401            }
1402            VIEW_STATE_SETS[i] = set;
1403        }
1404
1405        EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1406        WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1407        SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1408        SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1409                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1410        FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1411        FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1412                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1413        FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1414                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1415        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1416                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1417                | VIEW_STATE_FOCUSED];
1418        ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1419        ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1420                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1421        ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1422                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1423        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1424                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1425                | VIEW_STATE_ENABLED];
1426        ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1427                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1428        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1429                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1430                | VIEW_STATE_ENABLED];
1431        ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1432                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1433                | VIEW_STATE_ENABLED];
1434        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1435                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1436                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1437
1438        PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1439        PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1440                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1441        PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1442                VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1443        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1444                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1445                | VIEW_STATE_PRESSED];
1446        PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1447                VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1448        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1449                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1450                | VIEW_STATE_PRESSED];
1451        PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1452                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1453                | VIEW_STATE_PRESSED];
1454        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1455                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1456                | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1457        PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1458                VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1459        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1460                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1461                | VIEW_STATE_PRESSED];
1462        PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1463                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1464                | VIEW_STATE_PRESSED];
1465        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1466                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1467                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1468        PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1469                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1470                | VIEW_STATE_PRESSED];
1471        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1472                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1473                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1474        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1475                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1476                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1477        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1478                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1479                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1480                | VIEW_STATE_PRESSED];
1481    }
1482
1483    /**
1484     * Accessibility event types that are dispatched for text population.
1485     */
1486    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1487            AccessibilityEvent.TYPE_VIEW_CLICKED
1488            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1489            | AccessibilityEvent.TYPE_VIEW_SELECTED
1490            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1491            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1492            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1493            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1494            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1495            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED;
1496
1497    /**
1498     * Temporary Rect currently for use in setBackground().  This will probably
1499     * be extended in the future to hold our own class with more than just
1500     * a Rect. :)
1501     */
1502    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1503
1504    /**
1505     * Map used to store views' tags.
1506     */
1507    private SparseArray<Object> mKeyedTags;
1508
1509    /**
1510     * The next available accessiiblity id.
1511     */
1512    private static int sNextAccessibilityViewId;
1513
1514    /**
1515     * The animation currently associated with this view.
1516     * @hide
1517     */
1518    protected Animation mCurrentAnimation = null;
1519
1520    /**
1521     * Width as measured during measure pass.
1522     * {@hide}
1523     */
1524    @ViewDebug.ExportedProperty(category = "measurement")
1525    int mMeasuredWidth;
1526
1527    /**
1528     * Height as measured during measure pass.
1529     * {@hide}
1530     */
1531    @ViewDebug.ExportedProperty(category = "measurement")
1532    int mMeasuredHeight;
1533
1534    /**
1535     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1536     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1537     * its display list. This flag, used only when hw accelerated, allows us to clear the
1538     * flag while retaining this information until it's needed (at getDisplayList() time and
1539     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1540     *
1541     * {@hide}
1542     */
1543    boolean mRecreateDisplayList = false;
1544
1545    /**
1546     * The view's identifier.
1547     * {@hide}
1548     *
1549     * @see #setId(int)
1550     * @see #getId()
1551     */
1552    @ViewDebug.ExportedProperty(resolveId = true)
1553    int mID = NO_ID;
1554
1555    /**
1556     * The stable ID of this view for accessibility purposes.
1557     */
1558    int mAccessibilityViewId = NO_ID;
1559
1560    /**
1561     * The view's tag.
1562     * {@hide}
1563     *
1564     * @see #setTag(Object)
1565     * @see #getTag()
1566     */
1567    protected Object mTag;
1568
1569    // for mPrivateFlags:
1570    /** {@hide} */
1571    static final int WANTS_FOCUS                    = 0x00000001;
1572    /** {@hide} */
1573    static final int FOCUSED                        = 0x00000002;
1574    /** {@hide} */
1575    static final int SELECTED                       = 0x00000004;
1576    /** {@hide} */
1577    static final int IS_ROOT_NAMESPACE              = 0x00000008;
1578    /** {@hide} */
1579    static final int HAS_BOUNDS                     = 0x00000010;
1580    /** {@hide} */
1581    static final int DRAWN                          = 0x00000020;
1582    /**
1583     * When this flag is set, this view is running an animation on behalf of its
1584     * children and should therefore not cancel invalidate requests, even if they
1585     * lie outside of this view's bounds.
1586     *
1587     * {@hide}
1588     */
1589    static final int DRAW_ANIMATION                 = 0x00000040;
1590    /** {@hide} */
1591    static final int SKIP_DRAW                      = 0x00000080;
1592    /** {@hide} */
1593    static final int ONLY_DRAWS_BACKGROUND          = 0x00000100;
1594    /** {@hide} */
1595    static final int REQUEST_TRANSPARENT_REGIONS    = 0x00000200;
1596    /** {@hide} */
1597    static final int DRAWABLE_STATE_DIRTY           = 0x00000400;
1598    /** {@hide} */
1599    static final int MEASURED_DIMENSION_SET         = 0x00000800;
1600    /** {@hide} */
1601    static final int FORCE_LAYOUT                   = 0x00001000;
1602    /** {@hide} */
1603    static final int LAYOUT_REQUIRED                = 0x00002000;
1604
1605    private static final int PRESSED                = 0x00004000;
1606
1607    /** {@hide} */
1608    static final int DRAWING_CACHE_VALID            = 0x00008000;
1609    /**
1610     * Flag used to indicate that this view should be drawn once more (and only once
1611     * more) after its animation has completed.
1612     * {@hide}
1613     */
1614    static final int ANIMATION_STARTED              = 0x00010000;
1615
1616    private static final int SAVE_STATE_CALLED      = 0x00020000;
1617
1618    /**
1619     * Indicates that the View returned true when onSetAlpha() was called and that
1620     * the alpha must be restored.
1621     * {@hide}
1622     */
1623    static final int ALPHA_SET                      = 0x00040000;
1624
1625    /**
1626     * Set by {@link #setScrollContainer(boolean)}.
1627     */
1628    static final int SCROLL_CONTAINER               = 0x00080000;
1629
1630    /**
1631     * Set by {@link #setScrollContainer(boolean)}.
1632     */
1633    static final int SCROLL_CONTAINER_ADDED         = 0x00100000;
1634
1635    /**
1636     * View flag indicating whether this view was invalidated (fully or partially.)
1637     *
1638     * @hide
1639     */
1640    static final int DIRTY                          = 0x00200000;
1641
1642    /**
1643     * View flag indicating whether this view was invalidated by an opaque
1644     * invalidate request.
1645     *
1646     * @hide
1647     */
1648    static final int DIRTY_OPAQUE                   = 0x00400000;
1649
1650    /**
1651     * Mask for {@link #DIRTY} and {@link #DIRTY_OPAQUE}.
1652     *
1653     * @hide
1654     */
1655    static final int DIRTY_MASK                     = 0x00600000;
1656
1657    /**
1658     * Indicates whether the background is opaque.
1659     *
1660     * @hide
1661     */
1662    static final int OPAQUE_BACKGROUND              = 0x00800000;
1663
1664    /**
1665     * Indicates whether the scrollbars are opaque.
1666     *
1667     * @hide
1668     */
1669    static final int OPAQUE_SCROLLBARS              = 0x01000000;
1670
1671    /**
1672     * Indicates whether the view is opaque.
1673     *
1674     * @hide
1675     */
1676    static final int OPAQUE_MASK                    = 0x01800000;
1677
1678    /**
1679     * Indicates a prepressed state;
1680     * the short time between ACTION_DOWN and recognizing
1681     * a 'real' press. Prepressed is used to recognize quick taps
1682     * even when they are shorter than ViewConfiguration.getTapTimeout().
1683     *
1684     * @hide
1685     */
1686    private static final int PREPRESSED             = 0x02000000;
1687
1688    /**
1689     * Indicates whether the view is temporarily detached.
1690     *
1691     * @hide
1692     */
1693    static final int CANCEL_NEXT_UP_EVENT = 0x04000000;
1694
1695    /**
1696     * Indicates that we should awaken scroll bars once attached
1697     *
1698     * @hide
1699     */
1700    private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1701
1702    /**
1703     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1704     * @hide
1705     */
1706    private static final int HOVERED              = 0x10000000;
1707
1708    /**
1709     * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
1710     * for transform operations
1711     *
1712     * @hide
1713     */
1714    private static final int PIVOT_EXPLICITLY_SET = 0x20000000;
1715
1716    /** {@hide} */
1717    static final int ACTIVATED                    = 0x40000000;
1718
1719    /**
1720     * Indicates that this view was specifically invalidated, not just dirtied because some
1721     * child view was invalidated. The flag is used to determine when we need to recreate
1722     * a view's display list (as opposed to just returning a reference to its existing
1723     * display list).
1724     *
1725     * @hide
1726     */
1727    static final int INVALIDATED                  = 0x80000000;
1728
1729    /* Masks for mPrivateFlags2 */
1730
1731    /**
1732     * Indicates that this view has reported that it can accept the current drag's content.
1733     * Cleared when the drag operation concludes.
1734     * @hide
1735     */
1736    static final int DRAG_CAN_ACCEPT              = 0x00000001;
1737
1738    /**
1739     * Indicates that this view is currently directly under the drag location in a
1740     * drag-and-drop operation involving content that it can accept.  Cleared when
1741     * the drag exits the view, or when the drag operation concludes.
1742     * @hide
1743     */
1744    static final int DRAG_HOVERED                 = 0x00000002;
1745
1746    /**
1747     * Indicates whether the view layout direction has been resolved and drawn to the
1748     * right-to-left direction.
1749     *
1750     * @hide
1751     */
1752    static final int LAYOUT_DIRECTION_RESOLVED_RTL = 0x00000004;
1753
1754    /**
1755     * Indicates whether the view layout direction has been resolved.
1756     *
1757     * @hide
1758     */
1759    static final int LAYOUT_DIRECTION_RESOLVED = 0x00000008;
1760
1761
1762    /**
1763     * Indicates that the view is tracking some sort of transient state
1764     * that the app should not need to be aware of, but that the framework
1765     * should take special care to preserve.
1766     *
1767     * @hide
1768     */
1769    static final int HAS_TRANSIENT_STATE = 0x00000010;
1770
1771
1772    /* End of masks for mPrivateFlags2 */
1773
1774    static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
1775
1776    /**
1777     * Always allow a user to over-scroll this view, provided it is a
1778     * view that can scroll.
1779     *
1780     * @see #getOverScrollMode()
1781     * @see #setOverScrollMode(int)
1782     */
1783    public static final int OVER_SCROLL_ALWAYS = 0;
1784
1785    /**
1786     * Allow a user to over-scroll this view only if the content is large
1787     * enough to meaningfully scroll, provided it is a view that can scroll.
1788     *
1789     * @see #getOverScrollMode()
1790     * @see #setOverScrollMode(int)
1791     */
1792    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
1793
1794    /**
1795     * Never allow a user to over-scroll this view.
1796     *
1797     * @see #getOverScrollMode()
1798     * @see #setOverScrollMode(int)
1799     */
1800    public static final int OVER_SCROLL_NEVER = 2;
1801
1802    /**
1803     * View has requested the system UI (status bar) to be visible (the default).
1804     *
1805     * @see #setSystemUiVisibility(int)
1806     */
1807    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
1808
1809    /**
1810     * View has requested the system UI to enter an unobtrusive "low profile" mode.
1811     *
1812     * This is for use in games, book readers, video players, or any other "immersive" application
1813     * where the usual system chrome is deemed too distracting.
1814     *
1815     * In low profile mode, the status bar and/or navigation icons may dim.
1816     *
1817     * @see #setSystemUiVisibility(int)
1818     */
1819    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
1820
1821    /**
1822     * View has requested that the system navigation be temporarily hidden.
1823     *
1824     * This is an even less obtrusive state than that called for by
1825     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
1826     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
1827     * those to disappear. This is useful (in conjunction with the
1828     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
1829     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
1830     * window flags) for displaying content using every last pixel on the display.
1831     *
1832     * There is a limitation: because navigation controls are so important, the least user
1833     * interaction will cause them to reappear immediately.
1834     *
1835     * @see #setSystemUiVisibility(int)
1836     */
1837    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
1838
1839    /**
1840     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
1841     */
1842    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
1843
1844    /**
1845     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
1846     */
1847    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
1848
1849    /**
1850     * @hide
1851     *
1852     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1853     * out of the public fields to keep the undefined bits out of the developer's way.
1854     *
1855     * Flag to make the status bar not expandable.  Unless you also
1856     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
1857     */
1858    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
1859
1860    /**
1861     * @hide
1862     *
1863     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1864     * out of the public fields to keep the undefined bits out of the developer's way.
1865     *
1866     * Flag to hide notification icons and scrolling ticker text.
1867     */
1868    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
1869
1870    /**
1871     * @hide
1872     *
1873     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1874     * out of the public fields to keep the undefined bits out of the developer's way.
1875     *
1876     * Flag to disable incoming notification alerts.  This will not block
1877     * icons, but it will block sound, vibrating and other visual or aural notifications.
1878     */
1879    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
1880
1881    /**
1882     * @hide
1883     *
1884     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1885     * out of the public fields to keep the undefined bits out of the developer's way.
1886     *
1887     * Flag to hide only the scrolling ticker.  Note that
1888     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
1889     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
1890     */
1891    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
1892
1893    /**
1894     * @hide
1895     *
1896     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1897     * out of the public fields to keep the undefined bits out of the developer's way.
1898     *
1899     * Flag to hide the center system info area.
1900     */
1901    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
1902
1903    /**
1904     * @hide
1905     *
1906     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1907     * out of the public fields to keep the undefined bits out of the developer's way.
1908     *
1909     * Flag to hide only the home button.  Don't use this
1910     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
1911     */
1912    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
1913
1914    /**
1915     * @hide
1916     *
1917     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1918     * out of the public fields to keep the undefined bits out of the developer's way.
1919     *
1920     * Flag to hide only the back button. Don't use this
1921     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
1922     */
1923    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
1924
1925    /**
1926     * @hide
1927     *
1928     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1929     * out of the public fields to keep the undefined bits out of the developer's way.
1930     *
1931     * Flag to hide only the clock.  You might use this if your activity has
1932     * its own clock making the status bar's clock redundant.
1933     */
1934    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
1935
1936    /**
1937     * @hide
1938     *
1939     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
1940     * out of the public fields to keep the undefined bits out of the developer's way.
1941     *
1942     * Flag to hide only the recent apps button. Don't use this
1943     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
1944     */
1945    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
1946
1947    /**
1948     * @hide
1949     *
1950     * NOTE: This flag may only be used in subtreeSystemUiVisibility, etc. etc.
1951     *
1952     * This hides HOME and RECENT and is provided for compatibility with interim implementations.
1953     */
1954    @Deprecated
1955    public static final int STATUS_BAR_DISABLE_NAVIGATION =
1956            STATUS_BAR_DISABLE_HOME | STATUS_BAR_DISABLE_RECENT;
1957
1958    /**
1959     * @hide
1960     */
1961    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
1962
1963    /**
1964     * These are the system UI flags that can be cleared by events outside
1965     * of an application.  Currently this is just the ability to tap on the
1966     * screen while hiding the navigation bar to have it return.
1967     * @hide
1968     */
1969    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
1970            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
1971
1972    /**
1973     * Find views that render the specified text.
1974     *
1975     * @see #findViewsWithText(ArrayList, CharSequence, int)
1976     */
1977    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
1978
1979    /**
1980     * Find find views that contain the specified content description.
1981     *
1982     * @see #findViewsWithText(ArrayList, CharSequence, int)
1983     */
1984    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
1985
1986    /**
1987     * Find views that contain {@link AccessibilityNodeProvider}. Such
1988     * a View is a root of virtual view hierarchy and may contain the searched
1989     * text. If this flag is set Views with providers are automatically
1990     * added and it is a responsibility of the client to call the APIs of
1991     * the provider to determine whether the virtual tree rooted at this View
1992     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
1993     * represeting the virtual views with this text.
1994     *
1995     * @see #findViewsWithText(ArrayList, CharSequence, int)
1996     *
1997     * @hide
1998     */
1999    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2000
2001    /**
2002     * Controls the over-scroll mode for this view.
2003     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2004     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2005     * and {@link #OVER_SCROLL_NEVER}.
2006     */
2007    private int mOverScrollMode;
2008
2009    /**
2010     * The parent this view is attached to.
2011     * {@hide}
2012     *
2013     * @see #getParent()
2014     */
2015    protected ViewParent mParent;
2016
2017    /**
2018     * {@hide}
2019     */
2020    AttachInfo mAttachInfo;
2021
2022    /**
2023     * {@hide}
2024     */
2025    @ViewDebug.ExportedProperty(flagMapping = {
2026        @ViewDebug.FlagToString(mask = FORCE_LAYOUT, equals = FORCE_LAYOUT,
2027                name = "FORCE_LAYOUT"),
2028        @ViewDebug.FlagToString(mask = LAYOUT_REQUIRED, equals = LAYOUT_REQUIRED,
2029                name = "LAYOUT_REQUIRED"),
2030        @ViewDebug.FlagToString(mask = DRAWING_CACHE_VALID, equals = DRAWING_CACHE_VALID,
2031            name = "DRAWING_CACHE_INVALID", outputIf = false),
2032        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "DRAWN", outputIf = true),
2033        @ViewDebug.FlagToString(mask = DRAWN, equals = DRAWN, name = "NOT_DRAWN", outputIf = false),
2034        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2035        @ViewDebug.FlagToString(mask = DIRTY_MASK, equals = DIRTY, name = "DIRTY")
2036    })
2037    int mPrivateFlags;
2038    int mPrivateFlags2;
2039
2040    /**
2041     * This view's request for the visibility of the status bar.
2042     * @hide
2043     */
2044    @ViewDebug.ExportedProperty(flagMapping = {
2045        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2046                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2047                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2048        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2049                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2050                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2051        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2052                                equals = SYSTEM_UI_FLAG_VISIBLE,
2053                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2054    })
2055    int mSystemUiVisibility;
2056
2057    /**
2058     * Count of how many windows this view has been attached to.
2059     */
2060    int mWindowAttachCount;
2061
2062    /**
2063     * The layout parameters associated with this view and used by the parent
2064     * {@link android.view.ViewGroup} to determine how this view should be
2065     * laid out.
2066     * {@hide}
2067     */
2068    protected ViewGroup.LayoutParams mLayoutParams;
2069
2070    /**
2071     * The view flags hold various views states.
2072     * {@hide}
2073     */
2074    @ViewDebug.ExportedProperty
2075    int mViewFlags;
2076
2077    static class TransformationInfo {
2078        /**
2079         * The transform matrix for the View. This transform is calculated internally
2080         * based on the rotation, scaleX, and scaleY properties. The identity matrix
2081         * is used by default. Do *not* use this variable directly; instead call
2082         * getMatrix(), which will automatically recalculate the matrix if necessary
2083         * to get the correct matrix based on the latest rotation and scale properties.
2084         */
2085        private final Matrix mMatrix = new Matrix();
2086
2087        /**
2088         * The transform matrix for the View. This transform is calculated internally
2089         * based on the rotation, scaleX, and scaleY properties. The identity matrix
2090         * is used by default. Do *not* use this variable directly; instead call
2091         * getInverseMatrix(), which will automatically recalculate the matrix if necessary
2092         * to get the correct matrix based on the latest rotation and scale properties.
2093         */
2094        private Matrix mInverseMatrix;
2095
2096        /**
2097         * An internal variable that tracks whether we need to recalculate the
2098         * transform matrix, based on whether the rotation or scaleX/Y properties
2099         * have changed since the matrix was last calculated.
2100         */
2101        boolean mMatrixDirty = false;
2102
2103        /**
2104         * An internal variable that tracks whether we need to recalculate the
2105         * transform matrix, based on whether the rotation or scaleX/Y properties
2106         * have changed since the matrix was last calculated.
2107         */
2108        private boolean mInverseMatrixDirty = true;
2109
2110        /**
2111         * A variable that tracks whether we need to recalculate the
2112         * transform matrix, based on whether the rotation or scaleX/Y properties
2113         * have changed since the matrix was last calculated. This variable
2114         * is only valid after a call to updateMatrix() or to a function that
2115         * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
2116         */
2117        private boolean mMatrixIsIdentity = true;
2118
2119        /**
2120         * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
2121         */
2122        private Camera mCamera = null;
2123
2124        /**
2125         * This matrix is used when computing the matrix for 3D rotations.
2126         */
2127        private Matrix matrix3D = null;
2128
2129        /**
2130         * These prev values are used to recalculate a centered pivot point when necessary. The
2131         * pivot point is only used in matrix operations (when rotation, scale, or translation are
2132         * set), so thes values are only used then as well.
2133         */
2134        private int mPrevWidth = -1;
2135        private int mPrevHeight = -1;
2136
2137        /**
2138         * The degrees rotation around the vertical axis through the pivot point.
2139         */
2140        @ViewDebug.ExportedProperty
2141        float mRotationY = 0f;
2142
2143        /**
2144         * The degrees rotation around the horizontal axis through the pivot point.
2145         */
2146        @ViewDebug.ExportedProperty
2147        float mRotationX = 0f;
2148
2149        /**
2150         * The degrees rotation around the pivot point.
2151         */
2152        @ViewDebug.ExportedProperty
2153        float mRotation = 0f;
2154
2155        /**
2156         * The amount of translation of the object away from its left property (post-layout).
2157         */
2158        @ViewDebug.ExportedProperty
2159        float mTranslationX = 0f;
2160
2161        /**
2162         * The amount of translation of the object away from its top property (post-layout).
2163         */
2164        @ViewDebug.ExportedProperty
2165        float mTranslationY = 0f;
2166
2167        /**
2168         * The amount of scale in the x direction around the pivot point. A
2169         * value of 1 means no scaling is applied.
2170         */
2171        @ViewDebug.ExportedProperty
2172        float mScaleX = 1f;
2173
2174        /**
2175         * The amount of scale in the y direction around the pivot point. A
2176         * value of 1 means no scaling is applied.
2177         */
2178        @ViewDebug.ExportedProperty
2179        float mScaleY = 1f;
2180
2181        /**
2182         * The x location of the point around which the view is rotated and scaled.
2183         */
2184        @ViewDebug.ExportedProperty
2185        float mPivotX = 0f;
2186
2187        /**
2188         * The y location of the point around which the view is rotated and scaled.
2189         */
2190        @ViewDebug.ExportedProperty
2191        float mPivotY = 0f;
2192
2193        /**
2194         * The opacity of the View. This is a value from 0 to 1, where 0 means
2195         * completely transparent and 1 means completely opaque.
2196         */
2197        @ViewDebug.ExportedProperty
2198        float mAlpha = 1f;
2199    }
2200
2201    TransformationInfo mTransformationInfo;
2202
2203    private boolean mLastIsOpaque;
2204
2205    /**
2206     * Convenience value to check for float values that are close enough to zero to be considered
2207     * zero.
2208     */
2209    private static final float NONZERO_EPSILON = .001f;
2210
2211    /**
2212     * The distance in pixels from the left edge of this view's parent
2213     * to the left edge of this view.
2214     * {@hide}
2215     */
2216    @ViewDebug.ExportedProperty(category = "layout")
2217    protected int mLeft;
2218    /**
2219     * The distance in pixels from the left edge of this view's parent
2220     * to the right edge of this view.
2221     * {@hide}
2222     */
2223    @ViewDebug.ExportedProperty(category = "layout")
2224    protected int mRight;
2225    /**
2226     * The distance in pixels from the top edge of this view's parent
2227     * to the top edge of this view.
2228     * {@hide}
2229     */
2230    @ViewDebug.ExportedProperty(category = "layout")
2231    protected int mTop;
2232    /**
2233     * The distance in pixels from the top edge of this view's parent
2234     * to the bottom edge of this view.
2235     * {@hide}
2236     */
2237    @ViewDebug.ExportedProperty(category = "layout")
2238    protected int mBottom;
2239
2240    /**
2241     * The offset, in pixels, by which the content of this view is scrolled
2242     * horizontally.
2243     * {@hide}
2244     */
2245    @ViewDebug.ExportedProperty(category = "scrolling")
2246    protected int mScrollX;
2247    /**
2248     * The offset, in pixels, by which the content of this view is scrolled
2249     * vertically.
2250     * {@hide}
2251     */
2252    @ViewDebug.ExportedProperty(category = "scrolling")
2253    protected int mScrollY;
2254
2255    /**
2256     * The left padding in pixels, that is the distance in pixels between the
2257     * left edge of this view and the left edge of its content.
2258     * {@hide}
2259     */
2260    @ViewDebug.ExportedProperty(category = "padding")
2261    protected int mPaddingLeft;
2262    /**
2263     * The right padding in pixels, that is the distance in pixels between the
2264     * right edge of this view and the right edge of its content.
2265     * {@hide}
2266     */
2267    @ViewDebug.ExportedProperty(category = "padding")
2268    protected int mPaddingRight;
2269    /**
2270     * The top padding in pixels, that is the distance in pixels between the
2271     * top edge of this view and the top edge of its content.
2272     * {@hide}
2273     */
2274    @ViewDebug.ExportedProperty(category = "padding")
2275    protected int mPaddingTop;
2276    /**
2277     * The bottom padding in pixels, that is the distance in pixels between the
2278     * bottom edge of this view and the bottom edge of its content.
2279     * {@hide}
2280     */
2281    @ViewDebug.ExportedProperty(category = "padding")
2282    protected int mPaddingBottom;
2283
2284    /**
2285     * Briefly describes the view and is primarily used for accessibility support.
2286     */
2287    private CharSequence mContentDescription;
2288
2289    /**
2290     * Cache the paddingRight set by the user to append to the scrollbar's size.
2291     *
2292     * @hide
2293     */
2294    @ViewDebug.ExportedProperty(category = "padding")
2295    protected int mUserPaddingRight;
2296
2297    /**
2298     * Cache the paddingBottom set by the user to append to the scrollbar's size.
2299     *
2300     * @hide
2301     */
2302    @ViewDebug.ExportedProperty(category = "padding")
2303    protected int mUserPaddingBottom;
2304
2305    /**
2306     * Cache the paddingLeft set by the user to append to the scrollbar's size.
2307     *
2308     * @hide
2309     */
2310    @ViewDebug.ExportedProperty(category = "padding")
2311    protected int mUserPaddingLeft;
2312
2313    /**
2314     * Cache if the user padding is relative.
2315     *
2316     */
2317    @ViewDebug.ExportedProperty(category = "padding")
2318    boolean mUserPaddingRelative;
2319
2320    /**
2321     * Cache the paddingStart set by the user to append to the scrollbar's size.
2322     *
2323     */
2324    @ViewDebug.ExportedProperty(category = "padding")
2325    int mUserPaddingStart;
2326
2327    /**
2328     * Cache the paddingEnd set by the user to append to the scrollbar's size.
2329     *
2330     */
2331    @ViewDebug.ExportedProperty(category = "padding")
2332    int mUserPaddingEnd;
2333
2334    /**
2335     * @hide
2336     */
2337    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
2338    /**
2339     * @hide
2340     */
2341    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
2342
2343    private Drawable mBGDrawable;
2344
2345    private int mBackgroundResource;
2346    private boolean mBackgroundSizeChanged;
2347
2348    static class ListenerInfo {
2349        /**
2350         * Listener used to dispatch focus change events.
2351         * This field should be made private, so it is hidden from the SDK.
2352         * {@hide}
2353         */
2354        protected OnFocusChangeListener mOnFocusChangeListener;
2355
2356        /**
2357         * Listeners for layout change events.
2358         */
2359        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
2360
2361        /**
2362         * Listeners for attach events.
2363         */
2364        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
2365
2366        /**
2367         * Listener used to dispatch click events.
2368         * This field should be made private, so it is hidden from the SDK.
2369         * {@hide}
2370         */
2371        public OnClickListener mOnClickListener;
2372
2373        /**
2374         * Listener used to dispatch long click events.
2375         * This field should be made private, so it is hidden from the SDK.
2376         * {@hide}
2377         */
2378        protected OnLongClickListener mOnLongClickListener;
2379
2380        /**
2381         * Listener used to build the context menu.
2382         * This field should be made private, so it is hidden from the SDK.
2383         * {@hide}
2384         */
2385        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
2386
2387        private OnKeyListener mOnKeyListener;
2388
2389        private OnTouchListener mOnTouchListener;
2390
2391        private OnHoverListener mOnHoverListener;
2392
2393        private OnGenericMotionListener mOnGenericMotionListener;
2394
2395        private OnDragListener mOnDragListener;
2396
2397        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
2398    }
2399
2400    ListenerInfo mListenerInfo;
2401
2402    /**
2403     * The application environment this view lives in.
2404     * This field should be made private, so it is hidden from the SDK.
2405     * {@hide}
2406     */
2407    protected Context mContext;
2408
2409    private final Resources mResources;
2410
2411    private ScrollabilityCache mScrollCache;
2412
2413    private int[] mDrawableState = null;
2414
2415    /**
2416     * Set to true when drawing cache is enabled and cannot be created.
2417     *
2418     * @hide
2419     */
2420    public boolean mCachingFailed;
2421
2422    private Bitmap mDrawingCache;
2423    private Bitmap mUnscaledDrawingCache;
2424    private HardwareLayer mHardwareLayer;
2425    DisplayList mDisplayList;
2426
2427    /**
2428     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
2429     * the user may specify which view to go to next.
2430     */
2431    private int mNextFocusLeftId = View.NO_ID;
2432
2433    /**
2434     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
2435     * the user may specify which view to go to next.
2436     */
2437    private int mNextFocusRightId = View.NO_ID;
2438
2439    /**
2440     * When this view has focus and the next focus is {@link #FOCUS_UP},
2441     * the user may specify which view to go to next.
2442     */
2443    private int mNextFocusUpId = View.NO_ID;
2444
2445    /**
2446     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
2447     * the user may specify which view to go to next.
2448     */
2449    private int mNextFocusDownId = View.NO_ID;
2450
2451    /**
2452     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
2453     * the user may specify which view to go to next.
2454     */
2455    int mNextFocusForwardId = View.NO_ID;
2456
2457    private CheckForLongPress mPendingCheckForLongPress;
2458    private CheckForTap mPendingCheckForTap = null;
2459    private PerformClick mPerformClick;
2460    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
2461
2462    private UnsetPressedState mUnsetPressedState;
2463
2464    /**
2465     * Whether the long press's action has been invoked.  The tap's action is invoked on the
2466     * up event while a long press is invoked as soon as the long press duration is reached, so
2467     * a long press could be performed before the tap is checked, in which case the tap's action
2468     * should not be invoked.
2469     */
2470    private boolean mHasPerformedLongPress;
2471
2472    /**
2473     * The minimum height of the view. We'll try our best to have the height
2474     * of this view to at least this amount.
2475     */
2476    @ViewDebug.ExportedProperty(category = "measurement")
2477    private int mMinHeight;
2478
2479    /**
2480     * The minimum width of the view. We'll try our best to have the width
2481     * of this view to at least this amount.
2482     */
2483    @ViewDebug.ExportedProperty(category = "measurement")
2484    private int mMinWidth;
2485
2486    /**
2487     * The delegate to handle touch events that are physically in this view
2488     * but should be handled by another view.
2489     */
2490    private TouchDelegate mTouchDelegate = null;
2491
2492    /**
2493     * Solid color to use as a background when creating the drawing cache. Enables
2494     * the cache to use 16 bit bitmaps instead of 32 bit.
2495     */
2496    private int mDrawingCacheBackgroundColor = 0;
2497
2498    /**
2499     * Special tree observer used when mAttachInfo is null.
2500     */
2501    private ViewTreeObserver mFloatingTreeObserver;
2502
2503    /**
2504     * Cache the touch slop from the context that created the view.
2505     */
2506    private int mTouchSlop;
2507
2508    /**
2509     * Object that handles automatic animation of view properties.
2510     */
2511    private ViewPropertyAnimator mAnimator = null;
2512
2513    /**
2514     * Flag indicating that a drag can cross window boundaries.  When
2515     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
2516     * with this flag set, all visible applications will be able to participate
2517     * in the drag operation and receive the dragged content.
2518     *
2519     * @hide
2520     */
2521    public static final int DRAG_FLAG_GLOBAL = 1;
2522
2523    /**
2524     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
2525     */
2526    private float mVerticalScrollFactor;
2527
2528    /**
2529     * Position of the vertical scroll bar.
2530     */
2531    private int mVerticalScrollbarPosition;
2532
2533    /**
2534     * Position the scroll bar at the default position as determined by the system.
2535     */
2536    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
2537
2538    /**
2539     * Position the scroll bar along the left edge.
2540     */
2541    public static final int SCROLLBAR_POSITION_LEFT = 1;
2542
2543    /**
2544     * Position the scroll bar along the right edge.
2545     */
2546    public static final int SCROLLBAR_POSITION_RIGHT = 2;
2547
2548    /**
2549     * Indicates that the view does not have a layer.
2550     *
2551     * @see #getLayerType()
2552     * @see #setLayerType(int, android.graphics.Paint)
2553     * @see #LAYER_TYPE_SOFTWARE
2554     * @see #LAYER_TYPE_HARDWARE
2555     */
2556    public static final int LAYER_TYPE_NONE = 0;
2557
2558    /**
2559     * <p>Indicates that the view has a software layer. A software layer is backed
2560     * by a bitmap and causes the view to be rendered using Android's software
2561     * rendering pipeline, even if hardware acceleration is enabled.</p>
2562     *
2563     * <p>Software layers have various usages:</p>
2564     * <p>When the application is not using hardware acceleration, a software layer
2565     * is useful to apply a specific color filter and/or blending mode and/or
2566     * translucency to a view and all its children.</p>
2567     * <p>When the application is using hardware acceleration, a software layer
2568     * is useful to render drawing primitives not supported by the hardware
2569     * accelerated pipeline. It can also be used to cache a complex view tree
2570     * into a texture and reduce the complexity of drawing operations. For instance,
2571     * when animating a complex view tree with a translation, a software layer can
2572     * be used to render the view tree only once.</p>
2573     * <p>Software layers should be avoided when the affected view tree updates
2574     * often. Every update will require to re-render the software layer, which can
2575     * potentially be slow (particularly when hardware acceleration is turned on
2576     * since the layer will have to be uploaded into a hardware texture after every
2577     * update.)</p>
2578     *
2579     * @see #getLayerType()
2580     * @see #setLayerType(int, android.graphics.Paint)
2581     * @see #LAYER_TYPE_NONE
2582     * @see #LAYER_TYPE_HARDWARE
2583     */
2584    public static final int LAYER_TYPE_SOFTWARE = 1;
2585
2586    /**
2587     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
2588     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
2589     * OpenGL hardware) and causes the view to be rendered using Android's hardware
2590     * rendering pipeline, but only if hardware acceleration is turned on for the
2591     * view hierarchy. When hardware acceleration is turned off, hardware layers
2592     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
2593     *
2594     * <p>A hardware layer is useful to apply a specific color filter and/or
2595     * blending mode and/or translucency to a view and all its children.</p>
2596     * <p>A hardware layer can be used to cache a complex view tree into a
2597     * texture and reduce the complexity of drawing operations. For instance,
2598     * when animating a complex view tree with a translation, a hardware layer can
2599     * be used to render the view tree only once.</p>
2600     * <p>A hardware layer can also be used to increase the rendering quality when
2601     * rotation transformations are applied on a view. It can also be used to
2602     * prevent potential clipping issues when applying 3D transforms on a view.</p>
2603     *
2604     * @see #getLayerType()
2605     * @see #setLayerType(int, android.graphics.Paint)
2606     * @see #LAYER_TYPE_NONE
2607     * @see #LAYER_TYPE_SOFTWARE
2608     */
2609    public static final int LAYER_TYPE_HARDWARE = 2;
2610
2611    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
2612            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
2613            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
2614            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
2615    })
2616    int mLayerType = LAYER_TYPE_NONE;
2617    Paint mLayerPaint;
2618    Rect mLocalDirtyRect;
2619
2620    /**
2621     * Set to true when the view is sending hover accessibility events because it
2622     * is the innermost hovered view.
2623     */
2624    private boolean mSendingHoverAccessibilityEvents;
2625
2626    /**
2627     * Delegate for injecting accessiblity functionality.
2628     */
2629    AccessibilityDelegate mAccessibilityDelegate;
2630
2631    /**
2632     * Text direction is inherited thru {@link ViewGroup}
2633     */
2634    public static final int TEXT_DIRECTION_INHERIT = 0;
2635
2636    /**
2637     * Text direction is using "first strong algorithm". The first strong directional character
2638     * determines the paragraph direction. If there is no strong directional character, the
2639     * paragraph direction is the view's resolved layout direction.
2640     *
2641     */
2642    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2643
2644    /**
2645     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2646     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2647     * If there are neither, the paragraph direction is the view's resolved layout direction.
2648     *
2649     */
2650    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2651
2652    /**
2653     * Text direction is forced to LTR.
2654     *
2655     */
2656    public static final int TEXT_DIRECTION_LTR = 3;
2657
2658    /**
2659     * Text direction is forced to RTL.
2660     *
2661     */
2662    public static final int TEXT_DIRECTION_RTL = 4;
2663
2664    /**
2665     * Text direction is coming from the system Locale.
2666     *
2667     */
2668    public static final int TEXT_DIRECTION_LOCALE = 5;
2669
2670    /**
2671     * Default text direction is inherited
2672     *
2673     */
2674    protected static int DEFAULT_TEXT_DIRECTION = TEXT_DIRECTION_INHERIT;
2675
2676    /**
2677     * The text direction that has been defined by {@link #setTextDirection(int)}.
2678     *
2679     */
2680    @ViewDebug.ExportedProperty(category = "text", mapping = {
2681            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
2682            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
2683            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
2684            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
2685            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
2686            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
2687    })
2688    private int mTextDirection = DEFAULT_TEXT_DIRECTION;
2689
2690    /**
2691     * The resolved text direction.  This needs resolution if the value is
2692     * TEXT_DIRECTION_INHERIT.  The resolution matches mTextDirection if it is
2693     * not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds up the parent
2694     * chain of the view.
2695     *
2696     */
2697    @ViewDebug.ExportedProperty(category = "text", mapping = {
2698            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
2699            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
2700            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
2701            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
2702            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
2703            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
2704    })
2705    private int mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
2706
2707    /**
2708     * Consistency verifier for debugging purposes.
2709     * @hide
2710     */
2711    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
2712            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
2713                    new InputEventConsistencyVerifier(this, 0) : null;
2714
2715    /**
2716     * Simple constructor to use when creating a view from code.
2717     *
2718     * @param context The Context the view is running in, through which it can
2719     *        access the current theme, resources, etc.
2720     */
2721    public View(Context context) {
2722        mContext = context;
2723        mResources = context != null ? context.getResources() : null;
2724        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | LAYOUT_DIRECTION_INHERIT;
2725        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
2726        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
2727        mUserPaddingStart = -1;
2728        mUserPaddingEnd = -1;
2729        mUserPaddingRelative = false;
2730    }
2731
2732    /**
2733     * Constructor that is called when inflating a view from XML. This is called
2734     * when a view is being constructed from an XML file, supplying attributes
2735     * that were specified in the XML file. This version uses a default style of
2736     * 0, so the only attribute values applied are those in the Context's Theme
2737     * and the given AttributeSet.
2738     *
2739     * <p>
2740     * The method onFinishInflate() will be called after all children have been
2741     * added.
2742     *
2743     * @param context The Context the view is running in, through which it can
2744     *        access the current theme, resources, etc.
2745     * @param attrs The attributes of the XML tag that is inflating the view.
2746     * @see #View(Context, AttributeSet, int)
2747     */
2748    public View(Context context, AttributeSet attrs) {
2749        this(context, attrs, 0);
2750    }
2751
2752    /**
2753     * Perform inflation from XML and apply a class-specific base style. This
2754     * constructor of View allows subclasses to use their own base style when
2755     * they are inflating. For example, a Button class's constructor would call
2756     * this version of the super class constructor and supply
2757     * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
2758     * the theme's button style to modify all of the base view attributes (in
2759     * particular its background) as well as the Button class's attributes.
2760     *
2761     * @param context The Context the view is running in, through which it can
2762     *        access the current theme, resources, etc.
2763     * @param attrs The attributes of the XML tag that is inflating the view.
2764     * @param defStyle The default style to apply to this view. If 0, no style
2765     *        will be applied (beyond what is included in the theme). This may
2766     *        either be an attribute resource, whose value will be retrieved
2767     *        from the current theme, or an explicit style resource.
2768     * @see #View(Context, AttributeSet)
2769     */
2770    public View(Context context, AttributeSet attrs, int defStyle) {
2771        this(context);
2772
2773        TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
2774                defStyle, 0);
2775
2776        Drawable background = null;
2777
2778        int leftPadding = -1;
2779        int topPadding = -1;
2780        int rightPadding = -1;
2781        int bottomPadding = -1;
2782        int startPadding = -1;
2783        int endPadding = -1;
2784
2785        int padding = -1;
2786
2787        int viewFlagValues = 0;
2788        int viewFlagMasks = 0;
2789
2790        boolean setScrollContainer = false;
2791
2792        int x = 0;
2793        int y = 0;
2794
2795        float tx = 0;
2796        float ty = 0;
2797        float rotation = 0;
2798        float rotationX = 0;
2799        float rotationY = 0;
2800        float sx = 1f;
2801        float sy = 1f;
2802        boolean transformSet = false;
2803
2804        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
2805
2806        int overScrollMode = mOverScrollMode;
2807        final int N = a.getIndexCount();
2808        for (int i = 0; i < N; i++) {
2809            int attr = a.getIndex(i);
2810            switch (attr) {
2811                case com.android.internal.R.styleable.View_background:
2812                    background = a.getDrawable(attr);
2813                    break;
2814                case com.android.internal.R.styleable.View_padding:
2815                    padding = a.getDimensionPixelSize(attr, -1);
2816                    break;
2817                 case com.android.internal.R.styleable.View_paddingLeft:
2818                    leftPadding = a.getDimensionPixelSize(attr, -1);
2819                    break;
2820                case com.android.internal.R.styleable.View_paddingTop:
2821                    topPadding = a.getDimensionPixelSize(attr, -1);
2822                    break;
2823                case com.android.internal.R.styleable.View_paddingRight:
2824                    rightPadding = a.getDimensionPixelSize(attr, -1);
2825                    break;
2826                case com.android.internal.R.styleable.View_paddingBottom:
2827                    bottomPadding = a.getDimensionPixelSize(attr, -1);
2828                    break;
2829                case com.android.internal.R.styleable.View_paddingStart:
2830                    startPadding = a.getDimensionPixelSize(attr, -1);
2831                    break;
2832                case com.android.internal.R.styleable.View_paddingEnd:
2833                    endPadding = a.getDimensionPixelSize(attr, -1);
2834                    break;
2835                case com.android.internal.R.styleable.View_scrollX:
2836                    x = a.getDimensionPixelOffset(attr, 0);
2837                    break;
2838                case com.android.internal.R.styleable.View_scrollY:
2839                    y = a.getDimensionPixelOffset(attr, 0);
2840                    break;
2841                case com.android.internal.R.styleable.View_alpha:
2842                    setAlpha(a.getFloat(attr, 1f));
2843                    break;
2844                case com.android.internal.R.styleable.View_transformPivotX:
2845                    setPivotX(a.getDimensionPixelOffset(attr, 0));
2846                    break;
2847                case com.android.internal.R.styleable.View_transformPivotY:
2848                    setPivotY(a.getDimensionPixelOffset(attr, 0));
2849                    break;
2850                case com.android.internal.R.styleable.View_translationX:
2851                    tx = a.getDimensionPixelOffset(attr, 0);
2852                    transformSet = true;
2853                    break;
2854                case com.android.internal.R.styleable.View_translationY:
2855                    ty = a.getDimensionPixelOffset(attr, 0);
2856                    transformSet = true;
2857                    break;
2858                case com.android.internal.R.styleable.View_rotation:
2859                    rotation = a.getFloat(attr, 0);
2860                    transformSet = true;
2861                    break;
2862                case com.android.internal.R.styleable.View_rotationX:
2863                    rotationX = a.getFloat(attr, 0);
2864                    transformSet = true;
2865                    break;
2866                case com.android.internal.R.styleable.View_rotationY:
2867                    rotationY = a.getFloat(attr, 0);
2868                    transformSet = true;
2869                    break;
2870                case com.android.internal.R.styleable.View_scaleX:
2871                    sx = a.getFloat(attr, 1f);
2872                    transformSet = true;
2873                    break;
2874                case com.android.internal.R.styleable.View_scaleY:
2875                    sy = a.getFloat(attr, 1f);
2876                    transformSet = true;
2877                    break;
2878                case com.android.internal.R.styleable.View_id:
2879                    mID = a.getResourceId(attr, NO_ID);
2880                    break;
2881                case com.android.internal.R.styleable.View_tag:
2882                    mTag = a.getText(attr);
2883                    break;
2884                case com.android.internal.R.styleable.View_fitsSystemWindows:
2885                    if (a.getBoolean(attr, false)) {
2886                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
2887                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
2888                    }
2889                    break;
2890                case com.android.internal.R.styleable.View_focusable:
2891                    if (a.getBoolean(attr, false)) {
2892                        viewFlagValues |= FOCUSABLE;
2893                        viewFlagMasks |= FOCUSABLE_MASK;
2894                    }
2895                    break;
2896                case com.android.internal.R.styleable.View_focusableInTouchMode:
2897                    if (a.getBoolean(attr, false)) {
2898                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
2899                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
2900                    }
2901                    break;
2902                case com.android.internal.R.styleable.View_clickable:
2903                    if (a.getBoolean(attr, false)) {
2904                        viewFlagValues |= CLICKABLE;
2905                        viewFlagMasks |= CLICKABLE;
2906                    }
2907                    break;
2908                case com.android.internal.R.styleable.View_longClickable:
2909                    if (a.getBoolean(attr, false)) {
2910                        viewFlagValues |= LONG_CLICKABLE;
2911                        viewFlagMasks |= LONG_CLICKABLE;
2912                    }
2913                    break;
2914                case com.android.internal.R.styleable.View_saveEnabled:
2915                    if (!a.getBoolean(attr, true)) {
2916                        viewFlagValues |= SAVE_DISABLED;
2917                        viewFlagMasks |= SAVE_DISABLED_MASK;
2918                    }
2919                    break;
2920                case com.android.internal.R.styleable.View_duplicateParentState:
2921                    if (a.getBoolean(attr, false)) {
2922                        viewFlagValues |= DUPLICATE_PARENT_STATE;
2923                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
2924                    }
2925                    break;
2926                case com.android.internal.R.styleable.View_visibility:
2927                    final int visibility = a.getInt(attr, 0);
2928                    if (visibility != 0) {
2929                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
2930                        viewFlagMasks |= VISIBILITY_MASK;
2931                    }
2932                    break;
2933                case com.android.internal.R.styleable.View_layoutDirection:
2934                    // Clear any HORIZONTAL_DIRECTION flag already set
2935                    viewFlagValues &= ~LAYOUT_DIRECTION_MASK;
2936                    // Set the HORIZONTAL_DIRECTION flags depending on the value of the attribute
2937                    final int layoutDirection = a.getInt(attr, -1);
2938                    if (layoutDirection != -1) {
2939                        viewFlagValues |= LAYOUT_DIRECTION_FLAGS[layoutDirection];
2940                    } else {
2941                        // Set to default (LAYOUT_DIRECTION_INHERIT)
2942                        viewFlagValues |= LAYOUT_DIRECTION_DEFAULT;
2943                    }
2944                    viewFlagMasks |= LAYOUT_DIRECTION_MASK;
2945                    break;
2946                case com.android.internal.R.styleable.View_drawingCacheQuality:
2947                    final int cacheQuality = a.getInt(attr, 0);
2948                    if (cacheQuality != 0) {
2949                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
2950                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
2951                    }
2952                    break;
2953                case com.android.internal.R.styleable.View_contentDescription:
2954                    mContentDescription = a.getString(attr);
2955                    break;
2956                case com.android.internal.R.styleable.View_soundEffectsEnabled:
2957                    if (!a.getBoolean(attr, true)) {
2958                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
2959                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
2960                    }
2961                    break;
2962                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
2963                    if (!a.getBoolean(attr, true)) {
2964                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
2965                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
2966                    }
2967                    break;
2968                case R.styleable.View_scrollbars:
2969                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
2970                    if (scrollbars != SCROLLBARS_NONE) {
2971                        viewFlagValues |= scrollbars;
2972                        viewFlagMasks |= SCROLLBARS_MASK;
2973                        initializeScrollbars(a);
2974                    }
2975                    break;
2976                //noinspection deprecation
2977                case R.styleable.View_fadingEdge:
2978                    if (context.getApplicationInfo().targetSdkVersion >= ICE_CREAM_SANDWICH) {
2979                        // Ignore the attribute starting with ICS
2980                        break;
2981                    }
2982                    // With builds < ICS, fall through and apply fading edges
2983                case R.styleable.View_requiresFadingEdge:
2984                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
2985                    if (fadingEdge != FADING_EDGE_NONE) {
2986                        viewFlagValues |= fadingEdge;
2987                        viewFlagMasks |= FADING_EDGE_MASK;
2988                        initializeFadingEdge(a);
2989                    }
2990                    break;
2991                case R.styleable.View_scrollbarStyle:
2992                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
2993                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
2994                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
2995                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
2996                    }
2997                    break;
2998                case R.styleable.View_isScrollContainer:
2999                    setScrollContainer = true;
3000                    if (a.getBoolean(attr, false)) {
3001                        setScrollContainer(true);
3002                    }
3003                    break;
3004                case com.android.internal.R.styleable.View_keepScreenOn:
3005                    if (a.getBoolean(attr, false)) {
3006                        viewFlagValues |= KEEP_SCREEN_ON;
3007                        viewFlagMasks |= KEEP_SCREEN_ON;
3008                    }
3009                    break;
3010                case R.styleable.View_filterTouchesWhenObscured:
3011                    if (a.getBoolean(attr, false)) {
3012                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3013                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3014                    }
3015                    break;
3016                case R.styleable.View_nextFocusLeft:
3017                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3018                    break;
3019                case R.styleable.View_nextFocusRight:
3020                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3021                    break;
3022                case R.styleable.View_nextFocusUp:
3023                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3024                    break;
3025                case R.styleable.View_nextFocusDown:
3026                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3027                    break;
3028                case R.styleable.View_nextFocusForward:
3029                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3030                    break;
3031                case R.styleable.View_minWidth:
3032                    mMinWidth = a.getDimensionPixelSize(attr, 0);
3033                    break;
3034                case R.styleable.View_minHeight:
3035                    mMinHeight = a.getDimensionPixelSize(attr, 0);
3036                    break;
3037                case R.styleable.View_onClick:
3038                    if (context.isRestricted()) {
3039                        throw new IllegalStateException("The android:onClick attribute cannot "
3040                                + "be used within a restricted context");
3041                    }
3042
3043                    final String handlerName = a.getString(attr);
3044                    if (handlerName != null) {
3045                        setOnClickListener(new OnClickListener() {
3046                            private Method mHandler;
3047
3048                            public void onClick(View v) {
3049                                if (mHandler == null) {
3050                                    try {
3051                                        mHandler = getContext().getClass().getMethod(handlerName,
3052                                                View.class);
3053                                    } catch (NoSuchMethodException e) {
3054                                        int id = getId();
3055                                        String idText = id == NO_ID ? "" : " with id '"
3056                                                + getContext().getResources().getResourceEntryName(
3057                                                    id) + "'";
3058                                        throw new IllegalStateException("Could not find a method " +
3059                                                handlerName + "(View) in the activity "
3060                                                + getContext().getClass() + " for onClick handler"
3061                                                + " on view " + View.this.getClass() + idText, e);
3062                                    }
3063                                }
3064
3065                                try {
3066                                    mHandler.invoke(getContext(), View.this);
3067                                } catch (IllegalAccessException e) {
3068                                    throw new IllegalStateException("Could not execute non "
3069                                            + "public method of the activity", e);
3070                                } catch (InvocationTargetException e) {
3071                                    throw new IllegalStateException("Could not execute "
3072                                            + "method of the activity", e);
3073                                }
3074                            }
3075                        });
3076                    }
3077                    break;
3078                case R.styleable.View_overScrollMode:
3079                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3080                    break;
3081                case R.styleable.View_verticalScrollbarPosition:
3082                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3083                    break;
3084                case R.styleable.View_layerType:
3085                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3086                    break;
3087                case R.styleable.View_textDirection:
3088                    mTextDirection = a.getInt(attr, DEFAULT_TEXT_DIRECTION);
3089                    break;
3090            }
3091        }
3092
3093        a.recycle();
3094
3095        setOverScrollMode(overScrollMode);
3096
3097        if (background != null) {
3098            setBackgroundDrawable(background);
3099        }
3100
3101        mUserPaddingRelative = (startPadding >= 0 || endPadding >= 0);
3102
3103        // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved
3104        // layout direction). Those cached values will be used later during padding resolution.
3105        mUserPaddingStart = startPadding;
3106        mUserPaddingEnd = endPadding;
3107
3108        if (padding >= 0) {
3109            leftPadding = padding;
3110            topPadding = padding;
3111            rightPadding = padding;
3112            bottomPadding = padding;
3113        }
3114
3115        // If the user specified the padding (either with android:padding or
3116        // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
3117        // use the default padding or the padding from the background drawable
3118        // (stored at this point in mPadding*)
3119        setPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
3120                topPadding >= 0 ? topPadding : mPaddingTop,
3121                rightPadding >= 0 ? rightPadding : mPaddingRight,
3122                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
3123
3124        if (viewFlagMasks != 0) {
3125            setFlags(viewFlagValues, viewFlagMasks);
3126        }
3127
3128        // Needs to be called after mViewFlags is set
3129        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3130            recomputePadding();
3131        }
3132
3133        if (x != 0 || y != 0) {
3134            scrollTo(x, y);
3135        }
3136
3137        if (transformSet) {
3138            setTranslationX(tx);
3139            setTranslationY(ty);
3140            setRotation(rotation);
3141            setRotationX(rotationX);
3142            setRotationY(rotationY);
3143            setScaleX(sx);
3144            setScaleY(sy);
3145        }
3146
3147        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
3148            setScrollContainer(true);
3149        }
3150
3151        computeOpaqueFlags();
3152    }
3153
3154    /**
3155     * Non-public constructor for use in testing
3156     */
3157    View() {
3158        mResources = null;
3159    }
3160
3161    /**
3162     * <p>
3163     * Initializes the fading edges from a given set of styled attributes. This
3164     * method should be called by subclasses that need fading edges and when an
3165     * instance of these subclasses is created programmatically rather than
3166     * being inflated from XML. This method is automatically called when the XML
3167     * is inflated.
3168     * </p>
3169     *
3170     * @param a the styled attributes set to initialize the fading edges from
3171     */
3172    protected void initializeFadingEdge(TypedArray a) {
3173        initScrollCache();
3174
3175        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
3176                R.styleable.View_fadingEdgeLength,
3177                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
3178    }
3179
3180    /**
3181     * Returns the size of the vertical faded edges used to indicate that more
3182     * content in this view is visible.
3183     *
3184     * @return The size in pixels of the vertical faded edge or 0 if vertical
3185     *         faded edges are not enabled for this view.
3186     * @attr ref android.R.styleable#View_fadingEdgeLength
3187     */
3188    public int getVerticalFadingEdgeLength() {
3189        if (isVerticalFadingEdgeEnabled()) {
3190            ScrollabilityCache cache = mScrollCache;
3191            if (cache != null) {
3192                return cache.fadingEdgeLength;
3193            }
3194        }
3195        return 0;
3196    }
3197
3198    /**
3199     * Set the size of the faded edge used to indicate that more content in this
3200     * view is available.  Will not change whether the fading edge is enabled; use
3201     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
3202     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
3203     * for the vertical or horizontal fading edges.
3204     *
3205     * @param length The size in pixels of the faded edge used to indicate that more
3206     *        content in this view is visible.
3207     */
3208    public void setFadingEdgeLength(int length) {
3209        initScrollCache();
3210        mScrollCache.fadingEdgeLength = length;
3211    }
3212
3213    /**
3214     * Returns the size of the horizontal faded edges used to indicate that more
3215     * content in this view is visible.
3216     *
3217     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
3218     *         faded edges are not enabled for this view.
3219     * @attr ref android.R.styleable#View_fadingEdgeLength
3220     */
3221    public int getHorizontalFadingEdgeLength() {
3222        if (isHorizontalFadingEdgeEnabled()) {
3223            ScrollabilityCache cache = mScrollCache;
3224            if (cache != null) {
3225                return cache.fadingEdgeLength;
3226            }
3227        }
3228        return 0;
3229    }
3230
3231    /**
3232     * Returns the width of the vertical scrollbar.
3233     *
3234     * @return The width in pixels of the vertical scrollbar or 0 if there
3235     *         is no vertical scrollbar.
3236     */
3237    public int getVerticalScrollbarWidth() {
3238        ScrollabilityCache cache = mScrollCache;
3239        if (cache != null) {
3240            ScrollBarDrawable scrollBar = cache.scrollBar;
3241            if (scrollBar != null) {
3242                int size = scrollBar.getSize(true);
3243                if (size <= 0) {
3244                    size = cache.scrollBarSize;
3245                }
3246                return size;
3247            }
3248            return 0;
3249        }
3250        return 0;
3251    }
3252
3253    /**
3254     * Returns the height of the horizontal scrollbar.
3255     *
3256     * @return The height in pixels of the horizontal scrollbar or 0 if
3257     *         there is no horizontal scrollbar.
3258     */
3259    protected int getHorizontalScrollbarHeight() {
3260        ScrollabilityCache cache = mScrollCache;
3261        if (cache != null) {
3262            ScrollBarDrawable scrollBar = cache.scrollBar;
3263            if (scrollBar != null) {
3264                int size = scrollBar.getSize(false);
3265                if (size <= 0) {
3266                    size = cache.scrollBarSize;
3267                }
3268                return size;
3269            }
3270            return 0;
3271        }
3272        return 0;
3273    }
3274
3275    /**
3276     * <p>
3277     * Initializes the scrollbars from a given set of styled attributes. This
3278     * method should be called by subclasses that need scrollbars and when an
3279     * instance of these subclasses is created programmatically rather than
3280     * being inflated from XML. This method is automatically called when the XML
3281     * is inflated.
3282     * </p>
3283     *
3284     * @param a the styled attributes set to initialize the scrollbars from
3285     */
3286    protected void initializeScrollbars(TypedArray a) {
3287        initScrollCache();
3288
3289        final ScrollabilityCache scrollabilityCache = mScrollCache;
3290
3291        if (scrollabilityCache.scrollBar == null) {
3292            scrollabilityCache.scrollBar = new ScrollBarDrawable();
3293        }
3294
3295        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
3296
3297        if (!fadeScrollbars) {
3298            scrollabilityCache.state = ScrollabilityCache.ON;
3299        }
3300        scrollabilityCache.fadeScrollBars = fadeScrollbars;
3301
3302
3303        scrollabilityCache.scrollBarFadeDuration = a.getInt(
3304                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
3305                        .getScrollBarFadeDuration());
3306        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
3307                R.styleable.View_scrollbarDefaultDelayBeforeFade,
3308                ViewConfiguration.getScrollDefaultDelay());
3309
3310
3311        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
3312                com.android.internal.R.styleable.View_scrollbarSize,
3313                ViewConfiguration.get(mContext).getScaledScrollBarSize());
3314
3315        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
3316        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
3317
3318        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
3319        if (thumb != null) {
3320            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
3321        }
3322
3323        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
3324                false);
3325        if (alwaysDraw) {
3326            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
3327        }
3328
3329        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
3330        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
3331
3332        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
3333        if (thumb != null) {
3334            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
3335        }
3336
3337        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
3338                false);
3339        if (alwaysDraw) {
3340            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
3341        }
3342
3343        // Re-apply user/background padding so that scrollbar(s) get added
3344        resolvePadding();
3345    }
3346
3347    /**
3348     * <p>
3349     * Initalizes the scrollability cache if necessary.
3350     * </p>
3351     */
3352    private void initScrollCache() {
3353        if (mScrollCache == null) {
3354            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
3355        }
3356    }
3357
3358    /**
3359     * Set the position of the vertical scroll bar. Should be one of
3360     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
3361     * {@link #SCROLLBAR_POSITION_RIGHT}.
3362     *
3363     * @param position Where the vertical scroll bar should be positioned.
3364     */
3365    public void setVerticalScrollbarPosition(int position) {
3366        if (mVerticalScrollbarPosition != position) {
3367            mVerticalScrollbarPosition = position;
3368            computeOpaqueFlags();
3369            resolvePadding();
3370        }
3371    }
3372
3373    /**
3374     * @return The position where the vertical scroll bar will show, if applicable.
3375     * @see #setVerticalScrollbarPosition(int)
3376     */
3377    public int getVerticalScrollbarPosition() {
3378        return mVerticalScrollbarPosition;
3379    }
3380
3381    ListenerInfo getListenerInfo() {
3382        if (mListenerInfo != null) {
3383            return mListenerInfo;
3384        }
3385        mListenerInfo = new ListenerInfo();
3386        return mListenerInfo;
3387    }
3388
3389    /**
3390     * Register a callback to be invoked when focus of this view changed.
3391     *
3392     * @param l The callback that will run.
3393     */
3394    public void setOnFocusChangeListener(OnFocusChangeListener l) {
3395        getListenerInfo().mOnFocusChangeListener = l;
3396    }
3397
3398    /**
3399     * Add a listener that will be called when the bounds of the view change due to
3400     * layout processing.
3401     *
3402     * @param listener The listener that will be called when layout bounds change.
3403     */
3404    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
3405        ListenerInfo li = getListenerInfo();
3406        if (li.mOnLayoutChangeListeners == null) {
3407            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
3408        }
3409        if (!li.mOnLayoutChangeListeners.contains(listener)) {
3410            li.mOnLayoutChangeListeners.add(listener);
3411        }
3412    }
3413
3414    /**
3415     * Remove a listener for layout changes.
3416     *
3417     * @param listener The listener for layout bounds change.
3418     */
3419    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
3420        ListenerInfo li = mListenerInfo;
3421        if (li == null || li.mOnLayoutChangeListeners == null) {
3422            return;
3423        }
3424        li.mOnLayoutChangeListeners.remove(listener);
3425    }
3426
3427    /**
3428     * Add a listener for attach state changes.
3429     *
3430     * This listener will be called whenever this view is attached or detached
3431     * from a window. Remove the listener using
3432     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
3433     *
3434     * @param listener Listener to attach
3435     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
3436     */
3437    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
3438        ListenerInfo li = getListenerInfo();
3439        if (li.mOnAttachStateChangeListeners == null) {
3440            li.mOnAttachStateChangeListeners
3441                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
3442        }
3443        li.mOnAttachStateChangeListeners.add(listener);
3444    }
3445
3446    /**
3447     * Remove a listener for attach state changes. The listener will receive no further
3448     * notification of window attach/detach events.
3449     *
3450     * @param listener Listener to remove
3451     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
3452     */
3453    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
3454        ListenerInfo li = mListenerInfo;
3455        if (li == null || li.mOnAttachStateChangeListeners == null) {
3456            return;
3457        }
3458        li.mOnAttachStateChangeListeners.remove(listener);
3459    }
3460
3461    /**
3462     * Returns the focus-change callback registered for this view.
3463     *
3464     * @return The callback, or null if one is not registered.
3465     */
3466    public OnFocusChangeListener getOnFocusChangeListener() {
3467        ListenerInfo li = mListenerInfo;
3468        return li != null ? li.mOnFocusChangeListener : null;
3469    }
3470
3471    /**
3472     * Register a callback to be invoked when this view is clicked. If this view is not
3473     * clickable, it becomes clickable.
3474     *
3475     * @param l The callback that will run
3476     *
3477     * @see #setClickable(boolean)
3478     */
3479    public void setOnClickListener(OnClickListener l) {
3480        if (!isClickable()) {
3481            setClickable(true);
3482        }
3483        getListenerInfo().mOnClickListener = l;
3484    }
3485
3486    /**
3487     * Return whether this view has an attached OnClickListener.  Returns
3488     * true if there is a listener, false if there is none.
3489     */
3490    public boolean hasOnClickListeners() {
3491        ListenerInfo li = mListenerInfo;
3492        return (li != null && li.mOnClickListener != null);
3493    }
3494
3495    /**
3496     * Register a callback to be invoked when this view is clicked and held. If this view is not
3497     * long clickable, it becomes long clickable.
3498     *
3499     * @param l The callback that will run
3500     *
3501     * @see #setLongClickable(boolean)
3502     */
3503    public void setOnLongClickListener(OnLongClickListener l) {
3504        if (!isLongClickable()) {
3505            setLongClickable(true);
3506        }
3507        getListenerInfo().mOnLongClickListener = l;
3508    }
3509
3510    /**
3511     * Register a callback to be invoked when the context menu for this view is
3512     * being built. If this view is not long clickable, it becomes long clickable.
3513     *
3514     * @param l The callback that will run
3515     *
3516     */
3517    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
3518        if (!isLongClickable()) {
3519            setLongClickable(true);
3520        }
3521        getListenerInfo().mOnCreateContextMenuListener = l;
3522    }
3523
3524    /**
3525     * Call this view's OnClickListener, if it is defined.  Performs all normal
3526     * actions associated with clicking: reporting accessibility event, playing
3527     * a sound, etc.
3528     *
3529     * @return True there was an assigned OnClickListener that was called, false
3530     *         otherwise is returned.
3531     */
3532    public boolean performClick() {
3533        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
3534
3535        ListenerInfo li = mListenerInfo;
3536        if (li != null && li.mOnClickListener != null) {
3537            playSoundEffect(SoundEffectConstants.CLICK);
3538            li.mOnClickListener.onClick(this);
3539            return true;
3540        }
3541
3542        return false;
3543    }
3544
3545    /**
3546     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
3547     * this only calls the listener, and does not do any associated clicking
3548     * actions like reporting an accessibility event.
3549     *
3550     * @return True there was an assigned OnClickListener that was called, false
3551     *         otherwise is returned.
3552     */
3553    public boolean callOnClick() {
3554        ListenerInfo li = mListenerInfo;
3555        if (li != null && li.mOnClickListener != null) {
3556            li.mOnClickListener.onClick(this);
3557            return true;
3558        }
3559        return false;
3560    }
3561
3562    /**
3563     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
3564     * OnLongClickListener did not consume the event.
3565     *
3566     * @return True if one of the above receivers consumed the event, false otherwise.
3567     */
3568    public boolean performLongClick() {
3569        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
3570
3571        boolean handled = false;
3572        ListenerInfo li = mListenerInfo;
3573        if (li != null && li.mOnLongClickListener != null) {
3574            handled = li.mOnLongClickListener.onLongClick(View.this);
3575        }
3576        if (!handled) {
3577            handled = showContextMenu();
3578        }
3579        if (handled) {
3580            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
3581        }
3582        return handled;
3583    }
3584
3585    /**
3586     * Performs button-related actions during a touch down event.
3587     *
3588     * @param event The event.
3589     * @return True if the down was consumed.
3590     *
3591     * @hide
3592     */
3593    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
3594        if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
3595            if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
3596                return true;
3597            }
3598        }
3599        return false;
3600    }
3601
3602    /**
3603     * Bring up the context menu for this view.
3604     *
3605     * @return Whether a context menu was displayed.
3606     */
3607    public boolean showContextMenu() {
3608        return getParent().showContextMenuForChild(this);
3609    }
3610
3611    /**
3612     * Bring up the context menu for this view, referring to the item under the specified point.
3613     *
3614     * @param x The referenced x coordinate.
3615     * @param y The referenced y coordinate.
3616     * @param metaState The keyboard modifiers that were pressed.
3617     * @return Whether a context menu was displayed.
3618     *
3619     * @hide
3620     */
3621    public boolean showContextMenu(float x, float y, int metaState) {
3622        return showContextMenu();
3623    }
3624
3625    /**
3626     * Start an action mode.
3627     *
3628     * @param callback Callback that will control the lifecycle of the action mode
3629     * @return The new action mode if it is started, null otherwise
3630     *
3631     * @see ActionMode
3632     */
3633    public ActionMode startActionMode(ActionMode.Callback callback) {
3634        ViewParent parent = getParent();
3635        if (parent == null) return null;
3636        return parent.startActionModeForChild(this, callback);
3637    }
3638
3639    /**
3640     * Register a callback to be invoked when a key is pressed in this view.
3641     * @param l the key listener to attach to this view
3642     */
3643    public void setOnKeyListener(OnKeyListener l) {
3644        getListenerInfo().mOnKeyListener = l;
3645    }
3646
3647    /**
3648     * Register a callback to be invoked when a touch event is sent to this view.
3649     * @param l the touch listener to attach to this view
3650     */
3651    public void setOnTouchListener(OnTouchListener l) {
3652        getListenerInfo().mOnTouchListener = l;
3653    }
3654
3655    /**
3656     * Register a callback to be invoked when a generic motion event is sent to this view.
3657     * @param l the generic motion listener to attach to this view
3658     */
3659    public void setOnGenericMotionListener(OnGenericMotionListener l) {
3660        getListenerInfo().mOnGenericMotionListener = l;
3661    }
3662
3663    /**
3664     * Register a callback to be invoked when a hover event is sent to this view.
3665     * @param l the hover listener to attach to this view
3666     */
3667    public void setOnHoverListener(OnHoverListener l) {
3668        getListenerInfo().mOnHoverListener = l;
3669    }
3670
3671    /**
3672     * Register a drag event listener callback object for this View. The parameter is
3673     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
3674     * View, the system calls the
3675     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
3676     * @param l An implementation of {@link android.view.View.OnDragListener}.
3677     */
3678    public void setOnDragListener(OnDragListener l) {
3679        getListenerInfo().mOnDragListener = l;
3680    }
3681
3682    /**
3683     * Give this view focus. This will cause
3684     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
3685     *
3686     * Note: this does not check whether this {@link View} should get focus, it just
3687     * gives it focus no matter what.  It should only be called internally by framework
3688     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
3689     *
3690     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
3691     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
3692     *        focus moved when requestFocus() is called. It may not always
3693     *        apply, in which case use the default View.FOCUS_DOWN.
3694     * @param previouslyFocusedRect The rectangle of the view that had focus
3695     *        prior in this View's coordinate system.
3696     */
3697    void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
3698        if (DBG) {
3699            System.out.println(this + " requestFocus()");
3700        }
3701
3702        if ((mPrivateFlags & FOCUSED) == 0) {
3703            mPrivateFlags |= FOCUSED;
3704
3705            if (mParent != null) {
3706                mParent.requestChildFocus(this, this);
3707            }
3708
3709            onFocusChanged(true, direction, previouslyFocusedRect);
3710            refreshDrawableState();
3711        }
3712    }
3713
3714    /**
3715     * Request that a rectangle of this view be visible on the screen,
3716     * scrolling if necessary just enough.
3717     *
3718     * <p>A View should call this if it maintains some notion of which part
3719     * of its content is interesting.  For example, a text editing view
3720     * should call this when its cursor moves.
3721     *
3722     * @param rectangle The rectangle.
3723     * @return Whether any parent scrolled.
3724     */
3725    public boolean requestRectangleOnScreen(Rect rectangle) {
3726        return requestRectangleOnScreen(rectangle, false);
3727    }
3728
3729    /**
3730     * Request that a rectangle of this view be visible on the screen,
3731     * scrolling if necessary just enough.
3732     *
3733     * <p>A View should call this if it maintains some notion of which part
3734     * of its content is interesting.  For example, a text editing view
3735     * should call this when its cursor moves.
3736     *
3737     * <p>When <code>immediate</code> is set to true, scrolling will not be
3738     * animated.
3739     *
3740     * @param rectangle The rectangle.
3741     * @param immediate True to forbid animated scrolling, false otherwise
3742     * @return Whether any parent scrolled.
3743     */
3744    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
3745        View child = this;
3746        ViewParent parent = mParent;
3747        boolean scrolled = false;
3748        while (parent != null) {
3749            scrolled |= parent.requestChildRectangleOnScreen(child,
3750                    rectangle, immediate);
3751
3752            // offset rect so next call has the rectangle in the
3753            // coordinate system of its direct child.
3754            rectangle.offset(child.getLeft(), child.getTop());
3755            rectangle.offset(-child.getScrollX(), -child.getScrollY());
3756
3757            if (!(parent instanceof View)) {
3758                break;
3759            }
3760
3761            child = (View) parent;
3762            parent = child.getParent();
3763        }
3764        return scrolled;
3765    }
3766
3767    /**
3768     * Called when this view wants to give up focus. If focus is cleared
3769     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
3770     * <p>
3771     * <strong>Note:</strong> When a View clears focus the framework is trying
3772     * to give focus to the first focusable View from the top. Hence, if this
3773     * View is the first from the top that can take focus, then its focus will
3774     * not be cleared nor will the focus change callback be invoked.
3775     * </p>
3776     */
3777    public void clearFocus() {
3778        if (DBG) {
3779            System.out.println(this + " clearFocus()");
3780        }
3781
3782        if ((mPrivateFlags & FOCUSED) != 0) {
3783            mPrivateFlags &= ~FOCUSED;
3784
3785            if (mParent != null) {
3786                mParent.clearChildFocus(this);
3787            }
3788
3789            onFocusChanged(false, 0, null);
3790            refreshDrawableState();
3791        }
3792    }
3793
3794    /**
3795     * Called to clear the focus of a view that is about to be removed.
3796     * Doesn't call clearChildFocus, which prevents this view from taking
3797     * focus again before it has been removed from the parent
3798     */
3799    void clearFocusForRemoval() {
3800        if ((mPrivateFlags & FOCUSED) != 0) {
3801            mPrivateFlags &= ~FOCUSED;
3802
3803            onFocusChanged(false, 0, null);
3804            refreshDrawableState();
3805
3806            // The view cleared focus and invoked the callbacks, so  now is the
3807            // time to give focus to the the first focusable from the top to
3808            // ensure that the gain focus is announced after clear focus.
3809            getRootView().requestFocus(FOCUS_FORWARD);
3810        }
3811    }
3812
3813    /**
3814     * Called internally by the view system when a new view is getting focus.
3815     * This is what clears the old focus.
3816     */
3817    void unFocus() {
3818        if (DBG) {
3819            System.out.println(this + " unFocus()");
3820        }
3821
3822        if ((mPrivateFlags & FOCUSED) != 0) {
3823            mPrivateFlags &= ~FOCUSED;
3824
3825            onFocusChanged(false, 0, null);
3826            refreshDrawableState();
3827        }
3828    }
3829
3830    /**
3831     * Returns true if this view has focus iteself, or is the ancestor of the
3832     * view that has focus.
3833     *
3834     * @return True if this view has or contains focus, false otherwise.
3835     */
3836    @ViewDebug.ExportedProperty(category = "focus")
3837    public boolean hasFocus() {
3838        return (mPrivateFlags & FOCUSED) != 0;
3839    }
3840
3841    /**
3842     * Returns true if this view is focusable or if it contains a reachable View
3843     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
3844     * is a View whose parents do not block descendants focus.
3845     *
3846     * Only {@link #VISIBLE} views are considered focusable.
3847     *
3848     * @return True if the view is focusable or if the view contains a focusable
3849     *         View, false otherwise.
3850     *
3851     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
3852     */
3853    public boolean hasFocusable() {
3854        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
3855    }
3856
3857    /**
3858     * Called by the view system when the focus state of this view changes.
3859     * When the focus change event is caused by directional navigation, direction
3860     * and previouslyFocusedRect provide insight into where the focus is coming from.
3861     * When overriding, be sure to call up through to the super class so that
3862     * the standard focus handling will occur.
3863     *
3864     * @param gainFocus True if the View has focus; false otherwise.
3865     * @param direction The direction focus has moved when requestFocus()
3866     *                  is called to give this view focus. Values are
3867     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
3868     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
3869     *                  It may not always apply, in which case use the default.
3870     * @param previouslyFocusedRect The rectangle, in this view's coordinate
3871     *        system, of the previously focused view.  If applicable, this will be
3872     *        passed in as finer grained information about where the focus is coming
3873     *        from (in addition to direction).  Will be <code>null</code> otherwise.
3874     */
3875    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
3876        if (gainFocus) {
3877            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
3878        }
3879
3880        InputMethodManager imm = InputMethodManager.peekInstance();
3881        if (!gainFocus) {
3882            if (isPressed()) {
3883                setPressed(false);
3884            }
3885            if (imm != null && mAttachInfo != null
3886                    && mAttachInfo.mHasWindowFocus) {
3887                imm.focusOut(this);
3888            }
3889            onFocusLost();
3890        } else if (imm != null && mAttachInfo != null
3891                && mAttachInfo.mHasWindowFocus) {
3892            imm.focusIn(this);
3893        }
3894
3895        invalidate(true);
3896        ListenerInfo li = mListenerInfo;
3897        if (li != null && li.mOnFocusChangeListener != null) {
3898            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
3899        }
3900
3901        if (mAttachInfo != null) {
3902            mAttachInfo.mKeyDispatchState.reset(this);
3903        }
3904    }
3905
3906    /**
3907     * Sends an accessibility event of the given type. If accessiiblity is
3908     * not enabled this method has no effect. The default implementation calls
3909     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
3910     * to populate information about the event source (this View), then calls
3911     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
3912     * populate the text content of the event source including its descendants,
3913     * and last calls
3914     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
3915     * on its parent to resuest sending of the event to interested parties.
3916     * <p>
3917     * If an {@link AccessibilityDelegate} has been specified via calling
3918     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3919     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
3920     * responsible for handling this call.
3921     * </p>
3922     *
3923     * @param eventType The type of the event to send, as defined by several types from
3924     * {@link android.view.accessibility.AccessibilityEvent}, such as
3925     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
3926     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
3927     *
3928     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
3929     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
3930     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
3931     * @see AccessibilityDelegate
3932     */
3933    public void sendAccessibilityEvent(int eventType) {
3934        if (mAccessibilityDelegate != null) {
3935            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
3936        } else {
3937            sendAccessibilityEventInternal(eventType);
3938        }
3939    }
3940
3941    /**
3942     * @see #sendAccessibilityEvent(int)
3943     *
3944     * Note: Called from the default {@link AccessibilityDelegate}.
3945     */
3946    void sendAccessibilityEventInternal(int eventType) {
3947        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
3948            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
3949        }
3950    }
3951
3952    /**
3953     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
3954     * takes as an argument an empty {@link AccessibilityEvent} and does not
3955     * perform a check whether accessibility is enabled.
3956     * <p>
3957     * If an {@link AccessibilityDelegate} has been specified via calling
3958     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
3959     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
3960     * is responsible for handling this call.
3961     * </p>
3962     *
3963     * @param event The event to send.
3964     *
3965     * @see #sendAccessibilityEvent(int)
3966     */
3967    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
3968        if (mAccessibilityDelegate != null) {
3969           mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
3970        } else {
3971            sendAccessibilityEventUncheckedInternal(event);
3972        }
3973    }
3974
3975    /**
3976     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
3977     *
3978     * Note: Called from the default {@link AccessibilityDelegate}.
3979     */
3980    void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
3981        if (!isShown()) {
3982            return;
3983        }
3984        onInitializeAccessibilityEvent(event);
3985        // Only a subset of accessibility events populates text content.
3986        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
3987            dispatchPopulateAccessibilityEvent(event);
3988        }
3989        // In the beginning we called #isShown(), so we know that getParent() is not null.
3990        getParent().requestSendAccessibilityEvent(this, event);
3991    }
3992
3993    /**
3994     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
3995     * to its children for adding their text content to the event. Note that the
3996     * event text is populated in a separate dispatch path since we add to the
3997     * event not only the text of the source but also the text of all its descendants.
3998     * A typical implementation will call
3999     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
4000     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4001     * on each child. Override this method if custom population of the event text
4002     * content is required.
4003     * <p>
4004     * If an {@link AccessibilityDelegate} has been specified via calling
4005     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4006     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
4007     * is responsible for handling this call.
4008     * </p>
4009     * <p>
4010     * <em>Note:</em> Accessibility events of certain types are not dispatched for
4011     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
4012     * </p>
4013     *
4014     * @param event The event.
4015     *
4016     * @return True if the event population was completed.
4017     */
4018    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
4019        if (mAccessibilityDelegate != null) {
4020            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
4021        } else {
4022            return dispatchPopulateAccessibilityEventInternal(event);
4023        }
4024    }
4025
4026    /**
4027     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4028     *
4029     * Note: Called from the default {@link AccessibilityDelegate}.
4030     */
4031    boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4032        onPopulateAccessibilityEvent(event);
4033        return false;
4034    }
4035
4036    /**
4037     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4038     * giving a chance to this View to populate the accessibility event with its
4039     * text content. While this method is free to modify event
4040     * attributes other than text content, doing so should normally be performed in
4041     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
4042     * <p>
4043     * Example: Adding formatted date string to an accessibility event in addition
4044     *          to the text added by the super implementation:
4045     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
4046     *     super.onPopulateAccessibilityEvent(event);
4047     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
4048     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
4049     *         mCurrentDate.getTimeInMillis(), flags);
4050     *     event.getText().add(selectedDateUtterance);
4051     * }</pre>
4052     * <p>
4053     * If an {@link AccessibilityDelegate} has been specified via calling
4054     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4055     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
4056     * is responsible for handling this call.
4057     * </p>
4058     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4059     * information to the event, in case the default implementation has basic information to add.
4060     * </p>
4061     *
4062     * @param event The accessibility event which to populate.
4063     *
4064     * @see #sendAccessibilityEvent(int)
4065     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4066     */
4067    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
4068        if (mAccessibilityDelegate != null) {
4069            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
4070        } else {
4071            onPopulateAccessibilityEventInternal(event);
4072        }
4073    }
4074
4075    /**
4076     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
4077     *
4078     * Note: Called from the default {@link AccessibilityDelegate}.
4079     */
4080    void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4081
4082    }
4083
4084    /**
4085     * Initializes an {@link AccessibilityEvent} with information about
4086     * this View which is the event source. In other words, the source of
4087     * an accessibility event is the view whose state change triggered firing
4088     * the event.
4089     * <p>
4090     * Example: Setting the password property of an event in addition
4091     *          to properties set by the super implementation:
4092     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4093     *     super.onInitializeAccessibilityEvent(event);
4094     *     event.setPassword(true);
4095     * }</pre>
4096     * <p>
4097     * If an {@link AccessibilityDelegate} has been specified via calling
4098     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4099     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
4100     * is responsible for handling this call.
4101     * </p>
4102     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4103     * information to the event, in case the default implementation has basic information to add.
4104     * </p>
4105     * @param event The event to initialize.
4106     *
4107     * @see #sendAccessibilityEvent(int)
4108     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4109     */
4110    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4111        if (mAccessibilityDelegate != null) {
4112            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
4113        } else {
4114            onInitializeAccessibilityEventInternal(event);
4115        }
4116    }
4117
4118    /**
4119     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4120     *
4121     * Note: Called from the default {@link AccessibilityDelegate}.
4122     */
4123    void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
4124        event.setSource(this);
4125        event.setClassName(View.class.getName());
4126        event.setPackageName(getContext().getPackageName());
4127        event.setEnabled(isEnabled());
4128        event.setContentDescription(mContentDescription);
4129
4130        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
4131            ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
4132            getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
4133                    FOCUSABLES_ALL);
4134            event.setItemCount(focusablesTempList.size());
4135            event.setCurrentItemIndex(focusablesTempList.indexOf(this));
4136            focusablesTempList.clear();
4137        }
4138    }
4139
4140    /**
4141     * Returns an {@link AccessibilityNodeInfo} representing this view from the
4142     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
4143     * This method is responsible for obtaining an accessibility node info from a
4144     * pool of reusable instances and calling
4145     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
4146     * initialize the former.
4147     * <p>
4148     * Note: The client is responsible for recycling the obtained instance by calling
4149     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
4150     * </p>
4151     *
4152     * @return A populated {@link AccessibilityNodeInfo}.
4153     *
4154     * @see AccessibilityNodeInfo
4155     */
4156    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
4157        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
4158        if (provider != null) {
4159            return provider.createAccessibilityNodeInfo(View.NO_ID);
4160        } else {
4161            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
4162            onInitializeAccessibilityNodeInfo(info);
4163            return info;
4164        }
4165    }
4166
4167    /**
4168     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
4169     * The base implementation sets:
4170     * <ul>
4171     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
4172     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
4173     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
4174     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
4175     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
4176     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
4177     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
4178     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
4179     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
4180     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
4181     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
4182     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
4183     * </ul>
4184     * <p>
4185     * Subclasses should override this method, call the super implementation,
4186     * and set additional attributes.
4187     * </p>
4188     * <p>
4189     * If an {@link AccessibilityDelegate} has been specified via calling
4190     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4191     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
4192     * is responsible for handling this call.
4193     * </p>
4194     *
4195     * @param info The instance to initialize.
4196     */
4197    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
4198        if (mAccessibilityDelegate != null) {
4199            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
4200        } else {
4201            onInitializeAccessibilityNodeInfoInternal(info);
4202        }
4203    }
4204
4205    /**
4206     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
4207     *
4208     * Note: Called from the default {@link AccessibilityDelegate}.
4209     */
4210    void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
4211        Rect bounds = mAttachInfo.mTmpInvalRect;
4212        getDrawingRect(bounds);
4213        info.setBoundsInParent(bounds);
4214
4215        int[] locationOnScreen = mAttachInfo.mInvalidateChildLocation;
4216        getLocationOnScreen(locationOnScreen);
4217        bounds.offsetTo(0, 0);
4218        bounds.offset(locationOnScreen[0], locationOnScreen[1]);
4219        info.setBoundsInScreen(bounds);
4220
4221        if ((mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
4222            ViewParent parent = getParent();
4223            if (parent instanceof View) {
4224                View parentView = (View) parent;
4225                info.setParent(parentView);
4226            }
4227        }
4228
4229        info.setPackageName(mContext.getPackageName());
4230        info.setClassName(View.class.getName());
4231        info.setContentDescription(getContentDescription());
4232
4233        info.setEnabled(isEnabled());
4234        info.setClickable(isClickable());
4235        info.setFocusable(isFocusable());
4236        info.setFocused(isFocused());
4237        info.setSelected(isSelected());
4238        info.setLongClickable(isLongClickable());
4239
4240        // TODO: These make sense only if we are in an AdapterView but all
4241        // views can be selected. Maybe from accessiiblity perspective
4242        // we should report as selectable view in an AdapterView.
4243        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
4244        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
4245
4246        if (isFocusable()) {
4247            if (isFocused()) {
4248                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
4249            } else {
4250                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
4251            }
4252        }
4253    }
4254
4255    /**
4256     * Sets a delegate for implementing accessibility support via compositon as
4257     * opposed to inheritance. The delegate's primary use is for implementing
4258     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
4259     *
4260     * @param delegate The delegate instance.
4261     *
4262     * @see AccessibilityDelegate
4263     */
4264    public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
4265        mAccessibilityDelegate = delegate;
4266    }
4267
4268    /**
4269     * Gets the provider for managing a virtual view hierarchy rooted at this View
4270     * and reported to {@link android.accessibilityservice.AccessibilityService}s
4271     * that explore the window content.
4272     * <p>
4273     * If this method returns an instance, this instance is responsible for managing
4274     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
4275     * View including the one representing the View itself. Similarly the returned
4276     * instance is responsible for performing accessibility actions on any virtual
4277     * view or the root view itself.
4278     * </p>
4279     * <p>
4280     * If an {@link AccessibilityDelegate} has been specified via calling
4281     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4282     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
4283     * is responsible for handling this call.
4284     * </p>
4285     *
4286     * @return The provider.
4287     *
4288     * @see AccessibilityNodeProvider
4289     */
4290    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
4291        if (mAccessibilityDelegate != null) {
4292            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
4293        } else {
4294            return null;
4295        }
4296    }
4297
4298    /**
4299     * Gets the unique identifier of this view on the screen for accessibility purposes.
4300     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
4301     *
4302     * @return The view accessibility id.
4303     *
4304     * @hide
4305     */
4306    public int getAccessibilityViewId() {
4307        if (mAccessibilityViewId == NO_ID) {
4308            mAccessibilityViewId = sNextAccessibilityViewId++;
4309        }
4310        return mAccessibilityViewId;
4311    }
4312
4313    /**
4314     * Gets the unique identifier of the window in which this View reseides.
4315     *
4316     * @return The window accessibility id.
4317     *
4318     * @hide
4319     */
4320    public int getAccessibilityWindowId() {
4321        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
4322    }
4323
4324    /**
4325     * Gets the {@link View} description. It briefly describes the view and is
4326     * primarily used for accessibility support. Set this property to enable
4327     * better accessibility support for your application. This is especially
4328     * true for views that do not have textual representation (For example,
4329     * ImageButton).
4330     *
4331     * @return The content descriptiopn.
4332     *
4333     * @attr ref android.R.styleable#View_contentDescription
4334     */
4335    public CharSequence getContentDescription() {
4336        return mContentDescription;
4337    }
4338
4339    /**
4340     * Sets the {@link View} description. It briefly describes the view and is
4341     * primarily used for accessibility support. Set this property to enable
4342     * better accessibility support for your application. This is especially
4343     * true for views that do not have textual representation (For example,
4344     * ImageButton).
4345     *
4346     * @param contentDescription The content description.
4347     *
4348     * @attr ref android.R.styleable#View_contentDescription
4349     */
4350    @RemotableViewMethod
4351    public void setContentDescription(CharSequence contentDescription) {
4352        mContentDescription = contentDescription;
4353    }
4354
4355    /**
4356     * Invoked whenever this view loses focus, either by losing window focus or by losing
4357     * focus within its window. This method can be used to clear any state tied to the
4358     * focus. For instance, if a button is held pressed with the trackball and the window
4359     * loses focus, this method can be used to cancel the press.
4360     *
4361     * Subclasses of View overriding this method should always call super.onFocusLost().
4362     *
4363     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
4364     * @see #onWindowFocusChanged(boolean)
4365     *
4366     * @hide pending API council approval
4367     */
4368    protected void onFocusLost() {
4369        resetPressedState();
4370    }
4371
4372    private void resetPressedState() {
4373        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
4374            return;
4375        }
4376
4377        if (isPressed()) {
4378            setPressed(false);
4379
4380            if (!mHasPerformedLongPress) {
4381                removeLongPressCallback();
4382            }
4383        }
4384    }
4385
4386    /**
4387     * Returns true if this view has focus
4388     *
4389     * @return True if this view has focus, false otherwise.
4390     */
4391    @ViewDebug.ExportedProperty(category = "focus")
4392    public boolean isFocused() {
4393        return (mPrivateFlags & FOCUSED) != 0;
4394    }
4395
4396    /**
4397     * Find the view in the hierarchy rooted at this view that currently has
4398     * focus.
4399     *
4400     * @return The view that currently has focus, or null if no focused view can
4401     *         be found.
4402     */
4403    public View findFocus() {
4404        return (mPrivateFlags & FOCUSED) != 0 ? this : null;
4405    }
4406
4407    /**
4408     * Change whether this view is one of the set of scrollable containers in
4409     * its window.  This will be used to determine whether the window can
4410     * resize or must pan when a soft input area is open -- scrollable
4411     * containers allow the window to use resize mode since the container
4412     * will appropriately shrink.
4413     */
4414    public void setScrollContainer(boolean isScrollContainer) {
4415        if (isScrollContainer) {
4416            if (mAttachInfo != null && (mPrivateFlags&SCROLL_CONTAINER_ADDED) == 0) {
4417                mAttachInfo.mScrollContainers.add(this);
4418                mPrivateFlags |= SCROLL_CONTAINER_ADDED;
4419            }
4420            mPrivateFlags |= SCROLL_CONTAINER;
4421        } else {
4422            if ((mPrivateFlags&SCROLL_CONTAINER_ADDED) != 0) {
4423                mAttachInfo.mScrollContainers.remove(this);
4424            }
4425            mPrivateFlags &= ~(SCROLL_CONTAINER|SCROLL_CONTAINER_ADDED);
4426        }
4427    }
4428
4429    /**
4430     * Returns the quality of the drawing cache.
4431     *
4432     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
4433     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
4434     *
4435     * @see #setDrawingCacheQuality(int)
4436     * @see #setDrawingCacheEnabled(boolean)
4437     * @see #isDrawingCacheEnabled()
4438     *
4439     * @attr ref android.R.styleable#View_drawingCacheQuality
4440     */
4441    public int getDrawingCacheQuality() {
4442        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
4443    }
4444
4445    /**
4446     * Set the drawing cache quality of this view. This value is used only when the
4447     * drawing cache is enabled
4448     *
4449     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
4450     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
4451     *
4452     * @see #getDrawingCacheQuality()
4453     * @see #setDrawingCacheEnabled(boolean)
4454     * @see #isDrawingCacheEnabled()
4455     *
4456     * @attr ref android.R.styleable#View_drawingCacheQuality
4457     */
4458    public void setDrawingCacheQuality(int quality) {
4459        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
4460    }
4461
4462    /**
4463     * Returns whether the screen should remain on, corresponding to the current
4464     * value of {@link #KEEP_SCREEN_ON}.
4465     *
4466     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
4467     *
4468     * @see #setKeepScreenOn(boolean)
4469     *
4470     * @attr ref android.R.styleable#View_keepScreenOn
4471     */
4472    public boolean getKeepScreenOn() {
4473        return (mViewFlags & KEEP_SCREEN_ON) != 0;
4474    }
4475
4476    /**
4477     * Controls whether the screen should remain on, modifying the
4478     * value of {@link #KEEP_SCREEN_ON}.
4479     *
4480     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
4481     *
4482     * @see #getKeepScreenOn()
4483     *
4484     * @attr ref android.R.styleable#View_keepScreenOn
4485     */
4486    public void setKeepScreenOn(boolean keepScreenOn) {
4487        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
4488    }
4489
4490    /**
4491     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
4492     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4493     *
4494     * @attr ref android.R.styleable#View_nextFocusLeft
4495     */
4496    public int getNextFocusLeftId() {
4497        return mNextFocusLeftId;
4498    }
4499
4500    /**
4501     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
4502     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
4503     * decide automatically.
4504     *
4505     * @attr ref android.R.styleable#View_nextFocusLeft
4506     */
4507    public void setNextFocusLeftId(int nextFocusLeftId) {
4508        mNextFocusLeftId = nextFocusLeftId;
4509    }
4510
4511    /**
4512     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
4513     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4514     *
4515     * @attr ref android.R.styleable#View_nextFocusRight
4516     */
4517    public int getNextFocusRightId() {
4518        return mNextFocusRightId;
4519    }
4520
4521    /**
4522     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
4523     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
4524     * decide automatically.
4525     *
4526     * @attr ref android.R.styleable#View_nextFocusRight
4527     */
4528    public void setNextFocusRightId(int nextFocusRightId) {
4529        mNextFocusRightId = nextFocusRightId;
4530    }
4531
4532    /**
4533     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
4534     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4535     *
4536     * @attr ref android.R.styleable#View_nextFocusUp
4537     */
4538    public int getNextFocusUpId() {
4539        return mNextFocusUpId;
4540    }
4541
4542    /**
4543     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
4544     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
4545     * decide automatically.
4546     *
4547     * @attr ref android.R.styleable#View_nextFocusUp
4548     */
4549    public void setNextFocusUpId(int nextFocusUpId) {
4550        mNextFocusUpId = nextFocusUpId;
4551    }
4552
4553    /**
4554     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
4555     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4556     *
4557     * @attr ref android.R.styleable#View_nextFocusDown
4558     */
4559    public int getNextFocusDownId() {
4560        return mNextFocusDownId;
4561    }
4562
4563    /**
4564     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
4565     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
4566     * decide automatically.
4567     *
4568     * @attr ref android.R.styleable#View_nextFocusDown
4569     */
4570    public void setNextFocusDownId(int nextFocusDownId) {
4571        mNextFocusDownId = nextFocusDownId;
4572    }
4573
4574    /**
4575     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
4576     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
4577     *
4578     * @attr ref android.R.styleable#View_nextFocusForward
4579     */
4580    public int getNextFocusForwardId() {
4581        return mNextFocusForwardId;
4582    }
4583
4584    /**
4585     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
4586     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
4587     * decide automatically.
4588     *
4589     * @attr ref android.R.styleable#View_nextFocusForward
4590     */
4591    public void setNextFocusForwardId(int nextFocusForwardId) {
4592        mNextFocusForwardId = nextFocusForwardId;
4593    }
4594
4595    /**
4596     * Returns the visibility of this view and all of its ancestors
4597     *
4598     * @return True if this view and all of its ancestors are {@link #VISIBLE}
4599     */
4600    public boolean isShown() {
4601        View current = this;
4602        //noinspection ConstantConditions
4603        do {
4604            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
4605                return false;
4606            }
4607            ViewParent parent = current.mParent;
4608            if (parent == null) {
4609                return false; // We are not attached to the view root
4610            }
4611            if (!(parent instanceof View)) {
4612                return true;
4613            }
4614            current = (View) parent;
4615        } while (current != null);
4616
4617        return false;
4618    }
4619
4620    /**
4621     * Apply the insets for system windows to this view, if the FITS_SYSTEM_WINDOWS flag
4622     * is set
4623     *
4624     * @param insets Insets for system windows
4625     *
4626     * @return True if this view applied the insets, false otherwise
4627     */
4628    protected boolean fitSystemWindows(Rect insets) {
4629        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
4630            mPaddingLeft = insets.left;
4631            mPaddingTop = insets.top;
4632            mPaddingRight = insets.right;
4633            mPaddingBottom = insets.bottom;
4634            requestLayout();
4635            return true;
4636        }
4637        return false;
4638    }
4639
4640    /**
4641     * Set whether or not this view should account for system screen decorations
4642     * such as the status bar and inset its content. This allows this view to be
4643     * positioned in absolute screen coordinates and remain visible to the user.
4644     *
4645     * <p>This should only be used by top-level window decor views.
4646     *
4647     * @param fitSystemWindows true to inset content for system screen decorations, false for
4648     *                         default behavior.
4649     *
4650     * @attr ref android.R.styleable#View_fitsSystemWindows
4651     */
4652    public void setFitsSystemWindows(boolean fitSystemWindows) {
4653        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
4654    }
4655
4656    /**
4657     * Check for the FITS_SYSTEM_WINDOWS flag. If this method returns true, this view
4658     * will account for system screen decorations such as the status bar and inset its
4659     * content. This allows the view to be positioned in absolute screen coordinates
4660     * and remain visible to the user.
4661     *
4662     * @return true if this view will adjust its content bounds for system screen decorations.
4663     *
4664     * @attr ref android.R.styleable#View_fitsSystemWindows
4665     */
4666    public boolean fitsSystemWindows() {
4667        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
4668    }
4669
4670    /**
4671     * Returns the visibility status for this view.
4672     *
4673     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
4674     * @attr ref android.R.styleable#View_visibility
4675     */
4676    @ViewDebug.ExportedProperty(mapping = {
4677        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
4678        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
4679        @ViewDebug.IntToString(from = GONE,      to = "GONE")
4680    })
4681    public int getVisibility() {
4682        return mViewFlags & VISIBILITY_MASK;
4683    }
4684
4685    /**
4686     * Set the enabled state of this view.
4687     *
4688     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
4689     * @attr ref android.R.styleable#View_visibility
4690     */
4691    @RemotableViewMethod
4692    public void setVisibility(int visibility) {
4693        setFlags(visibility, VISIBILITY_MASK);
4694        if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
4695    }
4696
4697    /**
4698     * Returns the enabled status for this view. The interpretation of the
4699     * enabled state varies by subclass.
4700     *
4701     * @return True if this view is enabled, false otherwise.
4702     */
4703    @ViewDebug.ExportedProperty
4704    public boolean isEnabled() {
4705        return (mViewFlags & ENABLED_MASK) == ENABLED;
4706    }
4707
4708    /**
4709     * Set the enabled state of this view. The interpretation of the enabled
4710     * state varies by subclass.
4711     *
4712     * @param enabled True if this view is enabled, false otherwise.
4713     */
4714    @RemotableViewMethod
4715    public void setEnabled(boolean enabled) {
4716        if (enabled == isEnabled()) return;
4717
4718        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
4719
4720        /*
4721         * The View most likely has to change its appearance, so refresh
4722         * the drawable state.
4723         */
4724        refreshDrawableState();
4725
4726        // Invalidate too, since the default behavior for views is to be
4727        // be drawn at 50% alpha rather than to change the drawable.
4728        invalidate(true);
4729    }
4730
4731    /**
4732     * Set whether this view can receive the focus.
4733     *
4734     * Setting this to false will also ensure that this view is not focusable
4735     * in touch mode.
4736     *
4737     * @param focusable If true, this view can receive the focus.
4738     *
4739     * @see #setFocusableInTouchMode(boolean)
4740     * @attr ref android.R.styleable#View_focusable
4741     */
4742    public void setFocusable(boolean focusable) {
4743        if (!focusable) {
4744            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
4745        }
4746        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
4747    }
4748
4749    /**
4750     * Set whether this view can receive focus while in touch mode.
4751     *
4752     * Setting this to true will also ensure that this view is focusable.
4753     *
4754     * @param focusableInTouchMode If true, this view can receive the focus while
4755     *   in touch mode.
4756     *
4757     * @see #setFocusable(boolean)
4758     * @attr ref android.R.styleable#View_focusableInTouchMode
4759     */
4760    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
4761        // Focusable in touch mode should always be set before the focusable flag
4762        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
4763        // which, in touch mode, will not successfully request focus on this view
4764        // because the focusable in touch mode flag is not set
4765        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
4766        if (focusableInTouchMode) {
4767            setFlags(FOCUSABLE, FOCUSABLE_MASK);
4768        }
4769    }
4770
4771    /**
4772     * Set whether this view should have sound effects enabled for events such as
4773     * clicking and touching.
4774     *
4775     * <p>You may wish to disable sound effects for a view if you already play sounds,
4776     * for instance, a dial key that plays dtmf tones.
4777     *
4778     * @param soundEffectsEnabled whether sound effects are enabled for this view.
4779     * @see #isSoundEffectsEnabled()
4780     * @see #playSoundEffect(int)
4781     * @attr ref android.R.styleable#View_soundEffectsEnabled
4782     */
4783    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
4784        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
4785    }
4786
4787    /**
4788     * @return whether this view should have sound effects enabled for events such as
4789     *     clicking and touching.
4790     *
4791     * @see #setSoundEffectsEnabled(boolean)
4792     * @see #playSoundEffect(int)
4793     * @attr ref android.R.styleable#View_soundEffectsEnabled
4794     */
4795    @ViewDebug.ExportedProperty
4796    public boolean isSoundEffectsEnabled() {
4797        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
4798    }
4799
4800    /**
4801     * Set whether this view should have haptic feedback for events such as
4802     * long presses.
4803     *
4804     * <p>You may wish to disable haptic feedback if your view already controls
4805     * its own haptic feedback.
4806     *
4807     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
4808     * @see #isHapticFeedbackEnabled()
4809     * @see #performHapticFeedback(int)
4810     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
4811     */
4812    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
4813        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
4814    }
4815
4816    /**
4817     * @return whether this view should have haptic feedback enabled for events
4818     * long presses.
4819     *
4820     * @see #setHapticFeedbackEnabled(boolean)
4821     * @see #performHapticFeedback(int)
4822     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
4823     */
4824    @ViewDebug.ExportedProperty
4825    public boolean isHapticFeedbackEnabled() {
4826        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
4827    }
4828
4829    /**
4830     * Returns the layout direction for this view.
4831     *
4832     * @return One of {@link #LAYOUT_DIRECTION_LTR},
4833     *   {@link #LAYOUT_DIRECTION_RTL},
4834     *   {@link #LAYOUT_DIRECTION_INHERIT} or
4835     *   {@link #LAYOUT_DIRECTION_LOCALE}.
4836     * @attr ref android.R.styleable#View_layoutDirection
4837     *
4838     * @hide
4839     */
4840    @ViewDebug.ExportedProperty(category = "layout", mapping = {
4841        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
4842        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
4843        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
4844        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
4845    })
4846    public int getLayoutDirection() {
4847        return mViewFlags & LAYOUT_DIRECTION_MASK;
4848    }
4849
4850    /**
4851     * Set the layout direction for this view. This will propagate a reset of layout direction
4852     * resolution to the view's children and resolve layout direction for this view.
4853     *
4854     * @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR},
4855     *   {@link #LAYOUT_DIRECTION_RTL},
4856     *   {@link #LAYOUT_DIRECTION_INHERIT} or
4857     *   {@link #LAYOUT_DIRECTION_LOCALE}.
4858     *
4859     * @attr ref android.R.styleable#View_layoutDirection
4860     *
4861     * @hide
4862     */
4863    @RemotableViewMethod
4864    public void setLayoutDirection(int layoutDirection) {
4865        if (getLayoutDirection() != layoutDirection) {
4866            resetResolvedLayoutDirection();
4867            // Setting the flag will also request a layout.
4868            setFlags(layoutDirection, LAYOUT_DIRECTION_MASK);
4869        }
4870    }
4871
4872    /**
4873     * Returns the resolved layout direction for this view.
4874     *
4875     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
4876     * {@link #LAYOUT_DIRECTION_LTR} id the layout direction is not RTL.
4877     *
4878     * @hide
4879     */
4880    @ViewDebug.ExportedProperty(category = "layout", mapping = {
4881        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "RESOLVED_DIRECTION_LTR"),
4882        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RESOLVED_DIRECTION_RTL")
4883    })
4884    public int getResolvedLayoutDirection() {
4885        resolveLayoutDirectionIfNeeded();
4886        return ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED_RTL) == LAYOUT_DIRECTION_RESOLVED_RTL) ?
4887                LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
4888    }
4889
4890    /**
4891     * <p>Indicates whether or not this view's layout is right-to-left. This is resolved from
4892     * layout attribute and/or the inherited value from the parent.</p>
4893     *
4894     * @return true if the layout is right-to-left.
4895     *
4896     * @hide
4897     */
4898    @ViewDebug.ExportedProperty(category = "layout")
4899    public boolean isLayoutRtl() {
4900        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
4901    }
4902
4903    /**
4904     * Indicates whether the view is currently tracking transient state that the
4905     * app should not need to concern itself with saving and restoring, but that
4906     * the framework should take special note to preserve when possible.
4907     *
4908     * @return true if the view has transient state
4909     *
4910     * @hide
4911     */
4912    @ViewDebug.ExportedProperty(category = "layout")
4913    public boolean hasTransientState() {
4914        return (mPrivateFlags2 & HAS_TRANSIENT_STATE) == HAS_TRANSIENT_STATE;
4915    }
4916
4917    /**
4918     * Set whether this view is currently tracking transient state that the
4919     * framework should attempt to preserve when possible.
4920     *
4921     * @param hasTransientState true if this view has transient state
4922     *
4923     * @hide
4924     */
4925    public void setHasTransientState(boolean hasTransientState) {
4926        if (hasTransientState() == hasTransientState) return;
4927
4928        mPrivateFlags2 = (mPrivateFlags2 & ~HAS_TRANSIENT_STATE) |
4929                (hasTransientState ? HAS_TRANSIENT_STATE : 0);
4930        if (mParent != null) {
4931            try {
4932                mParent.childHasTransientStateChanged(this, hasTransientState);
4933            } catch (AbstractMethodError e) {
4934                Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
4935                        " does not fully implement ViewParent", e);
4936            }
4937        }
4938    }
4939
4940    /**
4941     * If this view doesn't do any drawing on its own, set this flag to
4942     * allow further optimizations. By default, this flag is not set on
4943     * View, but could be set on some View subclasses such as ViewGroup.
4944     *
4945     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
4946     * you should clear this flag.
4947     *
4948     * @param willNotDraw whether or not this View draw on its own
4949     */
4950    public void setWillNotDraw(boolean willNotDraw) {
4951        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
4952    }
4953
4954    /**
4955     * Returns whether or not this View draws on its own.
4956     *
4957     * @return true if this view has nothing to draw, false otherwise
4958     */
4959    @ViewDebug.ExportedProperty(category = "drawing")
4960    public boolean willNotDraw() {
4961        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
4962    }
4963
4964    /**
4965     * When a View's drawing cache is enabled, drawing is redirected to an
4966     * offscreen bitmap. Some views, like an ImageView, must be able to
4967     * bypass this mechanism if they already draw a single bitmap, to avoid
4968     * unnecessary usage of the memory.
4969     *
4970     * @param willNotCacheDrawing true if this view does not cache its
4971     *        drawing, false otherwise
4972     */
4973    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
4974        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
4975    }
4976
4977    /**
4978     * Returns whether or not this View can cache its drawing or not.
4979     *
4980     * @return true if this view does not cache its drawing, false otherwise
4981     */
4982    @ViewDebug.ExportedProperty(category = "drawing")
4983    public boolean willNotCacheDrawing() {
4984        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
4985    }
4986
4987    /**
4988     * Indicates whether this view reacts to click events or not.
4989     *
4990     * @return true if the view is clickable, false otherwise
4991     *
4992     * @see #setClickable(boolean)
4993     * @attr ref android.R.styleable#View_clickable
4994     */
4995    @ViewDebug.ExportedProperty
4996    public boolean isClickable() {
4997        return (mViewFlags & CLICKABLE) == CLICKABLE;
4998    }
4999
5000    /**
5001     * Enables or disables click events for this view. When a view
5002     * is clickable it will change its state to "pressed" on every click.
5003     * Subclasses should set the view clickable to visually react to
5004     * user's clicks.
5005     *
5006     * @param clickable true to make the view clickable, false otherwise
5007     *
5008     * @see #isClickable()
5009     * @attr ref android.R.styleable#View_clickable
5010     */
5011    public void setClickable(boolean clickable) {
5012        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
5013    }
5014
5015    /**
5016     * Indicates whether this view reacts to long click events or not.
5017     *
5018     * @return true if the view is long clickable, false otherwise
5019     *
5020     * @see #setLongClickable(boolean)
5021     * @attr ref android.R.styleable#View_longClickable
5022     */
5023    public boolean isLongClickable() {
5024        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
5025    }
5026
5027    /**
5028     * Enables or disables long click events for this view. When a view is long
5029     * clickable it reacts to the user holding down the button for a longer
5030     * duration than a tap. This event can either launch the listener or a
5031     * context menu.
5032     *
5033     * @param longClickable true to make the view long clickable, false otherwise
5034     * @see #isLongClickable()
5035     * @attr ref android.R.styleable#View_longClickable
5036     */
5037    public void setLongClickable(boolean longClickable) {
5038        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
5039    }
5040
5041    /**
5042     * Sets the pressed state for this view.
5043     *
5044     * @see #isClickable()
5045     * @see #setClickable(boolean)
5046     *
5047     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
5048     *        the View's internal state from a previously set "pressed" state.
5049     */
5050    public void setPressed(boolean pressed) {
5051        final boolean needsRefresh = pressed != ((mPrivateFlags & PRESSED) == PRESSED);
5052
5053        if (pressed) {
5054            mPrivateFlags |= PRESSED;
5055        } else {
5056            mPrivateFlags &= ~PRESSED;
5057        }
5058
5059        if (needsRefresh) {
5060            refreshDrawableState();
5061        }
5062        dispatchSetPressed(pressed);
5063    }
5064
5065    /**
5066     * Dispatch setPressed to all of this View's children.
5067     *
5068     * @see #setPressed(boolean)
5069     *
5070     * @param pressed The new pressed state
5071     */
5072    protected void dispatchSetPressed(boolean pressed) {
5073    }
5074
5075    /**
5076     * Indicates whether the view is currently in pressed state. Unless
5077     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
5078     * the pressed state.
5079     *
5080     * @see #setPressed(boolean)
5081     * @see #isClickable()
5082     * @see #setClickable(boolean)
5083     *
5084     * @return true if the view is currently pressed, false otherwise
5085     */
5086    public boolean isPressed() {
5087        return (mPrivateFlags & PRESSED) == PRESSED;
5088    }
5089
5090    /**
5091     * Indicates whether this view will save its state (that is,
5092     * whether its {@link #onSaveInstanceState} method will be called).
5093     *
5094     * @return Returns true if the view state saving is enabled, else false.
5095     *
5096     * @see #setSaveEnabled(boolean)
5097     * @attr ref android.R.styleable#View_saveEnabled
5098     */
5099    public boolean isSaveEnabled() {
5100        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
5101    }
5102
5103    /**
5104     * Controls whether the saving of this view's state is
5105     * enabled (that is, whether its {@link #onSaveInstanceState} method
5106     * will be called).  Note that even if freezing is enabled, the
5107     * view still must have an id assigned to it (via {@link #setId(int)})
5108     * for its state to be saved.  This flag can only disable the
5109     * saving of this view; any child views may still have their state saved.
5110     *
5111     * @param enabled Set to false to <em>disable</em> state saving, or true
5112     * (the default) to allow it.
5113     *
5114     * @see #isSaveEnabled()
5115     * @see #setId(int)
5116     * @see #onSaveInstanceState()
5117     * @attr ref android.R.styleable#View_saveEnabled
5118     */
5119    public void setSaveEnabled(boolean enabled) {
5120        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
5121    }
5122
5123    /**
5124     * Gets whether the framework should discard touches when the view's
5125     * window is obscured by another visible window.
5126     * Refer to the {@link View} security documentation for more details.
5127     *
5128     * @return True if touch filtering is enabled.
5129     *
5130     * @see #setFilterTouchesWhenObscured(boolean)
5131     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
5132     */
5133    @ViewDebug.ExportedProperty
5134    public boolean getFilterTouchesWhenObscured() {
5135        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
5136    }
5137
5138    /**
5139     * Sets whether the framework should discard touches when the view's
5140     * window is obscured by another visible window.
5141     * Refer to the {@link View} security documentation for more details.
5142     *
5143     * @param enabled True if touch filtering should be enabled.
5144     *
5145     * @see #getFilterTouchesWhenObscured
5146     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
5147     */
5148    public void setFilterTouchesWhenObscured(boolean enabled) {
5149        setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
5150                FILTER_TOUCHES_WHEN_OBSCURED);
5151    }
5152
5153    /**
5154     * Indicates whether the entire hierarchy under this view will save its
5155     * state when a state saving traversal occurs from its parent.  The default
5156     * is true; if false, these views will not be saved unless
5157     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
5158     *
5159     * @return Returns true if the view state saving from parent is enabled, else false.
5160     *
5161     * @see #setSaveFromParentEnabled(boolean)
5162     */
5163    public boolean isSaveFromParentEnabled() {
5164        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
5165    }
5166
5167    /**
5168     * Controls whether the entire hierarchy under this view will save its
5169     * state when a state saving traversal occurs from its parent.  The default
5170     * is true; if false, these views will not be saved unless
5171     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
5172     *
5173     * @param enabled Set to false to <em>disable</em> state saving, or true
5174     * (the default) to allow it.
5175     *
5176     * @see #isSaveFromParentEnabled()
5177     * @see #setId(int)
5178     * @see #onSaveInstanceState()
5179     */
5180    public void setSaveFromParentEnabled(boolean enabled) {
5181        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
5182    }
5183
5184
5185    /**
5186     * Returns whether this View is able to take focus.
5187     *
5188     * @return True if this view can take focus, or false otherwise.
5189     * @attr ref android.R.styleable#View_focusable
5190     */
5191    @ViewDebug.ExportedProperty(category = "focus")
5192    public final boolean isFocusable() {
5193        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
5194    }
5195
5196    /**
5197     * When a view is focusable, it may not want to take focus when in touch mode.
5198     * For example, a button would like focus when the user is navigating via a D-pad
5199     * so that the user can click on it, but once the user starts touching the screen,
5200     * the button shouldn't take focus
5201     * @return Whether the view is focusable in touch mode.
5202     * @attr ref android.R.styleable#View_focusableInTouchMode
5203     */
5204    @ViewDebug.ExportedProperty
5205    public final boolean isFocusableInTouchMode() {
5206        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
5207    }
5208
5209    /**
5210     * Find the nearest view in the specified direction that can take focus.
5211     * This does not actually give focus to that view.
5212     *
5213     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5214     *
5215     * @return The nearest focusable in the specified direction, or null if none
5216     *         can be found.
5217     */
5218    public View focusSearch(int direction) {
5219        if (mParent != null) {
5220            return mParent.focusSearch(this, direction);
5221        } else {
5222            return null;
5223        }
5224    }
5225
5226    /**
5227     * This method is the last chance for the focused view and its ancestors to
5228     * respond to an arrow key. This is called when the focused view did not
5229     * consume the key internally, nor could the view system find a new view in
5230     * the requested direction to give focus to.
5231     *
5232     * @param focused The currently focused view.
5233     * @param direction The direction focus wants to move. One of FOCUS_UP,
5234     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
5235     * @return True if the this view consumed this unhandled move.
5236     */
5237    public boolean dispatchUnhandledMove(View focused, int direction) {
5238        return false;
5239    }
5240
5241    /**
5242     * If a user manually specified the next view id for a particular direction,
5243     * use the root to look up the view.
5244     * @param root The root view of the hierarchy containing this view.
5245     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
5246     * or FOCUS_BACKWARD.
5247     * @return The user specified next view, or null if there is none.
5248     */
5249    View findUserSetNextFocus(View root, int direction) {
5250        switch (direction) {
5251            case FOCUS_LEFT:
5252                if (mNextFocusLeftId == View.NO_ID) return null;
5253                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
5254            case FOCUS_RIGHT:
5255                if (mNextFocusRightId == View.NO_ID) return null;
5256                return findViewInsideOutShouldExist(root, mNextFocusRightId);
5257            case FOCUS_UP:
5258                if (mNextFocusUpId == View.NO_ID) return null;
5259                return findViewInsideOutShouldExist(root, mNextFocusUpId);
5260            case FOCUS_DOWN:
5261                if (mNextFocusDownId == View.NO_ID) return null;
5262                return findViewInsideOutShouldExist(root, mNextFocusDownId);
5263            case FOCUS_FORWARD:
5264                if (mNextFocusForwardId == View.NO_ID) return null;
5265                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
5266            case FOCUS_BACKWARD: {
5267                final int id = mID;
5268                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
5269                    @Override
5270                    public boolean apply(View t) {
5271                        return t.mNextFocusForwardId == id;
5272                    }
5273                });
5274            }
5275        }
5276        return null;
5277    }
5278
5279    private View findViewInsideOutShouldExist(View root, final int childViewId) {
5280        View result = root.findViewByPredicateInsideOut(this, new Predicate<View>() {
5281            @Override
5282            public boolean apply(View t) {
5283                return t.mID == childViewId;
5284            }
5285        });
5286
5287        if (result == null) {
5288            Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
5289                    + "by user for id " + childViewId);
5290        }
5291        return result;
5292    }
5293
5294    /**
5295     * Find and return all focusable views that are descendants of this view,
5296     * possibly including this view if it is focusable itself.
5297     *
5298     * @param direction The direction of the focus
5299     * @return A list of focusable views
5300     */
5301    public ArrayList<View> getFocusables(int direction) {
5302        ArrayList<View> result = new ArrayList<View>(24);
5303        addFocusables(result, direction);
5304        return result;
5305    }
5306
5307    /**
5308     * Add any focusable views that are descendants of this view (possibly
5309     * including this view if it is focusable itself) to views.  If we are in touch mode,
5310     * only add views that are also focusable in touch mode.
5311     *
5312     * @param views Focusable views found so far
5313     * @param direction The direction of the focus
5314     */
5315    public void addFocusables(ArrayList<View> views, int direction) {
5316        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
5317    }
5318
5319    /**
5320     * Adds any focusable views that are descendants of this view (possibly
5321     * including this view if it is focusable itself) to views. This method
5322     * adds all focusable views regardless if we are in touch mode or
5323     * only views focusable in touch mode if we are in touch mode depending on
5324     * the focusable mode paramater.
5325     *
5326     * @param views Focusable views found so far or null if all we are interested is
5327     *        the number of focusables.
5328     * @param direction The direction of the focus.
5329     * @param focusableMode The type of focusables to be added.
5330     *
5331     * @see #FOCUSABLES_ALL
5332     * @see #FOCUSABLES_TOUCH_MODE
5333     */
5334    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
5335        if (!isFocusable()) {
5336            return;
5337        }
5338
5339        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE &&
5340                isInTouchMode() && !isFocusableInTouchMode()) {
5341            return;
5342        }
5343
5344        if (views != null) {
5345            views.add(this);
5346        }
5347    }
5348
5349    /**
5350     * Finds the Views that contain given text. The containment is case insensitive.
5351     * The search is performed by either the text that the View renders or the content
5352     * description that describes the view for accessibility purposes and the view does
5353     * not render or both. Clients can specify how the search is to be performed via
5354     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
5355     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
5356     *
5357     * @param outViews The output list of matching Views.
5358     * @param searched The text to match against.
5359     *
5360     * @see #FIND_VIEWS_WITH_TEXT
5361     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
5362     * @see #setContentDescription(CharSequence)
5363     */
5364    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
5365        if (getAccessibilityNodeProvider() != null) {
5366            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
5367                outViews.add(this);
5368            }
5369        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
5370                && !TextUtils.isEmpty(searched) && !TextUtils.isEmpty(mContentDescription)) {
5371            String searchedLowerCase = searched.toString().toLowerCase();
5372            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
5373            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
5374                outViews.add(this);
5375            }
5376        }
5377    }
5378
5379    /**
5380     * Find and return all touchable views that are descendants of this view,
5381     * possibly including this view if it is touchable itself.
5382     *
5383     * @return A list of touchable views
5384     */
5385    public ArrayList<View> getTouchables() {
5386        ArrayList<View> result = new ArrayList<View>();
5387        addTouchables(result);
5388        return result;
5389    }
5390
5391    /**
5392     * Add any touchable views that are descendants of this view (possibly
5393     * including this view if it is touchable itself) to views.
5394     *
5395     * @param views Touchable views found so far
5396     */
5397    public void addTouchables(ArrayList<View> views) {
5398        final int viewFlags = mViewFlags;
5399
5400        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
5401                && (viewFlags & ENABLED_MASK) == ENABLED) {
5402            views.add(this);
5403        }
5404    }
5405
5406    /**
5407     * Call this to try to give focus to a specific view or to one of its
5408     * descendants.
5409     *
5410     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
5411     * false), or if it is focusable and it is not focusable in touch mode
5412     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
5413     *
5414     * See also {@link #focusSearch(int)}, which is what you call to say that you
5415     * have focus, and you want your parent to look for the next one.
5416     *
5417     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
5418     * {@link #FOCUS_DOWN} and <code>null</code>.
5419     *
5420     * @return Whether this view or one of its descendants actually took focus.
5421     */
5422    public final boolean requestFocus() {
5423        return requestFocus(View.FOCUS_DOWN);
5424    }
5425
5426
5427    /**
5428     * Call this to try to give focus to a specific view or to one of its
5429     * descendants and give it a hint about what direction focus is heading.
5430     *
5431     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
5432     * false), or if it is focusable and it is not focusable in touch mode
5433     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
5434     *
5435     * See also {@link #focusSearch(int)}, which is what you call to say that you
5436     * have focus, and you want your parent to look for the next one.
5437     *
5438     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
5439     * <code>null</code> set for the previously focused rectangle.
5440     *
5441     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5442     * @return Whether this view or one of its descendants actually took focus.
5443     */
5444    public final boolean requestFocus(int direction) {
5445        return requestFocus(direction, null);
5446    }
5447
5448    /**
5449     * Call this to try to give focus to a specific view or to one of its descendants
5450     * and give it hints about the direction and a specific rectangle that the focus
5451     * is coming from.  The rectangle can help give larger views a finer grained hint
5452     * about where focus is coming from, and therefore, where to show selection, or
5453     * forward focus change internally.
5454     *
5455     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
5456     * false), or if it is focusable and it is not focusable in touch mode
5457     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
5458     *
5459     * A View will not take focus if it is not visible.
5460     *
5461     * A View will not take focus if one of its parents has
5462     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
5463     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
5464     *
5465     * See also {@link #focusSearch(int)}, which is what you call to say that you
5466     * have focus, and you want your parent to look for the next one.
5467     *
5468     * You may wish to override this method if your custom {@link View} has an internal
5469     * {@link View} that it wishes to forward the request to.
5470     *
5471     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
5472     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
5473     *        to give a finer grained hint about where focus is coming from.  May be null
5474     *        if there is no hint.
5475     * @return Whether this view or one of its descendants actually took focus.
5476     */
5477    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
5478        // need to be focusable
5479        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
5480                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
5481            return false;
5482        }
5483
5484        // need to be focusable in touch mode if in touch mode
5485        if (isInTouchMode() &&
5486            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
5487               return false;
5488        }
5489
5490        // need to not have any parents blocking us
5491        if (hasAncestorThatBlocksDescendantFocus()) {
5492            return false;
5493        }
5494
5495        handleFocusGainInternal(direction, previouslyFocusedRect);
5496        return true;
5497    }
5498
5499    /**
5500     * Call this to try to give focus to a specific view or to one of its descendants. This is a
5501     * special variant of {@link #requestFocus() } that will allow views that are not focuable in
5502     * touch mode to request focus when they are touched.
5503     *
5504     * @return Whether this view or one of its descendants actually took focus.
5505     *
5506     * @see #isInTouchMode()
5507     *
5508     */
5509    public final boolean requestFocusFromTouch() {
5510        // Leave touch mode if we need to
5511        if (isInTouchMode()) {
5512            ViewRootImpl viewRoot = getViewRootImpl();
5513            if (viewRoot != null) {
5514                viewRoot.ensureTouchMode(false);
5515            }
5516        }
5517        return requestFocus(View.FOCUS_DOWN);
5518    }
5519
5520    /**
5521     * @return Whether any ancestor of this view blocks descendant focus.
5522     */
5523    private boolean hasAncestorThatBlocksDescendantFocus() {
5524        ViewParent ancestor = mParent;
5525        while (ancestor instanceof ViewGroup) {
5526            final ViewGroup vgAncestor = (ViewGroup) ancestor;
5527            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
5528                return true;
5529            } else {
5530                ancestor = vgAncestor.getParent();
5531            }
5532        }
5533        return false;
5534    }
5535
5536    /**
5537     * @hide
5538     */
5539    public void dispatchStartTemporaryDetach() {
5540        onStartTemporaryDetach();
5541    }
5542
5543    /**
5544     * This is called when a container is going to temporarily detach a child, with
5545     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
5546     * It will either be followed by {@link #onFinishTemporaryDetach()} or
5547     * {@link #onDetachedFromWindow()} when the container is done.
5548     */
5549    public void onStartTemporaryDetach() {
5550        removeUnsetPressCallback();
5551        mPrivateFlags |= CANCEL_NEXT_UP_EVENT;
5552    }
5553
5554    /**
5555     * @hide
5556     */
5557    public void dispatchFinishTemporaryDetach() {
5558        onFinishTemporaryDetach();
5559    }
5560
5561    /**
5562     * Called after {@link #onStartTemporaryDetach} when the container is done
5563     * changing the view.
5564     */
5565    public void onFinishTemporaryDetach() {
5566    }
5567
5568    /**
5569     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
5570     * for this view's window.  Returns null if the view is not currently attached
5571     * to the window.  Normally you will not need to use this directly, but
5572     * just use the standard high-level event callbacks like
5573     * {@link #onKeyDown(int, KeyEvent)}.
5574     */
5575    public KeyEvent.DispatcherState getKeyDispatcherState() {
5576        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
5577    }
5578
5579    /**
5580     * Dispatch a key event before it is processed by any input method
5581     * associated with the view hierarchy.  This can be used to intercept
5582     * key events in special situations before the IME consumes them; a
5583     * typical example would be handling the BACK key to update the application's
5584     * UI instead of allowing the IME to see it and close itself.
5585     *
5586     * @param event The key event to be dispatched.
5587     * @return True if the event was handled, false otherwise.
5588     */
5589    public boolean dispatchKeyEventPreIme(KeyEvent event) {
5590        return onKeyPreIme(event.getKeyCode(), event);
5591    }
5592
5593    /**
5594     * Dispatch a key event to the next view on the focus path. This path runs
5595     * from the top of the view tree down to the currently focused view. If this
5596     * view has focus, it will dispatch to itself. Otherwise it will dispatch
5597     * the next node down the focus path. This method also fires any key
5598     * listeners.
5599     *
5600     * @param event The key event to be dispatched.
5601     * @return True if the event was handled, false otherwise.
5602     */
5603    public boolean dispatchKeyEvent(KeyEvent event) {
5604        if (mInputEventConsistencyVerifier != null) {
5605            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
5606        }
5607
5608        // Give any attached key listener a first crack at the event.
5609        //noinspection SimplifiableIfStatement
5610        ListenerInfo li = mListenerInfo;
5611        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
5612                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
5613            return true;
5614        }
5615
5616        if (event.dispatch(this, mAttachInfo != null
5617                ? mAttachInfo.mKeyDispatchState : null, this)) {
5618            return true;
5619        }
5620
5621        if (mInputEventConsistencyVerifier != null) {
5622            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5623        }
5624        return false;
5625    }
5626
5627    /**
5628     * Dispatches a key shortcut event.
5629     *
5630     * @param event The key event to be dispatched.
5631     * @return True if the event was handled by the view, false otherwise.
5632     */
5633    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
5634        return onKeyShortcut(event.getKeyCode(), event);
5635    }
5636
5637    /**
5638     * Pass the touch screen motion event down to the target view, or this
5639     * view if it is the target.
5640     *
5641     * @param event The motion event to be dispatched.
5642     * @return True if the event was handled by the view, false otherwise.
5643     */
5644    public boolean dispatchTouchEvent(MotionEvent event) {
5645        if (mInputEventConsistencyVerifier != null) {
5646            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
5647        }
5648
5649        if (onFilterTouchEventForSecurity(event)) {
5650            //noinspection SimplifiableIfStatement
5651            ListenerInfo li = mListenerInfo;
5652            if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
5653                    && li.mOnTouchListener.onTouch(this, event)) {
5654                return true;
5655            }
5656
5657            if (onTouchEvent(event)) {
5658                return true;
5659            }
5660        }
5661
5662        if (mInputEventConsistencyVerifier != null) {
5663            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5664        }
5665        return false;
5666    }
5667
5668    /**
5669     * Filter the touch event to apply security policies.
5670     *
5671     * @param event The motion event to be filtered.
5672     * @return True if the event should be dispatched, false if the event should be dropped.
5673     *
5674     * @see #getFilterTouchesWhenObscured
5675     */
5676    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
5677        //noinspection RedundantIfStatement
5678        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
5679                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
5680            // Window is obscured, drop this touch.
5681            return false;
5682        }
5683        return true;
5684    }
5685
5686    /**
5687     * Pass a trackball motion event down to the focused view.
5688     *
5689     * @param event The motion event to be dispatched.
5690     * @return True if the event was handled by the view, false otherwise.
5691     */
5692    public boolean dispatchTrackballEvent(MotionEvent event) {
5693        if (mInputEventConsistencyVerifier != null) {
5694            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
5695        }
5696
5697        return onTrackballEvent(event);
5698    }
5699
5700    /**
5701     * Dispatch a generic motion event.
5702     * <p>
5703     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
5704     * are delivered to the view under the pointer.  All other generic motion events are
5705     * delivered to the focused view.  Hover events are handled specially and are delivered
5706     * to {@link #onHoverEvent(MotionEvent)}.
5707     * </p>
5708     *
5709     * @param event The motion event to be dispatched.
5710     * @return True if the event was handled by the view, false otherwise.
5711     */
5712    public boolean dispatchGenericMotionEvent(MotionEvent event) {
5713        if (mInputEventConsistencyVerifier != null) {
5714            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
5715        }
5716
5717        final int source = event.getSource();
5718        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
5719            final int action = event.getAction();
5720            if (action == MotionEvent.ACTION_HOVER_ENTER
5721                    || action == MotionEvent.ACTION_HOVER_MOVE
5722                    || action == MotionEvent.ACTION_HOVER_EXIT) {
5723                if (dispatchHoverEvent(event)) {
5724                    return true;
5725                }
5726            } else if (dispatchGenericPointerEvent(event)) {
5727                return true;
5728            }
5729        } else if (dispatchGenericFocusedEvent(event)) {
5730            return true;
5731        }
5732
5733        if (dispatchGenericMotionEventInternal(event)) {
5734            return true;
5735        }
5736
5737        if (mInputEventConsistencyVerifier != null) {
5738            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5739        }
5740        return false;
5741    }
5742
5743    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
5744        //noinspection SimplifiableIfStatement
5745        ListenerInfo li = mListenerInfo;
5746        if (li != null && li.mOnGenericMotionListener != null
5747                && (mViewFlags & ENABLED_MASK) == ENABLED
5748                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
5749            return true;
5750        }
5751
5752        if (onGenericMotionEvent(event)) {
5753            return true;
5754        }
5755
5756        if (mInputEventConsistencyVerifier != null) {
5757            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
5758        }
5759        return false;
5760    }
5761
5762    /**
5763     * Dispatch a hover event.
5764     * <p>
5765     * Do not call this method directly.
5766     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
5767     * </p>
5768     *
5769     * @param event The motion event to be dispatched.
5770     * @return True if the event was handled by the view, false otherwise.
5771     */
5772    protected boolean dispatchHoverEvent(MotionEvent event) {
5773        //noinspection SimplifiableIfStatement
5774        ListenerInfo li = mListenerInfo;
5775        if (li != null && li.mOnHoverListener != null
5776                && (mViewFlags & ENABLED_MASK) == ENABLED
5777                && li.mOnHoverListener.onHover(this, event)) {
5778            return true;
5779        }
5780
5781        return onHoverEvent(event);
5782    }
5783
5784    /**
5785     * Returns true if the view has a child to which it has recently sent
5786     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
5787     * it does not have a hovered child, then it must be the innermost hovered view.
5788     * @hide
5789     */
5790    protected boolean hasHoveredChild() {
5791        return false;
5792    }
5793
5794    /**
5795     * Dispatch a generic motion event to the view under the first pointer.
5796     * <p>
5797     * Do not call this method directly.
5798     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
5799     * </p>
5800     *
5801     * @param event The motion event to be dispatched.
5802     * @return True if the event was handled by the view, false otherwise.
5803     */
5804    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
5805        return false;
5806    }
5807
5808    /**
5809     * Dispatch a generic motion event to the currently focused view.
5810     * <p>
5811     * Do not call this method directly.
5812     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
5813     * </p>
5814     *
5815     * @param event The motion event to be dispatched.
5816     * @return True if the event was handled by the view, false otherwise.
5817     */
5818    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
5819        return false;
5820    }
5821
5822    /**
5823     * Dispatch a pointer event.
5824     * <p>
5825     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
5826     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
5827     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
5828     * and should not be expected to handle other pointing device features.
5829     * </p>
5830     *
5831     * @param event The motion event to be dispatched.
5832     * @return True if the event was handled by the view, false otherwise.
5833     * @hide
5834     */
5835    public final boolean dispatchPointerEvent(MotionEvent event) {
5836        if (event.isTouchEvent()) {
5837            return dispatchTouchEvent(event);
5838        } else {
5839            return dispatchGenericMotionEvent(event);
5840        }
5841    }
5842
5843    /**
5844     * Called when the window containing this view gains or loses window focus.
5845     * ViewGroups should override to route to their children.
5846     *
5847     * @param hasFocus True if the window containing this view now has focus,
5848     *        false otherwise.
5849     */
5850    public void dispatchWindowFocusChanged(boolean hasFocus) {
5851        onWindowFocusChanged(hasFocus);
5852    }
5853
5854    /**
5855     * Called when the window containing this view gains or loses focus.  Note
5856     * that this is separate from view focus: to receive key events, both
5857     * your view and its window must have focus.  If a window is displayed
5858     * on top of yours that takes input focus, then your own window will lose
5859     * focus but the view focus will remain unchanged.
5860     *
5861     * @param hasWindowFocus True if the window containing this view now has
5862     *        focus, false otherwise.
5863     */
5864    public void onWindowFocusChanged(boolean hasWindowFocus) {
5865        InputMethodManager imm = InputMethodManager.peekInstance();
5866        if (!hasWindowFocus) {
5867            if (isPressed()) {
5868                setPressed(false);
5869            }
5870            if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
5871                imm.focusOut(this);
5872            }
5873            removeLongPressCallback();
5874            removeTapCallback();
5875            onFocusLost();
5876        } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
5877            imm.focusIn(this);
5878        }
5879        refreshDrawableState();
5880    }
5881
5882    /**
5883     * Returns true if this view is in a window that currently has window focus.
5884     * Note that this is not the same as the view itself having focus.
5885     *
5886     * @return True if this view is in a window that currently has window focus.
5887     */
5888    public boolean hasWindowFocus() {
5889        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
5890    }
5891
5892    /**
5893     * Dispatch a view visibility change down the view hierarchy.
5894     * ViewGroups should override to route to their children.
5895     * @param changedView The view whose visibility changed. Could be 'this' or
5896     * an ancestor view.
5897     * @param visibility The new visibility of changedView: {@link #VISIBLE},
5898     * {@link #INVISIBLE} or {@link #GONE}.
5899     */
5900    protected void dispatchVisibilityChanged(View changedView, int visibility) {
5901        onVisibilityChanged(changedView, visibility);
5902    }
5903
5904    /**
5905     * Called when the visibility of the view or an ancestor of the view is changed.
5906     * @param changedView The view whose visibility changed. Could be 'this' or
5907     * an ancestor view.
5908     * @param visibility The new visibility of changedView: {@link #VISIBLE},
5909     * {@link #INVISIBLE} or {@link #GONE}.
5910     */
5911    protected void onVisibilityChanged(View changedView, int visibility) {
5912        if (visibility == VISIBLE) {
5913            if (mAttachInfo != null) {
5914                initialAwakenScrollBars();
5915            } else {
5916                mPrivateFlags |= AWAKEN_SCROLL_BARS_ON_ATTACH;
5917            }
5918        }
5919    }
5920
5921    /**
5922     * Dispatch a hint about whether this view is displayed. For instance, when
5923     * a View moves out of the screen, it might receives a display hint indicating
5924     * the view is not displayed. Applications should not <em>rely</em> on this hint
5925     * as there is no guarantee that they will receive one.
5926     *
5927     * @param hint A hint about whether or not this view is displayed:
5928     * {@link #VISIBLE} or {@link #INVISIBLE}.
5929     */
5930    public void dispatchDisplayHint(int hint) {
5931        onDisplayHint(hint);
5932    }
5933
5934    /**
5935     * Gives this view a hint about whether is displayed or not. For instance, when
5936     * a View moves out of the screen, it might receives a display hint indicating
5937     * the view is not displayed. Applications should not <em>rely</em> on this hint
5938     * as there is no guarantee that they will receive one.
5939     *
5940     * @param hint A hint about whether or not this view is displayed:
5941     * {@link #VISIBLE} or {@link #INVISIBLE}.
5942     */
5943    protected void onDisplayHint(int hint) {
5944    }
5945
5946    /**
5947     * Dispatch a window visibility change down the view hierarchy.
5948     * ViewGroups should override to route to their children.
5949     *
5950     * @param visibility The new visibility of the window.
5951     *
5952     * @see #onWindowVisibilityChanged(int)
5953     */
5954    public void dispatchWindowVisibilityChanged(int visibility) {
5955        onWindowVisibilityChanged(visibility);
5956    }
5957
5958    /**
5959     * Called when the window containing has change its visibility
5960     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
5961     * that this tells you whether or not your window is being made visible
5962     * to the window manager; this does <em>not</em> tell you whether or not
5963     * your window is obscured by other windows on the screen, even if it
5964     * is itself visible.
5965     *
5966     * @param visibility The new visibility of the window.
5967     */
5968    protected void onWindowVisibilityChanged(int visibility) {
5969        if (visibility == VISIBLE) {
5970            initialAwakenScrollBars();
5971        }
5972    }
5973
5974    /**
5975     * Returns the current visibility of the window this view is attached to
5976     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
5977     *
5978     * @return Returns the current visibility of the view's window.
5979     */
5980    public int getWindowVisibility() {
5981        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
5982    }
5983
5984    /**
5985     * Retrieve the overall visible display size in which the window this view is
5986     * attached to has been positioned in.  This takes into account screen
5987     * decorations above the window, for both cases where the window itself
5988     * is being position inside of them or the window is being placed under
5989     * then and covered insets are used for the window to position its content
5990     * inside.  In effect, this tells you the available area where content can
5991     * be placed and remain visible to users.
5992     *
5993     * <p>This function requires an IPC back to the window manager to retrieve
5994     * the requested information, so should not be used in performance critical
5995     * code like drawing.
5996     *
5997     * @param outRect Filled in with the visible display frame.  If the view
5998     * is not attached to a window, this is simply the raw display size.
5999     */
6000    public void getWindowVisibleDisplayFrame(Rect outRect) {
6001        if (mAttachInfo != null) {
6002            try {
6003                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
6004            } catch (RemoteException e) {
6005                return;
6006            }
6007            // XXX This is really broken, and probably all needs to be done
6008            // in the window manager, and we need to know more about whether
6009            // we want the area behind or in front of the IME.
6010            final Rect insets = mAttachInfo.mVisibleInsets;
6011            outRect.left += insets.left;
6012            outRect.top += insets.top;
6013            outRect.right -= insets.right;
6014            outRect.bottom -= insets.bottom;
6015            return;
6016        }
6017        Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
6018        d.getRectSize(outRect);
6019    }
6020
6021    /**
6022     * Dispatch a notification about a resource configuration change down
6023     * the view hierarchy.
6024     * ViewGroups should override to route to their children.
6025     *
6026     * @param newConfig The new resource configuration.
6027     *
6028     * @see #onConfigurationChanged(android.content.res.Configuration)
6029     */
6030    public void dispatchConfigurationChanged(Configuration newConfig) {
6031        onConfigurationChanged(newConfig);
6032    }
6033
6034    /**
6035     * Called when the current configuration of the resources being used
6036     * by the application have changed.  You can use this to decide when
6037     * to reload resources that can changed based on orientation and other
6038     * configuration characterstics.  You only need to use this if you are
6039     * not relying on the normal {@link android.app.Activity} mechanism of
6040     * recreating the activity instance upon a configuration change.
6041     *
6042     * @param newConfig The new resource configuration.
6043     */
6044    protected void onConfigurationChanged(Configuration newConfig) {
6045    }
6046
6047    /**
6048     * Private function to aggregate all per-view attributes in to the view
6049     * root.
6050     */
6051    void dispatchCollectViewAttributes(int visibility) {
6052        performCollectViewAttributes(visibility);
6053    }
6054
6055    void performCollectViewAttributes(int visibility) {
6056        if ((visibility & VISIBILITY_MASK) == VISIBLE && mAttachInfo != null) {
6057            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
6058                mAttachInfo.mKeepScreenOn = true;
6059            }
6060            mAttachInfo.mSystemUiVisibility |= mSystemUiVisibility;
6061            ListenerInfo li = mListenerInfo;
6062            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
6063                mAttachInfo.mHasSystemUiListeners = true;
6064            }
6065        }
6066    }
6067
6068    void needGlobalAttributesUpdate(boolean force) {
6069        final AttachInfo ai = mAttachInfo;
6070        if (ai != null) {
6071            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
6072                    || ai.mHasSystemUiListeners) {
6073                ai.mRecomputeGlobalAttributes = true;
6074            }
6075        }
6076    }
6077
6078    /**
6079     * Returns whether the device is currently in touch mode.  Touch mode is entered
6080     * once the user begins interacting with the device by touch, and affects various
6081     * things like whether focus is always visible to the user.
6082     *
6083     * @return Whether the device is in touch mode.
6084     */
6085    @ViewDebug.ExportedProperty
6086    public boolean isInTouchMode() {
6087        if (mAttachInfo != null) {
6088            return mAttachInfo.mInTouchMode;
6089        } else {
6090            return ViewRootImpl.isInTouchMode();
6091        }
6092    }
6093
6094    /**
6095     * Returns the context the view is running in, through which it can
6096     * access the current theme, resources, etc.
6097     *
6098     * @return The view's Context.
6099     */
6100    @ViewDebug.CapturedViewProperty
6101    public final Context getContext() {
6102        return mContext;
6103    }
6104
6105    /**
6106     * Handle a key event before it is processed by any input method
6107     * associated with the view hierarchy.  This can be used to intercept
6108     * key events in special situations before the IME consumes them; a
6109     * typical example would be handling the BACK key to update the application's
6110     * UI instead of allowing the IME to see it and close itself.
6111     *
6112     * @param keyCode The value in event.getKeyCode().
6113     * @param event Description of the key event.
6114     * @return If you handled the event, return true. If you want to allow the
6115     *         event to be handled by the next receiver, return false.
6116     */
6117    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
6118        return false;
6119    }
6120
6121    /**
6122     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
6123     * KeyEvent.Callback.onKeyDown()}: perform press of the view
6124     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
6125     * is released, if the view is enabled and clickable.
6126     *
6127     * @param keyCode A key code that represents the button pressed, from
6128     *                {@link android.view.KeyEvent}.
6129     * @param event   The KeyEvent object that defines the button action.
6130     */
6131    public boolean onKeyDown(int keyCode, KeyEvent event) {
6132        boolean result = false;
6133
6134        switch (keyCode) {
6135            case KeyEvent.KEYCODE_DPAD_CENTER:
6136            case KeyEvent.KEYCODE_ENTER: {
6137                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6138                    return true;
6139                }
6140                // Long clickable items don't necessarily have to be clickable
6141                if (((mViewFlags & CLICKABLE) == CLICKABLE ||
6142                        (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
6143                        (event.getRepeatCount() == 0)) {
6144                    setPressed(true);
6145                    checkForLongClick(0);
6146                    return true;
6147                }
6148                break;
6149            }
6150        }
6151        return result;
6152    }
6153
6154    /**
6155     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
6156     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
6157     * the event).
6158     */
6159    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
6160        return false;
6161    }
6162
6163    /**
6164     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
6165     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
6166     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
6167     * {@link KeyEvent#KEYCODE_ENTER} is released.
6168     *
6169     * @param keyCode A key code that represents the button pressed, from
6170     *                {@link android.view.KeyEvent}.
6171     * @param event   The KeyEvent object that defines the button action.
6172     */
6173    public boolean onKeyUp(int keyCode, KeyEvent event) {
6174        boolean result = false;
6175
6176        switch (keyCode) {
6177            case KeyEvent.KEYCODE_DPAD_CENTER:
6178            case KeyEvent.KEYCODE_ENTER: {
6179                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6180                    return true;
6181                }
6182                if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
6183                    setPressed(false);
6184
6185                    if (!mHasPerformedLongPress) {
6186                        // This is a tap, so remove the longpress check
6187                        removeLongPressCallback();
6188
6189                        result = performClick();
6190                    }
6191                }
6192                break;
6193            }
6194        }
6195        return result;
6196    }
6197
6198    /**
6199     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
6200     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
6201     * the event).
6202     *
6203     * @param keyCode     A key code that represents the button pressed, from
6204     *                    {@link android.view.KeyEvent}.
6205     * @param repeatCount The number of times the action was made.
6206     * @param event       The KeyEvent object that defines the button action.
6207     */
6208    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
6209        return false;
6210    }
6211
6212    /**
6213     * Called on the focused view when a key shortcut event is not handled.
6214     * Override this method to implement local key shortcuts for the View.
6215     * Key shortcuts can also be implemented by setting the
6216     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
6217     *
6218     * @param keyCode The value in event.getKeyCode().
6219     * @param event Description of the key event.
6220     * @return If you handled the event, return true. If you want to allow the
6221     *         event to be handled by the next receiver, return false.
6222     */
6223    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
6224        return false;
6225    }
6226
6227    /**
6228     * Check whether the called view is a text editor, in which case it
6229     * would make sense to automatically display a soft input window for
6230     * it.  Subclasses should override this if they implement
6231     * {@link #onCreateInputConnection(EditorInfo)} to return true if
6232     * a call on that method would return a non-null InputConnection, and
6233     * they are really a first-class editor that the user would normally
6234     * start typing on when the go into a window containing your view.
6235     *
6236     * <p>The default implementation always returns false.  This does
6237     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
6238     * will not be called or the user can not otherwise perform edits on your
6239     * view; it is just a hint to the system that this is not the primary
6240     * purpose of this view.
6241     *
6242     * @return Returns true if this view is a text editor, else false.
6243     */
6244    public boolean onCheckIsTextEditor() {
6245        return false;
6246    }
6247
6248    /**
6249     * Create a new InputConnection for an InputMethod to interact
6250     * with the view.  The default implementation returns null, since it doesn't
6251     * support input methods.  You can override this to implement such support.
6252     * This is only needed for views that take focus and text input.
6253     *
6254     * <p>When implementing this, you probably also want to implement
6255     * {@link #onCheckIsTextEditor()} to indicate you will return a
6256     * non-null InputConnection.
6257     *
6258     * @param outAttrs Fill in with attribute information about the connection.
6259     */
6260    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
6261        return null;
6262    }
6263
6264    /**
6265     * Called by the {@link android.view.inputmethod.InputMethodManager}
6266     * when a view who is not the current
6267     * input connection target is trying to make a call on the manager.  The
6268     * default implementation returns false; you can override this to return
6269     * true for certain views if you are performing InputConnection proxying
6270     * to them.
6271     * @param view The View that is making the InputMethodManager call.
6272     * @return Return true to allow the call, false to reject.
6273     */
6274    public boolean checkInputConnectionProxy(View view) {
6275        return false;
6276    }
6277
6278    /**
6279     * Show the context menu for this view. It is not safe to hold on to the
6280     * menu after returning from this method.
6281     *
6282     * You should normally not overload this method. Overload
6283     * {@link #onCreateContextMenu(ContextMenu)} or define an
6284     * {@link OnCreateContextMenuListener} to add items to the context menu.
6285     *
6286     * @param menu The context menu to populate
6287     */
6288    public void createContextMenu(ContextMenu menu) {
6289        ContextMenuInfo menuInfo = getContextMenuInfo();
6290
6291        // Sets the current menu info so all items added to menu will have
6292        // my extra info set.
6293        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
6294
6295        onCreateContextMenu(menu);
6296        ListenerInfo li = mListenerInfo;
6297        if (li != null && li.mOnCreateContextMenuListener != null) {
6298            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
6299        }
6300
6301        // Clear the extra information so subsequent items that aren't mine don't
6302        // have my extra info.
6303        ((MenuBuilder)menu).setCurrentMenuInfo(null);
6304
6305        if (mParent != null) {
6306            mParent.createContextMenu(menu);
6307        }
6308    }
6309
6310    /**
6311     * Views should implement this if they have extra information to associate
6312     * with the context menu. The return result is supplied as a parameter to
6313     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
6314     * callback.
6315     *
6316     * @return Extra information about the item for which the context menu
6317     *         should be shown. This information will vary across different
6318     *         subclasses of View.
6319     */
6320    protected ContextMenuInfo getContextMenuInfo() {
6321        return null;
6322    }
6323
6324    /**
6325     * Views should implement this if the view itself is going to add items to
6326     * the context menu.
6327     *
6328     * @param menu the context menu to populate
6329     */
6330    protected void onCreateContextMenu(ContextMenu menu) {
6331    }
6332
6333    /**
6334     * Implement this method to handle trackball motion events.  The
6335     * <em>relative</em> movement of the trackball since the last event
6336     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
6337     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
6338     * that a movement of 1 corresponds to the user pressing one DPAD key (so
6339     * they will often be fractional values, representing the more fine-grained
6340     * movement information available from a trackball).
6341     *
6342     * @param event The motion event.
6343     * @return True if the event was handled, false otherwise.
6344     */
6345    public boolean onTrackballEvent(MotionEvent event) {
6346        return false;
6347    }
6348
6349    /**
6350     * Implement this method to handle generic motion events.
6351     * <p>
6352     * Generic motion events describe joystick movements, mouse hovers, track pad
6353     * touches, scroll wheel movements and other input events.  The
6354     * {@link MotionEvent#getSource() source} of the motion event specifies
6355     * the class of input that was received.  Implementations of this method
6356     * must examine the bits in the source before processing the event.
6357     * The following code example shows how this is done.
6358     * </p><p>
6359     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
6360     * are delivered to the view under the pointer.  All other generic motion events are
6361     * delivered to the focused view.
6362     * </p>
6363     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
6364     *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
6365     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
6366     *             // process the joystick movement...
6367     *             return true;
6368     *         }
6369     *     }
6370     *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_POINTER) != 0) {
6371     *         switch (event.getAction()) {
6372     *             case MotionEvent.ACTION_HOVER_MOVE:
6373     *                 // process the mouse hover movement...
6374     *                 return true;
6375     *             case MotionEvent.ACTION_SCROLL:
6376     *                 // process the scroll wheel movement...
6377     *                 return true;
6378     *         }
6379     *     }
6380     *     return super.onGenericMotionEvent(event);
6381     * }</pre>
6382     *
6383     * @param event The generic motion event being processed.
6384     * @return True if the event was handled, false otherwise.
6385     */
6386    public boolean onGenericMotionEvent(MotionEvent event) {
6387        return false;
6388    }
6389
6390    /**
6391     * Implement this method to handle hover events.
6392     * <p>
6393     * This method is called whenever a pointer is hovering into, over, or out of the
6394     * bounds of a view and the view is not currently being touched.
6395     * Hover events are represented as pointer events with action
6396     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
6397     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
6398     * </p>
6399     * <ul>
6400     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
6401     * when the pointer enters the bounds of the view.</li>
6402     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
6403     * when the pointer has already entered the bounds of the view and has moved.</li>
6404     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
6405     * when the pointer has exited the bounds of the view or when the pointer is
6406     * about to go down due to a button click, tap, or similar user action that
6407     * causes the view to be touched.</li>
6408     * </ul>
6409     * <p>
6410     * The view should implement this method to return true to indicate that it is
6411     * handling the hover event, such as by changing its drawable state.
6412     * </p><p>
6413     * The default implementation calls {@link #setHovered} to update the hovered state
6414     * of the view when a hover enter or hover exit event is received, if the view
6415     * is enabled and is clickable.  The default implementation also sends hover
6416     * accessibility events.
6417     * </p>
6418     *
6419     * @param event The motion event that describes the hover.
6420     * @return True if the view handled the hover event.
6421     *
6422     * @see #isHovered
6423     * @see #setHovered
6424     * @see #onHoverChanged
6425     */
6426    public boolean onHoverEvent(MotionEvent event) {
6427        // The root view may receive hover (or touch) events that are outside the bounds of
6428        // the window.  This code ensures that we only send accessibility events for
6429        // hovers that are actually within the bounds of the root view.
6430        final int action = event.getAction();
6431        if (!mSendingHoverAccessibilityEvents) {
6432            if ((action == MotionEvent.ACTION_HOVER_ENTER
6433                    || action == MotionEvent.ACTION_HOVER_MOVE)
6434                    && !hasHoveredChild()
6435                    && pointInView(event.getX(), event.getY())) {
6436                mSendingHoverAccessibilityEvents = true;
6437                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
6438            }
6439        } else {
6440            if (action == MotionEvent.ACTION_HOVER_EXIT
6441                    || (action == MotionEvent.ACTION_HOVER_MOVE
6442                            && !pointInView(event.getX(), event.getY()))) {
6443                mSendingHoverAccessibilityEvents = false;
6444                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
6445            }
6446        }
6447
6448        if (isHoverable()) {
6449            switch (action) {
6450                case MotionEvent.ACTION_HOVER_ENTER:
6451                    setHovered(true);
6452                    break;
6453                case MotionEvent.ACTION_HOVER_EXIT:
6454                    setHovered(false);
6455                    break;
6456            }
6457
6458            // Dispatch the event to onGenericMotionEvent before returning true.
6459            // This is to provide compatibility with existing applications that
6460            // handled HOVER_MOVE events in onGenericMotionEvent and that would
6461            // break because of the new default handling for hoverable views
6462            // in onHoverEvent.
6463            // Note that onGenericMotionEvent will be called by default when
6464            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
6465            dispatchGenericMotionEventInternal(event);
6466            return true;
6467        }
6468        return false;
6469    }
6470
6471    /**
6472     * Returns true if the view should handle {@link #onHoverEvent}
6473     * by calling {@link #setHovered} to change its hovered state.
6474     *
6475     * @return True if the view is hoverable.
6476     */
6477    private boolean isHoverable() {
6478        final int viewFlags = mViewFlags;
6479        //noinspection SimplifiableIfStatement
6480        if ((viewFlags & ENABLED_MASK) == DISABLED) {
6481            return false;
6482        }
6483
6484        return (viewFlags & CLICKABLE) == CLICKABLE
6485                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
6486    }
6487
6488    /**
6489     * Returns true if the view is currently hovered.
6490     *
6491     * @return True if the view is currently hovered.
6492     *
6493     * @see #setHovered
6494     * @see #onHoverChanged
6495     */
6496    @ViewDebug.ExportedProperty
6497    public boolean isHovered() {
6498        return (mPrivateFlags & HOVERED) != 0;
6499    }
6500
6501    /**
6502     * Sets whether the view is currently hovered.
6503     * <p>
6504     * Calling this method also changes the drawable state of the view.  This
6505     * enables the view to react to hover by using different drawable resources
6506     * to change its appearance.
6507     * </p><p>
6508     * The {@link #onHoverChanged} method is called when the hovered state changes.
6509     * </p>
6510     *
6511     * @param hovered True if the view is hovered.
6512     *
6513     * @see #isHovered
6514     * @see #onHoverChanged
6515     */
6516    public void setHovered(boolean hovered) {
6517        if (hovered) {
6518            if ((mPrivateFlags & HOVERED) == 0) {
6519                mPrivateFlags |= HOVERED;
6520                refreshDrawableState();
6521                onHoverChanged(true);
6522            }
6523        } else {
6524            if ((mPrivateFlags & HOVERED) != 0) {
6525                mPrivateFlags &= ~HOVERED;
6526                refreshDrawableState();
6527                onHoverChanged(false);
6528            }
6529        }
6530    }
6531
6532    /**
6533     * Implement this method to handle hover state changes.
6534     * <p>
6535     * This method is called whenever the hover state changes as a result of a
6536     * call to {@link #setHovered}.
6537     * </p>
6538     *
6539     * @param hovered The current hover state, as returned by {@link #isHovered}.
6540     *
6541     * @see #isHovered
6542     * @see #setHovered
6543     */
6544    public void onHoverChanged(boolean hovered) {
6545    }
6546
6547    /**
6548     * Implement this method to handle touch screen motion events.
6549     *
6550     * @param event The motion event.
6551     * @return True if the event was handled, false otherwise.
6552     */
6553    public boolean onTouchEvent(MotionEvent event) {
6554        final int viewFlags = mViewFlags;
6555
6556        if ((viewFlags & ENABLED_MASK) == DISABLED) {
6557            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PRESSED) != 0) {
6558                setPressed(false);
6559            }
6560            // A disabled view that is clickable still consumes the touch
6561            // events, it just doesn't respond to them.
6562            return (((viewFlags & CLICKABLE) == CLICKABLE ||
6563                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
6564        }
6565
6566        if (mTouchDelegate != null) {
6567            if (mTouchDelegate.onTouchEvent(event)) {
6568                return true;
6569            }
6570        }
6571
6572        if (((viewFlags & CLICKABLE) == CLICKABLE ||
6573                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
6574            switch (event.getAction()) {
6575                case MotionEvent.ACTION_UP:
6576                    boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;
6577                    if ((mPrivateFlags & PRESSED) != 0 || prepressed) {
6578                        // take focus if we don't have it already and we should in
6579                        // touch mode.
6580                        boolean focusTaken = false;
6581                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
6582                            focusTaken = requestFocus();
6583                        }
6584
6585                        if (prepressed) {
6586                            // The button is being released before we actually
6587                            // showed it as pressed.  Make it show the pressed
6588                            // state now (before scheduling the click) to ensure
6589                            // the user sees it.
6590                            setPressed(true);
6591                       }
6592
6593                        if (!mHasPerformedLongPress) {
6594                            // This is a tap, so remove the longpress check
6595                            removeLongPressCallback();
6596
6597                            // Only perform take click actions if we were in the pressed state
6598                            if (!focusTaken) {
6599                                // Use a Runnable and post this rather than calling
6600                                // performClick directly. This lets other visual state
6601                                // of the view update before click actions start.
6602                                if (mPerformClick == null) {
6603                                    mPerformClick = new PerformClick();
6604                                }
6605                                if (!post(mPerformClick)) {
6606                                    performClick();
6607                                }
6608                            }
6609                        }
6610
6611                        if (mUnsetPressedState == null) {
6612                            mUnsetPressedState = new UnsetPressedState();
6613                        }
6614
6615                        if (prepressed) {
6616                            postDelayed(mUnsetPressedState,
6617                                    ViewConfiguration.getPressedStateDuration());
6618                        } else if (!post(mUnsetPressedState)) {
6619                            // If the post failed, unpress right now
6620                            mUnsetPressedState.run();
6621                        }
6622                        removeTapCallback();
6623                    }
6624                    break;
6625
6626                case MotionEvent.ACTION_DOWN:
6627                    mHasPerformedLongPress = false;
6628
6629                    if (performButtonActionOnTouchDown(event)) {
6630                        break;
6631                    }
6632
6633                    // Walk up the hierarchy to determine if we're inside a scrolling container.
6634                    boolean isInScrollingContainer = isInScrollingContainer();
6635
6636                    // For views inside a scrolling container, delay the pressed feedback for
6637                    // a short period in case this is a scroll.
6638                    if (isInScrollingContainer) {
6639                        mPrivateFlags |= PREPRESSED;
6640                        if (mPendingCheckForTap == null) {
6641                            mPendingCheckForTap = new CheckForTap();
6642                        }
6643                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
6644                    } else {
6645                        // Not inside a scrolling container, so show the feedback right away
6646                        setPressed(true);
6647                        checkForLongClick(0);
6648                    }
6649                    break;
6650
6651                case MotionEvent.ACTION_CANCEL:
6652                    setPressed(false);
6653                    removeTapCallback();
6654                    break;
6655
6656                case MotionEvent.ACTION_MOVE:
6657                    final int x = (int) event.getX();
6658                    final int y = (int) event.getY();
6659
6660                    // Be lenient about moving outside of buttons
6661                    if (!pointInView(x, y, mTouchSlop)) {
6662                        // Outside button
6663                        removeTapCallback();
6664                        if ((mPrivateFlags & PRESSED) != 0) {
6665                            // Remove any future long press/tap checks
6666                            removeLongPressCallback();
6667
6668                            setPressed(false);
6669                        }
6670                    }
6671                    break;
6672            }
6673            return true;
6674        }
6675
6676        return false;
6677    }
6678
6679    /**
6680     * @hide
6681     */
6682    public boolean isInScrollingContainer() {
6683        ViewParent p = getParent();
6684        while (p != null && p instanceof ViewGroup) {
6685            if (((ViewGroup) p).shouldDelayChildPressedState()) {
6686                return true;
6687            }
6688            p = p.getParent();
6689        }
6690        return false;
6691    }
6692
6693    /**
6694     * Remove the longpress detection timer.
6695     */
6696    private void removeLongPressCallback() {
6697        if (mPendingCheckForLongPress != null) {
6698          removeCallbacks(mPendingCheckForLongPress);
6699        }
6700    }
6701
6702    /**
6703     * Remove the pending click action
6704     */
6705    private void removePerformClickCallback() {
6706        if (mPerformClick != null) {
6707            removeCallbacks(mPerformClick);
6708        }
6709    }
6710
6711    /**
6712     * Remove the prepress detection timer.
6713     */
6714    private void removeUnsetPressCallback() {
6715        if ((mPrivateFlags & PRESSED) != 0 && mUnsetPressedState != null) {
6716            setPressed(false);
6717            removeCallbacks(mUnsetPressedState);
6718        }
6719    }
6720
6721    /**
6722     * Remove the tap detection timer.
6723     */
6724    private void removeTapCallback() {
6725        if (mPendingCheckForTap != null) {
6726            mPrivateFlags &= ~PREPRESSED;
6727            removeCallbacks(mPendingCheckForTap);
6728        }
6729    }
6730
6731    /**
6732     * Cancels a pending long press.  Your subclass can use this if you
6733     * want the context menu to come up if the user presses and holds
6734     * at the same place, but you don't want it to come up if they press
6735     * and then move around enough to cause scrolling.
6736     */
6737    public void cancelLongPress() {
6738        removeLongPressCallback();
6739
6740        /*
6741         * The prepressed state handled by the tap callback is a display
6742         * construct, but the tap callback will post a long press callback
6743         * less its own timeout. Remove it here.
6744         */
6745        removeTapCallback();
6746    }
6747
6748    /**
6749     * Remove the pending callback for sending a
6750     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
6751     */
6752    private void removeSendViewScrolledAccessibilityEventCallback() {
6753        if (mSendViewScrolledAccessibilityEvent != null) {
6754            removeCallbacks(mSendViewScrolledAccessibilityEvent);
6755        }
6756    }
6757
6758    /**
6759     * Sets the TouchDelegate for this View.
6760     */
6761    public void setTouchDelegate(TouchDelegate delegate) {
6762        mTouchDelegate = delegate;
6763    }
6764
6765    /**
6766     * Gets the TouchDelegate for this View.
6767     */
6768    public TouchDelegate getTouchDelegate() {
6769        return mTouchDelegate;
6770    }
6771
6772    /**
6773     * Set flags controlling behavior of this view.
6774     *
6775     * @param flags Constant indicating the value which should be set
6776     * @param mask Constant indicating the bit range that should be changed
6777     */
6778    void setFlags(int flags, int mask) {
6779        int old = mViewFlags;
6780        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
6781
6782        int changed = mViewFlags ^ old;
6783        if (changed == 0) {
6784            return;
6785        }
6786        int privateFlags = mPrivateFlags;
6787
6788        /* Check if the FOCUSABLE bit has changed */
6789        if (((changed & FOCUSABLE_MASK) != 0) &&
6790                ((privateFlags & HAS_BOUNDS) !=0)) {
6791            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
6792                    && ((privateFlags & FOCUSED) != 0)) {
6793                /* Give up focus if we are no longer focusable */
6794                clearFocus();
6795            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
6796                    && ((privateFlags & FOCUSED) == 0)) {
6797                /*
6798                 * Tell the view system that we are now available to take focus
6799                 * if no one else already has it.
6800                 */
6801                if (mParent != null) mParent.focusableViewAvailable(this);
6802            }
6803        }
6804
6805        if ((flags & VISIBILITY_MASK) == VISIBLE) {
6806            if ((changed & VISIBILITY_MASK) != 0) {
6807                /*
6808                 * If this view is becoming visible, invalidate it in case it changed while
6809                 * it was not visible. Marking it drawn ensures that the invalidation will
6810                 * go through.
6811                 */
6812                mPrivateFlags |= DRAWN;
6813                invalidate(true);
6814
6815                needGlobalAttributesUpdate(true);
6816
6817                // a view becoming visible is worth notifying the parent
6818                // about in case nothing has focus.  even if this specific view
6819                // isn't focusable, it may contain something that is, so let
6820                // the root view try to give this focus if nothing else does.
6821                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
6822                    mParent.focusableViewAvailable(this);
6823                }
6824            }
6825        }
6826
6827        /* Check if the GONE bit has changed */
6828        if ((changed & GONE) != 0) {
6829            needGlobalAttributesUpdate(false);
6830            requestLayout();
6831
6832            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
6833                if (hasFocus()) clearFocus();
6834                destroyDrawingCache();
6835                if (mParent instanceof View) {
6836                    // GONE views noop invalidation, so invalidate the parent
6837                    ((View) mParent).invalidate(true);
6838                }
6839                // Mark the view drawn to ensure that it gets invalidated properly the next
6840                // time it is visible and gets invalidated
6841                mPrivateFlags |= DRAWN;
6842            }
6843            if (mAttachInfo != null) {
6844                mAttachInfo.mViewVisibilityChanged = true;
6845            }
6846        }
6847
6848        /* Check if the VISIBLE bit has changed */
6849        if ((changed & INVISIBLE) != 0) {
6850            needGlobalAttributesUpdate(false);
6851            /*
6852             * If this view is becoming invisible, set the DRAWN flag so that
6853             * the next invalidate() will not be skipped.
6854             */
6855            mPrivateFlags |= DRAWN;
6856
6857            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
6858                // root view becoming invisible shouldn't clear focus
6859                if (getRootView() != this) {
6860                    clearFocus();
6861                }
6862            }
6863            if (mAttachInfo != null) {
6864                mAttachInfo.mViewVisibilityChanged = true;
6865            }
6866        }
6867
6868        if ((changed & VISIBILITY_MASK) != 0) {
6869            if (mParent instanceof ViewGroup) {
6870                ((ViewGroup) mParent).onChildVisibilityChanged(this,
6871                        (changed & VISIBILITY_MASK), (flags & VISIBILITY_MASK));
6872                ((View) mParent).invalidate(true);
6873            } else if (mParent != null) {
6874                mParent.invalidateChild(this, null);
6875            }
6876            dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
6877        }
6878
6879        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
6880            destroyDrawingCache();
6881        }
6882
6883        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
6884            destroyDrawingCache();
6885            mPrivateFlags &= ~DRAWING_CACHE_VALID;
6886            invalidateParentCaches();
6887        }
6888
6889        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
6890            destroyDrawingCache();
6891            mPrivateFlags &= ~DRAWING_CACHE_VALID;
6892        }
6893
6894        if ((changed & DRAW_MASK) != 0) {
6895            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
6896                if (mBGDrawable != null) {
6897                    mPrivateFlags &= ~SKIP_DRAW;
6898                    mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
6899                } else {
6900                    mPrivateFlags |= SKIP_DRAW;
6901                }
6902            } else {
6903                mPrivateFlags &= ~SKIP_DRAW;
6904            }
6905            requestLayout();
6906            invalidate(true);
6907        }
6908
6909        if ((changed & KEEP_SCREEN_ON) != 0) {
6910            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
6911                mParent.recomputeViewAttributes(this);
6912            }
6913        }
6914
6915        if ((changed & LAYOUT_DIRECTION_MASK) != 0) {
6916            requestLayout();
6917        }
6918    }
6919
6920    /**
6921     * Change the view's z order in the tree, so it's on top of other sibling
6922     * views
6923     */
6924    public void bringToFront() {
6925        if (mParent != null) {
6926            mParent.bringChildToFront(this);
6927        }
6928    }
6929
6930    /**
6931     * This is called in response to an internal scroll in this view (i.e., the
6932     * view scrolled its own contents). This is typically as a result of
6933     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
6934     * called.
6935     *
6936     * @param l Current horizontal scroll origin.
6937     * @param t Current vertical scroll origin.
6938     * @param oldl Previous horizontal scroll origin.
6939     * @param oldt Previous vertical scroll origin.
6940     */
6941    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
6942        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
6943            postSendViewScrolledAccessibilityEventCallback();
6944        }
6945
6946        mBackgroundSizeChanged = true;
6947
6948        final AttachInfo ai = mAttachInfo;
6949        if (ai != null) {
6950            ai.mViewScrollChanged = true;
6951        }
6952    }
6953
6954    /**
6955     * Interface definition for a callback to be invoked when the layout bounds of a view
6956     * changes due to layout processing.
6957     */
6958    public interface OnLayoutChangeListener {
6959        /**
6960         * Called when the focus state of a view has changed.
6961         *
6962         * @param v The view whose state has changed.
6963         * @param left The new value of the view's left property.
6964         * @param top The new value of the view's top property.
6965         * @param right The new value of the view's right property.
6966         * @param bottom The new value of the view's bottom property.
6967         * @param oldLeft The previous value of the view's left property.
6968         * @param oldTop The previous value of the view's top property.
6969         * @param oldRight The previous value of the view's right property.
6970         * @param oldBottom The previous value of the view's bottom property.
6971         */
6972        void onLayoutChange(View v, int left, int top, int right, int bottom,
6973            int oldLeft, int oldTop, int oldRight, int oldBottom);
6974    }
6975
6976    /**
6977     * This is called during layout when the size of this view has changed. If
6978     * you were just added to the view hierarchy, you're called with the old
6979     * values of 0.
6980     *
6981     * @param w Current width of this view.
6982     * @param h Current height of this view.
6983     * @param oldw Old width of this view.
6984     * @param oldh Old height of this view.
6985     */
6986    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
6987    }
6988
6989    /**
6990     * Called by draw to draw the child views. This may be overridden
6991     * by derived classes to gain control just before its children are drawn
6992     * (but after its own view has been drawn).
6993     * @param canvas the canvas on which to draw the view
6994     */
6995    protected void dispatchDraw(Canvas canvas) {
6996    }
6997
6998    /**
6999     * Gets the parent of this view. Note that the parent is a
7000     * ViewParent and not necessarily a View.
7001     *
7002     * @return Parent of this view.
7003     */
7004    public final ViewParent getParent() {
7005        return mParent;
7006    }
7007
7008    /**
7009     * Set the horizontal scrolled position of your view. This will cause a call to
7010     * {@link #onScrollChanged(int, int, int, int)} and the view will be
7011     * invalidated.
7012     * @param value the x position to scroll to
7013     */
7014    public void setScrollX(int value) {
7015        scrollTo(value, mScrollY);
7016    }
7017
7018    /**
7019     * Set the vertical scrolled position of your view. This will cause a call to
7020     * {@link #onScrollChanged(int, int, int, int)} and the view will be
7021     * invalidated.
7022     * @param value the y position to scroll to
7023     */
7024    public void setScrollY(int value) {
7025        scrollTo(mScrollX, value);
7026    }
7027
7028    /**
7029     * Return the scrolled left position of this view. This is the left edge of
7030     * the displayed part of your view. You do not need to draw any pixels
7031     * farther left, since those are outside of the frame of your view on
7032     * screen.
7033     *
7034     * @return The left edge of the displayed part of your view, in pixels.
7035     */
7036    public final int getScrollX() {
7037        return mScrollX;
7038    }
7039
7040    /**
7041     * Return the scrolled top position of this view. This is the top edge of
7042     * the displayed part of your view. You do not need to draw any pixels above
7043     * it, since those are outside of the frame of your view on screen.
7044     *
7045     * @return The top edge of the displayed part of your view, in pixels.
7046     */
7047    public final int getScrollY() {
7048        return mScrollY;
7049    }
7050
7051    /**
7052     * Return the width of the your view.
7053     *
7054     * @return The width of your view, in pixels.
7055     */
7056    @ViewDebug.ExportedProperty(category = "layout")
7057    public final int getWidth() {
7058        return mRight - mLeft;
7059    }
7060
7061    /**
7062     * Return the height of your view.
7063     *
7064     * @return The height of your view, in pixels.
7065     */
7066    @ViewDebug.ExportedProperty(category = "layout")
7067    public final int getHeight() {
7068        return mBottom - mTop;
7069    }
7070
7071    /**
7072     * Return the visible drawing bounds of your view. Fills in the output
7073     * rectangle with the values from getScrollX(), getScrollY(),
7074     * getWidth(), and getHeight().
7075     *
7076     * @param outRect The (scrolled) drawing bounds of the view.
7077     */
7078    public void getDrawingRect(Rect outRect) {
7079        outRect.left = mScrollX;
7080        outRect.top = mScrollY;
7081        outRect.right = mScrollX + (mRight - mLeft);
7082        outRect.bottom = mScrollY + (mBottom - mTop);
7083    }
7084
7085    /**
7086     * Like {@link #getMeasuredWidthAndState()}, but only returns the
7087     * raw width component (that is the result is masked by
7088     * {@link #MEASURED_SIZE_MASK}).
7089     *
7090     * @return The raw measured width of this view.
7091     */
7092    public final int getMeasuredWidth() {
7093        return mMeasuredWidth & MEASURED_SIZE_MASK;
7094    }
7095
7096    /**
7097     * Return the full width measurement information for this view as computed
7098     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
7099     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
7100     * This should be used during measurement and layout calculations only. Use
7101     * {@link #getWidth()} to see how wide a view is after layout.
7102     *
7103     * @return The measured width of this view as a bit mask.
7104     */
7105    public final int getMeasuredWidthAndState() {
7106        return mMeasuredWidth;
7107    }
7108
7109    /**
7110     * Like {@link #getMeasuredHeightAndState()}, but only returns the
7111     * raw width component (that is the result is masked by
7112     * {@link #MEASURED_SIZE_MASK}).
7113     *
7114     * @return The raw measured height of this view.
7115     */
7116    public final int getMeasuredHeight() {
7117        return mMeasuredHeight & MEASURED_SIZE_MASK;
7118    }
7119
7120    /**
7121     * Return the full height measurement information for this view as computed
7122     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
7123     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
7124     * This should be used during measurement and layout calculations only. Use
7125     * {@link #getHeight()} to see how wide a view is after layout.
7126     *
7127     * @return The measured width of this view as a bit mask.
7128     */
7129    public final int getMeasuredHeightAndState() {
7130        return mMeasuredHeight;
7131    }
7132
7133    /**
7134     * Return only the state bits of {@link #getMeasuredWidthAndState()}
7135     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
7136     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
7137     * and the height component is at the shifted bits
7138     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
7139     */
7140    public final int getMeasuredState() {
7141        return (mMeasuredWidth&MEASURED_STATE_MASK)
7142                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
7143                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
7144    }
7145
7146    /**
7147     * The transform matrix of this view, which is calculated based on the current
7148     * roation, scale, and pivot properties.
7149     *
7150     * @see #getRotation()
7151     * @see #getScaleX()
7152     * @see #getScaleY()
7153     * @see #getPivotX()
7154     * @see #getPivotY()
7155     * @return The current transform matrix for the view
7156     */
7157    public Matrix getMatrix() {
7158        if (mTransformationInfo != null) {
7159            updateMatrix();
7160            return mTransformationInfo.mMatrix;
7161        }
7162        return Matrix.IDENTITY_MATRIX;
7163    }
7164
7165    /**
7166     * Utility function to determine if the value is far enough away from zero to be
7167     * considered non-zero.
7168     * @param value A floating point value to check for zero-ness
7169     * @return whether the passed-in value is far enough away from zero to be considered non-zero
7170     */
7171    private static boolean nonzero(float value) {
7172        return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
7173    }
7174
7175    /**
7176     * Returns true if the transform matrix is the identity matrix.
7177     * Recomputes the matrix if necessary.
7178     *
7179     * @return True if the transform matrix is the identity matrix, false otherwise.
7180     */
7181    final boolean hasIdentityMatrix() {
7182        if (mTransformationInfo != null) {
7183            updateMatrix();
7184            return mTransformationInfo.mMatrixIsIdentity;
7185        }
7186        return true;
7187    }
7188
7189    void ensureTransformationInfo() {
7190        if (mTransformationInfo == null) {
7191            mTransformationInfo = new TransformationInfo();
7192        }
7193    }
7194
7195    /**
7196     * Recomputes the transform matrix if necessary.
7197     */
7198    private void updateMatrix() {
7199        final TransformationInfo info = mTransformationInfo;
7200        if (info == null) {
7201            return;
7202        }
7203        if (info.mMatrixDirty) {
7204            // transform-related properties have changed since the last time someone
7205            // asked for the matrix; recalculate it with the current values
7206
7207            // Figure out if we need to update the pivot point
7208            if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7209                if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
7210                    info.mPrevWidth = mRight - mLeft;
7211                    info.mPrevHeight = mBottom - mTop;
7212                    info.mPivotX = info.mPrevWidth / 2f;
7213                    info.mPivotY = info.mPrevHeight / 2f;
7214                }
7215            }
7216            info.mMatrix.reset();
7217            if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
7218                info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
7219                info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
7220                info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
7221            } else {
7222                if (info.mCamera == null) {
7223                    info.mCamera = new Camera();
7224                    info.matrix3D = new Matrix();
7225                }
7226                info.mCamera.save();
7227                info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
7228                info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
7229                info.mCamera.getMatrix(info.matrix3D);
7230                info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
7231                info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
7232                        info.mPivotY + info.mTranslationY);
7233                info.mMatrix.postConcat(info.matrix3D);
7234                info.mCamera.restore();
7235            }
7236            info.mMatrixDirty = false;
7237            info.mMatrixIsIdentity = info.mMatrix.isIdentity();
7238            info.mInverseMatrixDirty = true;
7239        }
7240    }
7241
7242    /**
7243     * Utility method to retrieve the inverse of the current mMatrix property.
7244     * We cache the matrix to avoid recalculating it when transform properties
7245     * have not changed.
7246     *
7247     * @return The inverse of the current matrix of this view.
7248     */
7249    final Matrix getInverseMatrix() {
7250        final TransformationInfo info = mTransformationInfo;
7251        if (info != null) {
7252            updateMatrix();
7253            if (info.mInverseMatrixDirty) {
7254                if (info.mInverseMatrix == null) {
7255                    info.mInverseMatrix = new Matrix();
7256                }
7257                info.mMatrix.invert(info.mInverseMatrix);
7258                info.mInverseMatrixDirty = false;
7259            }
7260            return info.mInverseMatrix;
7261        }
7262        return Matrix.IDENTITY_MATRIX;
7263    }
7264
7265    /**
7266     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
7267     * views are drawn) from the camera to this view. The camera's distance
7268     * affects 3D transformations, for instance rotations around the X and Y
7269     * axis. If the rotationX or rotationY properties are changed and this view is
7270     * large (more than half the size of the screen), it is recommended to always
7271     * use a camera distance that's greater than the height (X axis rotation) or
7272     * the width (Y axis rotation) of this view.</p>
7273     *
7274     * <p>The distance of the camera from the view plane can have an affect on the
7275     * perspective distortion of the view when it is rotated around the x or y axis.
7276     * For example, a large distance will result in a large viewing angle, and there
7277     * will not be much perspective distortion of the view as it rotates. A short
7278     * distance may cause much more perspective distortion upon rotation, and can
7279     * also result in some drawing artifacts if the rotated view ends up partially
7280     * behind the camera (which is why the recommendation is to use a distance at
7281     * least as far as the size of the view, if the view is to be rotated.)</p>
7282     *
7283     * <p>The distance is expressed in "depth pixels." The default distance depends
7284     * on the screen density. For instance, on a medium density display, the
7285     * default distance is 1280. On a high density display, the default distance
7286     * is 1920.</p>
7287     *
7288     * <p>If you want to specify a distance that leads to visually consistent
7289     * results across various densities, use the following formula:</p>
7290     * <pre>
7291     * float scale = context.getResources().getDisplayMetrics().density;
7292     * view.setCameraDistance(distance * scale);
7293     * </pre>
7294     *
7295     * <p>The density scale factor of a high density display is 1.5,
7296     * and 1920 = 1280 * 1.5.</p>
7297     *
7298     * @param distance The distance in "depth pixels", if negative the opposite
7299     *        value is used
7300     *
7301     * @see #setRotationX(float)
7302     * @see #setRotationY(float)
7303     */
7304    public void setCameraDistance(float distance) {
7305        invalidateParentCaches();
7306        invalidate(false);
7307
7308        ensureTransformationInfo();
7309        final float dpi = mResources.getDisplayMetrics().densityDpi;
7310        final TransformationInfo info = mTransformationInfo;
7311        if (info.mCamera == null) {
7312            info.mCamera = new Camera();
7313            info.matrix3D = new Matrix();
7314        }
7315
7316        info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
7317        info.mMatrixDirty = true;
7318
7319        invalidate(false);
7320    }
7321
7322    /**
7323     * The degrees that the view is rotated around the pivot point.
7324     *
7325     * @see #setRotation(float)
7326     * @see #getPivotX()
7327     * @see #getPivotY()
7328     *
7329     * @return The degrees of rotation.
7330     */
7331    @ViewDebug.ExportedProperty(category = "drawing")
7332    public float getRotation() {
7333        return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
7334    }
7335
7336    /**
7337     * Sets the degrees that the view is rotated around the pivot point. Increasing values
7338     * result in clockwise rotation.
7339     *
7340     * @param rotation The degrees of rotation.
7341     *
7342     * @see #getRotation()
7343     * @see #getPivotX()
7344     * @see #getPivotY()
7345     * @see #setRotationX(float)
7346     * @see #setRotationY(float)
7347     *
7348     * @attr ref android.R.styleable#View_rotation
7349     */
7350    public void setRotation(float rotation) {
7351        ensureTransformationInfo();
7352        final TransformationInfo info = mTransformationInfo;
7353        if (info.mRotation != rotation) {
7354            invalidateParentCaches();
7355            // Double-invalidation is necessary to capture view's old and new areas
7356            invalidate(false);
7357            info.mRotation = rotation;
7358            info.mMatrixDirty = true;
7359            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7360            invalidate(false);
7361        }
7362    }
7363
7364    /**
7365     * The degrees that the view is rotated around the vertical axis through the pivot point.
7366     *
7367     * @see #getPivotX()
7368     * @see #getPivotY()
7369     * @see #setRotationY(float)
7370     *
7371     * @return The degrees of Y rotation.
7372     */
7373    @ViewDebug.ExportedProperty(category = "drawing")
7374    public float getRotationY() {
7375        return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
7376    }
7377
7378    /**
7379     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
7380     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
7381     * down the y axis.
7382     *
7383     * When rotating large views, it is recommended to adjust the camera distance
7384     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
7385     *
7386     * @param rotationY The degrees of Y rotation.
7387     *
7388     * @see #getRotationY()
7389     * @see #getPivotX()
7390     * @see #getPivotY()
7391     * @see #setRotation(float)
7392     * @see #setRotationX(float)
7393     * @see #setCameraDistance(float)
7394     *
7395     * @attr ref android.R.styleable#View_rotationY
7396     */
7397    public void setRotationY(float rotationY) {
7398        ensureTransformationInfo();
7399        final TransformationInfo info = mTransformationInfo;
7400        if (info.mRotationY != rotationY) {
7401            invalidateParentCaches();
7402            // Double-invalidation is necessary to capture view's old and new areas
7403            invalidate(false);
7404            info.mRotationY = rotationY;
7405            info.mMatrixDirty = true;
7406            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7407            invalidate(false);
7408        }
7409    }
7410
7411    /**
7412     * The degrees that the view is rotated around the horizontal axis through the pivot point.
7413     *
7414     * @see #getPivotX()
7415     * @see #getPivotY()
7416     * @see #setRotationX(float)
7417     *
7418     * @return The degrees of X rotation.
7419     */
7420    @ViewDebug.ExportedProperty(category = "drawing")
7421    public float getRotationX() {
7422        return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
7423    }
7424
7425    /**
7426     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
7427     * Increasing values result in clockwise rotation from the viewpoint of looking down the
7428     * x axis.
7429     *
7430     * When rotating large views, it is recommended to adjust the camera distance
7431     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
7432     *
7433     * @param rotationX The degrees of X rotation.
7434     *
7435     * @see #getRotationX()
7436     * @see #getPivotX()
7437     * @see #getPivotY()
7438     * @see #setRotation(float)
7439     * @see #setRotationY(float)
7440     * @see #setCameraDistance(float)
7441     *
7442     * @attr ref android.R.styleable#View_rotationX
7443     */
7444    public void setRotationX(float rotationX) {
7445        ensureTransformationInfo();
7446        final TransformationInfo info = mTransformationInfo;
7447        if (info.mRotationX != rotationX) {
7448            invalidateParentCaches();
7449            // Double-invalidation is necessary to capture view's old and new areas
7450            invalidate(false);
7451            info.mRotationX = rotationX;
7452            info.mMatrixDirty = true;
7453            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7454            invalidate(false);
7455        }
7456    }
7457
7458    /**
7459     * The amount that the view is scaled in x around the pivot point, as a proportion of
7460     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
7461     *
7462     * <p>By default, this is 1.0f.
7463     *
7464     * @see #getPivotX()
7465     * @see #getPivotY()
7466     * @return The scaling factor.
7467     */
7468    @ViewDebug.ExportedProperty(category = "drawing")
7469    public float getScaleX() {
7470        return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
7471    }
7472
7473    /**
7474     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
7475     * the view's unscaled width. A value of 1 means that no scaling is applied.
7476     *
7477     * @param scaleX The scaling factor.
7478     * @see #getPivotX()
7479     * @see #getPivotY()
7480     *
7481     * @attr ref android.R.styleable#View_scaleX
7482     */
7483    public void setScaleX(float scaleX) {
7484        ensureTransformationInfo();
7485        final TransformationInfo info = mTransformationInfo;
7486        if (info.mScaleX != scaleX) {
7487            invalidateParentCaches();
7488            // Double-invalidation is necessary to capture view's old and new areas
7489            invalidate(false);
7490            info.mScaleX = scaleX;
7491            info.mMatrixDirty = true;
7492            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7493            invalidate(false);
7494        }
7495    }
7496
7497    /**
7498     * The amount that the view is scaled in y around the pivot point, as a proportion of
7499     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
7500     *
7501     * <p>By default, this is 1.0f.
7502     *
7503     * @see #getPivotX()
7504     * @see #getPivotY()
7505     * @return The scaling factor.
7506     */
7507    @ViewDebug.ExportedProperty(category = "drawing")
7508    public float getScaleY() {
7509        return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
7510    }
7511
7512    /**
7513     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
7514     * the view's unscaled width. A value of 1 means that no scaling is applied.
7515     *
7516     * @param scaleY The scaling factor.
7517     * @see #getPivotX()
7518     * @see #getPivotY()
7519     *
7520     * @attr ref android.R.styleable#View_scaleY
7521     */
7522    public void setScaleY(float scaleY) {
7523        ensureTransformationInfo();
7524        final TransformationInfo info = mTransformationInfo;
7525        if (info.mScaleY != scaleY) {
7526            invalidateParentCaches();
7527            // Double-invalidation is necessary to capture view's old and new areas
7528            invalidate(false);
7529            info.mScaleY = scaleY;
7530            info.mMatrixDirty = true;
7531            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7532            invalidate(false);
7533        }
7534    }
7535
7536    /**
7537     * The x location of the point around which the view is {@link #setRotation(float) rotated}
7538     * and {@link #setScaleX(float) scaled}.
7539     *
7540     * @see #getRotation()
7541     * @see #getScaleX()
7542     * @see #getScaleY()
7543     * @see #getPivotY()
7544     * @return The x location of the pivot point.
7545     */
7546    @ViewDebug.ExportedProperty(category = "drawing")
7547    public float getPivotX() {
7548        return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
7549    }
7550
7551    /**
7552     * Sets the x location of the point around which the view is
7553     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
7554     * By default, the pivot point is centered on the object.
7555     * Setting this property disables this behavior and causes the view to use only the
7556     * explicitly set pivotX and pivotY values.
7557     *
7558     * @param pivotX The x location of the pivot point.
7559     * @see #getRotation()
7560     * @see #getScaleX()
7561     * @see #getScaleY()
7562     * @see #getPivotY()
7563     *
7564     * @attr ref android.R.styleable#View_transformPivotX
7565     */
7566    public void setPivotX(float pivotX) {
7567        ensureTransformationInfo();
7568        mPrivateFlags |= PIVOT_EXPLICITLY_SET;
7569        final TransformationInfo info = mTransformationInfo;
7570        if (info.mPivotX != pivotX) {
7571            invalidateParentCaches();
7572            // Double-invalidation is necessary to capture view's old and new areas
7573            invalidate(false);
7574            info.mPivotX = pivotX;
7575            info.mMatrixDirty = true;
7576            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7577            invalidate(false);
7578        }
7579    }
7580
7581    /**
7582     * The y location of the point around which the view is {@link #setRotation(float) rotated}
7583     * and {@link #setScaleY(float) scaled}.
7584     *
7585     * @see #getRotation()
7586     * @see #getScaleX()
7587     * @see #getScaleY()
7588     * @see #getPivotY()
7589     * @return The y location of the pivot point.
7590     */
7591    @ViewDebug.ExportedProperty(category = "drawing")
7592    public float getPivotY() {
7593        return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
7594    }
7595
7596    /**
7597     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
7598     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
7599     * Setting this property disables this behavior and causes the view to use only the
7600     * explicitly set pivotX and pivotY values.
7601     *
7602     * @param pivotY The y location of the pivot point.
7603     * @see #getRotation()
7604     * @see #getScaleX()
7605     * @see #getScaleY()
7606     * @see #getPivotY()
7607     *
7608     * @attr ref android.R.styleable#View_transformPivotY
7609     */
7610    public void setPivotY(float pivotY) {
7611        ensureTransformationInfo();
7612        mPrivateFlags |= PIVOT_EXPLICITLY_SET;
7613        final TransformationInfo info = mTransformationInfo;
7614        if (info.mPivotY != pivotY) {
7615            invalidateParentCaches();
7616            // Double-invalidation is necessary to capture view's old and new areas
7617            invalidate(false);
7618            info.mPivotY = pivotY;
7619            info.mMatrixDirty = true;
7620            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7621            invalidate(false);
7622        }
7623    }
7624
7625    /**
7626     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
7627     * completely transparent and 1 means the view is completely opaque.
7628     *
7629     * <p>By default this is 1.0f.
7630     * @return The opacity of the view.
7631     */
7632    @ViewDebug.ExportedProperty(category = "drawing")
7633    public float getAlpha() {
7634        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
7635    }
7636
7637    /**
7638     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
7639     * completely transparent and 1 means the view is completely opaque.</p>
7640     *
7641     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
7642     * responsible for applying the opacity itself. Otherwise, calling this method is
7643     * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
7644     * setting a hardware layer.</p>
7645     *
7646     * <p>Note that setting alpha to a translucent value (0 < alpha < 1) may have
7647     * performance implications. It is generally best to use the alpha property sparingly and
7648     * transiently, as in the case of fading animations.</p>
7649     *
7650     * @param alpha The opacity of the view.
7651     *
7652     * @see #setLayerType(int, android.graphics.Paint)
7653     *
7654     * @attr ref android.R.styleable#View_alpha
7655     */
7656    public void setAlpha(float alpha) {
7657        ensureTransformationInfo();
7658        if (mTransformationInfo.mAlpha != alpha) {
7659            mTransformationInfo.mAlpha = alpha;
7660            invalidateParentCaches();
7661            if (onSetAlpha((int) (alpha * 255))) {
7662                mPrivateFlags |= ALPHA_SET;
7663                // subclass is handling alpha - don't optimize rendering cache invalidation
7664                invalidate(true);
7665            } else {
7666                mPrivateFlags &= ~ALPHA_SET;
7667                invalidate(false);
7668            }
7669        }
7670    }
7671
7672    /**
7673     * Faster version of setAlpha() which performs the same steps except there are
7674     * no calls to invalidate(). The caller of this function should perform proper invalidation
7675     * on the parent and this object. The return value indicates whether the subclass handles
7676     * alpha (the return value for onSetAlpha()).
7677     *
7678     * @param alpha The new value for the alpha property
7679     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
7680     *         the new value for the alpha property is different from the old value
7681     */
7682    boolean setAlphaNoInvalidation(float alpha) {
7683        ensureTransformationInfo();
7684        if (mTransformationInfo.mAlpha != alpha) {
7685            mTransformationInfo.mAlpha = alpha;
7686            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
7687            if (subclassHandlesAlpha) {
7688                mPrivateFlags |= ALPHA_SET;
7689                return true;
7690            } else {
7691                mPrivateFlags &= ~ALPHA_SET;
7692            }
7693        }
7694        return false;
7695    }
7696
7697    /**
7698     * Top position of this view relative to its parent.
7699     *
7700     * @return The top of this view, in pixels.
7701     */
7702    @ViewDebug.CapturedViewProperty
7703    public final int getTop() {
7704        return mTop;
7705    }
7706
7707    /**
7708     * Sets the top position of this view relative to its parent. This method is meant to be called
7709     * by the layout system and should not generally be called otherwise, because the property
7710     * may be changed at any time by the layout.
7711     *
7712     * @param top The top of this view, in pixels.
7713     */
7714    public final void setTop(int top) {
7715        if (top != mTop) {
7716            updateMatrix();
7717            final boolean matrixIsIdentity = mTransformationInfo == null
7718                    || mTransformationInfo.mMatrixIsIdentity;
7719            if (matrixIsIdentity) {
7720                if (mAttachInfo != null) {
7721                    int minTop;
7722                    int yLoc;
7723                    if (top < mTop) {
7724                        minTop = top;
7725                        yLoc = top - mTop;
7726                    } else {
7727                        minTop = mTop;
7728                        yLoc = 0;
7729                    }
7730                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
7731                }
7732            } else {
7733                // Double-invalidation is necessary to capture view's old and new areas
7734                invalidate(true);
7735            }
7736
7737            int width = mRight - mLeft;
7738            int oldHeight = mBottom - mTop;
7739
7740            mTop = top;
7741
7742            onSizeChanged(width, mBottom - mTop, width, oldHeight);
7743
7744            if (!matrixIsIdentity) {
7745                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7746                    // A change in dimension means an auto-centered pivot point changes, too
7747                    mTransformationInfo.mMatrixDirty = true;
7748                }
7749                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7750                invalidate(true);
7751            }
7752            mBackgroundSizeChanged = true;
7753            invalidateParentIfNeeded();
7754        }
7755    }
7756
7757    /**
7758     * Bottom position of this view relative to its parent.
7759     *
7760     * @return The bottom of this view, in pixels.
7761     */
7762    @ViewDebug.CapturedViewProperty
7763    public final int getBottom() {
7764        return mBottom;
7765    }
7766
7767    /**
7768     * True if this view has changed since the last time being drawn.
7769     *
7770     * @return The dirty state of this view.
7771     */
7772    public boolean isDirty() {
7773        return (mPrivateFlags & DIRTY_MASK) != 0;
7774    }
7775
7776    /**
7777     * Sets the bottom position of this view relative to its parent. This method is meant to be
7778     * called by the layout system and should not generally be called otherwise, because the
7779     * property may be changed at any time by the layout.
7780     *
7781     * @param bottom The bottom of this view, in pixels.
7782     */
7783    public final void setBottom(int bottom) {
7784        if (bottom != mBottom) {
7785            updateMatrix();
7786            final boolean matrixIsIdentity = mTransformationInfo == null
7787                    || mTransformationInfo.mMatrixIsIdentity;
7788            if (matrixIsIdentity) {
7789                if (mAttachInfo != null) {
7790                    int maxBottom;
7791                    if (bottom < mBottom) {
7792                        maxBottom = mBottom;
7793                    } else {
7794                        maxBottom = bottom;
7795                    }
7796                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
7797                }
7798            } else {
7799                // Double-invalidation is necessary to capture view's old and new areas
7800                invalidate(true);
7801            }
7802
7803            int width = mRight - mLeft;
7804            int oldHeight = mBottom - mTop;
7805
7806            mBottom = bottom;
7807
7808            onSizeChanged(width, mBottom - mTop, width, oldHeight);
7809
7810            if (!matrixIsIdentity) {
7811                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7812                    // A change in dimension means an auto-centered pivot point changes, too
7813                    mTransformationInfo.mMatrixDirty = true;
7814                }
7815                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7816                invalidate(true);
7817            }
7818            mBackgroundSizeChanged = true;
7819            invalidateParentIfNeeded();
7820        }
7821    }
7822
7823    /**
7824     * Left position of this view relative to its parent.
7825     *
7826     * @return The left edge of this view, in pixels.
7827     */
7828    @ViewDebug.CapturedViewProperty
7829    public final int getLeft() {
7830        return mLeft;
7831    }
7832
7833    /**
7834     * Sets the left position of this view relative to its parent. This method is meant to be called
7835     * by the layout system and should not generally be called otherwise, because the property
7836     * may be changed at any time by the layout.
7837     *
7838     * @param left The bottom of this view, in pixels.
7839     */
7840    public final void setLeft(int left) {
7841        if (left != mLeft) {
7842            updateMatrix();
7843            final boolean matrixIsIdentity = mTransformationInfo == null
7844                    || mTransformationInfo.mMatrixIsIdentity;
7845            if (matrixIsIdentity) {
7846                if (mAttachInfo != null) {
7847                    int minLeft;
7848                    int xLoc;
7849                    if (left < mLeft) {
7850                        minLeft = left;
7851                        xLoc = left - mLeft;
7852                    } else {
7853                        minLeft = mLeft;
7854                        xLoc = 0;
7855                    }
7856                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
7857                }
7858            } else {
7859                // Double-invalidation is necessary to capture view's old and new areas
7860                invalidate(true);
7861            }
7862
7863            int oldWidth = mRight - mLeft;
7864            int height = mBottom - mTop;
7865
7866            mLeft = left;
7867
7868            onSizeChanged(mRight - mLeft, height, oldWidth, height);
7869
7870            if (!matrixIsIdentity) {
7871                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7872                    // A change in dimension means an auto-centered pivot point changes, too
7873                    mTransformationInfo.mMatrixDirty = true;
7874                }
7875                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7876                invalidate(true);
7877            }
7878            mBackgroundSizeChanged = true;
7879            invalidateParentIfNeeded();
7880        }
7881    }
7882
7883    /**
7884     * Right position of this view relative to its parent.
7885     *
7886     * @return The right edge of this view, in pixels.
7887     */
7888    @ViewDebug.CapturedViewProperty
7889    public final int getRight() {
7890        return mRight;
7891    }
7892
7893    /**
7894     * Sets the right position of this view relative to its parent. This method is meant to be called
7895     * by the layout system and should not generally be called otherwise, because the property
7896     * may be changed at any time by the layout.
7897     *
7898     * @param right The bottom of this view, in pixels.
7899     */
7900    public final void setRight(int right) {
7901        if (right != mRight) {
7902            updateMatrix();
7903            final boolean matrixIsIdentity = mTransformationInfo == null
7904                    || mTransformationInfo.mMatrixIsIdentity;
7905            if (matrixIsIdentity) {
7906                if (mAttachInfo != null) {
7907                    int maxRight;
7908                    if (right < mRight) {
7909                        maxRight = mRight;
7910                    } else {
7911                        maxRight = right;
7912                    }
7913                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
7914                }
7915            } else {
7916                // Double-invalidation is necessary to capture view's old and new areas
7917                invalidate(true);
7918            }
7919
7920            int oldWidth = mRight - mLeft;
7921            int height = mBottom - mTop;
7922
7923            mRight = right;
7924
7925            onSizeChanged(mRight - mLeft, height, oldWidth, height);
7926
7927            if (!matrixIsIdentity) {
7928                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
7929                    // A change in dimension means an auto-centered pivot point changes, too
7930                    mTransformationInfo.mMatrixDirty = true;
7931                }
7932                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
7933                invalidate(true);
7934            }
7935            mBackgroundSizeChanged = true;
7936            invalidateParentIfNeeded();
7937        }
7938    }
7939
7940    /**
7941     * The visual x position of this view, in pixels. This is equivalent to the
7942     * {@link #setTranslationX(float) translationX} property plus the current
7943     * {@link #getLeft() left} property.
7944     *
7945     * @return The visual x position of this view, in pixels.
7946     */
7947    @ViewDebug.ExportedProperty(category = "drawing")
7948    public float getX() {
7949        return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
7950    }
7951
7952    /**
7953     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
7954     * {@link #setTranslationX(float) translationX} property to be the difference between
7955     * the x value passed in and the current {@link #getLeft() left} property.
7956     *
7957     * @param x The visual x position of this view, in pixels.
7958     */
7959    public void setX(float x) {
7960        setTranslationX(x - mLeft);
7961    }
7962
7963    /**
7964     * The visual y position of this view, in pixels. This is equivalent to the
7965     * {@link #setTranslationY(float) translationY} property plus the current
7966     * {@link #getTop() top} property.
7967     *
7968     * @return The visual y position of this view, in pixels.
7969     */
7970    @ViewDebug.ExportedProperty(category = "drawing")
7971    public float getY() {
7972        return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
7973    }
7974
7975    /**
7976     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
7977     * {@link #setTranslationY(float) translationY} property to be the difference between
7978     * the y value passed in and the current {@link #getTop() top} property.
7979     *
7980     * @param y The visual y position of this view, in pixels.
7981     */
7982    public void setY(float y) {
7983        setTranslationY(y - mTop);
7984    }
7985
7986
7987    /**
7988     * The horizontal location of this view relative to its {@link #getLeft() left} position.
7989     * This position is post-layout, in addition to wherever the object's
7990     * layout placed it.
7991     *
7992     * @return The horizontal position of this view relative to its left position, in pixels.
7993     */
7994    @ViewDebug.ExportedProperty(category = "drawing")
7995    public float getTranslationX() {
7996        return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
7997    }
7998
7999    /**
8000     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
8001     * This effectively positions the object post-layout, in addition to wherever the object's
8002     * layout placed it.
8003     *
8004     * @param translationX The horizontal position of this view relative to its left position,
8005     * in pixels.
8006     *
8007     * @attr ref android.R.styleable#View_translationX
8008     */
8009    public void setTranslationX(float translationX) {
8010        ensureTransformationInfo();
8011        final TransformationInfo info = mTransformationInfo;
8012        if (info.mTranslationX != translationX) {
8013            invalidateParentCaches();
8014            // Double-invalidation is necessary to capture view's old and new areas
8015            invalidate(false);
8016            info.mTranslationX = translationX;
8017            info.mMatrixDirty = true;
8018            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
8019            invalidate(false);
8020        }
8021    }
8022
8023    /**
8024     * The horizontal location of this view relative to its {@link #getTop() top} position.
8025     * This position is post-layout, in addition to wherever the object's
8026     * layout placed it.
8027     *
8028     * @return The vertical position of this view relative to its top position,
8029     * in pixels.
8030     */
8031    @ViewDebug.ExportedProperty(category = "drawing")
8032    public float getTranslationY() {
8033        return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
8034    }
8035
8036    /**
8037     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
8038     * This effectively positions the object post-layout, in addition to wherever the object's
8039     * layout placed it.
8040     *
8041     * @param translationY The vertical position of this view relative to its top position,
8042     * in pixels.
8043     *
8044     * @attr ref android.R.styleable#View_translationY
8045     */
8046    public void setTranslationY(float translationY) {
8047        ensureTransformationInfo();
8048        final TransformationInfo info = mTransformationInfo;
8049        if (info.mTranslationY != translationY) {
8050            invalidateParentCaches();
8051            // Double-invalidation is necessary to capture view's old and new areas
8052            invalidate(false);
8053            info.mTranslationY = translationY;
8054            info.mMatrixDirty = true;
8055            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
8056            invalidate(false);
8057        }
8058    }
8059
8060    /**
8061     * Hit rectangle in parent's coordinates
8062     *
8063     * @param outRect The hit rectangle of the view.
8064     */
8065    public void getHitRect(Rect outRect) {
8066        updateMatrix();
8067        final TransformationInfo info = mTransformationInfo;
8068        if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
8069            outRect.set(mLeft, mTop, mRight, mBottom);
8070        } else {
8071            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
8072            tmpRect.set(-info.mPivotX, -info.mPivotY,
8073                    getWidth() - info.mPivotX, getHeight() - info.mPivotY);
8074            info.mMatrix.mapRect(tmpRect);
8075            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
8076                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
8077        }
8078    }
8079
8080    /**
8081     * Determines whether the given point, in local coordinates is inside the view.
8082     */
8083    /*package*/ final boolean pointInView(float localX, float localY) {
8084        return localX >= 0 && localX < (mRight - mLeft)
8085                && localY >= 0 && localY < (mBottom - mTop);
8086    }
8087
8088    /**
8089     * Utility method to determine whether the given point, in local coordinates,
8090     * is inside the view, where the area of the view is expanded by the slop factor.
8091     * This method is called while processing touch-move events to determine if the event
8092     * is still within the view.
8093     */
8094    private boolean pointInView(float localX, float localY, float slop) {
8095        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
8096                localY < ((mBottom - mTop) + slop);
8097    }
8098
8099    /**
8100     * When a view has focus and the user navigates away from it, the next view is searched for
8101     * starting from the rectangle filled in by this method.
8102     *
8103     * By default, the rectange is the {@link #getDrawingRect(android.graphics.Rect)})
8104     * of the view.  However, if your view maintains some idea of internal selection,
8105     * such as a cursor, or a selected row or column, you should override this method and
8106     * fill in a more specific rectangle.
8107     *
8108     * @param r The rectangle to fill in, in this view's coordinates.
8109     */
8110    public void getFocusedRect(Rect r) {
8111        getDrawingRect(r);
8112    }
8113
8114    /**
8115     * If some part of this view is not clipped by any of its parents, then
8116     * return that area in r in global (root) coordinates. To convert r to local
8117     * coordinates (without taking possible View rotations into account), offset
8118     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
8119     * If the view is completely clipped or translated out, return false.
8120     *
8121     * @param r If true is returned, r holds the global coordinates of the
8122     *        visible portion of this view.
8123     * @param globalOffset If true is returned, globalOffset holds the dx,dy
8124     *        between this view and its root. globalOffet may be null.
8125     * @return true if r is non-empty (i.e. part of the view is visible at the
8126     *         root level.
8127     */
8128    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
8129        int width = mRight - mLeft;
8130        int height = mBottom - mTop;
8131        if (width > 0 && height > 0) {
8132            r.set(0, 0, width, height);
8133            if (globalOffset != null) {
8134                globalOffset.set(-mScrollX, -mScrollY);
8135            }
8136            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
8137        }
8138        return false;
8139    }
8140
8141    public final boolean getGlobalVisibleRect(Rect r) {
8142        return getGlobalVisibleRect(r, null);
8143    }
8144
8145    public final boolean getLocalVisibleRect(Rect r) {
8146        Point offset = new Point();
8147        if (getGlobalVisibleRect(r, offset)) {
8148            r.offset(-offset.x, -offset.y); // make r local
8149            return true;
8150        }
8151        return false;
8152    }
8153
8154    /**
8155     * Offset this view's vertical location by the specified number of pixels.
8156     *
8157     * @param offset the number of pixels to offset the view by
8158     */
8159    public void offsetTopAndBottom(int offset) {
8160        if (offset != 0) {
8161            updateMatrix();
8162            final boolean matrixIsIdentity = mTransformationInfo == null
8163                    || mTransformationInfo.mMatrixIsIdentity;
8164            if (matrixIsIdentity) {
8165                final ViewParent p = mParent;
8166                if (p != null && mAttachInfo != null) {
8167                    final Rect r = mAttachInfo.mTmpInvalRect;
8168                    int minTop;
8169                    int maxBottom;
8170                    int yLoc;
8171                    if (offset < 0) {
8172                        minTop = mTop + offset;
8173                        maxBottom = mBottom;
8174                        yLoc = offset;
8175                    } else {
8176                        minTop = mTop;
8177                        maxBottom = mBottom + offset;
8178                        yLoc = 0;
8179                    }
8180                    r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
8181                    p.invalidateChild(this, r);
8182                }
8183            } else {
8184                invalidate(false);
8185            }
8186
8187            mTop += offset;
8188            mBottom += offset;
8189
8190            if (!matrixIsIdentity) {
8191                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
8192                invalidate(false);
8193            }
8194            invalidateParentIfNeeded();
8195        }
8196    }
8197
8198    /**
8199     * Offset this view's horizontal location by the specified amount of pixels.
8200     *
8201     * @param offset the numer of pixels to offset the view by
8202     */
8203    public void offsetLeftAndRight(int offset) {
8204        if (offset != 0) {
8205            updateMatrix();
8206            final boolean matrixIsIdentity = mTransformationInfo == null
8207                    || mTransformationInfo.mMatrixIsIdentity;
8208            if (matrixIsIdentity) {
8209                final ViewParent p = mParent;
8210                if (p != null && mAttachInfo != null) {
8211                    final Rect r = mAttachInfo.mTmpInvalRect;
8212                    int minLeft;
8213                    int maxRight;
8214                    if (offset < 0) {
8215                        minLeft = mLeft + offset;
8216                        maxRight = mRight;
8217                    } else {
8218                        minLeft = mLeft;
8219                        maxRight = mRight + offset;
8220                    }
8221                    r.set(0, 0, maxRight - minLeft, mBottom - mTop);
8222                    p.invalidateChild(this, r);
8223                }
8224            } else {
8225                invalidate(false);
8226            }
8227
8228            mLeft += offset;
8229            mRight += offset;
8230
8231            if (!matrixIsIdentity) {
8232                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
8233                invalidate(false);
8234            }
8235            invalidateParentIfNeeded();
8236        }
8237    }
8238
8239    /**
8240     * Get the LayoutParams associated with this view. All views should have
8241     * layout parameters. These supply parameters to the <i>parent</i> of this
8242     * view specifying how it should be arranged. There are many subclasses of
8243     * ViewGroup.LayoutParams, and these correspond to the different subclasses
8244     * of ViewGroup that are responsible for arranging their children.
8245     *
8246     * This method may return null if this View is not attached to a parent
8247     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
8248     * was not invoked successfully. When a View is attached to a parent
8249     * ViewGroup, this method must not return null.
8250     *
8251     * @return The LayoutParams associated with this view, or null if no
8252     *         parameters have been set yet
8253     */
8254    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
8255    public ViewGroup.LayoutParams getLayoutParams() {
8256        return mLayoutParams;
8257    }
8258
8259    /**
8260     * Set the layout parameters associated with this view. These supply
8261     * parameters to the <i>parent</i> of this view specifying how it should be
8262     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
8263     * correspond to the different subclasses of ViewGroup that are responsible
8264     * for arranging their children.
8265     *
8266     * @param params The layout parameters for this view, cannot be null
8267     */
8268    public void setLayoutParams(ViewGroup.LayoutParams params) {
8269        if (params == null) {
8270            throw new NullPointerException("Layout parameters cannot be null");
8271        }
8272        mLayoutParams = params;
8273        if (mParent instanceof ViewGroup) {
8274            ((ViewGroup) mParent).onSetLayoutParams(this, params);
8275        }
8276        requestLayout();
8277    }
8278
8279    /**
8280     * Set the scrolled position of your view. This will cause a call to
8281     * {@link #onScrollChanged(int, int, int, int)} and the view will be
8282     * invalidated.
8283     * @param x the x position to scroll to
8284     * @param y the y position to scroll to
8285     */
8286    public void scrollTo(int x, int y) {
8287        if (mScrollX != x || mScrollY != y) {
8288            int oldX = mScrollX;
8289            int oldY = mScrollY;
8290            mScrollX = x;
8291            mScrollY = y;
8292            invalidateParentCaches();
8293            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
8294            if (!awakenScrollBars()) {
8295                invalidate(true);
8296            }
8297        }
8298    }
8299
8300    /**
8301     * Move the scrolled position of your view. This will cause a call to
8302     * {@link #onScrollChanged(int, int, int, int)} and the view will be
8303     * invalidated.
8304     * @param x the amount of pixels to scroll by horizontally
8305     * @param y the amount of pixels to scroll by vertically
8306     */
8307    public void scrollBy(int x, int y) {
8308        scrollTo(mScrollX + x, mScrollY + y);
8309    }
8310
8311    /**
8312     * <p>Trigger the scrollbars to draw. When invoked this method starts an
8313     * animation to fade the scrollbars out after a default delay. If a subclass
8314     * provides animated scrolling, the start delay should equal the duration
8315     * of the scrolling animation.</p>
8316     *
8317     * <p>The animation starts only if at least one of the scrollbars is
8318     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
8319     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
8320     * this method returns true, and false otherwise. If the animation is
8321     * started, this method calls {@link #invalidate()}; in that case the
8322     * caller should not call {@link #invalidate()}.</p>
8323     *
8324     * <p>This method should be invoked every time a subclass directly updates
8325     * the scroll parameters.</p>
8326     *
8327     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
8328     * and {@link #scrollTo(int, int)}.</p>
8329     *
8330     * @return true if the animation is played, false otherwise
8331     *
8332     * @see #awakenScrollBars(int)
8333     * @see #scrollBy(int, int)
8334     * @see #scrollTo(int, int)
8335     * @see #isHorizontalScrollBarEnabled()
8336     * @see #isVerticalScrollBarEnabled()
8337     * @see #setHorizontalScrollBarEnabled(boolean)
8338     * @see #setVerticalScrollBarEnabled(boolean)
8339     */
8340    protected boolean awakenScrollBars() {
8341        return mScrollCache != null &&
8342                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
8343    }
8344
8345    /**
8346     * Trigger the scrollbars to draw.
8347     * This method differs from awakenScrollBars() only in its default duration.
8348     * initialAwakenScrollBars() will show the scroll bars for longer than
8349     * usual to give the user more of a chance to notice them.
8350     *
8351     * @return true if the animation is played, false otherwise.
8352     */
8353    private boolean initialAwakenScrollBars() {
8354        return mScrollCache != null &&
8355                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
8356    }
8357
8358    /**
8359     * <p>
8360     * Trigger the scrollbars to draw. When invoked this method starts an
8361     * animation to fade the scrollbars out after a fixed delay. If a subclass
8362     * provides animated scrolling, the start delay should equal the duration of
8363     * the scrolling animation.
8364     * </p>
8365     *
8366     * <p>
8367     * The animation starts only if at least one of the scrollbars is enabled,
8368     * as specified by {@link #isHorizontalScrollBarEnabled()} and
8369     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
8370     * this method returns true, and false otherwise. If the animation is
8371     * started, this method calls {@link #invalidate()}; in that case the caller
8372     * should not call {@link #invalidate()}.
8373     * </p>
8374     *
8375     * <p>
8376     * This method should be invoked everytime a subclass directly updates the
8377     * scroll parameters.
8378     * </p>
8379     *
8380     * @param startDelay the delay, in milliseconds, after which the animation
8381     *        should start; when the delay is 0, the animation starts
8382     *        immediately
8383     * @return true if the animation is played, false otherwise
8384     *
8385     * @see #scrollBy(int, int)
8386     * @see #scrollTo(int, int)
8387     * @see #isHorizontalScrollBarEnabled()
8388     * @see #isVerticalScrollBarEnabled()
8389     * @see #setHorizontalScrollBarEnabled(boolean)
8390     * @see #setVerticalScrollBarEnabled(boolean)
8391     */
8392    protected boolean awakenScrollBars(int startDelay) {
8393        return awakenScrollBars(startDelay, true);
8394    }
8395
8396    /**
8397     * <p>
8398     * Trigger the scrollbars to draw. When invoked this method starts an
8399     * animation to fade the scrollbars out after a fixed delay. If a subclass
8400     * provides animated scrolling, the start delay should equal the duration of
8401     * the scrolling animation.
8402     * </p>
8403     *
8404     * <p>
8405     * The animation starts only if at least one of the scrollbars is enabled,
8406     * as specified by {@link #isHorizontalScrollBarEnabled()} and
8407     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
8408     * this method returns true, and false otherwise. If the animation is
8409     * started, this method calls {@link #invalidate()} if the invalidate parameter
8410     * is set to true; in that case the caller
8411     * should not call {@link #invalidate()}.
8412     * </p>
8413     *
8414     * <p>
8415     * This method should be invoked everytime a subclass directly updates the
8416     * scroll parameters.
8417     * </p>
8418     *
8419     * @param startDelay the delay, in milliseconds, after which the animation
8420     *        should start; when the delay is 0, the animation starts
8421     *        immediately
8422     *
8423     * @param invalidate Wheter this method should call invalidate
8424     *
8425     * @return true if the animation is played, false otherwise
8426     *
8427     * @see #scrollBy(int, int)
8428     * @see #scrollTo(int, int)
8429     * @see #isHorizontalScrollBarEnabled()
8430     * @see #isVerticalScrollBarEnabled()
8431     * @see #setHorizontalScrollBarEnabled(boolean)
8432     * @see #setVerticalScrollBarEnabled(boolean)
8433     */
8434    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
8435        final ScrollabilityCache scrollCache = mScrollCache;
8436
8437        if (scrollCache == null || !scrollCache.fadeScrollBars) {
8438            return false;
8439        }
8440
8441        if (scrollCache.scrollBar == null) {
8442            scrollCache.scrollBar = new ScrollBarDrawable();
8443        }
8444
8445        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
8446
8447            if (invalidate) {
8448                // Invalidate to show the scrollbars
8449                invalidate(true);
8450            }
8451
8452            if (scrollCache.state == ScrollabilityCache.OFF) {
8453                // FIXME: this is copied from WindowManagerService.
8454                // We should get this value from the system when it
8455                // is possible to do so.
8456                final int KEY_REPEAT_FIRST_DELAY = 750;
8457                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
8458            }
8459
8460            // Tell mScrollCache when we should start fading. This may
8461            // extend the fade start time if one was already scheduled
8462            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
8463            scrollCache.fadeStartTime = fadeStartTime;
8464            scrollCache.state = ScrollabilityCache.ON;
8465
8466            // Schedule our fader to run, unscheduling any old ones first
8467            if (mAttachInfo != null) {
8468                mAttachInfo.mHandler.removeCallbacks(scrollCache);
8469                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
8470            }
8471
8472            return true;
8473        }
8474
8475        return false;
8476    }
8477
8478    /**
8479     * Do not invalidate views which are not visible and which are not running an animation. They
8480     * will not get drawn and they should not set dirty flags as if they will be drawn
8481     */
8482    private boolean skipInvalidate() {
8483        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
8484                (!(mParent instanceof ViewGroup) ||
8485                        !((ViewGroup) mParent).isViewTransitioning(this));
8486    }
8487    /**
8488     * Mark the area defined by dirty as needing to be drawn. If the view is
8489     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
8490     * in the future. This must be called from a UI thread. To call from a non-UI
8491     * thread, call {@link #postInvalidate()}.
8492     *
8493     * WARNING: This method is destructive to dirty.
8494     * @param dirty the rectangle representing the bounds of the dirty region
8495     */
8496    public void invalidate(Rect dirty) {
8497        if (ViewDebug.TRACE_HIERARCHY) {
8498            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
8499        }
8500
8501        if (skipInvalidate()) {
8502            return;
8503        }
8504        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8505                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
8506                (mPrivateFlags & INVALIDATED) != INVALIDATED) {
8507            mPrivateFlags &= ~DRAWING_CACHE_VALID;
8508            mPrivateFlags |= INVALIDATED;
8509            mPrivateFlags |= DIRTY;
8510            final ViewParent p = mParent;
8511            final AttachInfo ai = mAttachInfo;
8512            //noinspection PointlessBooleanExpression,ConstantConditions
8513            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
8514                if (p != null && ai != null && ai.mHardwareAccelerated) {
8515                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
8516                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
8517                    p.invalidateChild(this, null);
8518                    return;
8519                }
8520            }
8521            if (p != null && ai != null) {
8522                final int scrollX = mScrollX;
8523                final int scrollY = mScrollY;
8524                final Rect r = ai.mTmpInvalRect;
8525                r.set(dirty.left - scrollX, dirty.top - scrollY,
8526                        dirty.right - scrollX, dirty.bottom - scrollY);
8527                mParent.invalidateChild(this, r);
8528            }
8529        }
8530    }
8531
8532    /**
8533     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn.
8534     * The coordinates of the dirty rect are relative to the view.
8535     * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
8536     * will be called at some point in the future. This must be called from
8537     * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
8538     * @param l the left position of the dirty region
8539     * @param t the top position of the dirty region
8540     * @param r the right position of the dirty region
8541     * @param b the bottom position of the dirty region
8542     */
8543    public void invalidate(int l, int t, int r, int b) {
8544        if (ViewDebug.TRACE_HIERARCHY) {
8545            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
8546        }
8547
8548        if (skipInvalidate()) {
8549            return;
8550        }
8551        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8552                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
8553                (mPrivateFlags & INVALIDATED) != INVALIDATED) {
8554            mPrivateFlags &= ~DRAWING_CACHE_VALID;
8555            mPrivateFlags |= INVALIDATED;
8556            mPrivateFlags |= DIRTY;
8557            final ViewParent p = mParent;
8558            final AttachInfo ai = mAttachInfo;
8559            //noinspection PointlessBooleanExpression,ConstantConditions
8560            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
8561                if (p != null && ai != null && ai.mHardwareAccelerated) {
8562                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
8563                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
8564                    p.invalidateChild(this, null);
8565                    return;
8566                }
8567            }
8568            if (p != null && ai != null && l < r && t < b) {
8569                final int scrollX = mScrollX;
8570                final int scrollY = mScrollY;
8571                final Rect tmpr = ai.mTmpInvalRect;
8572                tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
8573                p.invalidateChild(this, tmpr);
8574            }
8575        }
8576    }
8577
8578    /**
8579     * Invalidate the whole view. If the view is visible,
8580     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
8581     * the future. This must be called from a UI thread. To call from a non-UI thread,
8582     * call {@link #postInvalidate()}.
8583     */
8584    public void invalidate() {
8585        invalidate(true);
8586    }
8587
8588    /**
8589     * This is where the invalidate() work actually happens. A full invalidate()
8590     * causes the drawing cache to be invalidated, but this function can be called with
8591     * invalidateCache set to false to skip that invalidation step for cases that do not
8592     * need it (for example, a component that remains at the same dimensions with the same
8593     * content).
8594     *
8595     * @param invalidateCache Whether the drawing cache for this view should be invalidated as
8596     * well. This is usually true for a full invalidate, but may be set to false if the
8597     * View's contents or dimensions have not changed.
8598     */
8599    void invalidate(boolean invalidateCache) {
8600        if (ViewDebug.TRACE_HIERARCHY) {
8601            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);
8602        }
8603
8604        if (skipInvalidate()) {
8605            return;
8606        }
8607        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
8608                (invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||
8609                (mPrivateFlags & INVALIDATED) != INVALIDATED || isOpaque() != mLastIsOpaque) {
8610            mLastIsOpaque = isOpaque();
8611            mPrivateFlags &= ~DRAWN;
8612            mPrivateFlags |= DIRTY;
8613            if (invalidateCache) {
8614                mPrivateFlags |= INVALIDATED;
8615                mPrivateFlags &= ~DRAWING_CACHE_VALID;
8616            }
8617            final AttachInfo ai = mAttachInfo;
8618            final ViewParent p = mParent;
8619            //noinspection PointlessBooleanExpression,ConstantConditions
8620            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
8621                if (p != null && ai != null && ai.mHardwareAccelerated) {
8622                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
8623                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
8624                    p.invalidateChild(this, null);
8625                    return;
8626                }
8627            }
8628
8629            if (p != null && ai != null) {
8630                final Rect r = ai.mTmpInvalRect;
8631                r.set(0, 0, mRight - mLeft, mBottom - mTop);
8632                // Don't call invalidate -- we don't want to internally scroll
8633                // our own bounds
8634                p.invalidateChild(this, r);
8635            }
8636        }
8637    }
8638
8639    /**
8640     * Used to indicate that the parent of this view should clear its caches. This functionality
8641     * is used to force the parent to rebuild its display list (when hardware-accelerated),
8642     * which is necessary when various parent-managed properties of the view change, such as
8643     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
8644     * clears the parent caches and does not causes an invalidate event.
8645     *
8646     * @hide
8647     */
8648    protected void invalidateParentCaches() {
8649        if (mParent instanceof View) {
8650            ((View) mParent).mPrivateFlags |= INVALIDATED;
8651        }
8652    }
8653
8654    /**
8655     * Used to indicate that the parent of this view should be invalidated. This functionality
8656     * is used to force the parent to rebuild its display list (when hardware-accelerated),
8657     * which is necessary when various parent-managed properties of the view change, such as
8658     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
8659     * an invalidation event to the parent.
8660     *
8661     * @hide
8662     */
8663    protected void invalidateParentIfNeeded() {
8664        if (isHardwareAccelerated() && mParent instanceof View) {
8665            ((View) mParent).invalidate(true);
8666        }
8667    }
8668
8669    /**
8670     * Indicates whether this View is opaque. An opaque View guarantees that it will
8671     * draw all the pixels overlapping its bounds using a fully opaque color.
8672     *
8673     * Subclasses of View should override this method whenever possible to indicate
8674     * whether an instance is opaque. Opaque Views are treated in a special way by
8675     * the View hierarchy, possibly allowing it to perform optimizations during
8676     * invalidate/draw passes.
8677     *
8678     * @return True if this View is guaranteed to be fully opaque, false otherwise.
8679     */
8680    @ViewDebug.ExportedProperty(category = "drawing")
8681    public boolean isOpaque() {
8682        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK &&
8683                ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1)
8684                        >= 1.0f - ViewConfiguration.ALPHA_THRESHOLD);
8685    }
8686
8687    /**
8688     * @hide
8689     */
8690    protected void computeOpaqueFlags() {
8691        // Opaque if:
8692        //   - Has a background
8693        //   - Background is opaque
8694        //   - Doesn't have scrollbars or scrollbars are inside overlay
8695
8696        if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
8697            mPrivateFlags |= OPAQUE_BACKGROUND;
8698        } else {
8699            mPrivateFlags &= ~OPAQUE_BACKGROUND;
8700        }
8701
8702        final int flags = mViewFlags;
8703        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
8704                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
8705            mPrivateFlags |= OPAQUE_SCROLLBARS;
8706        } else {
8707            mPrivateFlags &= ~OPAQUE_SCROLLBARS;
8708        }
8709    }
8710
8711    /**
8712     * @hide
8713     */
8714    protected boolean hasOpaqueScrollbars() {
8715        return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
8716    }
8717
8718    /**
8719     * @return A handler associated with the thread running the View. This
8720     * handler can be used to pump events in the UI events queue.
8721     */
8722    public Handler getHandler() {
8723        if (mAttachInfo != null) {
8724            return mAttachInfo.mHandler;
8725        }
8726        return null;
8727    }
8728
8729    /**
8730     * Gets the view root associated with the View.
8731     * @return The view root, or null if none.
8732     * @hide
8733     */
8734    public ViewRootImpl getViewRootImpl() {
8735        if (mAttachInfo != null) {
8736            return mAttachInfo.mViewRootImpl;
8737        }
8738        return null;
8739    }
8740
8741    /**
8742     * <p>Causes the Runnable to be added to the message queue.
8743     * The runnable will be run on the user interface thread.</p>
8744     *
8745     * <p>This method can be invoked from outside of the UI thread
8746     * only when this View is attached to a window.</p>
8747     *
8748     * @param action The Runnable that will be executed.
8749     *
8750     * @return Returns true if the Runnable was successfully placed in to the
8751     *         message queue.  Returns false on failure, usually because the
8752     *         looper processing the message queue is exiting.
8753     */
8754    public boolean post(Runnable action) {
8755        final AttachInfo attachInfo = mAttachInfo;
8756        if (attachInfo != null) {
8757            return attachInfo.mHandler.post(action);
8758        }
8759        // Assume that post will succeed later
8760        ViewRootImpl.getRunQueue().post(action);
8761        return true;
8762    }
8763
8764    /**
8765     * <p>Causes the Runnable to be added to the message queue, to be run
8766     * after the specified amount of time elapses.
8767     * The runnable will be run on the user interface thread.</p>
8768     *
8769     * <p>This method can be invoked from outside of the UI thread
8770     * only when this View is attached to a window.</p>
8771     *
8772     * @param action The Runnable that will be executed.
8773     * @param delayMillis The delay (in milliseconds) until the Runnable
8774     *        will be executed.
8775     *
8776     * @return true if the Runnable was successfully placed in to the
8777     *         message queue.  Returns false on failure, usually because the
8778     *         looper processing the message queue is exiting.  Note that a
8779     *         result of true does not mean the Runnable will be processed --
8780     *         if the looper is quit before the delivery time of the message
8781     *         occurs then the message will be dropped.
8782     */
8783    public boolean postDelayed(Runnable action, long delayMillis) {
8784        final AttachInfo attachInfo = mAttachInfo;
8785        if (attachInfo != null) {
8786            return attachInfo.mHandler.postDelayed(action, delayMillis);
8787        }
8788        // Assume that post will succeed later
8789        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
8790        return true;
8791    }
8792
8793    /**
8794     * <p>Removes the specified Runnable from the message queue.</p>
8795     *
8796     * <p>This method can be invoked from outside of the UI thread
8797     * only when this View is attached to a window.</p>
8798     *
8799     * @param action The Runnable to remove from the message handling queue
8800     *
8801     * @return true if this view could ask the Handler to remove the Runnable,
8802     *         false otherwise. When the returned value is true, the Runnable
8803     *         may or may not have been actually removed from the message queue
8804     *         (for instance, if the Runnable was not in the queue already.)
8805     */
8806    public boolean removeCallbacks(Runnable action) {
8807        final AttachInfo attachInfo = mAttachInfo;
8808        if (attachInfo != null) {
8809            attachInfo.mHandler.removeCallbacks(action);
8810        } else {
8811            // Assume that post will succeed later
8812            ViewRootImpl.getRunQueue().removeCallbacks(action);
8813        }
8814        return true;
8815    }
8816
8817    /**
8818     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
8819     * Use this to invalidate the View from a non-UI thread.</p>
8820     *
8821     * <p>This method can be invoked from outside of the UI thread
8822     * only when this View is attached to a window.</p>
8823     *
8824     * @see #invalidate()
8825     */
8826    public void postInvalidate() {
8827        postInvalidateDelayed(0);
8828    }
8829
8830    /**
8831     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
8832     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
8833     *
8834     * <p>This method can be invoked from outside of the UI thread
8835     * only when this View is attached to a window.</p>
8836     *
8837     * @param left The left coordinate of the rectangle to invalidate.
8838     * @param top The top coordinate of the rectangle to invalidate.
8839     * @param right The right coordinate of the rectangle to invalidate.
8840     * @param bottom The bottom coordinate of the rectangle to invalidate.
8841     *
8842     * @see #invalidate(int, int, int, int)
8843     * @see #invalidate(Rect)
8844     */
8845    public void postInvalidate(int left, int top, int right, int bottom) {
8846        postInvalidateDelayed(0, left, top, right, bottom);
8847    }
8848
8849    /**
8850     * <p>Cause an invalidate to happen on a subsequent cycle through the event
8851     * loop. Waits for the specified amount of time.</p>
8852     *
8853     * <p>This method can be invoked from outside of the UI thread
8854     * only when this View is attached to a window.</p>
8855     *
8856     * @param delayMilliseconds the duration in milliseconds to delay the
8857     *         invalidation by
8858     */
8859    public void postInvalidateDelayed(long delayMilliseconds) {
8860        // We try only with the AttachInfo because there's no point in invalidating
8861        // if we are not attached to our window
8862        final AttachInfo attachInfo = mAttachInfo;
8863        if (attachInfo != null) {
8864            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
8865        }
8866    }
8867
8868    /**
8869     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
8870     * through the event loop. Waits for the specified amount of time.</p>
8871     *
8872     * <p>This method can be invoked from outside of the UI thread
8873     * only when this View is attached to a window.</p>
8874     *
8875     * @param delayMilliseconds the duration in milliseconds to delay the
8876     *         invalidation by
8877     * @param left The left coordinate of the rectangle to invalidate.
8878     * @param top The top coordinate of the rectangle to invalidate.
8879     * @param right The right coordinate of the rectangle to invalidate.
8880     * @param bottom The bottom coordinate of the rectangle to invalidate.
8881     */
8882    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
8883            int right, int bottom) {
8884
8885        // We try only with the AttachInfo because there's no point in invalidating
8886        // if we are not attached to our window
8887        final AttachInfo attachInfo = mAttachInfo;
8888        if (attachInfo != null) {
8889            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
8890            info.target = this;
8891            info.left = left;
8892            info.top = top;
8893            info.right = right;
8894            info.bottom = bottom;
8895
8896            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
8897        }
8898    }
8899
8900    /**
8901     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
8902     * This event is sent at most once every
8903     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
8904     */
8905    private void postSendViewScrolledAccessibilityEventCallback() {
8906        if (mSendViewScrolledAccessibilityEvent == null) {
8907            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
8908        }
8909        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
8910            mSendViewScrolledAccessibilityEvent.mIsPending = true;
8911            postDelayed(mSendViewScrolledAccessibilityEvent,
8912                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
8913        }
8914    }
8915
8916    /**
8917     * Called by a parent to request that a child update its values for mScrollX
8918     * and mScrollY if necessary. This will typically be done if the child is
8919     * animating a scroll using a {@link android.widget.Scroller Scroller}
8920     * object.
8921     */
8922    public void computeScroll() {
8923    }
8924
8925    /**
8926     * <p>Indicate whether the horizontal edges are faded when the view is
8927     * scrolled horizontally.</p>
8928     *
8929     * @return true if the horizontal edges should are faded on scroll, false
8930     *         otherwise
8931     *
8932     * @see #setHorizontalFadingEdgeEnabled(boolean)
8933     * @attr ref android.R.styleable#View_requiresFadingEdge
8934     */
8935    public boolean isHorizontalFadingEdgeEnabled() {
8936        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
8937    }
8938
8939    /**
8940     * <p>Define whether the horizontal edges should be faded when this view
8941     * is scrolled horizontally.</p>
8942     *
8943     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
8944     *                                    be faded when the view is scrolled
8945     *                                    horizontally
8946     *
8947     * @see #isHorizontalFadingEdgeEnabled()
8948     * @attr ref android.R.styleable#View_requiresFadingEdge
8949     */
8950    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
8951        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
8952            if (horizontalFadingEdgeEnabled) {
8953                initScrollCache();
8954            }
8955
8956            mViewFlags ^= FADING_EDGE_HORIZONTAL;
8957        }
8958    }
8959
8960    /**
8961     * <p>Indicate whether the vertical edges are faded when the view is
8962     * scrolled horizontally.</p>
8963     *
8964     * @return true if the vertical edges should are faded on scroll, false
8965     *         otherwise
8966     *
8967     * @see #setVerticalFadingEdgeEnabled(boolean)
8968     * @attr ref android.R.styleable#View_requiresFadingEdge
8969     */
8970    public boolean isVerticalFadingEdgeEnabled() {
8971        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
8972    }
8973
8974    /**
8975     * <p>Define whether the vertical edges should be faded when this view
8976     * is scrolled vertically.</p>
8977     *
8978     * @param verticalFadingEdgeEnabled true if the vertical edges should
8979     *                                  be faded when the view is scrolled
8980     *                                  vertically
8981     *
8982     * @see #isVerticalFadingEdgeEnabled()
8983     * @attr ref android.R.styleable#View_requiresFadingEdge
8984     */
8985    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
8986        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
8987            if (verticalFadingEdgeEnabled) {
8988                initScrollCache();
8989            }
8990
8991            mViewFlags ^= FADING_EDGE_VERTICAL;
8992        }
8993    }
8994
8995    /**
8996     * Returns the strength, or intensity, of the top faded edge. The strength is
8997     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
8998     * returns 0.0 or 1.0 but no value in between.
8999     *
9000     * Subclasses should override this method to provide a smoother fade transition
9001     * when scrolling occurs.
9002     *
9003     * @return the intensity of the top fade as a float between 0.0f and 1.0f
9004     */
9005    protected float getTopFadingEdgeStrength() {
9006        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
9007    }
9008
9009    /**
9010     * Returns the strength, or intensity, of the bottom faded edge. The strength is
9011     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
9012     * returns 0.0 or 1.0 but no value in between.
9013     *
9014     * Subclasses should override this method to provide a smoother fade transition
9015     * when scrolling occurs.
9016     *
9017     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
9018     */
9019    protected float getBottomFadingEdgeStrength() {
9020        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
9021                computeVerticalScrollRange() ? 1.0f : 0.0f;
9022    }
9023
9024    /**
9025     * Returns the strength, or intensity, of the left faded edge. The strength is
9026     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
9027     * returns 0.0 or 1.0 but no value in between.
9028     *
9029     * Subclasses should override this method to provide a smoother fade transition
9030     * when scrolling occurs.
9031     *
9032     * @return the intensity of the left fade as a float between 0.0f and 1.0f
9033     */
9034    protected float getLeftFadingEdgeStrength() {
9035        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
9036    }
9037
9038    /**
9039     * Returns the strength, or intensity, of the right faded edge. The strength is
9040     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
9041     * returns 0.0 or 1.0 but no value in between.
9042     *
9043     * Subclasses should override this method to provide a smoother fade transition
9044     * when scrolling occurs.
9045     *
9046     * @return the intensity of the right fade as a float between 0.0f and 1.0f
9047     */
9048    protected float getRightFadingEdgeStrength() {
9049        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
9050                computeHorizontalScrollRange() ? 1.0f : 0.0f;
9051    }
9052
9053    /**
9054     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
9055     * scrollbar is not drawn by default.</p>
9056     *
9057     * @return true if the horizontal scrollbar should be painted, false
9058     *         otherwise
9059     *
9060     * @see #setHorizontalScrollBarEnabled(boolean)
9061     */
9062    public boolean isHorizontalScrollBarEnabled() {
9063        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
9064    }
9065
9066    /**
9067     * <p>Define whether the horizontal scrollbar should be drawn or not. The
9068     * scrollbar is not drawn by default.</p>
9069     *
9070     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
9071     *                                   be painted
9072     *
9073     * @see #isHorizontalScrollBarEnabled()
9074     */
9075    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
9076        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
9077            mViewFlags ^= SCROLLBARS_HORIZONTAL;
9078            computeOpaqueFlags();
9079            resolvePadding();
9080        }
9081    }
9082
9083    /**
9084     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
9085     * scrollbar is not drawn by default.</p>
9086     *
9087     * @return true if the vertical scrollbar should be painted, false
9088     *         otherwise
9089     *
9090     * @see #setVerticalScrollBarEnabled(boolean)
9091     */
9092    public boolean isVerticalScrollBarEnabled() {
9093        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
9094    }
9095
9096    /**
9097     * <p>Define whether the vertical scrollbar should be drawn or not. The
9098     * scrollbar is not drawn by default.</p>
9099     *
9100     * @param verticalScrollBarEnabled true if the vertical scrollbar should
9101     *                                 be painted
9102     *
9103     * @see #isVerticalScrollBarEnabled()
9104     */
9105    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
9106        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
9107            mViewFlags ^= SCROLLBARS_VERTICAL;
9108            computeOpaqueFlags();
9109            resolvePadding();
9110        }
9111    }
9112
9113    /**
9114     * @hide
9115     */
9116    protected void recomputePadding() {
9117        setPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
9118    }
9119
9120    /**
9121     * Define whether scrollbars will fade when the view is not scrolling.
9122     *
9123     * @param fadeScrollbars wheter to enable fading
9124     *
9125     */
9126    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
9127        initScrollCache();
9128        final ScrollabilityCache scrollabilityCache = mScrollCache;
9129        scrollabilityCache.fadeScrollBars = fadeScrollbars;
9130        if (fadeScrollbars) {
9131            scrollabilityCache.state = ScrollabilityCache.OFF;
9132        } else {
9133            scrollabilityCache.state = ScrollabilityCache.ON;
9134        }
9135    }
9136
9137    /**
9138     *
9139     * Returns true if scrollbars will fade when this view is not scrolling
9140     *
9141     * @return true if scrollbar fading is enabled
9142     */
9143    public boolean isScrollbarFadingEnabled() {
9144        return mScrollCache != null && mScrollCache.fadeScrollBars;
9145    }
9146
9147    /**
9148     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
9149     * inset. When inset, they add to the padding of the view. And the scrollbars
9150     * can be drawn inside the padding area or on the edge of the view. For example,
9151     * if a view has a background drawable and you want to draw the scrollbars
9152     * inside the padding specified by the drawable, you can use
9153     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
9154     * appear at the edge of the view, ignoring the padding, then you can use
9155     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
9156     * @param style the style of the scrollbars. Should be one of
9157     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
9158     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
9159     * @see #SCROLLBARS_INSIDE_OVERLAY
9160     * @see #SCROLLBARS_INSIDE_INSET
9161     * @see #SCROLLBARS_OUTSIDE_OVERLAY
9162     * @see #SCROLLBARS_OUTSIDE_INSET
9163     */
9164    public void setScrollBarStyle(int style) {
9165        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
9166            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
9167            computeOpaqueFlags();
9168            resolvePadding();
9169        }
9170    }
9171
9172    /**
9173     * <p>Returns the current scrollbar style.</p>
9174     * @return the current scrollbar style
9175     * @see #SCROLLBARS_INSIDE_OVERLAY
9176     * @see #SCROLLBARS_INSIDE_INSET
9177     * @see #SCROLLBARS_OUTSIDE_OVERLAY
9178     * @see #SCROLLBARS_OUTSIDE_INSET
9179     */
9180    @ViewDebug.ExportedProperty(mapping = {
9181            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
9182            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
9183            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
9184            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
9185    })
9186    public int getScrollBarStyle() {
9187        return mViewFlags & SCROLLBARS_STYLE_MASK;
9188    }
9189
9190    /**
9191     * <p>Compute the horizontal range that the horizontal scrollbar
9192     * represents.</p>
9193     *
9194     * <p>The range is expressed in arbitrary units that must be the same as the
9195     * units used by {@link #computeHorizontalScrollExtent()} and
9196     * {@link #computeHorizontalScrollOffset()}.</p>
9197     *
9198     * <p>The default range is the drawing width of this view.</p>
9199     *
9200     * @return the total horizontal range represented by the horizontal
9201     *         scrollbar
9202     *
9203     * @see #computeHorizontalScrollExtent()
9204     * @see #computeHorizontalScrollOffset()
9205     * @see android.widget.ScrollBarDrawable
9206     */
9207    protected int computeHorizontalScrollRange() {
9208        return getWidth();
9209    }
9210
9211    /**
9212     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
9213     * within the horizontal range. This value is used to compute the position
9214     * of the thumb within the scrollbar's track.</p>
9215     *
9216     * <p>The range is expressed in arbitrary units that must be the same as the
9217     * units used by {@link #computeHorizontalScrollRange()} and
9218     * {@link #computeHorizontalScrollExtent()}.</p>
9219     *
9220     * <p>The default offset is the scroll offset of this view.</p>
9221     *
9222     * @return the horizontal offset of the scrollbar's thumb
9223     *
9224     * @see #computeHorizontalScrollRange()
9225     * @see #computeHorizontalScrollExtent()
9226     * @see android.widget.ScrollBarDrawable
9227     */
9228    protected int computeHorizontalScrollOffset() {
9229        return mScrollX;
9230    }
9231
9232    /**
9233     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
9234     * within the horizontal range. This value is used to compute the length
9235     * of the thumb within the scrollbar's track.</p>
9236     *
9237     * <p>The range is expressed in arbitrary units that must be the same as the
9238     * units used by {@link #computeHorizontalScrollRange()} and
9239     * {@link #computeHorizontalScrollOffset()}.</p>
9240     *
9241     * <p>The default extent is the drawing width of this view.</p>
9242     *
9243     * @return the horizontal extent of the scrollbar's thumb
9244     *
9245     * @see #computeHorizontalScrollRange()
9246     * @see #computeHorizontalScrollOffset()
9247     * @see android.widget.ScrollBarDrawable
9248     */
9249    protected int computeHorizontalScrollExtent() {
9250        return getWidth();
9251    }
9252
9253    /**
9254     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
9255     *
9256     * <p>The range is expressed in arbitrary units that must be the same as the
9257     * units used by {@link #computeVerticalScrollExtent()} and
9258     * {@link #computeVerticalScrollOffset()}.</p>
9259     *
9260     * @return the total vertical range represented by the vertical scrollbar
9261     *
9262     * <p>The default range is the drawing height of this view.</p>
9263     *
9264     * @see #computeVerticalScrollExtent()
9265     * @see #computeVerticalScrollOffset()
9266     * @see android.widget.ScrollBarDrawable
9267     */
9268    protected int computeVerticalScrollRange() {
9269        return getHeight();
9270    }
9271
9272    /**
9273     * <p>Compute the vertical offset of the vertical scrollbar's thumb
9274     * within the horizontal range. This value is used to compute the position
9275     * of the thumb within the scrollbar's track.</p>
9276     *
9277     * <p>The range is expressed in arbitrary units that must be the same as the
9278     * units used by {@link #computeVerticalScrollRange()} and
9279     * {@link #computeVerticalScrollExtent()}.</p>
9280     *
9281     * <p>The default offset is the scroll offset of this view.</p>
9282     *
9283     * @return the vertical offset of the scrollbar's thumb
9284     *
9285     * @see #computeVerticalScrollRange()
9286     * @see #computeVerticalScrollExtent()
9287     * @see android.widget.ScrollBarDrawable
9288     */
9289    protected int computeVerticalScrollOffset() {
9290        return mScrollY;
9291    }
9292
9293    /**
9294     * <p>Compute the vertical extent of the horizontal scrollbar's thumb
9295     * within the vertical range. This value is used to compute the length
9296     * of the thumb within the scrollbar's track.</p>
9297     *
9298     * <p>The range is expressed in arbitrary units that must be the same as the
9299     * units used by {@link #computeVerticalScrollRange()} and
9300     * {@link #computeVerticalScrollOffset()}.</p>
9301     *
9302     * <p>The default extent is the drawing height of this view.</p>
9303     *
9304     * @return the vertical extent of the scrollbar's thumb
9305     *
9306     * @see #computeVerticalScrollRange()
9307     * @see #computeVerticalScrollOffset()
9308     * @see android.widget.ScrollBarDrawable
9309     */
9310    protected int computeVerticalScrollExtent() {
9311        return getHeight();
9312    }
9313
9314    /**
9315     * Check if this view can be scrolled horizontally in a certain direction.
9316     *
9317     * @param direction Negative to check scrolling left, positive to check scrolling right.
9318     * @return true if this view can be scrolled in the specified direction, false otherwise.
9319     */
9320    public boolean canScrollHorizontally(int direction) {
9321        final int offset = computeHorizontalScrollOffset();
9322        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
9323        if (range == 0) return false;
9324        if (direction < 0) {
9325            return offset > 0;
9326        } else {
9327            return offset < range - 1;
9328        }
9329    }
9330
9331    /**
9332     * Check if this view can be scrolled vertically in a certain direction.
9333     *
9334     * @param direction Negative to check scrolling up, positive to check scrolling down.
9335     * @return true if this view can be scrolled in the specified direction, false otherwise.
9336     */
9337    public boolean canScrollVertically(int direction) {
9338        final int offset = computeVerticalScrollOffset();
9339        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
9340        if (range == 0) return false;
9341        if (direction < 0) {
9342            return offset > 0;
9343        } else {
9344            return offset < range - 1;
9345        }
9346    }
9347
9348    /**
9349     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
9350     * scrollbars are painted only if they have been awakened first.</p>
9351     *
9352     * @param canvas the canvas on which to draw the scrollbars
9353     *
9354     * @see #awakenScrollBars(int)
9355     */
9356    protected final void onDrawScrollBars(Canvas canvas) {
9357        // scrollbars are drawn only when the animation is running
9358        final ScrollabilityCache cache = mScrollCache;
9359        if (cache != null) {
9360
9361            int state = cache.state;
9362
9363            if (state == ScrollabilityCache.OFF) {
9364                return;
9365            }
9366
9367            boolean invalidate = false;
9368
9369            if (state == ScrollabilityCache.FADING) {
9370                // We're fading -- get our fade interpolation
9371                if (cache.interpolatorValues == null) {
9372                    cache.interpolatorValues = new float[1];
9373                }
9374
9375                float[] values = cache.interpolatorValues;
9376
9377                // Stops the animation if we're done
9378                if (cache.scrollBarInterpolator.timeToValues(values) ==
9379                        Interpolator.Result.FREEZE_END) {
9380                    cache.state = ScrollabilityCache.OFF;
9381                } else {
9382                    cache.scrollBar.setAlpha(Math.round(values[0]));
9383                }
9384
9385                // This will make the scroll bars inval themselves after
9386                // drawing. We only want this when we're fading so that
9387                // we prevent excessive redraws
9388                invalidate = true;
9389            } else {
9390                // We're just on -- but we may have been fading before so
9391                // reset alpha
9392                cache.scrollBar.setAlpha(255);
9393            }
9394
9395
9396            final int viewFlags = mViewFlags;
9397
9398            final boolean drawHorizontalScrollBar =
9399                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
9400            final boolean drawVerticalScrollBar =
9401                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
9402                && !isVerticalScrollBarHidden();
9403
9404            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
9405                final int width = mRight - mLeft;
9406                final int height = mBottom - mTop;
9407
9408                final ScrollBarDrawable scrollBar = cache.scrollBar;
9409
9410                final int scrollX = mScrollX;
9411                final int scrollY = mScrollY;
9412                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
9413
9414                int left, top, right, bottom;
9415
9416                if (drawHorizontalScrollBar) {
9417                    int size = scrollBar.getSize(false);
9418                    if (size <= 0) {
9419                        size = cache.scrollBarSize;
9420                    }
9421
9422                    scrollBar.setParameters(computeHorizontalScrollRange(),
9423                                            computeHorizontalScrollOffset(),
9424                                            computeHorizontalScrollExtent(), false);
9425                    final int verticalScrollBarGap = drawVerticalScrollBar ?
9426                            getVerticalScrollbarWidth() : 0;
9427                    top = scrollY + height - size - (mUserPaddingBottom & inside);
9428                    left = scrollX + (mPaddingLeft & inside);
9429                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
9430                    bottom = top + size;
9431                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
9432                    if (invalidate) {
9433                        invalidate(left, top, right, bottom);
9434                    }
9435                }
9436
9437                if (drawVerticalScrollBar) {
9438                    int size = scrollBar.getSize(true);
9439                    if (size <= 0) {
9440                        size = cache.scrollBarSize;
9441                    }
9442
9443                    scrollBar.setParameters(computeVerticalScrollRange(),
9444                                            computeVerticalScrollOffset(),
9445                                            computeVerticalScrollExtent(), true);
9446                    switch (mVerticalScrollbarPosition) {
9447                        default:
9448                        case SCROLLBAR_POSITION_DEFAULT:
9449                        case SCROLLBAR_POSITION_RIGHT:
9450                            left = scrollX + width - size - (mUserPaddingRight & inside);
9451                            break;
9452                        case SCROLLBAR_POSITION_LEFT:
9453                            left = scrollX + (mUserPaddingLeft & inside);
9454                            break;
9455                    }
9456                    top = scrollY + (mPaddingTop & inside);
9457                    right = left + size;
9458                    bottom = scrollY + height - (mUserPaddingBottom & inside);
9459                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
9460                    if (invalidate) {
9461                        invalidate(left, top, right, bottom);
9462                    }
9463                }
9464            }
9465        }
9466    }
9467
9468    /**
9469     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
9470     * FastScroller is visible.
9471     * @return whether to temporarily hide the vertical scrollbar
9472     * @hide
9473     */
9474    protected boolean isVerticalScrollBarHidden() {
9475        return false;
9476    }
9477
9478    /**
9479     * <p>Draw the horizontal scrollbar if
9480     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
9481     *
9482     * @param canvas the canvas on which to draw the scrollbar
9483     * @param scrollBar the scrollbar's drawable
9484     *
9485     * @see #isHorizontalScrollBarEnabled()
9486     * @see #computeHorizontalScrollRange()
9487     * @see #computeHorizontalScrollExtent()
9488     * @see #computeHorizontalScrollOffset()
9489     * @see android.widget.ScrollBarDrawable
9490     * @hide
9491     */
9492    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
9493            int l, int t, int r, int b) {
9494        scrollBar.setBounds(l, t, r, b);
9495        scrollBar.draw(canvas);
9496    }
9497
9498    /**
9499     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
9500     * returns true.</p>
9501     *
9502     * @param canvas the canvas on which to draw the scrollbar
9503     * @param scrollBar the scrollbar's drawable
9504     *
9505     * @see #isVerticalScrollBarEnabled()
9506     * @see #computeVerticalScrollRange()
9507     * @see #computeVerticalScrollExtent()
9508     * @see #computeVerticalScrollOffset()
9509     * @see android.widget.ScrollBarDrawable
9510     * @hide
9511     */
9512    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
9513            int l, int t, int r, int b) {
9514        scrollBar.setBounds(l, t, r, b);
9515        scrollBar.draw(canvas);
9516    }
9517
9518    /**
9519     * Implement this to do your drawing.
9520     *
9521     * @param canvas the canvas on which the background will be drawn
9522     */
9523    protected void onDraw(Canvas canvas) {
9524    }
9525
9526    /*
9527     * Caller is responsible for calling requestLayout if necessary.
9528     * (This allows addViewInLayout to not request a new layout.)
9529     */
9530    void assignParent(ViewParent parent) {
9531        if (mParent == null) {
9532            mParent = parent;
9533        } else if (parent == null) {
9534            mParent = null;
9535        } else {
9536            throw new RuntimeException("view " + this + " being added, but"
9537                    + " it already has a parent");
9538        }
9539    }
9540
9541    /**
9542     * This is called when the view is attached to a window.  At this point it
9543     * has a Surface and will start drawing.  Note that this function is
9544     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
9545     * however it may be called any time before the first onDraw -- including
9546     * before or after {@link #onMeasure(int, int)}.
9547     *
9548     * @see #onDetachedFromWindow()
9549     */
9550    protected void onAttachedToWindow() {
9551        if ((mPrivateFlags & REQUEST_TRANSPARENT_REGIONS) != 0) {
9552            mParent.requestTransparentRegion(this);
9553        }
9554        if ((mPrivateFlags & AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
9555            initialAwakenScrollBars();
9556            mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
9557        }
9558        jumpDrawablesToCurrentState();
9559        // Order is important here: LayoutDirection MUST be resolved before Padding
9560        // and TextDirection
9561        resolveLayoutDirectionIfNeeded();
9562        resolvePadding();
9563        resolveTextDirection();
9564        if (isFocused()) {
9565            InputMethodManager imm = InputMethodManager.peekInstance();
9566            imm.focusIn(this);
9567        }
9568    }
9569
9570    /**
9571     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
9572     * that the parent directionality can and will be resolved before its children.
9573     */
9574    private void resolveLayoutDirectionIfNeeded() {
9575        // Do not resolve if it is not needed
9576        if ((mPrivateFlags2 & LAYOUT_DIRECTION_RESOLVED) == LAYOUT_DIRECTION_RESOLVED) return;
9577
9578        // Clear any previous layout direction resolution
9579        mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_RTL;
9580
9581        // Set resolved depending on layout direction
9582        switch (getLayoutDirection()) {
9583            case LAYOUT_DIRECTION_INHERIT:
9584                // We cannot do the resolution if there is no parent
9585                if (mParent == null) return;
9586
9587                // If this is root view, no need to look at parent's layout dir.
9588                if (mParent instanceof ViewGroup) {
9589                    ViewGroup viewGroup = ((ViewGroup) mParent);
9590
9591                    // Check if the parent view group can resolve
9592                    if (! viewGroup.canResolveLayoutDirection()) {
9593                        return;
9594                    }
9595                    if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
9596                        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9597                    }
9598                }
9599                break;
9600            case LAYOUT_DIRECTION_RTL:
9601                mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9602                break;
9603            case LAYOUT_DIRECTION_LOCALE:
9604                if(isLayoutDirectionRtl(Locale.getDefault())) {
9605                    mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
9606                }
9607                break;
9608            default:
9609                // Nothing to do, LTR by default
9610        }
9611
9612        // Set to resolved
9613        mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED;
9614    }
9615
9616    /**
9617     * Force padding depending on layout direction.
9618     */
9619    public void resolvePadding() {
9620        // If the user specified the absolute padding (either with android:padding or
9621        // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
9622        // use the default padding or the padding from the background drawable
9623        // (stored at this point in mPadding*)
9624        int resolvedLayoutDirection = getResolvedLayoutDirection();
9625        switch (resolvedLayoutDirection) {
9626            case LAYOUT_DIRECTION_RTL:
9627                // Start user padding override Right user padding. Otherwise, if Right user
9628                // padding is not defined, use the default Right padding. If Right user padding
9629                // is defined, just use it.
9630                if (mUserPaddingStart >= 0) {
9631                    mUserPaddingRight = mUserPaddingStart;
9632                } else if (mUserPaddingRight < 0) {
9633                    mUserPaddingRight = mPaddingRight;
9634                }
9635                if (mUserPaddingEnd >= 0) {
9636                    mUserPaddingLeft = mUserPaddingEnd;
9637                } else if (mUserPaddingLeft < 0) {
9638                    mUserPaddingLeft = mPaddingLeft;
9639                }
9640                break;
9641            case LAYOUT_DIRECTION_LTR:
9642            default:
9643                // Start user padding override Left user padding. Otherwise, if Left user
9644                // padding is not defined, use the default left padding. If Left user padding
9645                // is defined, just use it.
9646                if (mUserPaddingStart >= 0) {
9647                    mUserPaddingLeft = mUserPaddingStart;
9648                } else if (mUserPaddingLeft < 0) {
9649                    mUserPaddingLeft = mPaddingLeft;
9650                }
9651                if (mUserPaddingEnd >= 0) {
9652                    mUserPaddingRight = mUserPaddingEnd;
9653                } else if (mUserPaddingRight < 0) {
9654                    mUserPaddingRight = mPaddingRight;
9655                }
9656        }
9657
9658        mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
9659
9660        recomputePadding();
9661        onResolvePadding(resolvedLayoutDirection);
9662    }
9663
9664    /**
9665     * Resolve padding depending on the layout direction. Subclasses that care about
9666     * padding resolution should override this method. The default implementation does
9667     * nothing.
9668     *
9669     * @param layoutDirection the direction of the layout
9670     *
9671     */
9672    public void onResolvePadding(int layoutDirection) {
9673    }
9674
9675    /**
9676     * Return true if layout direction resolution can be done
9677     *
9678     * @hide
9679     */
9680    protected boolean canResolveLayoutDirection() {
9681        switch (getLayoutDirection()) {
9682            case LAYOUT_DIRECTION_INHERIT:
9683                return (mParent != null);
9684            default:
9685                return true;
9686        }
9687    }
9688
9689    /**
9690     * Reset the resolved layout direction.
9691     *
9692     * Subclasses need to override this method to clear cached information that depends on the
9693     * resolved layout direction, or to inform child views that inherit their layout direction.
9694     * Overrides must also call the superclass implementation at the start of their implementation.
9695     *
9696     * @hide
9697     */
9698    protected void resetResolvedLayoutDirection() {
9699        // Reset the layout direction resolution
9700        mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED;
9701        // Reset also the text direction
9702        resetResolvedTextDirection();
9703    }
9704
9705    /**
9706     * Check if a Locale is corresponding to a RTL script.
9707     *
9708     * @param locale Locale to check
9709     * @return true if a Locale is corresponding to a RTL script.
9710     *
9711     * @hide
9712     */
9713    protected static boolean isLayoutDirectionRtl(Locale locale) {
9714        return (LocaleUtil.TEXT_LAYOUT_DIRECTION_RTL_DO_NOT_USE ==
9715                LocaleUtil.getLayoutDirectionFromLocale(locale));
9716    }
9717
9718    /**
9719     * This is called when the view is detached from a window.  At this point it
9720     * no longer has a surface for drawing.
9721     *
9722     * @see #onAttachedToWindow()
9723     */
9724    protected void onDetachedFromWindow() {
9725        mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
9726
9727        removeUnsetPressCallback();
9728        removeLongPressCallback();
9729        removePerformClickCallback();
9730        removeSendViewScrolledAccessibilityEventCallback();
9731
9732        destroyDrawingCache();
9733
9734        destroyLayer();
9735
9736        if (mDisplayList != null) {
9737            mDisplayList.invalidate();
9738        }
9739
9740        if (mAttachInfo != null) {
9741            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
9742        }
9743
9744        mCurrentAnimation = null;
9745
9746        resetResolvedLayoutDirection();
9747    }
9748
9749    /**
9750     * @return The number of times this view has been attached to a window
9751     */
9752    protected int getWindowAttachCount() {
9753        return mWindowAttachCount;
9754    }
9755
9756    /**
9757     * Retrieve a unique token identifying the window this view is attached to.
9758     * @return Return the window's token for use in
9759     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
9760     */
9761    public IBinder getWindowToken() {
9762        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
9763    }
9764
9765    /**
9766     * Retrieve a unique token identifying the top-level "real" window of
9767     * the window that this view is attached to.  That is, this is like
9768     * {@link #getWindowToken}, except if the window this view in is a panel
9769     * window (attached to another containing window), then the token of
9770     * the containing window is returned instead.
9771     *
9772     * @return Returns the associated window token, either
9773     * {@link #getWindowToken()} or the containing window's token.
9774     */
9775    public IBinder getApplicationWindowToken() {
9776        AttachInfo ai = mAttachInfo;
9777        if (ai != null) {
9778            IBinder appWindowToken = ai.mPanelParentWindowToken;
9779            if (appWindowToken == null) {
9780                appWindowToken = ai.mWindowToken;
9781            }
9782            return appWindowToken;
9783        }
9784        return null;
9785    }
9786
9787    /**
9788     * Retrieve private session object this view hierarchy is using to
9789     * communicate with the window manager.
9790     * @return the session object to communicate with the window manager
9791     */
9792    /*package*/ IWindowSession getWindowSession() {
9793        return mAttachInfo != null ? mAttachInfo.mSession : null;
9794    }
9795
9796    /**
9797     * @param info the {@link android.view.View.AttachInfo} to associated with
9798     *        this view
9799     */
9800    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
9801        //System.out.println("Attached! " + this);
9802        mAttachInfo = info;
9803        mWindowAttachCount++;
9804        // We will need to evaluate the drawable state at least once.
9805        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
9806        if (mFloatingTreeObserver != null) {
9807            info.mTreeObserver.merge(mFloatingTreeObserver);
9808            mFloatingTreeObserver = null;
9809        }
9810        if ((mPrivateFlags&SCROLL_CONTAINER) != 0) {
9811            mAttachInfo.mScrollContainers.add(this);
9812            mPrivateFlags |= SCROLL_CONTAINER_ADDED;
9813        }
9814        performCollectViewAttributes(visibility);
9815        onAttachedToWindow();
9816
9817        ListenerInfo li = mListenerInfo;
9818        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
9819                li != null ? li.mOnAttachStateChangeListeners : null;
9820        if (listeners != null && listeners.size() > 0) {
9821            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
9822            // perform the dispatching. The iterator is a safe guard against listeners that
9823            // could mutate the list by calling the various add/remove methods. This prevents
9824            // the array from being modified while we iterate it.
9825            for (OnAttachStateChangeListener listener : listeners) {
9826                listener.onViewAttachedToWindow(this);
9827            }
9828        }
9829
9830        int vis = info.mWindowVisibility;
9831        if (vis != GONE) {
9832            onWindowVisibilityChanged(vis);
9833        }
9834        if ((mPrivateFlags&DRAWABLE_STATE_DIRTY) != 0) {
9835            // If nobody has evaluated the drawable state yet, then do it now.
9836            refreshDrawableState();
9837        }
9838    }
9839
9840    void dispatchDetachedFromWindow() {
9841        AttachInfo info = mAttachInfo;
9842        if (info != null) {
9843            int vis = info.mWindowVisibility;
9844            if (vis != GONE) {
9845                onWindowVisibilityChanged(GONE);
9846            }
9847        }
9848
9849        onDetachedFromWindow();
9850
9851        ListenerInfo li = mListenerInfo;
9852        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
9853                li != null ? li.mOnAttachStateChangeListeners : null;
9854        if (listeners != null && listeners.size() > 0) {
9855            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
9856            // perform the dispatching. The iterator is a safe guard against listeners that
9857            // could mutate the list by calling the various add/remove methods. This prevents
9858            // the array from being modified while we iterate it.
9859            for (OnAttachStateChangeListener listener : listeners) {
9860                listener.onViewDetachedFromWindow(this);
9861            }
9862        }
9863
9864        if ((mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0) {
9865            mAttachInfo.mScrollContainers.remove(this);
9866            mPrivateFlags &= ~SCROLL_CONTAINER_ADDED;
9867        }
9868
9869        mAttachInfo = null;
9870    }
9871
9872    /**
9873     * Store this view hierarchy's frozen state into the given container.
9874     *
9875     * @param container The SparseArray in which to save the view's state.
9876     *
9877     * @see #restoreHierarchyState(android.util.SparseArray)
9878     * @see #dispatchSaveInstanceState(android.util.SparseArray)
9879     * @see #onSaveInstanceState()
9880     */
9881    public void saveHierarchyState(SparseArray<Parcelable> container) {
9882        dispatchSaveInstanceState(container);
9883    }
9884
9885    /**
9886     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
9887     * this view and its children. May be overridden to modify how freezing happens to a
9888     * view's children; for example, some views may want to not store state for their children.
9889     *
9890     * @param container The SparseArray in which to save the view's state.
9891     *
9892     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
9893     * @see #saveHierarchyState(android.util.SparseArray)
9894     * @see #onSaveInstanceState()
9895     */
9896    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
9897        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
9898            mPrivateFlags &= ~SAVE_STATE_CALLED;
9899            Parcelable state = onSaveInstanceState();
9900            if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
9901                throw new IllegalStateException(
9902                        "Derived class did not call super.onSaveInstanceState()");
9903            }
9904            if (state != null) {
9905                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
9906                // + ": " + state);
9907                container.put(mID, state);
9908            }
9909        }
9910    }
9911
9912    /**
9913     * Hook allowing a view to generate a representation of its internal state
9914     * that can later be used to create a new instance with that same state.
9915     * This state should only contain information that is not persistent or can
9916     * not be reconstructed later. For example, you will never store your
9917     * current position on screen because that will be computed again when a
9918     * new instance of the view is placed in its view hierarchy.
9919     * <p>
9920     * Some examples of things you may store here: the current cursor position
9921     * in a text view (but usually not the text itself since that is stored in a
9922     * content provider or other persistent storage), the currently selected
9923     * item in a list view.
9924     *
9925     * @return Returns a Parcelable object containing the view's current dynamic
9926     *         state, or null if there is nothing interesting to save. The
9927     *         default implementation returns null.
9928     * @see #onRestoreInstanceState(android.os.Parcelable)
9929     * @see #saveHierarchyState(android.util.SparseArray)
9930     * @see #dispatchSaveInstanceState(android.util.SparseArray)
9931     * @see #setSaveEnabled(boolean)
9932     */
9933    protected Parcelable onSaveInstanceState() {
9934        mPrivateFlags |= SAVE_STATE_CALLED;
9935        return BaseSavedState.EMPTY_STATE;
9936    }
9937
9938    /**
9939     * Restore this view hierarchy's frozen state from the given container.
9940     *
9941     * @param container The SparseArray which holds previously frozen states.
9942     *
9943     * @see #saveHierarchyState(android.util.SparseArray)
9944     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
9945     * @see #onRestoreInstanceState(android.os.Parcelable)
9946     */
9947    public void restoreHierarchyState(SparseArray<Parcelable> container) {
9948        dispatchRestoreInstanceState(container);
9949    }
9950
9951    /**
9952     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
9953     * state for this view and its children. May be overridden to modify how restoring
9954     * happens to a view's children; for example, some views may want to not store state
9955     * for their children.
9956     *
9957     * @param container The SparseArray which holds previously saved state.
9958     *
9959     * @see #dispatchSaveInstanceState(android.util.SparseArray)
9960     * @see #restoreHierarchyState(android.util.SparseArray)
9961     * @see #onRestoreInstanceState(android.os.Parcelable)
9962     */
9963    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
9964        if (mID != NO_ID) {
9965            Parcelable state = container.get(mID);
9966            if (state != null) {
9967                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
9968                // + ": " + state);
9969                mPrivateFlags &= ~SAVE_STATE_CALLED;
9970                onRestoreInstanceState(state);
9971                if ((mPrivateFlags & SAVE_STATE_CALLED) == 0) {
9972                    throw new IllegalStateException(
9973                            "Derived class did not call super.onRestoreInstanceState()");
9974                }
9975            }
9976        }
9977    }
9978
9979    /**
9980     * Hook allowing a view to re-apply a representation of its internal state that had previously
9981     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
9982     * null state.
9983     *
9984     * @param state The frozen state that had previously been returned by
9985     *        {@link #onSaveInstanceState}.
9986     *
9987     * @see #onSaveInstanceState()
9988     * @see #restoreHierarchyState(android.util.SparseArray)
9989     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
9990     */
9991    protected void onRestoreInstanceState(Parcelable state) {
9992        mPrivateFlags |= SAVE_STATE_CALLED;
9993        if (state != BaseSavedState.EMPTY_STATE && state != null) {
9994            throw new IllegalArgumentException("Wrong state class, expecting View State but "
9995                    + "received " + state.getClass().toString() + " instead. This usually happens "
9996                    + "when two views of different type have the same id in the same hierarchy. "
9997                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
9998                    + "other views do not use the same id.");
9999        }
10000    }
10001
10002    /**
10003     * <p>Return the time at which the drawing of the view hierarchy started.</p>
10004     *
10005     * @return the drawing start time in milliseconds
10006     */
10007    public long getDrawingTime() {
10008        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
10009    }
10010
10011    /**
10012     * <p>Enables or disables the duplication of the parent's state into this view. When
10013     * duplication is enabled, this view gets its drawable state from its parent rather
10014     * than from its own internal properties.</p>
10015     *
10016     * <p>Note: in the current implementation, setting this property to true after the
10017     * view was added to a ViewGroup might have no effect at all. This property should
10018     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
10019     *
10020     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
10021     * property is enabled, an exception will be thrown.</p>
10022     *
10023     * <p>Note: if the child view uses and updates additionnal states which are unknown to the
10024     * parent, these states should not be affected by this method.</p>
10025     *
10026     * @param enabled True to enable duplication of the parent's drawable state, false
10027     *                to disable it.
10028     *
10029     * @see #getDrawableState()
10030     * @see #isDuplicateParentStateEnabled()
10031     */
10032    public void setDuplicateParentStateEnabled(boolean enabled) {
10033        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
10034    }
10035
10036    /**
10037     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
10038     *
10039     * @return True if this view's drawable state is duplicated from the parent,
10040     *         false otherwise
10041     *
10042     * @see #getDrawableState()
10043     * @see #setDuplicateParentStateEnabled(boolean)
10044     */
10045    public boolean isDuplicateParentStateEnabled() {
10046        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
10047    }
10048
10049    /**
10050     * <p>Specifies the type of layer backing this view. The layer can be
10051     * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
10052     * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
10053     *
10054     * <p>A layer is associated with an optional {@link android.graphics.Paint}
10055     * instance that controls how the layer is composed on screen. The following
10056     * properties of the paint are taken into account when composing the layer:</p>
10057     * <ul>
10058     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
10059     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
10060     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
10061     * </ul>
10062     *
10063     * <p>If this view has an alpha value set to < 1.0 by calling
10064     * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
10065     * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
10066     * equivalent to setting a hardware layer on this view and providing a paint with
10067     * the desired alpha value.<p>
10068     *
10069     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
10070     * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
10071     * for more information on when and how to use layers.</p>
10072     *
10073     * @param layerType The ype of layer to use with this view, must be one of
10074     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
10075     *        {@link #LAYER_TYPE_HARDWARE}
10076     * @param paint The paint used to compose the layer. This argument is optional
10077     *        and can be null. It is ignored when the layer type is
10078     *        {@link #LAYER_TYPE_NONE}
10079     *
10080     * @see #getLayerType()
10081     * @see #LAYER_TYPE_NONE
10082     * @see #LAYER_TYPE_SOFTWARE
10083     * @see #LAYER_TYPE_HARDWARE
10084     * @see #setAlpha(float)
10085     *
10086     * @attr ref android.R.styleable#View_layerType
10087     */
10088    public void setLayerType(int layerType, Paint paint) {
10089        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
10090            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
10091                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
10092        }
10093
10094        if (layerType == mLayerType) {
10095            if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
10096                mLayerPaint = paint == null ? new Paint() : paint;
10097                invalidateParentCaches();
10098                invalidate(true);
10099            }
10100            return;
10101        }
10102
10103        // Destroy any previous software drawing cache if needed
10104        switch (mLayerType) {
10105            case LAYER_TYPE_HARDWARE:
10106                destroyLayer();
10107                // fall through - non-accelerated views may use software layer mechanism instead
10108            case LAYER_TYPE_SOFTWARE:
10109                destroyDrawingCache();
10110                break;
10111            default:
10112                break;
10113        }
10114
10115        mLayerType = layerType;
10116        final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
10117        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
10118        mLocalDirtyRect = layerDisabled ? null : new Rect();
10119
10120        invalidateParentCaches();
10121        invalidate(true);
10122    }
10123
10124    /**
10125     * Indicates whether this view has a static layer. A view with layer type
10126     * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
10127     * dynamic.
10128     */
10129    boolean hasStaticLayer() {
10130        return mLayerType == LAYER_TYPE_NONE;
10131    }
10132
10133    /**
10134     * Indicates what type of layer is currently associated with this view. By default
10135     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
10136     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
10137     * for more information on the different types of layers.
10138     *
10139     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
10140     *         {@link #LAYER_TYPE_HARDWARE}
10141     *
10142     * @see #setLayerType(int, android.graphics.Paint)
10143     * @see #buildLayer()
10144     * @see #LAYER_TYPE_NONE
10145     * @see #LAYER_TYPE_SOFTWARE
10146     * @see #LAYER_TYPE_HARDWARE
10147     */
10148    public int getLayerType() {
10149        return mLayerType;
10150    }
10151
10152    /**
10153     * Forces this view's layer to be created and this view to be rendered
10154     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
10155     * invoking this method will have no effect.
10156     *
10157     * This method can for instance be used to render a view into its layer before
10158     * starting an animation. If this view is complex, rendering into the layer
10159     * before starting the animation will avoid skipping frames.
10160     *
10161     * @throws IllegalStateException If this view is not attached to a window
10162     *
10163     * @see #setLayerType(int, android.graphics.Paint)
10164     */
10165    public void buildLayer() {
10166        if (mLayerType == LAYER_TYPE_NONE) return;
10167
10168        if (mAttachInfo == null) {
10169            throw new IllegalStateException("This view must be attached to a window first");
10170        }
10171
10172        switch (mLayerType) {
10173            case LAYER_TYPE_HARDWARE:
10174                if (mAttachInfo.mHardwareRenderer != null &&
10175                        mAttachInfo.mHardwareRenderer.isEnabled() &&
10176                        mAttachInfo.mHardwareRenderer.validate()) {
10177                    getHardwareLayer();
10178                }
10179                break;
10180            case LAYER_TYPE_SOFTWARE:
10181                buildDrawingCache(true);
10182                break;
10183        }
10184    }
10185
10186    // Make sure the HardwareRenderer.validate() was invoked before calling this method
10187    void flushLayer() {
10188        if (mLayerType == LAYER_TYPE_HARDWARE && mHardwareLayer != null) {
10189            mHardwareLayer.flush();
10190        }
10191    }
10192
10193    /**
10194     * <p>Returns a hardware layer that can be used to draw this view again
10195     * without executing its draw method.</p>
10196     *
10197     * @return A HardwareLayer ready to render, or null if an error occurred.
10198     */
10199    HardwareLayer getHardwareLayer() {
10200        if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
10201                !mAttachInfo.mHardwareRenderer.isEnabled()) {
10202            return null;
10203        }
10204
10205        if (!mAttachInfo.mHardwareRenderer.validate()) return null;
10206
10207        final int width = mRight - mLeft;
10208        final int height = mBottom - mTop;
10209
10210        if (width == 0 || height == 0) {
10211            return null;
10212        }
10213
10214        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
10215            if (mHardwareLayer == null) {
10216                mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
10217                        width, height, isOpaque());
10218                mLocalDirtyRect.setEmpty();
10219            } else if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
10220                mHardwareLayer.resize(width, height);
10221                mLocalDirtyRect.setEmpty();
10222            }
10223
10224            // The layer is not valid if the underlying GPU resources cannot be allocated
10225            if (!mHardwareLayer.isValid()) {
10226                return null;
10227            }
10228
10229            HardwareCanvas currentCanvas = mAttachInfo.mHardwareCanvas;
10230            final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas);
10231
10232            // Make sure all the GPU resources have been properly allocated
10233            if (canvas == null) {
10234                mHardwareLayer.end(currentCanvas);
10235                return null;
10236            }
10237
10238            mAttachInfo.mHardwareCanvas = canvas;
10239            try {
10240                canvas.setViewport(width, height);
10241                canvas.onPreDraw(mLocalDirtyRect);
10242                mLocalDirtyRect.setEmpty();
10243
10244                final int restoreCount = canvas.save();
10245
10246                computeScroll();
10247                canvas.translate(-mScrollX, -mScrollY);
10248
10249                mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10250
10251                // Fast path for layouts with no backgrounds
10252                if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10253                    mPrivateFlags &= ~DIRTY_MASK;
10254                    dispatchDraw(canvas);
10255                } else {
10256                    draw(canvas);
10257                }
10258
10259                canvas.restoreToCount(restoreCount);
10260            } finally {
10261                canvas.onPostDraw();
10262                mHardwareLayer.end(currentCanvas);
10263                mAttachInfo.mHardwareCanvas = currentCanvas;
10264            }
10265        }
10266
10267        return mHardwareLayer;
10268    }
10269
10270    /**
10271     * Destroys this View's hardware layer if possible.
10272     *
10273     * @return True if the layer was destroyed, false otherwise.
10274     *
10275     * @see #setLayerType(int, android.graphics.Paint)
10276     * @see #LAYER_TYPE_HARDWARE
10277     */
10278    boolean destroyLayer() {
10279        if (mHardwareLayer != null) {
10280            AttachInfo info = mAttachInfo;
10281            if (info != null && info.mHardwareRenderer != null &&
10282                    info.mHardwareRenderer.isEnabled() && info.mHardwareRenderer.validate()) {
10283                mHardwareLayer.destroy();
10284                mHardwareLayer = null;
10285
10286                invalidate(true);
10287                invalidateParentCaches();
10288            }
10289            return true;
10290        }
10291        return false;
10292    }
10293
10294    /**
10295     * Destroys all hardware rendering resources. This method is invoked
10296     * when the system needs to reclaim resources. Upon execution of this
10297     * method, you should free any OpenGL resources created by the view.
10298     *
10299     * Note: you <strong>must</strong> call
10300     * <code>super.destroyHardwareResources()</code> when overriding
10301     * this method.
10302     *
10303     * @hide
10304     */
10305    protected void destroyHardwareResources() {
10306        destroyLayer();
10307    }
10308
10309    /**
10310     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
10311     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
10312     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
10313     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
10314     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
10315     * null.</p>
10316     *
10317     * <p>Enabling the drawing cache is similar to
10318     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
10319     * acceleration is turned off. When hardware acceleration is turned on, enabling the
10320     * drawing cache has no effect on rendering because the system uses a different mechanism
10321     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
10322     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
10323     * for information on how to enable software and hardware layers.</p>
10324     *
10325     * <p>This API can be used to manually generate
10326     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
10327     * {@link #getDrawingCache()}.</p>
10328     *
10329     * @param enabled true to enable the drawing cache, false otherwise
10330     *
10331     * @see #isDrawingCacheEnabled()
10332     * @see #getDrawingCache()
10333     * @see #buildDrawingCache()
10334     * @see #setLayerType(int, android.graphics.Paint)
10335     */
10336    public void setDrawingCacheEnabled(boolean enabled) {
10337        mCachingFailed = false;
10338        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
10339    }
10340
10341    /**
10342     * <p>Indicates whether the drawing cache is enabled for this view.</p>
10343     *
10344     * @return true if the drawing cache is enabled
10345     *
10346     * @see #setDrawingCacheEnabled(boolean)
10347     * @see #getDrawingCache()
10348     */
10349    @ViewDebug.ExportedProperty(category = "drawing")
10350    public boolean isDrawingCacheEnabled() {
10351        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
10352    }
10353
10354    /**
10355     * Debugging utility which recursively outputs the dirty state of a view and its
10356     * descendants.
10357     *
10358     * @hide
10359     */
10360    @SuppressWarnings({"UnusedDeclaration"})
10361    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
10362        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.DIRTY_MASK) +
10363                ") DRAWN(" + (mPrivateFlags & DRAWN) + ")" + " CACHE_VALID(" +
10364                (mPrivateFlags & View.DRAWING_CACHE_VALID) +
10365                ") INVALIDATED(" + (mPrivateFlags & INVALIDATED) + ")");
10366        if (clear) {
10367            mPrivateFlags &= clearMask;
10368        }
10369        if (this instanceof ViewGroup) {
10370            ViewGroup parent = (ViewGroup) this;
10371            final int count = parent.getChildCount();
10372            for (int i = 0; i < count; i++) {
10373                final View child = parent.getChildAt(i);
10374                child.outputDirtyFlags(indent + "  ", clear, clearMask);
10375            }
10376        }
10377    }
10378
10379    /**
10380     * This method is used by ViewGroup to cause its children to restore or recreate their
10381     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
10382     * to recreate its own display list, which would happen if it went through the normal
10383     * draw/dispatchDraw mechanisms.
10384     *
10385     * @hide
10386     */
10387    protected void dispatchGetDisplayList() {}
10388
10389    /**
10390     * A view that is not attached or hardware accelerated cannot create a display list.
10391     * This method checks these conditions and returns the appropriate result.
10392     *
10393     * @return true if view has the ability to create a display list, false otherwise.
10394     *
10395     * @hide
10396     */
10397    public boolean canHaveDisplayList() {
10398        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
10399    }
10400
10401    /**
10402     * @return The HardwareRenderer associated with that view or null if hardware rendering
10403     * is not supported or this this has not been attached to a window.
10404     *
10405     * @hide
10406     */
10407    public HardwareRenderer getHardwareRenderer() {
10408        if (mAttachInfo != null) {
10409            return mAttachInfo.mHardwareRenderer;
10410        }
10411        return null;
10412    }
10413
10414    /**
10415     * <p>Returns a display list that can be used to draw this view again
10416     * without executing its draw method.</p>
10417     *
10418     * @return A DisplayList ready to replay, or null if caching is not enabled.
10419     *
10420     * @hide
10421     */
10422    public DisplayList getDisplayList() {
10423        if (!canHaveDisplayList()) {
10424            return null;
10425        }
10426
10427        if (((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
10428                mDisplayList == null || !mDisplayList.isValid() ||
10429                mRecreateDisplayList)) {
10430            // Don't need to recreate the display list, just need to tell our
10431            // children to restore/recreate theirs
10432            if (mDisplayList != null && mDisplayList.isValid() &&
10433                    !mRecreateDisplayList) {
10434                mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10435                mPrivateFlags &= ~DIRTY_MASK;
10436                dispatchGetDisplayList();
10437
10438                return mDisplayList;
10439            }
10440
10441            // If we got here, we're recreating it. Mark it as such to ensure that
10442            // we copy in child display lists into ours in drawChild()
10443            mRecreateDisplayList = true;
10444            if (mDisplayList == null) {
10445                final String name = getClass().getSimpleName();
10446                mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
10447                // If we're creating a new display list, make sure our parent gets invalidated
10448                // since they will need to recreate their display list to account for this
10449                // new child display list.
10450                invalidateParentCaches();
10451            }
10452
10453            final HardwareCanvas canvas = mDisplayList.start();
10454            int restoreCount = 0;
10455            try {
10456                int width = mRight - mLeft;
10457                int height = mBottom - mTop;
10458
10459                canvas.setViewport(width, height);
10460                // The dirty rect should always be null for a display list
10461                canvas.onPreDraw(null);
10462
10463                computeScroll();
10464
10465                restoreCount = canvas.save();
10466                canvas.translate(-mScrollX, -mScrollY);
10467                mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10468                mPrivateFlags &= ~DIRTY_MASK;
10469
10470                // Fast path for layouts with no backgrounds
10471                if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10472                    dispatchDraw(canvas);
10473                } else {
10474                    draw(canvas);
10475                }
10476            } finally {
10477                canvas.restoreToCount(restoreCount);
10478                canvas.onPostDraw();
10479
10480                mDisplayList.end();
10481            }
10482        } else {
10483            mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
10484            mPrivateFlags &= ~DIRTY_MASK;
10485        }
10486
10487        return mDisplayList;
10488    }
10489
10490    /**
10491     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
10492     *
10493     * @return A non-scaled bitmap representing this view or null if cache is disabled.
10494     *
10495     * @see #getDrawingCache(boolean)
10496     */
10497    public Bitmap getDrawingCache() {
10498        return getDrawingCache(false);
10499    }
10500
10501    /**
10502     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
10503     * is null when caching is disabled. If caching is enabled and the cache is not ready,
10504     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
10505     * draw from the cache when the cache is enabled. To benefit from the cache, you must
10506     * request the drawing cache by calling this method and draw it on screen if the
10507     * returned bitmap is not null.</p>
10508     *
10509     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
10510     * this method will create a bitmap of the same size as this view. Because this bitmap
10511     * will be drawn scaled by the parent ViewGroup, the result on screen might show
10512     * scaling artifacts. To avoid such artifacts, you should call this method by setting
10513     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
10514     * size than the view. This implies that your application must be able to handle this
10515     * size.</p>
10516     *
10517     * @param autoScale Indicates whether the generated bitmap should be scaled based on
10518     *        the current density of the screen when the application is in compatibility
10519     *        mode.
10520     *
10521     * @return A bitmap representing this view or null if cache is disabled.
10522     *
10523     * @see #setDrawingCacheEnabled(boolean)
10524     * @see #isDrawingCacheEnabled()
10525     * @see #buildDrawingCache(boolean)
10526     * @see #destroyDrawingCache()
10527     */
10528    public Bitmap getDrawingCache(boolean autoScale) {
10529        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
10530            return null;
10531        }
10532        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
10533            buildDrawingCache(autoScale);
10534        }
10535        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
10536    }
10537
10538    /**
10539     * <p>Frees the resources used by the drawing cache. If you call
10540     * {@link #buildDrawingCache()} manually without calling
10541     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
10542     * should cleanup the cache with this method afterwards.</p>
10543     *
10544     * @see #setDrawingCacheEnabled(boolean)
10545     * @see #buildDrawingCache()
10546     * @see #getDrawingCache()
10547     */
10548    public void destroyDrawingCache() {
10549        if (mDrawingCache != null) {
10550            mDrawingCache.recycle();
10551            mDrawingCache = null;
10552        }
10553        if (mUnscaledDrawingCache != null) {
10554            mUnscaledDrawingCache.recycle();
10555            mUnscaledDrawingCache = null;
10556        }
10557    }
10558
10559    /**
10560     * Setting a solid background color for the drawing cache's bitmaps will improve
10561     * performance and memory usage. Note, though that this should only be used if this
10562     * view will always be drawn on top of a solid color.
10563     *
10564     * @param color The background color to use for the drawing cache's bitmap
10565     *
10566     * @see #setDrawingCacheEnabled(boolean)
10567     * @see #buildDrawingCache()
10568     * @see #getDrawingCache()
10569     */
10570    public void setDrawingCacheBackgroundColor(int color) {
10571        if (color != mDrawingCacheBackgroundColor) {
10572            mDrawingCacheBackgroundColor = color;
10573            mPrivateFlags &= ~DRAWING_CACHE_VALID;
10574        }
10575    }
10576
10577    /**
10578     * @see #setDrawingCacheBackgroundColor(int)
10579     *
10580     * @return The background color to used for the drawing cache's bitmap
10581     */
10582    public int getDrawingCacheBackgroundColor() {
10583        return mDrawingCacheBackgroundColor;
10584    }
10585
10586    /**
10587     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
10588     *
10589     * @see #buildDrawingCache(boolean)
10590     */
10591    public void buildDrawingCache() {
10592        buildDrawingCache(false);
10593    }
10594
10595    /**
10596     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
10597     *
10598     * <p>If you call {@link #buildDrawingCache()} manually without calling
10599     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
10600     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
10601     *
10602     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
10603     * this method will create a bitmap of the same size as this view. Because this bitmap
10604     * will be drawn scaled by the parent ViewGroup, the result on screen might show
10605     * scaling artifacts. To avoid such artifacts, you should call this method by setting
10606     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
10607     * size than the view. This implies that your application must be able to handle this
10608     * size.</p>
10609     *
10610     * <p>You should avoid calling this method when hardware acceleration is enabled. If
10611     * you do not need the drawing cache bitmap, calling this method will increase memory
10612     * usage and cause the view to be rendered in software once, thus negatively impacting
10613     * performance.</p>
10614     *
10615     * @see #getDrawingCache()
10616     * @see #destroyDrawingCache()
10617     */
10618    public void buildDrawingCache(boolean autoScale) {
10619        if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || (autoScale ?
10620                mDrawingCache == null : mUnscaledDrawingCache == null)) {
10621            mCachingFailed = false;
10622
10623            if (ViewDebug.TRACE_HIERARCHY) {
10624                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.BUILD_CACHE);
10625            }
10626
10627            int width = mRight - mLeft;
10628            int height = mBottom - mTop;
10629
10630            final AttachInfo attachInfo = mAttachInfo;
10631            final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
10632
10633            if (autoScale && scalingRequired) {
10634                width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
10635                height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
10636            }
10637
10638            final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
10639            final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
10640            final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
10641
10642            if (width <= 0 || height <= 0 ||
10643                     // Projected bitmap size in bytes
10644                    (width * height * (opaque && !use32BitCache ? 2 : 4) >
10645                            ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
10646                destroyDrawingCache();
10647                mCachingFailed = true;
10648                return;
10649            }
10650
10651            boolean clear = true;
10652            Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
10653
10654            if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
10655                Bitmap.Config quality;
10656                if (!opaque) {
10657                    // Never pick ARGB_4444 because it looks awful
10658                    // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
10659                    switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
10660                        case DRAWING_CACHE_QUALITY_AUTO:
10661                            quality = Bitmap.Config.ARGB_8888;
10662                            break;
10663                        case DRAWING_CACHE_QUALITY_LOW:
10664                            quality = Bitmap.Config.ARGB_8888;
10665                            break;
10666                        case DRAWING_CACHE_QUALITY_HIGH:
10667                            quality = Bitmap.Config.ARGB_8888;
10668                            break;
10669                        default:
10670                            quality = Bitmap.Config.ARGB_8888;
10671                            break;
10672                    }
10673                } else {
10674                    // Optimization for translucent windows
10675                    // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
10676                    quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
10677                }
10678
10679                // Try to cleanup memory
10680                if (bitmap != null) bitmap.recycle();
10681
10682                try {
10683                    bitmap = Bitmap.createBitmap(width, height, quality);
10684                    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
10685                    if (autoScale) {
10686                        mDrawingCache = bitmap;
10687                    } else {
10688                        mUnscaledDrawingCache = bitmap;
10689                    }
10690                    if (opaque && use32BitCache) bitmap.setHasAlpha(false);
10691                } catch (OutOfMemoryError e) {
10692                    // If there is not enough memory to create the bitmap cache, just
10693                    // ignore the issue as bitmap caches are not required to draw the
10694                    // view hierarchy
10695                    if (autoScale) {
10696                        mDrawingCache = null;
10697                    } else {
10698                        mUnscaledDrawingCache = null;
10699                    }
10700                    mCachingFailed = true;
10701                    return;
10702                }
10703
10704                clear = drawingCacheBackgroundColor != 0;
10705            }
10706
10707            Canvas canvas;
10708            if (attachInfo != null) {
10709                canvas = attachInfo.mCanvas;
10710                if (canvas == null) {
10711                    canvas = new Canvas();
10712                }
10713                canvas.setBitmap(bitmap);
10714                // Temporarily clobber the cached Canvas in case one of our children
10715                // is also using a drawing cache. Without this, the children would
10716                // steal the canvas by attaching their own bitmap to it and bad, bad
10717                // thing would happen (invisible views, corrupted drawings, etc.)
10718                attachInfo.mCanvas = null;
10719            } else {
10720                // This case should hopefully never or seldom happen
10721                canvas = new Canvas(bitmap);
10722            }
10723
10724            if (clear) {
10725                bitmap.eraseColor(drawingCacheBackgroundColor);
10726            }
10727
10728            computeScroll();
10729            final int restoreCount = canvas.save();
10730
10731            if (autoScale && scalingRequired) {
10732                final float scale = attachInfo.mApplicationScale;
10733                canvas.scale(scale, scale);
10734            }
10735
10736            canvas.translate(-mScrollX, -mScrollY);
10737
10738            mPrivateFlags |= DRAWN;
10739            if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
10740                    mLayerType != LAYER_TYPE_NONE) {
10741                mPrivateFlags |= DRAWING_CACHE_VALID;
10742            }
10743
10744            // Fast path for layouts with no backgrounds
10745            if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10746                if (ViewDebug.TRACE_HIERARCHY) {
10747                    ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
10748                }
10749                mPrivateFlags &= ~DIRTY_MASK;
10750                dispatchDraw(canvas);
10751            } else {
10752                draw(canvas);
10753            }
10754
10755            canvas.restoreToCount(restoreCount);
10756            canvas.setBitmap(null);
10757
10758            if (attachInfo != null) {
10759                // Restore the cached Canvas for our siblings
10760                attachInfo.mCanvas = canvas;
10761            }
10762        }
10763    }
10764
10765    /**
10766     * Create a snapshot of the view into a bitmap.  We should probably make
10767     * some form of this public, but should think about the API.
10768     */
10769    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
10770        int width = mRight - mLeft;
10771        int height = mBottom - mTop;
10772
10773        final AttachInfo attachInfo = mAttachInfo;
10774        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
10775        width = (int) ((width * scale) + 0.5f);
10776        height = (int) ((height * scale) + 0.5f);
10777
10778        Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
10779        if (bitmap == null) {
10780            throw new OutOfMemoryError();
10781        }
10782
10783        Resources resources = getResources();
10784        if (resources != null) {
10785            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
10786        }
10787
10788        Canvas canvas;
10789        if (attachInfo != null) {
10790            canvas = attachInfo.mCanvas;
10791            if (canvas == null) {
10792                canvas = new Canvas();
10793            }
10794            canvas.setBitmap(bitmap);
10795            // Temporarily clobber the cached Canvas in case one of our children
10796            // is also using a drawing cache. Without this, the children would
10797            // steal the canvas by attaching their own bitmap to it and bad, bad
10798            // things would happen (invisible views, corrupted drawings, etc.)
10799            attachInfo.mCanvas = null;
10800        } else {
10801            // This case should hopefully never or seldom happen
10802            canvas = new Canvas(bitmap);
10803        }
10804
10805        if ((backgroundColor & 0xff000000) != 0) {
10806            bitmap.eraseColor(backgroundColor);
10807        }
10808
10809        computeScroll();
10810        final int restoreCount = canvas.save();
10811        canvas.scale(scale, scale);
10812        canvas.translate(-mScrollX, -mScrollY);
10813
10814        // Temporarily remove the dirty mask
10815        int flags = mPrivateFlags;
10816        mPrivateFlags &= ~DIRTY_MASK;
10817
10818        // Fast path for layouts with no backgrounds
10819        if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
10820            dispatchDraw(canvas);
10821        } else {
10822            draw(canvas);
10823        }
10824
10825        mPrivateFlags = flags;
10826
10827        canvas.restoreToCount(restoreCount);
10828        canvas.setBitmap(null);
10829
10830        if (attachInfo != null) {
10831            // Restore the cached Canvas for our siblings
10832            attachInfo.mCanvas = canvas;
10833        }
10834
10835        return bitmap;
10836    }
10837
10838    /**
10839     * Indicates whether this View is currently in edit mode. A View is usually
10840     * in edit mode when displayed within a developer tool. For instance, if
10841     * this View is being drawn by a visual user interface builder, this method
10842     * should return true.
10843     *
10844     * Subclasses should check the return value of this method to provide
10845     * different behaviors if their normal behavior might interfere with the
10846     * host environment. For instance: the class spawns a thread in its
10847     * constructor, the drawing code relies on device-specific features, etc.
10848     *
10849     * This method is usually checked in the drawing code of custom widgets.
10850     *
10851     * @return True if this View is in edit mode, false otherwise.
10852     */
10853    public boolean isInEditMode() {
10854        return false;
10855    }
10856
10857    /**
10858     * If the View draws content inside its padding and enables fading edges,
10859     * it needs to support padding offsets. Padding offsets are added to the
10860     * fading edges to extend the length of the fade so that it covers pixels
10861     * drawn inside the padding.
10862     *
10863     * Subclasses of this class should override this method if they need
10864     * to draw content inside the padding.
10865     *
10866     * @return True if padding offset must be applied, false otherwise.
10867     *
10868     * @see #getLeftPaddingOffset()
10869     * @see #getRightPaddingOffset()
10870     * @see #getTopPaddingOffset()
10871     * @see #getBottomPaddingOffset()
10872     *
10873     * @since CURRENT
10874     */
10875    protected boolean isPaddingOffsetRequired() {
10876        return false;
10877    }
10878
10879    /**
10880     * Amount by which to extend the left fading region. Called only when
10881     * {@link #isPaddingOffsetRequired()} returns true.
10882     *
10883     * @return The left padding offset in pixels.
10884     *
10885     * @see #isPaddingOffsetRequired()
10886     *
10887     * @since CURRENT
10888     */
10889    protected int getLeftPaddingOffset() {
10890        return 0;
10891    }
10892
10893    /**
10894     * Amount by which to extend the right fading region. Called only when
10895     * {@link #isPaddingOffsetRequired()} returns true.
10896     *
10897     * @return The right padding offset in pixels.
10898     *
10899     * @see #isPaddingOffsetRequired()
10900     *
10901     * @since CURRENT
10902     */
10903    protected int getRightPaddingOffset() {
10904        return 0;
10905    }
10906
10907    /**
10908     * Amount by which to extend the top fading region. Called only when
10909     * {@link #isPaddingOffsetRequired()} returns true.
10910     *
10911     * @return The top padding offset in pixels.
10912     *
10913     * @see #isPaddingOffsetRequired()
10914     *
10915     * @since CURRENT
10916     */
10917    protected int getTopPaddingOffset() {
10918        return 0;
10919    }
10920
10921    /**
10922     * Amount by which to extend the bottom fading region. Called only when
10923     * {@link #isPaddingOffsetRequired()} returns true.
10924     *
10925     * @return The bottom padding offset in pixels.
10926     *
10927     * @see #isPaddingOffsetRequired()
10928     *
10929     * @since CURRENT
10930     */
10931    protected int getBottomPaddingOffset() {
10932        return 0;
10933    }
10934
10935    /**
10936     * @hide
10937     * @param offsetRequired
10938     */
10939    protected int getFadeTop(boolean offsetRequired) {
10940        int top = mPaddingTop;
10941        if (offsetRequired) top += getTopPaddingOffset();
10942        return top;
10943    }
10944
10945    /**
10946     * @hide
10947     * @param offsetRequired
10948     */
10949    protected int getFadeHeight(boolean offsetRequired) {
10950        int padding = mPaddingTop;
10951        if (offsetRequired) padding += getTopPaddingOffset();
10952        return mBottom - mTop - mPaddingBottom - padding;
10953    }
10954
10955    /**
10956     * <p>Indicates whether this view is attached to an hardware accelerated
10957     * window or not.</p>
10958     *
10959     * <p>Even if this method returns true, it does not mean that every call
10960     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
10961     * accelerated {@link android.graphics.Canvas}. For instance, if this view
10962     * is drawn onto an offscren {@link android.graphics.Bitmap} and its
10963     * window is hardware accelerated,
10964     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
10965     * return false, and this method will return true.</p>
10966     *
10967     * @return True if the view is attached to a window and the window is
10968     *         hardware accelerated; false in any other case.
10969     */
10970    public boolean isHardwareAccelerated() {
10971        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
10972    }
10973
10974    /**
10975     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
10976     * case of an active Animation being run on the view.
10977     */
10978    private boolean drawAnimation(ViewGroup parent, long drawingTime,
10979            Animation a, boolean scalingRequired) {
10980        Transformation invalidationTransform;
10981        final int flags = parent.mGroupFlags;
10982        final boolean initialized = a.isInitialized();
10983        if (!initialized) {
10984            a.initialize(mRight - mLeft, mBottom - mTop, getWidth(), getHeight());
10985            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
10986            onAnimationStart();
10987        }
10988
10989        boolean more = a.getTransformation(drawingTime, parent.mChildTransformation, 1f);
10990        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
10991            if (parent.mInvalidationTransformation == null) {
10992                parent.mInvalidationTransformation = new Transformation();
10993            }
10994            invalidationTransform = parent.mInvalidationTransformation;
10995            a.getTransformation(drawingTime, invalidationTransform, 1f);
10996        } else {
10997            invalidationTransform = parent.mChildTransformation;
10998        }
10999        if (more) {
11000            if (!a.willChangeBounds()) {
11001                if ((flags & (parent.FLAG_OPTIMIZE_INVALIDATE | parent.FLAG_ANIMATION_DONE)) ==
11002                        parent.FLAG_OPTIMIZE_INVALIDATE) {
11003                    parent.mGroupFlags |= parent.FLAG_INVALIDATE_REQUIRED;
11004                } else if ((flags & parent.FLAG_INVALIDATE_REQUIRED) == 0) {
11005                    // The child need to draw an animation, potentially offscreen, so
11006                    // make sure we do not cancel invalidate requests
11007                    parent.mPrivateFlags |= DRAW_ANIMATION;
11008                    parent.invalidate(mLeft, mTop, mRight, mBottom);
11009                }
11010            } else {
11011                if (parent.mInvalidateRegion == null) {
11012                    parent.mInvalidateRegion = new RectF();
11013                }
11014                final RectF region = parent.mInvalidateRegion;
11015                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
11016                        invalidationTransform);
11017
11018                // The child need to draw an animation, potentially offscreen, so
11019                // make sure we do not cancel invalidate requests
11020                parent.mPrivateFlags |= DRAW_ANIMATION;
11021
11022                final int left = mLeft + (int) region.left;
11023                final int top = mTop + (int) region.top;
11024                parent.invalidate(left, top, left + (int) (region.width() + .5f),
11025                        top + (int) (region.height() + .5f));
11026            }
11027        }
11028        return more;
11029    }
11030
11031    /**
11032     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
11033     * This draw() method is an implementation detail and is not intended to be overridden or
11034     * to be called from anywhere else other than ViewGroup.drawChild().
11035     */
11036    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
11037        boolean more = false;
11038        final boolean childHasIdentityMatrix = hasIdentityMatrix();
11039        final int flags = parent.mGroupFlags;
11040
11041        if ((flags & parent.FLAG_CLEAR_TRANSFORMATION) == parent.FLAG_CLEAR_TRANSFORMATION) {
11042            parent.mChildTransformation.clear();
11043            parent.mGroupFlags &= ~parent.FLAG_CLEAR_TRANSFORMATION;
11044        }
11045
11046        Transformation transformToApply = null;
11047        boolean concatMatrix = false;
11048
11049        boolean scalingRequired = false;
11050        boolean caching;
11051        int layerType = parent.mDrawLayers ? getLayerType() : LAYER_TYPE_NONE;
11052
11053        final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
11054        if ((flags & parent.FLAG_CHILDREN_DRAWN_WITH_CACHE) == parent.FLAG_CHILDREN_DRAWN_WITH_CACHE ||
11055                (flags & parent.FLAG_ALWAYS_DRAWN_WITH_CACHE) == parent.FLAG_ALWAYS_DRAWN_WITH_CACHE) {
11056            caching = true;
11057            if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
11058        } else {
11059            caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
11060        }
11061
11062        final Animation a = getAnimation();
11063        if (a != null) {
11064            more = drawAnimation(parent, drawingTime, a, scalingRequired);
11065            concatMatrix = a.willChangeTransformationMatrix();
11066            transformToApply = parent.mChildTransformation;
11067        } else if ((flags & parent.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) ==
11068                parent.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) {
11069            final boolean hasTransform =
11070                    parent.getChildStaticTransformation(this, parent.mChildTransformation);
11071            if (hasTransform) {
11072                final int transformType = parent.mChildTransformation.getTransformationType();
11073                transformToApply = transformType != Transformation.TYPE_IDENTITY ?
11074                        parent.mChildTransformation : null;
11075                concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
11076            }
11077        }
11078
11079        concatMatrix |= !childHasIdentityMatrix;
11080
11081        // Sets the flag as early as possible to allow draw() implementations
11082        // to call invalidate() successfully when doing animations
11083        mPrivateFlags |= DRAWN;
11084
11085        if (!concatMatrix && canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
11086                (mPrivateFlags & DRAW_ANIMATION) == 0) {
11087            return more;
11088        }
11089
11090        if (hardwareAccelerated) {
11091            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
11092            // retain the flag's value temporarily in the mRecreateDisplayList flag
11093            mRecreateDisplayList = (mPrivateFlags & INVALIDATED) == INVALIDATED;
11094            mPrivateFlags &= ~INVALIDATED;
11095        }
11096
11097        computeScroll();
11098
11099        final int sx = mScrollX;
11100        final int sy = mScrollY;
11101
11102        DisplayList displayList = null;
11103        Bitmap cache = null;
11104        boolean hasDisplayList = false;
11105        if (caching) {
11106            if (!hardwareAccelerated) {
11107                if (layerType != LAYER_TYPE_NONE) {
11108                    layerType = LAYER_TYPE_SOFTWARE;
11109                    buildDrawingCache(true);
11110                }
11111                cache = getDrawingCache(true);
11112            } else {
11113                switch (layerType) {
11114                    case LAYER_TYPE_SOFTWARE:
11115                        buildDrawingCache(true);
11116                        cache = getDrawingCache(true);
11117                        break;
11118                    case LAYER_TYPE_NONE:
11119                        // Delay getting the display list until animation-driven alpha values are
11120                        // set up and possibly passed on to the view
11121                        hasDisplayList = canHaveDisplayList();
11122                        break;
11123                }
11124            }
11125        }
11126
11127        final boolean hasNoCache = cache == null || hasDisplayList;
11128        final boolean offsetForScroll = cache == null && !hasDisplayList &&
11129                layerType != LAYER_TYPE_HARDWARE;
11130
11131        final int restoreTo = canvas.save();
11132        if (offsetForScroll) {
11133            canvas.translate(mLeft - sx, mTop - sy);
11134        } else {
11135            canvas.translate(mLeft, mTop);
11136            if (scalingRequired) {
11137                // mAttachInfo cannot be null, otherwise scalingRequired == false
11138                final float scale = 1.0f / mAttachInfo.mApplicationScale;
11139                canvas.scale(scale, scale);
11140            }
11141        }
11142
11143        float alpha = getAlpha();
11144        if (transformToApply != null || alpha < 1.0f || !hasIdentityMatrix()) {
11145            if (transformToApply != null || !childHasIdentityMatrix) {
11146                int transX = 0;
11147                int transY = 0;
11148
11149                if (offsetForScroll) {
11150                    transX = -sx;
11151                    transY = -sy;
11152                }
11153
11154                if (transformToApply != null) {
11155                    if (concatMatrix) {
11156                        // Undo the scroll translation, apply the transformation matrix,
11157                        // then redo the scroll translate to get the correct result.
11158                        canvas.translate(-transX, -transY);
11159                        canvas.concat(transformToApply.getMatrix());
11160                        canvas.translate(transX, transY);
11161                        parent.mGroupFlags |= parent.FLAG_CLEAR_TRANSFORMATION;
11162                    }
11163
11164                    float transformAlpha = transformToApply.getAlpha();
11165                    if (transformAlpha < 1.0f) {
11166                        alpha *= transformToApply.getAlpha();
11167                        parent.mGroupFlags |= parent.FLAG_CLEAR_TRANSFORMATION;
11168                    }
11169                }
11170
11171                if (!childHasIdentityMatrix) {
11172                    canvas.translate(-transX, -transY);
11173                    canvas.concat(getMatrix());
11174                    canvas.translate(transX, transY);
11175                }
11176            }
11177
11178            if (alpha < 1.0f) {
11179                parent.mGroupFlags |= parent.FLAG_CLEAR_TRANSFORMATION;
11180                if (hasNoCache) {
11181                    final int multipliedAlpha = (int) (255 * alpha);
11182                    if (!onSetAlpha(multipliedAlpha)) {
11183                        int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
11184                        if ((flags & parent.FLAG_CLIP_CHILDREN) == parent.FLAG_CLIP_CHILDREN ||
11185                                layerType != LAYER_TYPE_NONE) {
11186                            layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
11187                        }
11188                        if (layerType == LAYER_TYPE_NONE) {
11189                            final int scrollX = hasDisplayList ? 0 : sx;
11190                            final int scrollY = hasDisplayList ? 0 : sy;
11191                            canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
11192                                    scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
11193                        }
11194                    } else {
11195                        // Alpha is handled by the child directly, clobber the layer's alpha
11196                        mPrivateFlags |= ALPHA_SET;
11197                    }
11198                }
11199            }
11200        } else if ((mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
11201            onSetAlpha(255);
11202            mPrivateFlags &= ~ALPHA_SET;
11203        }
11204
11205        if ((flags & parent.FLAG_CLIP_CHILDREN) == parent.FLAG_CLIP_CHILDREN) {
11206            if (offsetForScroll) {
11207                canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
11208            } else {
11209                if (!scalingRequired || cache == null) {
11210                    canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
11211                } else {
11212                    canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
11213                }
11214            }
11215        }
11216
11217        if (hasDisplayList) {
11218            displayList = getDisplayList();
11219            if (!displayList.isValid()) {
11220                // Uncommon, but possible. If a view is removed from the hierarchy during the call
11221                // to getDisplayList(), the display list will be marked invalid and we should not
11222                // try to use it again.
11223                displayList = null;
11224                hasDisplayList = false;
11225            }
11226        }
11227
11228        if (hasNoCache) {
11229            boolean layerRendered = false;
11230            if (layerType == LAYER_TYPE_HARDWARE) {
11231                final HardwareLayer layer = getHardwareLayer();
11232                if (layer != null && layer.isValid()) {
11233                    mLayerPaint.setAlpha((int) (alpha * 255));
11234                    ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
11235                    layerRendered = true;
11236                } else {
11237                    final int scrollX = hasDisplayList ? 0 : sx;
11238                    final int scrollY = hasDisplayList ? 0 : sy;
11239                    canvas.saveLayer(scrollX, scrollY,
11240                            scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
11241                            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
11242                }
11243            }
11244
11245            if (!layerRendered) {
11246                if (!hasDisplayList) {
11247                    // Fast path for layouts with no backgrounds
11248                    if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
11249                        if (ViewDebug.TRACE_HIERARCHY) {
11250                            ViewDebug.trace(parent, ViewDebug.HierarchyTraceType.DRAW);
11251                        }
11252                        mPrivateFlags &= ~DIRTY_MASK;
11253                        dispatchDraw(canvas);
11254                    } else {
11255                        draw(canvas);
11256                    }
11257                } else {
11258                    mPrivateFlags &= ~DIRTY_MASK;
11259                    ((HardwareCanvas) canvas).drawDisplayList(displayList,
11260                            mRight - mLeft, mBottom - mTop, null, flags);
11261                }
11262            }
11263        } else if (cache != null) {
11264            mPrivateFlags &= ~DIRTY_MASK;
11265            Paint cachePaint;
11266
11267            if (layerType == LAYER_TYPE_NONE) {
11268                cachePaint = parent.mCachePaint;
11269                if (cachePaint == null) {
11270                    cachePaint = new Paint();
11271                    cachePaint.setDither(false);
11272                    parent.mCachePaint = cachePaint;
11273                }
11274                if (alpha < 1.0f) {
11275                    cachePaint.setAlpha((int) (alpha * 255));
11276                    parent.mGroupFlags |= parent.FLAG_ALPHA_LOWER_THAN_ONE;
11277                } else if  ((flags & parent.FLAG_ALPHA_LOWER_THAN_ONE) ==
11278                        parent.FLAG_ALPHA_LOWER_THAN_ONE) {
11279                    cachePaint.setAlpha(255);
11280                    parent.mGroupFlags &= ~parent.FLAG_ALPHA_LOWER_THAN_ONE;
11281                }
11282            } else {
11283                cachePaint = mLayerPaint;
11284                cachePaint.setAlpha((int) (alpha * 255));
11285            }
11286            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
11287        }
11288
11289        canvas.restoreToCount(restoreTo);
11290
11291        if (a != null && !more) {
11292            if (!hardwareAccelerated && !a.getFillAfter()) {
11293                onSetAlpha(255);
11294            }
11295            parent.finishAnimatingView(this, a);
11296        }
11297
11298        if (more && hardwareAccelerated) {
11299            // invalidation is the trigger to recreate display lists, so if we're using
11300            // display lists to render, force an invalidate to allow the animation to
11301            // continue drawing another frame
11302            parent.invalidate(true);
11303            if (a.hasAlpha() && (mPrivateFlags & ALPHA_SET) == ALPHA_SET) {
11304                // alpha animations should cause the child to recreate its display list
11305                invalidate(true);
11306            }
11307        }
11308
11309        mRecreateDisplayList = false;
11310
11311        return more;
11312    }
11313
11314    /**
11315     * Manually render this view (and all of its children) to the given Canvas.
11316     * The view must have already done a full layout before this function is
11317     * called.  When implementing a view, implement
11318     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
11319     * If you do need to override this method, call the superclass version.
11320     *
11321     * @param canvas The Canvas to which the View is rendered.
11322     */
11323    public void draw(Canvas canvas) {
11324        if (ViewDebug.TRACE_HIERARCHY) {
11325            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
11326        }
11327
11328        final int privateFlags = mPrivateFlags;
11329        final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&
11330                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
11331        mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;
11332
11333        /*
11334         * Draw traversal performs several drawing steps which must be executed
11335         * in the appropriate order:
11336         *
11337         *      1. Draw the background
11338         *      2. If necessary, save the canvas' layers to prepare for fading
11339         *      3. Draw view's content
11340         *      4. Draw children
11341         *      5. If necessary, draw the fading edges and restore layers
11342         *      6. Draw decorations (scrollbars for instance)
11343         */
11344
11345        // Step 1, draw the background, if needed
11346        int saveCount;
11347
11348        if (!dirtyOpaque) {
11349            final Drawable background = mBGDrawable;
11350            if (background != null) {
11351                final int scrollX = mScrollX;
11352                final int scrollY = mScrollY;
11353
11354                if (mBackgroundSizeChanged) {
11355                    background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
11356                    mBackgroundSizeChanged = false;
11357                }
11358
11359                if ((scrollX | scrollY) == 0) {
11360                    background.draw(canvas);
11361                } else {
11362                    canvas.translate(scrollX, scrollY);
11363                    background.draw(canvas);
11364                    canvas.translate(-scrollX, -scrollY);
11365                }
11366            }
11367        }
11368
11369        // skip step 2 & 5 if possible (common case)
11370        final int viewFlags = mViewFlags;
11371        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
11372        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
11373        if (!verticalEdges && !horizontalEdges) {
11374            // Step 3, draw the content
11375            if (!dirtyOpaque) onDraw(canvas);
11376
11377            // Step 4, draw the children
11378            dispatchDraw(canvas);
11379
11380            // Step 6, draw decorations (scrollbars)
11381            onDrawScrollBars(canvas);
11382
11383            // we're done...
11384            return;
11385        }
11386
11387        /*
11388         * Here we do the full fledged routine...
11389         * (this is an uncommon case where speed matters less,
11390         * this is why we repeat some of the tests that have been
11391         * done above)
11392         */
11393
11394        boolean drawTop = false;
11395        boolean drawBottom = false;
11396        boolean drawLeft = false;
11397        boolean drawRight = false;
11398
11399        float topFadeStrength = 0.0f;
11400        float bottomFadeStrength = 0.0f;
11401        float leftFadeStrength = 0.0f;
11402        float rightFadeStrength = 0.0f;
11403
11404        // Step 2, save the canvas' layers
11405        int paddingLeft = mPaddingLeft;
11406
11407        final boolean offsetRequired = isPaddingOffsetRequired();
11408        if (offsetRequired) {
11409            paddingLeft += getLeftPaddingOffset();
11410        }
11411
11412        int left = mScrollX + paddingLeft;
11413        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
11414        int top = mScrollY + getFadeTop(offsetRequired);
11415        int bottom = top + getFadeHeight(offsetRequired);
11416
11417        if (offsetRequired) {
11418            right += getRightPaddingOffset();
11419            bottom += getBottomPaddingOffset();
11420        }
11421
11422        final ScrollabilityCache scrollabilityCache = mScrollCache;
11423        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
11424        int length = (int) fadeHeight;
11425
11426        // clip the fade length if top and bottom fades overlap
11427        // overlapping fades produce odd-looking artifacts
11428        if (verticalEdges && (top + length > bottom - length)) {
11429            length = (bottom - top) / 2;
11430        }
11431
11432        // also clip horizontal fades if necessary
11433        if (horizontalEdges && (left + length > right - length)) {
11434            length = (right - left) / 2;
11435        }
11436
11437        if (verticalEdges) {
11438            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
11439            drawTop = topFadeStrength * fadeHeight > 1.0f;
11440            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
11441            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
11442        }
11443
11444        if (horizontalEdges) {
11445            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
11446            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
11447            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
11448            drawRight = rightFadeStrength * fadeHeight > 1.0f;
11449        }
11450
11451        saveCount = canvas.getSaveCount();
11452
11453        int solidColor = getSolidColor();
11454        if (solidColor == 0) {
11455            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
11456
11457            if (drawTop) {
11458                canvas.saveLayer(left, top, right, top + length, null, flags);
11459            }
11460
11461            if (drawBottom) {
11462                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
11463            }
11464
11465            if (drawLeft) {
11466                canvas.saveLayer(left, top, left + length, bottom, null, flags);
11467            }
11468
11469            if (drawRight) {
11470                canvas.saveLayer(right - length, top, right, bottom, null, flags);
11471            }
11472        } else {
11473            scrollabilityCache.setFadeColor(solidColor);
11474        }
11475
11476        // Step 3, draw the content
11477        if (!dirtyOpaque) onDraw(canvas);
11478
11479        // Step 4, draw the children
11480        dispatchDraw(canvas);
11481
11482        // Step 5, draw the fade effect and restore layers
11483        final Paint p = scrollabilityCache.paint;
11484        final Matrix matrix = scrollabilityCache.matrix;
11485        final Shader fade = scrollabilityCache.shader;
11486
11487        if (drawTop) {
11488            matrix.setScale(1, fadeHeight * topFadeStrength);
11489            matrix.postTranslate(left, top);
11490            fade.setLocalMatrix(matrix);
11491            canvas.drawRect(left, top, right, top + length, p);
11492        }
11493
11494        if (drawBottom) {
11495            matrix.setScale(1, fadeHeight * bottomFadeStrength);
11496            matrix.postRotate(180);
11497            matrix.postTranslate(left, bottom);
11498            fade.setLocalMatrix(matrix);
11499            canvas.drawRect(left, bottom - length, right, bottom, p);
11500        }
11501
11502        if (drawLeft) {
11503            matrix.setScale(1, fadeHeight * leftFadeStrength);
11504            matrix.postRotate(-90);
11505            matrix.postTranslate(left, top);
11506            fade.setLocalMatrix(matrix);
11507            canvas.drawRect(left, top, left + length, bottom, p);
11508        }
11509
11510        if (drawRight) {
11511            matrix.setScale(1, fadeHeight * rightFadeStrength);
11512            matrix.postRotate(90);
11513            matrix.postTranslate(right, top);
11514            fade.setLocalMatrix(matrix);
11515            canvas.drawRect(right - length, top, right, bottom, p);
11516        }
11517
11518        canvas.restoreToCount(saveCount);
11519
11520        // Step 6, draw decorations (scrollbars)
11521        onDrawScrollBars(canvas);
11522    }
11523
11524    /**
11525     * Override this if your view is known to always be drawn on top of a solid color background,
11526     * and needs to draw fading edges. Returning a non-zero color enables the view system to
11527     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
11528     * should be set to 0xFF.
11529     *
11530     * @see #setVerticalFadingEdgeEnabled(boolean)
11531     * @see #setHorizontalFadingEdgeEnabled(boolean)
11532     *
11533     * @return The known solid color background for this view, or 0 if the color may vary
11534     */
11535    @ViewDebug.ExportedProperty(category = "drawing")
11536    public int getSolidColor() {
11537        return 0;
11538    }
11539
11540    /**
11541     * Build a human readable string representation of the specified view flags.
11542     *
11543     * @param flags the view flags to convert to a string
11544     * @return a String representing the supplied flags
11545     */
11546    private static String printFlags(int flags) {
11547        String output = "";
11548        int numFlags = 0;
11549        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
11550            output += "TAKES_FOCUS";
11551            numFlags++;
11552        }
11553
11554        switch (flags & VISIBILITY_MASK) {
11555        case INVISIBLE:
11556            if (numFlags > 0) {
11557                output += " ";
11558            }
11559            output += "INVISIBLE";
11560            // USELESS HERE numFlags++;
11561            break;
11562        case GONE:
11563            if (numFlags > 0) {
11564                output += " ";
11565            }
11566            output += "GONE";
11567            // USELESS HERE numFlags++;
11568            break;
11569        default:
11570            break;
11571        }
11572        return output;
11573    }
11574
11575    /**
11576     * Build a human readable string representation of the specified private
11577     * view flags.
11578     *
11579     * @param privateFlags the private view flags to convert to a string
11580     * @return a String representing the supplied flags
11581     */
11582    private static String printPrivateFlags(int privateFlags) {
11583        String output = "";
11584        int numFlags = 0;
11585
11586        if ((privateFlags & WANTS_FOCUS) == WANTS_FOCUS) {
11587            output += "WANTS_FOCUS";
11588            numFlags++;
11589        }
11590
11591        if ((privateFlags & FOCUSED) == FOCUSED) {
11592            if (numFlags > 0) {
11593                output += " ";
11594            }
11595            output += "FOCUSED";
11596            numFlags++;
11597        }
11598
11599        if ((privateFlags & SELECTED) == SELECTED) {
11600            if (numFlags > 0) {
11601                output += " ";
11602            }
11603            output += "SELECTED";
11604            numFlags++;
11605        }
11606
11607        if ((privateFlags & IS_ROOT_NAMESPACE) == IS_ROOT_NAMESPACE) {
11608            if (numFlags > 0) {
11609                output += " ";
11610            }
11611            output += "IS_ROOT_NAMESPACE";
11612            numFlags++;
11613        }
11614
11615        if ((privateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
11616            if (numFlags > 0) {
11617                output += " ";
11618            }
11619            output += "HAS_BOUNDS";
11620            numFlags++;
11621        }
11622
11623        if ((privateFlags & DRAWN) == DRAWN) {
11624            if (numFlags > 0) {
11625                output += " ";
11626            }
11627            output += "DRAWN";
11628            // USELESS HERE numFlags++;
11629        }
11630        return output;
11631    }
11632
11633    /**
11634     * <p>Indicates whether or not this view's layout will be requested during
11635     * the next hierarchy layout pass.</p>
11636     *
11637     * @return true if the layout will be forced during next layout pass
11638     */
11639    public boolean isLayoutRequested() {
11640        return (mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT;
11641    }
11642
11643    /**
11644     * Assign a size and position to a view and all of its
11645     * descendants
11646     *
11647     * <p>This is the second phase of the layout mechanism.
11648     * (The first is measuring). In this phase, each parent calls
11649     * layout on all of its children to position them.
11650     * This is typically done using the child measurements
11651     * that were stored in the measure pass().</p>
11652     *
11653     * <p>Derived classes should not override this method.
11654     * Derived classes with children should override
11655     * onLayout. In that method, they should
11656     * call layout on each of their children.</p>
11657     *
11658     * @param l Left position, relative to parent
11659     * @param t Top position, relative to parent
11660     * @param r Right position, relative to parent
11661     * @param b Bottom position, relative to parent
11662     */
11663    @SuppressWarnings({"unchecked"})
11664    public void layout(int l, int t, int r, int b) {
11665        int oldL = mLeft;
11666        int oldT = mTop;
11667        int oldB = mBottom;
11668        int oldR = mRight;
11669        boolean changed = setFrame(l, t, r, b);
11670        if (changed || (mPrivateFlags & LAYOUT_REQUIRED) == LAYOUT_REQUIRED) {
11671            if (ViewDebug.TRACE_HIERARCHY) {
11672                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_LAYOUT);
11673            }
11674
11675            onLayout(changed, l, t, r, b);
11676            mPrivateFlags &= ~LAYOUT_REQUIRED;
11677
11678            ListenerInfo li = mListenerInfo;
11679            if (li != null && li.mOnLayoutChangeListeners != null) {
11680                ArrayList<OnLayoutChangeListener> listenersCopy =
11681                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
11682                int numListeners = listenersCopy.size();
11683                for (int i = 0; i < numListeners; ++i) {
11684                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
11685                }
11686            }
11687        }
11688        mPrivateFlags &= ~FORCE_LAYOUT;
11689    }
11690
11691    /**
11692     * Called from layout when this view should
11693     * assign a size and position to each of its children.
11694     *
11695     * Derived classes with children should override
11696     * this method and call layout on each of
11697     * their children.
11698     * @param changed This is a new size or position for this view
11699     * @param left Left position, relative to parent
11700     * @param top Top position, relative to parent
11701     * @param right Right position, relative to parent
11702     * @param bottom Bottom position, relative to parent
11703     */
11704    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
11705    }
11706
11707    /**
11708     * Assign a size and position to this view.
11709     *
11710     * This is called from layout.
11711     *
11712     * @param left Left position, relative to parent
11713     * @param top Top position, relative to parent
11714     * @param right Right position, relative to parent
11715     * @param bottom Bottom position, relative to parent
11716     * @return true if the new size and position are different than the
11717     *         previous ones
11718     * {@hide}
11719     */
11720    protected boolean setFrame(int left, int top, int right, int bottom) {
11721        boolean changed = false;
11722
11723        if (DBG) {
11724            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
11725                    + right + "," + bottom + ")");
11726        }
11727
11728        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
11729            changed = true;
11730
11731            // Remember our drawn bit
11732            int drawn = mPrivateFlags & DRAWN;
11733
11734            int oldWidth = mRight - mLeft;
11735            int oldHeight = mBottom - mTop;
11736            int newWidth = right - left;
11737            int newHeight = bottom - top;
11738            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
11739
11740            // Invalidate our old position
11741            invalidate(sizeChanged);
11742
11743            mLeft = left;
11744            mTop = top;
11745            mRight = right;
11746            mBottom = bottom;
11747
11748            mPrivateFlags |= HAS_BOUNDS;
11749
11750
11751            if (sizeChanged) {
11752                if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) {
11753                    // A change in dimension means an auto-centered pivot point changes, too
11754                    if (mTransformationInfo != null) {
11755                        mTransformationInfo.mMatrixDirty = true;
11756                    }
11757                }
11758                onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
11759            }
11760
11761            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
11762                // If we are visible, force the DRAWN bit to on so that
11763                // this invalidate will go through (at least to our parent).
11764                // This is because someone may have invalidated this view
11765                // before this call to setFrame came in, thereby clearing
11766                // the DRAWN bit.
11767                mPrivateFlags |= DRAWN;
11768                invalidate(sizeChanged);
11769                // parent display list may need to be recreated based on a change in the bounds
11770                // of any child
11771                invalidateParentCaches();
11772            }
11773
11774            // Reset drawn bit to original value (invalidate turns it off)
11775            mPrivateFlags |= drawn;
11776
11777            mBackgroundSizeChanged = true;
11778        }
11779        return changed;
11780    }
11781
11782    /**
11783     * Finalize inflating a view from XML.  This is called as the last phase
11784     * of inflation, after all child views have been added.
11785     *
11786     * <p>Even if the subclass overrides onFinishInflate, they should always be
11787     * sure to call the super method, so that we get called.
11788     */
11789    protected void onFinishInflate() {
11790    }
11791
11792    /**
11793     * Returns the resources associated with this view.
11794     *
11795     * @return Resources object.
11796     */
11797    public Resources getResources() {
11798        return mResources;
11799    }
11800
11801    /**
11802     * Invalidates the specified Drawable.
11803     *
11804     * @param drawable the drawable to invalidate
11805     */
11806    public void invalidateDrawable(Drawable drawable) {
11807        if (verifyDrawable(drawable)) {
11808            final Rect dirty = drawable.getBounds();
11809            final int scrollX = mScrollX;
11810            final int scrollY = mScrollY;
11811
11812            invalidate(dirty.left + scrollX, dirty.top + scrollY,
11813                    dirty.right + scrollX, dirty.bottom + scrollY);
11814        }
11815    }
11816
11817    /**
11818     * Schedules an action on a drawable to occur at a specified time.
11819     *
11820     * @param who the recipient of the action
11821     * @param what the action to run on the drawable
11822     * @param when the time at which the action must occur. Uses the
11823     *        {@link SystemClock#uptimeMillis} timebase.
11824     */
11825    public void scheduleDrawable(Drawable who, Runnable what, long when) {
11826        if (verifyDrawable(who) && what != null) {
11827            if (mAttachInfo != null) {
11828                mAttachInfo.mHandler.postAtTime(what, who, when);
11829            } else {
11830                ViewRootImpl.getRunQueue().postDelayed(what, when - SystemClock.uptimeMillis());
11831            }
11832        }
11833    }
11834
11835    /**
11836     * Cancels a scheduled action on a drawable.
11837     *
11838     * @param who the recipient of the action
11839     * @param what the action to cancel
11840     */
11841    public void unscheduleDrawable(Drawable who, Runnable what) {
11842        if (verifyDrawable(who) && what != null) {
11843            if (mAttachInfo != null) {
11844                mAttachInfo.mHandler.removeCallbacks(what, who);
11845            } else {
11846                ViewRootImpl.getRunQueue().removeCallbacks(what);
11847            }
11848        }
11849    }
11850
11851    /**
11852     * Unschedule any events associated with the given Drawable.  This can be
11853     * used when selecting a new Drawable into a view, so that the previous
11854     * one is completely unscheduled.
11855     *
11856     * @param who The Drawable to unschedule.
11857     *
11858     * @see #drawableStateChanged
11859     */
11860    public void unscheduleDrawable(Drawable who) {
11861        if (mAttachInfo != null) {
11862            mAttachInfo.mHandler.removeCallbacksAndMessages(who);
11863        }
11864    }
11865
11866    /**
11867    * Return the layout direction of a given Drawable.
11868    *
11869    * @param who the Drawable to query
11870    *
11871    * @hide
11872    */
11873    public int getResolvedLayoutDirection(Drawable who) {
11874        return (who == mBGDrawable) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT;
11875    }
11876
11877    /**
11878     * If your view subclass is displaying its own Drawable objects, it should
11879     * override this function and return true for any Drawable it is
11880     * displaying.  This allows animations for those drawables to be
11881     * scheduled.
11882     *
11883     * <p>Be sure to call through to the super class when overriding this
11884     * function.
11885     *
11886     * @param who The Drawable to verify.  Return true if it is one you are
11887     *            displaying, else return the result of calling through to the
11888     *            super class.
11889     *
11890     * @return boolean If true than the Drawable is being displayed in the
11891     *         view; else false and it is not allowed to animate.
11892     *
11893     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
11894     * @see #drawableStateChanged()
11895     */
11896    protected boolean verifyDrawable(Drawable who) {
11897        return who == mBGDrawable;
11898    }
11899
11900    /**
11901     * This function is called whenever the state of the view changes in such
11902     * a way that it impacts the state of drawables being shown.
11903     *
11904     * <p>Be sure to call through to the superclass when overriding this
11905     * function.
11906     *
11907     * @see Drawable#setState(int[])
11908     */
11909    protected void drawableStateChanged() {
11910        Drawable d = mBGDrawable;
11911        if (d != null && d.isStateful()) {
11912            d.setState(getDrawableState());
11913        }
11914    }
11915
11916    /**
11917     * Call this to force a view to update its drawable state. This will cause
11918     * drawableStateChanged to be called on this view. Views that are interested
11919     * in the new state should call getDrawableState.
11920     *
11921     * @see #drawableStateChanged
11922     * @see #getDrawableState
11923     */
11924    public void refreshDrawableState() {
11925        mPrivateFlags |= DRAWABLE_STATE_DIRTY;
11926        drawableStateChanged();
11927
11928        ViewParent parent = mParent;
11929        if (parent != null) {
11930            parent.childDrawableStateChanged(this);
11931        }
11932    }
11933
11934    /**
11935     * Return an array of resource IDs of the drawable states representing the
11936     * current state of the view.
11937     *
11938     * @return The current drawable state
11939     *
11940     * @see Drawable#setState(int[])
11941     * @see #drawableStateChanged()
11942     * @see #onCreateDrawableState(int)
11943     */
11944    public final int[] getDrawableState() {
11945        if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
11946            return mDrawableState;
11947        } else {
11948            mDrawableState = onCreateDrawableState(0);
11949            mPrivateFlags &= ~DRAWABLE_STATE_DIRTY;
11950            return mDrawableState;
11951        }
11952    }
11953
11954    /**
11955     * Generate the new {@link android.graphics.drawable.Drawable} state for
11956     * this view. This is called by the view
11957     * system when the cached Drawable state is determined to be invalid.  To
11958     * retrieve the current state, you should use {@link #getDrawableState}.
11959     *
11960     * @param extraSpace if non-zero, this is the number of extra entries you
11961     * would like in the returned array in which you can place your own
11962     * states.
11963     *
11964     * @return Returns an array holding the current {@link Drawable} state of
11965     * the view.
11966     *
11967     * @see #mergeDrawableStates(int[], int[])
11968     */
11969    protected int[] onCreateDrawableState(int extraSpace) {
11970        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
11971                mParent instanceof View) {
11972            return ((View) mParent).onCreateDrawableState(extraSpace);
11973        }
11974
11975        int[] drawableState;
11976
11977        int privateFlags = mPrivateFlags;
11978
11979        int viewStateIndex = 0;
11980        if ((privateFlags & PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
11981        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
11982        if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
11983        if ((privateFlags & SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
11984        if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
11985        if ((privateFlags & ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
11986        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
11987                HardwareRenderer.isAvailable()) {
11988            // This is set if HW acceleration is requested, even if the current
11989            // process doesn't allow it.  This is just to allow app preview
11990            // windows to better match their app.
11991            viewStateIndex |= VIEW_STATE_ACCELERATED;
11992        }
11993        if ((privateFlags & HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
11994
11995        final int privateFlags2 = mPrivateFlags2;
11996        if ((privateFlags2 & DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
11997        if ((privateFlags2 & DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
11998
11999        drawableState = VIEW_STATE_SETS[viewStateIndex];
12000
12001        //noinspection ConstantIfStatement
12002        if (false) {
12003            Log.i("View", "drawableStateIndex=" + viewStateIndex);
12004            Log.i("View", toString()
12005                    + " pressed=" + ((privateFlags & PRESSED) != 0)
12006                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
12007                    + " fo=" + hasFocus()
12008                    + " sl=" + ((privateFlags & SELECTED) != 0)
12009                    + " wf=" + hasWindowFocus()
12010                    + ": " + Arrays.toString(drawableState));
12011        }
12012
12013        if (extraSpace == 0) {
12014            return drawableState;
12015        }
12016
12017        final int[] fullState;
12018        if (drawableState != null) {
12019            fullState = new int[drawableState.length + extraSpace];
12020            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
12021        } else {
12022            fullState = new int[extraSpace];
12023        }
12024
12025        return fullState;
12026    }
12027
12028    /**
12029     * Merge your own state values in <var>additionalState</var> into the base
12030     * state values <var>baseState</var> that were returned by
12031     * {@link #onCreateDrawableState(int)}.
12032     *
12033     * @param baseState The base state values returned by
12034     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
12035     * own additional state values.
12036     *
12037     * @param additionalState The additional state values you would like
12038     * added to <var>baseState</var>; this array is not modified.
12039     *
12040     * @return As a convenience, the <var>baseState</var> array you originally
12041     * passed into the function is returned.
12042     *
12043     * @see #onCreateDrawableState(int)
12044     */
12045    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
12046        final int N = baseState.length;
12047        int i = N - 1;
12048        while (i >= 0 && baseState[i] == 0) {
12049            i--;
12050        }
12051        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
12052        return baseState;
12053    }
12054
12055    /**
12056     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
12057     * on all Drawable objects associated with this view.
12058     */
12059    public void jumpDrawablesToCurrentState() {
12060        if (mBGDrawable != null) {
12061            mBGDrawable.jumpToCurrentState();
12062        }
12063    }
12064
12065    /**
12066     * Sets the background color for this view.
12067     * @param color the color of the background
12068     */
12069    @RemotableViewMethod
12070    public void setBackgroundColor(int color) {
12071        if (mBGDrawable instanceof ColorDrawable) {
12072            ((ColorDrawable) mBGDrawable).setColor(color);
12073        } else {
12074            setBackgroundDrawable(new ColorDrawable(color));
12075        }
12076    }
12077
12078    /**
12079     * Set the background to a given resource. The resource should refer to
12080     * a Drawable object or 0 to remove the background.
12081     * @param resid The identifier of the resource.
12082     * @attr ref android.R.styleable#View_background
12083     */
12084    @RemotableViewMethod
12085    public void setBackgroundResource(int resid) {
12086        if (resid != 0 && resid == mBackgroundResource) {
12087            return;
12088        }
12089
12090        Drawable d= null;
12091        if (resid != 0) {
12092            d = mResources.getDrawable(resid);
12093        }
12094        setBackgroundDrawable(d);
12095
12096        mBackgroundResource = resid;
12097    }
12098
12099    /**
12100     * Set the background to a given Drawable, or remove the background. If the
12101     * background has padding, this View's padding is set to the background's
12102     * padding. However, when a background is removed, this View's padding isn't
12103     * touched. If setting the padding is desired, please use
12104     * {@link #setPadding(int, int, int, int)}.
12105     *
12106     * @param d The Drawable to use as the background, or null to remove the
12107     *        background
12108     */
12109    public void setBackgroundDrawable(Drawable d) {
12110        if (d == mBGDrawable) {
12111            return;
12112        }
12113
12114        boolean requestLayout = false;
12115
12116        mBackgroundResource = 0;
12117
12118        /*
12119         * Regardless of whether we're setting a new background or not, we want
12120         * to clear the previous drawable.
12121         */
12122        if (mBGDrawable != null) {
12123            mBGDrawable.setCallback(null);
12124            unscheduleDrawable(mBGDrawable);
12125        }
12126
12127        if (d != null) {
12128            Rect padding = sThreadLocal.get();
12129            if (padding == null) {
12130                padding = new Rect();
12131                sThreadLocal.set(padding);
12132            }
12133            if (d.getPadding(padding)) {
12134                switch (d.getResolvedLayoutDirectionSelf()) {
12135                    case LAYOUT_DIRECTION_RTL:
12136                        setPadding(padding.right, padding.top, padding.left, padding.bottom);
12137                        break;
12138                    case LAYOUT_DIRECTION_LTR:
12139                    default:
12140                        setPadding(padding.left, padding.top, padding.right, padding.bottom);
12141                }
12142            }
12143
12144            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
12145            // if it has a different minimum size, we should layout again
12146            if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
12147                    mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
12148                requestLayout = true;
12149            }
12150
12151            d.setCallback(this);
12152            if (d.isStateful()) {
12153                d.setState(getDrawableState());
12154            }
12155            d.setVisible(getVisibility() == VISIBLE, false);
12156            mBGDrawable = d;
12157
12158            if ((mPrivateFlags & SKIP_DRAW) != 0) {
12159                mPrivateFlags &= ~SKIP_DRAW;
12160                mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
12161                requestLayout = true;
12162            }
12163        } else {
12164            /* Remove the background */
12165            mBGDrawable = null;
12166
12167            if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
12168                /*
12169                 * This view ONLY drew the background before and we're removing
12170                 * the background, so now it won't draw anything
12171                 * (hence we SKIP_DRAW)
12172                 */
12173                mPrivateFlags &= ~ONLY_DRAWS_BACKGROUND;
12174                mPrivateFlags |= SKIP_DRAW;
12175            }
12176
12177            /*
12178             * When the background is set, we try to apply its padding to this
12179             * View. When the background is removed, we don't touch this View's
12180             * padding. This is noted in the Javadocs. Hence, we don't need to
12181             * requestLayout(), the invalidate() below is sufficient.
12182             */
12183
12184            // The old background's minimum size could have affected this
12185            // View's layout, so let's requestLayout
12186            requestLayout = true;
12187        }
12188
12189        computeOpaqueFlags();
12190
12191        if (requestLayout) {
12192            requestLayout();
12193        }
12194
12195        mBackgroundSizeChanged = true;
12196        invalidate(true);
12197    }
12198
12199    /**
12200     * Gets the background drawable
12201     * @return The drawable used as the background for this view, if any.
12202     */
12203    public Drawable getBackground() {
12204        return mBGDrawable;
12205    }
12206
12207    /**
12208     * Sets the padding. The view may add on the space required to display
12209     * the scrollbars, depending on the style and visibility of the scrollbars.
12210     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
12211     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
12212     * from the values set in this call.
12213     *
12214     * @attr ref android.R.styleable#View_padding
12215     * @attr ref android.R.styleable#View_paddingBottom
12216     * @attr ref android.R.styleable#View_paddingLeft
12217     * @attr ref android.R.styleable#View_paddingRight
12218     * @attr ref android.R.styleable#View_paddingTop
12219     * @param left the left padding in pixels
12220     * @param top the top padding in pixels
12221     * @param right the right padding in pixels
12222     * @param bottom the bottom padding in pixels
12223     */
12224    public void setPadding(int left, int top, int right, int bottom) {
12225        boolean changed = false;
12226
12227        mUserPaddingRelative = false;
12228
12229        mUserPaddingLeft = left;
12230        mUserPaddingRight = right;
12231        mUserPaddingBottom = bottom;
12232
12233        final int viewFlags = mViewFlags;
12234
12235        // Common case is there are no scroll bars.
12236        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
12237            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
12238                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
12239                        ? 0 : getVerticalScrollbarWidth();
12240                switch (mVerticalScrollbarPosition) {
12241                    case SCROLLBAR_POSITION_DEFAULT:
12242                        if (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
12243                            left += offset;
12244                        } else {
12245                            right += offset;
12246                        }
12247                        break;
12248                    case SCROLLBAR_POSITION_RIGHT:
12249                        right += offset;
12250                        break;
12251                    case SCROLLBAR_POSITION_LEFT:
12252                        left += offset;
12253                        break;
12254                }
12255            }
12256            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
12257                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
12258                        ? 0 : getHorizontalScrollbarHeight();
12259            }
12260        }
12261
12262        if (mPaddingLeft != left) {
12263            changed = true;
12264            mPaddingLeft = left;
12265        }
12266        if (mPaddingTop != top) {
12267            changed = true;
12268            mPaddingTop = top;
12269        }
12270        if (mPaddingRight != right) {
12271            changed = true;
12272            mPaddingRight = right;
12273        }
12274        if (mPaddingBottom != bottom) {
12275            changed = true;
12276            mPaddingBottom = bottom;
12277        }
12278
12279        if (changed) {
12280            requestLayout();
12281        }
12282    }
12283
12284    /**
12285     * Sets the relative padding. The view may add on the space required to display
12286     * the scrollbars, depending on the style and visibility of the scrollbars.
12287     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
12288     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
12289     * from the values set in this call.
12290     *
12291     * @attr ref android.R.styleable#View_padding
12292     * @attr ref android.R.styleable#View_paddingBottom
12293     * @attr ref android.R.styleable#View_paddingStart
12294     * @attr ref android.R.styleable#View_paddingEnd
12295     * @attr ref android.R.styleable#View_paddingTop
12296     * @param start the start padding in pixels
12297     * @param top the top padding in pixels
12298     * @param end the end padding in pixels
12299     * @param bottom the bottom padding in pixels
12300     */
12301    public void setPaddingRelative(int start, int top, int end, int bottom) {
12302        mUserPaddingRelative = true;
12303
12304        mUserPaddingStart = start;
12305        mUserPaddingEnd = end;
12306
12307        switch(getResolvedLayoutDirection()) {
12308            case LAYOUT_DIRECTION_RTL:
12309                setPadding(end, top, start, bottom);
12310                break;
12311            case LAYOUT_DIRECTION_LTR:
12312            default:
12313                setPadding(start, top, end, bottom);
12314        }
12315    }
12316
12317    /**
12318     * Returns the top padding of this view.
12319     *
12320     * @return the top padding in pixels
12321     */
12322    public int getPaddingTop() {
12323        return mPaddingTop;
12324    }
12325
12326    /**
12327     * Returns the bottom padding of this view. If there are inset and enabled
12328     * scrollbars, this value may include the space required to display the
12329     * scrollbars as well.
12330     *
12331     * @return the bottom padding in pixels
12332     */
12333    public int getPaddingBottom() {
12334        return mPaddingBottom;
12335    }
12336
12337    /**
12338     * Returns the left padding of this view. If there are inset and enabled
12339     * scrollbars, this value may include the space required to display the
12340     * scrollbars as well.
12341     *
12342     * @return the left padding in pixels
12343     */
12344    public int getPaddingLeft() {
12345        return mPaddingLeft;
12346    }
12347
12348    /**
12349     * Returns the start padding of this view. If there are inset and enabled
12350     * scrollbars, this value may include the space required to display the
12351     * scrollbars as well.
12352     *
12353     * @return the start padding in pixels
12354     */
12355    public int getPaddingStart() {
12356        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
12357                mPaddingRight : mPaddingLeft;
12358    }
12359
12360    /**
12361     * Returns the right padding of this view. If there are inset and enabled
12362     * scrollbars, this value may include the space required to display the
12363     * scrollbars as well.
12364     *
12365     * @return the right padding in pixels
12366     */
12367    public int getPaddingRight() {
12368        return mPaddingRight;
12369    }
12370
12371    /**
12372     * Returns the end padding of this view. If there are inset and enabled
12373     * scrollbars, this value may include the space required to display the
12374     * scrollbars as well.
12375     *
12376     * @return the end padding in pixels
12377     */
12378    public int getPaddingEnd() {
12379        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
12380                mPaddingLeft : mPaddingRight;
12381    }
12382
12383    /**
12384     * Return if the padding as been set thru relative values
12385     * {@link #setPaddingRelative(int, int, int, int)} or thru
12386     * @attr ref android.R.styleable#View_paddingStart or
12387     * @attr ref android.R.styleable#View_paddingEnd
12388     *
12389     * @return true if the padding is relative or false if it is not.
12390     */
12391    public boolean isPaddingRelative() {
12392        return mUserPaddingRelative;
12393    }
12394
12395    /**
12396     * Changes the selection state of this view. A view can be selected or not.
12397     * Note that selection is not the same as focus. Views are typically
12398     * selected in the context of an AdapterView like ListView or GridView;
12399     * the selected view is the view that is highlighted.
12400     *
12401     * @param selected true if the view must be selected, false otherwise
12402     */
12403    public void setSelected(boolean selected) {
12404        if (((mPrivateFlags & SELECTED) != 0) != selected) {
12405            mPrivateFlags = (mPrivateFlags & ~SELECTED) | (selected ? SELECTED : 0);
12406            if (!selected) resetPressedState();
12407            invalidate(true);
12408            refreshDrawableState();
12409            dispatchSetSelected(selected);
12410        }
12411    }
12412
12413    /**
12414     * Dispatch setSelected to all of this View's children.
12415     *
12416     * @see #setSelected(boolean)
12417     *
12418     * @param selected The new selected state
12419     */
12420    protected void dispatchSetSelected(boolean selected) {
12421    }
12422
12423    /**
12424     * Indicates the selection state of this view.
12425     *
12426     * @return true if the view is selected, false otherwise
12427     */
12428    @ViewDebug.ExportedProperty
12429    public boolean isSelected() {
12430        return (mPrivateFlags & SELECTED) != 0;
12431    }
12432
12433    /**
12434     * Changes the activated state of this view. A view can be activated or not.
12435     * Note that activation is not the same as selection.  Selection is
12436     * a transient property, representing the view (hierarchy) the user is
12437     * currently interacting with.  Activation is a longer-term state that the
12438     * user can move views in and out of.  For example, in a list view with
12439     * single or multiple selection enabled, the views in the current selection
12440     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
12441     * here.)  The activated state is propagated down to children of the view it
12442     * is set on.
12443     *
12444     * @param activated true if the view must be activated, false otherwise
12445     */
12446    public void setActivated(boolean activated) {
12447        if (((mPrivateFlags & ACTIVATED) != 0) != activated) {
12448            mPrivateFlags = (mPrivateFlags & ~ACTIVATED) | (activated ? ACTIVATED : 0);
12449            invalidate(true);
12450            refreshDrawableState();
12451            dispatchSetActivated(activated);
12452        }
12453    }
12454
12455    /**
12456     * Dispatch setActivated to all of this View's children.
12457     *
12458     * @see #setActivated(boolean)
12459     *
12460     * @param activated The new activated state
12461     */
12462    protected void dispatchSetActivated(boolean activated) {
12463    }
12464
12465    /**
12466     * Indicates the activation state of this view.
12467     *
12468     * @return true if the view is activated, false otherwise
12469     */
12470    @ViewDebug.ExportedProperty
12471    public boolean isActivated() {
12472        return (mPrivateFlags & ACTIVATED) != 0;
12473    }
12474
12475    /**
12476     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
12477     * observer can be used to get notifications when global events, like
12478     * layout, happen.
12479     *
12480     * The returned ViewTreeObserver observer is not guaranteed to remain
12481     * valid for the lifetime of this View. If the caller of this method keeps
12482     * a long-lived reference to ViewTreeObserver, it should always check for
12483     * the return value of {@link ViewTreeObserver#isAlive()}.
12484     *
12485     * @return The ViewTreeObserver for this view's hierarchy.
12486     */
12487    public ViewTreeObserver getViewTreeObserver() {
12488        if (mAttachInfo != null) {
12489            return mAttachInfo.mTreeObserver;
12490        }
12491        if (mFloatingTreeObserver == null) {
12492            mFloatingTreeObserver = new ViewTreeObserver();
12493        }
12494        return mFloatingTreeObserver;
12495    }
12496
12497    /**
12498     * <p>Finds the topmost view in the current view hierarchy.</p>
12499     *
12500     * @return the topmost view containing this view
12501     */
12502    public View getRootView() {
12503        if (mAttachInfo != null) {
12504            final View v = mAttachInfo.mRootView;
12505            if (v != null) {
12506                return v;
12507            }
12508        }
12509
12510        View parent = this;
12511
12512        while (parent.mParent != null && parent.mParent instanceof View) {
12513            parent = (View) parent.mParent;
12514        }
12515
12516        return parent;
12517    }
12518
12519    /**
12520     * <p>Computes the coordinates of this view on the screen. The argument
12521     * must be an array of two integers. After the method returns, the array
12522     * contains the x and y location in that order.</p>
12523     *
12524     * @param location an array of two integers in which to hold the coordinates
12525     */
12526    public void getLocationOnScreen(int[] location) {
12527        getLocationInWindow(location);
12528
12529        final AttachInfo info = mAttachInfo;
12530        if (info != null) {
12531            location[0] += info.mWindowLeft;
12532            location[1] += info.mWindowTop;
12533        }
12534    }
12535
12536    /**
12537     * <p>Computes the coordinates of this view in its window. The argument
12538     * must be an array of two integers. After the method returns, the array
12539     * contains the x and y location in that order.</p>
12540     *
12541     * @param location an array of two integers in which to hold the coordinates
12542     */
12543    public void getLocationInWindow(int[] location) {
12544        if (location == null || location.length < 2) {
12545            throw new IllegalArgumentException("location must be an array of two integers");
12546        }
12547
12548        if (mAttachInfo == null) {
12549            // When the view is not attached to a window, this method does not make sense
12550            location[0] = location[1] = 0;
12551            return;
12552        }
12553
12554        float[] position = mAttachInfo.mTmpTransformLocation;
12555        position[0] = position[1] = 0.0f;
12556
12557        if (!hasIdentityMatrix()) {
12558            getMatrix().mapPoints(position);
12559        }
12560
12561        position[0] += mLeft;
12562        position[1] += mTop;
12563
12564        ViewParent viewParent = mParent;
12565        while (viewParent instanceof View) {
12566            final View view = (View) viewParent;
12567
12568            position[0] -= view.mScrollX;
12569            position[1] -= view.mScrollY;
12570
12571            if (!view.hasIdentityMatrix()) {
12572                view.getMatrix().mapPoints(position);
12573            }
12574
12575            position[0] += view.mLeft;
12576            position[1] += view.mTop;
12577
12578            viewParent = view.mParent;
12579        }
12580
12581        if (viewParent instanceof ViewRootImpl) {
12582            // *cough*
12583            final ViewRootImpl vr = (ViewRootImpl) viewParent;
12584            position[1] -= vr.mCurScrollY;
12585        }
12586
12587        location[0] = (int) (position[0] + 0.5f);
12588        location[1] = (int) (position[1] + 0.5f);
12589    }
12590
12591    /**
12592     * {@hide}
12593     * @param id the id of the view to be found
12594     * @return the view of the specified id, null if cannot be found
12595     */
12596    protected View findViewTraversal(int id) {
12597        if (id == mID) {
12598            return this;
12599        }
12600        return null;
12601    }
12602
12603    /**
12604     * {@hide}
12605     * @param tag the tag of the view to be found
12606     * @return the view of specified tag, null if cannot be found
12607     */
12608    protected View findViewWithTagTraversal(Object tag) {
12609        if (tag != null && tag.equals(mTag)) {
12610            return this;
12611        }
12612        return null;
12613    }
12614
12615    /**
12616     * {@hide}
12617     * @param predicate The predicate to evaluate.
12618     * @param childToSkip If not null, ignores this child during the recursive traversal.
12619     * @return The first view that matches the predicate or null.
12620     */
12621    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
12622        if (predicate.apply(this)) {
12623            return this;
12624        }
12625        return null;
12626    }
12627
12628    /**
12629     * Look for a child view with the given id.  If this view has the given
12630     * id, return this view.
12631     *
12632     * @param id The id to search for.
12633     * @return The view that has the given id in the hierarchy or null
12634     */
12635    public final View findViewById(int id) {
12636        if (id < 0) {
12637            return null;
12638        }
12639        return findViewTraversal(id);
12640    }
12641
12642    /**
12643     * Finds a view by its unuque and stable accessibility id.
12644     *
12645     * @param accessibilityId The searched accessibility id.
12646     * @return The found view.
12647     */
12648    final View findViewByAccessibilityId(int accessibilityId) {
12649        if (accessibilityId < 0) {
12650            return null;
12651        }
12652        return findViewByAccessibilityIdTraversal(accessibilityId);
12653    }
12654
12655    /**
12656     * Performs the traversal to find a view by its unuque and stable accessibility id.
12657     *
12658     * <strong>Note:</strong>This method does not stop at the root namespace
12659     * boundary since the user can touch the screen at an arbitrary location
12660     * potentially crossing the root namespace bounday which will send an
12661     * accessibility event to accessibility services and they should be able
12662     * to obtain the event source. Also accessibility ids are guaranteed to be
12663     * unique in the window.
12664     *
12665     * @param accessibilityId The accessibility id.
12666     * @return The found view.
12667     */
12668    View findViewByAccessibilityIdTraversal(int accessibilityId) {
12669        if (getAccessibilityViewId() == accessibilityId) {
12670            return this;
12671        }
12672        return null;
12673    }
12674
12675    /**
12676     * Look for a child view with the given tag.  If this view has the given
12677     * tag, return this view.
12678     *
12679     * @param tag The tag to search for, using "tag.equals(getTag())".
12680     * @return The View that has the given tag in the hierarchy or null
12681     */
12682    public final View findViewWithTag(Object tag) {
12683        if (tag == null) {
12684            return null;
12685        }
12686        return findViewWithTagTraversal(tag);
12687    }
12688
12689    /**
12690     * {@hide}
12691     * Look for a child view that matches the specified predicate.
12692     * If this view matches the predicate, return this view.
12693     *
12694     * @param predicate The predicate to evaluate.
12695     * @return The first view that matches the predicate or null.
12696     */
12697    public final View findViewByPredicate(Predicate<View> predicate) {
12698        return findViewByPredicateTraversal(predicate, null);
12699    }
12700
12701    /**
12702     * {@hide}
12703     * Look for a child view that matches the specified predicate,
12704     * starting with the specified view and its descendents and then
12705     * recusively searching the ancestors and siblings of that view
12706     * until this view is reached.
12707     *
12708     * This method is useful in cases where the predicate does not match
12709     * a single unique view (perhaps multiple views use the same id)
12710     * and we are trying to find the view that is "closest" in scope to the
12711     * starting view.
12712     *
12713     * @param start The view to start from.
12714     * @param predicate The predicate to evaluate.
12715     * @return The first view that matches the predicate or null.
12716     */
12717    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
12718        View childToSkip = null;
12719        for (;;) {
12720            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
12721            if (view != null || start == this) {
12722                return view;
12723            }
12724
12725            ViewParent parent = start.getParent();
12726            if (parent == null || !(parent instanceof View)) {
12727                return null;
12728            }
12729
12730            childToSkip = start;
12731            start = (View) parent;
12732        }
12733    }
12734
12735    /**
12736     * Sets the identifier for this view. The identifier does not have to be
12737     * unique in this view's hierarchy. The identifier should be a positive
12738     * number.
12739     *
12740     * @see #NO_ID
12741     * @see #getId()
12742     * @see #findViewById(int)
12743     *
12744     * @param id a number used to identify the view
12745     *
12746     * @attr ref android.R.styleable#View_id
12747     */
12748    public void setId(int id) {
12749        mID = id;
12750    }
12751
12752    /**
12753     * {@hide}
12754     *
12755     * @param isRoot true if the view belongs to the root namespace, false
12756     *        otherwise
12757     */
12758    public void setIsRootNamespace(boolean isRoot) {
12759        if (isRoot) {
12760            mPrivateFlags |= IS_ROOT_NAMESPACE;
12761        } else {
12762            mPrivateFlags &= ~IS_ROOT_NAMESPACE;
12763        }
12764    }
12765
12766    /**
12767     * {@hide}
12768     *
12769     * @return true if the view belongs to the root namespace, false otherwise
12770     */
12771    public boolean isRootNamespace() {
12772        return (mPrivateFlags&IS_ROOT_NAMESPACE) != 0;
12773    }
12774
12775    /**
12776     * Returns this view's identifier.
12777     *
12778     * @return a positive integer used to identify the view or {@link #NO_ID}
12779     *         if the view has no ID
12780     *
12781     * @see #setId(int)
12782     * @see #findViewById(int)
12783     * @attr ref android.R.styleable#View_id
12784     */
12785    @ViewDebug.CapturedViewProperty
12786    public int getId() {
12787        return mID;
12788    }
12789
12790    /**
12791     * Returns this view's tag.
12792     *
12793     * @return the Object stored in this view as a tag
12794     *
12795     * @see #setTag(Object)
12796     * @see #getTag(int)
12797     */
12798    @ViewDebug.ExportedProperty
12799    public Object getTag() {
12800        return mTag;
12801    }
12802
12803    /**
12804     * Sets the tag associated with this view. A tag can be used to mark
12805     * a view in its hierarchy and does not have to be unique within the
12806     * hierarchy. Tags can also be used to store data within a view without
12807     * resorting to another data structure.
12808     *
12809     * @param tag an Object to tag the view with
12810     *
12811     * @see #getTag()
12812     * @see #setTag(int, Object)
12813     */
12814    public void setTag(final Object tag) {
12815        mTag = tag;
12816    }
12817
12818    /**
12819     * Returns the tag associated with this view and the specified key.
12820     *
12821     * @param key The key identifying the tag
12822     *
12823     * @return the Object stored in this view as a tag
12824     *
12825     * @see #setTag(int, Object)
12826     * @see #getTag()
12827     */
12828    public Object getTag(int key) {
12829        if (mKeyedTags != null) return mKeyedTags.get(key);
12830        return null;
12831    }
12832
12833    /**
12834     * Sets a tag associated with this view and a key. A tag can be used
12835     * to mark a view in its hierarchy and does not have to be unique within
12836     * the hierarchy. Tags can also be used to store data within a view
12837     * without resorting to another data structure.
12838     *
12839     * The specified key should be an id declared in the resources of the
12840     * application to ensure it is unique (see the <a
12841     * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
12842     * Keys identified as belonging to
12843     * the Android framework or not associated with any package will cause
12844     * an {@link IllegalArgumentException} to be thrown.
12845     *
12846     * @param key The key identifying the tag
12847     * @param tag An Object to tag the view with
12848     *
12849     * @throws IllegalArgumentException If they specified key is not valid
12850     *
12851     * @see #setTag(Object)
12852     * @see #getTag(int)
12853     */
12854    public void setTag(int key, final Object tag) {
12855        // If the package id is 0x00 or 0x01, it's either an undefined package
12856        // or a framework id
12857        if ((key >>> 24) < 2) {
12858            throw new IllegalArgumentException("The key must be an application-specific "
12859                    + "resource id.");
12860        }
12861
12862        setKeyedTag(key, tag);
12863    }
12864
12865    /**
12866     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
12867     * framework id.
12868     *
12869     * @hide
12870     */
12871    public void setTagInternal(int key, Object tag) {
12872        if ((key >>> 24) != 0x1) {
12873            throw new IllegalArgumentException("The key must be a framework-specific "
12874                    + "resource id.");
12875        }
12876
12877        setKeyedTag(key, tag);
12878    }
12879
12880    private void setKeyedTag(int key, Object tag) {
12881        if (mKeyedTags == null) {
12882            mKeyedTags = new SparseArray<Object>();
12883        }
12884
12885        mKeyedTags.put(key, tag);
12886    }
12887
12888    /**
12889     * @param consistency The type of consistency. See ViewDebug for more information.
12890     *
12891     * @hide
12892     */
12893    protected boolean dispatchConsistencyCheck(int consistency) {
12894        return onConsistencyCheck(consistency);
12895    }
12896
12897    /**
12898     * Method that subclasses should implement to check their consistency. The type of
12899     * consistency check is indicated by the bit field passed as a parameter.
12900     *
12901     * @param consistency The type of consistency. See ViewDebug for more information.
12902     *
12903     * @throws IllegalStateException if the view is in an inconsistent state.
12904     *
12905     * @hide
12906     */
12907    protected boolean onConsistencyCheck(int consistency) {
12908        boolean result = true;
12909
12910        final boolean checkLayout = (consistency & ViewDebug.CONSISTENCY_LAYOUT) != 0;
12911        final boolean checkDrawing = (consistency & ViewDebug.CONSISTENCY_DRAWING) != 0;
12912
12913        if (checkLayout) {
12914            if (getParent() == null) {
12915                result = false;
12916                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
12917                        "View " + this + " does not have a parent.");
12918            }
12919
12920            if (mAttachInfo == null) {
12921                result = false;
12922                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
12923                        "View " + this + " is not attached to a window.");
12924            }
12925        }
12926
12927        if (checkDrawing) {
12928            // Do not check the DIRTY/DRAWN flags because views can call invalidate()
12929            // from their draw() method
12930
12931            if ((mPrivateFlags & DRAWN) != DRAWN &&
12932                    (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
12933                result = false;
12934                android.util.Log.d(ViewDebug.CONSISTENCY_LOG_TAG,
12935                        "View " + this + " was invalidated but its drawing cache is valid.");
12936            }
12937        }
12938
12939        return result;
12940    }
12941
12942    /**
12943     * Prints information about this view in the log output, with the tag
12944     * {@link #VIEW_LOG_TAG}.
12945     *
12946     * @hide
12947     */
12948    public void debug() {
12949        debug(0);
12950    }
12951
12952    /**
12953     * Prints information about this view in the log output, with the tag
12954     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
12955     * indentation defined by the <code>depth</code>.
12956     *
12957     * @param depth the indentation level
12958     *
12959     * @hide
12960     */
12961    protected void debug(int depth) {
12962        String output = debugIndent(depth - 1);
12963
12964        output += "+ " + this;
12965        int id = getId();
12966        if (id != -1) {
12967            output += " (id=" + id + ")";
12968        }
12969        Object tag = getTag();
12970        if (tag != null) {
12971            output += " (tag=" + tag + ")";
12972        }
12973        Log.d(VIEW_LOG_TAG, output);
12974
12975        if ((mPrivateFlags & FOCUSED) != 0) {
12976            output = debugIndent(depth) + " FOCUSED";
12977            Log.d(VIEW_LOG_TAG, output);
12978        }
12979
12980        output = debugIndent(depth);
12981        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
12982                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
12983                + "} ";
12984        Log.d(VIEW_LOG_TAG, output);
12985
12986        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
12987                || mPaddingBottom != 0) {
12988            output = debugIndent(depth);
12989            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
12990                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
12991            Log.d(VIEW_LOG_TAG, output);
12992        }
12993
12994        output = debugIndent(depth);
12995        output += "mMeasureWidth=" + mMeasuredWidth +
12996                " mMeasureHeight=" + mMeasuredHeight;
12997        Log.d(VIEW_LOG_TAG, output);
12998
12999        output = debugIndent(depth);
13000        if (mLayoutParams == null) {
13001            output += "BAD! no layout params";
13002        } else {
13003            output = mLayoutParams.debug(output);
13004        }
13005        Log.d(VIEW_LOG_TAG, output);
13006
13007        output = debugIndent(depth);
13008        output += "flags={";
13009        output += View.printFlags(mViewFlags);
13010        output += "}";
13011        Log.d(VIEW_LOG_TAG, output);
13012
13013        output = debugIndent(depth);
13014        output += "privateFlags={";
13015        output += View.printPrivateFlags(mPrivateFlags);
13016        output += "}";
13017        Log.d(VIEW_LOG_TAG, output);
13018    }
13019
13020    /**
13021     * Creates an string of whitespaces used for indentation.
13022     *
13023     * @param depth the indentation level
13024     * @return a String containing (depth * 2 + 3) * 2 white spaces
13025     *
13026     * @hide
13027     */
13028    protected static String debugIndent(int depth) {
13029        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
13030        for (int i = 0; i < (depth * 2) + 3; i++) {
13031            spaces.append(' ').append(' ');
13032        }
13033        return spaces.toString();
13034    }
13035
13036    /**
13037     * <p>Return the offset of the widget's text baseline from the widget's top
13038     * boundary. If this widget does not support baseline alignment, this
13039     * method returns -1. </p>
13040     *
13041     * @return the offset of the baseline within the widget's bounds or -1
13042     *         if baseline alignment is not supported
13043     */
13044    @ViewDebug.ExportedProperty(category = "layout")
13045    public int getBaseline() {
13046        return -1;
13047    }
13048
13049    /**
13050     * Call this when something has changed which has invalidated the
13051     * layout of this view. This will schedule a layout pass of the view
13052     * tree.
13053     */
13054    public void requestLayout() {
13055        if (ViewDebug.TRACE_HIERARCHY) {
13056            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT);
13057        }
13058
13059        mPrivateFlags |= FORCE_LAYOUT;
13060        mPrivateFlags |= INVALIDATED;
13061
13062        if (mParent != null) {
13063            if (mLayoutParams != null) {
13064                mLayoutParams.resolveWithDirection(getResolvedLayoutDirection());
13065            }
13066            if (!mParent.isLayoutRequested()) {
13067                mParent.requestLayout();
13068            }
13069        }
13070    }
13071
13072    /**
13073     * Forces this view to be laid out during the next layout pass.
13074     * This method does not call requestLayout() or forceLayout()
13075     * on the parent.
13076     */
13077    public void forceLayout() {
13078        mPrivateFlags |= FORCE_LAYOUT;
13079        mPrivateFlags |= INVALIDATED;
13080    }
13081
13082    /**
13083     * <p>
13084     * This is called to find out how big a view should be. The parent
13085     * supplies constraint information in the width and height parameters.
13086     * </p>
13087     *
13088     * <p>
13089     * The actual measurement work of a view is performed in
13090     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
13091     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
13092     * </p>
13093     *
13094     *
13095     * @param widthMeasureSpec Horizontal space requirements as imposed by the
13096     *        parent
13097     * @param heightMeasureSpec Vertical space requirements as imposed by the
13098     *        parent
13099     *
13100     * @see #onMeasure(int, int)
13101     */
13102    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
13103        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
13104                widthMeasureSpec != mOldWidthMeasureSpec ||
13105                heightMeasureSpec != mOldHeightMeasureSpec) {
13106
13107            // first clears the measured dimension flag
13108            mPrivateFlags &= ~MEASURED_DIMENSION_SET;
13109
13110            if (ViewDebug.TRACE_HIERARCHY) {
13111                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
13112            }
13113
13114            // measure ourselves, this should set the measured dimension flag back
13115            onMeasure(widthMeasureSpec, heightMeasureSpec);
13116
13117            // flag not set, setMeasuredDimension() was not invoked, we raise
13118            // an exception to warn the developer
13119            if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
13120                throw new IllegalStateException("onMeasure() did not set the"
13121                        + " measured dimension by calling"
13122                        + " setMeasuredDimension()");
13123            }
13124
13125            mPrivateFlags |= LAYOUT_REQUIRED;
13126        }
13127
13128        mOldWidthMeasureSpec = widthMeasureSpec;
13129        mOldHeightMeasureSpec = heightMeasureSpec;
13130    }
13131
13132    /**
13133     * <p>
13134     * Measure the view and its content to determine the measured width and the
13135     * measured height. This method is invoked by {@link #measure(int, int)} and
13136     * should be overriden by subclasses to provide accurate and efficient
13137     * measurement of their contents.
13138     * </p>
13139     *
13140     * <p>
13141     * <strong>CONTRACT:</strong> When overriding this method, you
13142     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
13143     * measured width and height of this view. Failure to do so will trigger an
13144     * <code>IllegalStateException</code>, thrown by
13145     * {@link #measure(int, int)}. Calling the superclass'
13146     * {@link #onMeasure(int, int)} is a valid use.
13147     * </p>
13148     *
13149     * <p>
13150     * The base class implementation of measure defaults to the background size,
13151     * unless a larger size is allowed by the MeasureSpec. Subclasses should
13152     * override {@link #onMeasure(int, int)} to provide better measurements of
13153     * their content.
13154     * </p>
13155     *
13156     * <p>
13157     * If this method is overridden, it is the subclass's responsibility to make
13158     * sure the measured height and width are at least the view's minimum height
13159     * and width ({@link #getSuggestedMinimumHeight()} and
13160     * {@link #getSuggestedMinimumWidth()}).
13161     * </p>
13162     *
13163     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
13164     *                         The requirements are encoded with
13165     *                         {@link android.view.View.MeasureSpec}.
13166     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
13167     *                         The requirements are encoded with
13168     *                         {@link android.view.View.MeasureSpec}.
13169     *
13170     * @see #getMeasuredWidth()
13171     * @see #getMeasuredHeight()
13172     * @see #setMeasuredDimension(int, int)
13173     * @see #getSuggestedMinimumHeight()
13174     * @see #getSuggestedMinimumWidth()
13175     * @see android.view.View.MeasureSpec#getMode(int)
13176     * @see android.view.View.MeasureSpec#getSize(int)
13177     */
13178    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
13179        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
13180                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
13181    }
13182
13183    /**
13184     * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
13185     * measured width and measured height. Failing to do so will trigger an
13186     * exception at measurement time.</p>
13187     *
13188     * @param measuredWidth The measured width of this view.  May be a complex
13189     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
13190     * {@link #MEASURED_STATE_TOO_SMALL}.
13191     * @param measuredHeight The measured height of this view.  May be a complex
13192     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
13193     * {@link #MEASURED_STATE_TOO_SMALL}.
13194     */
13195    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
13196        mMeasuredWidth = measuredWidth;
13197        mMeasuredHeight = measuredHeight;
13198
13199        mPrivateFlags |= MEASURED_DIMENSION_SET;
13200    }
13201
13202    /**
13203     * Merge two states as returned by {@link #getMeasuredState()}.
13204     * @param curState The current state as returned from a view or the result
13205     * of combining multiple views.
13206     * @param newState The new view state to combine.
13207     * @return Returns a new integer reflecting the combination of the two
13208     * states.
13209     */
13210    public static int combineMeasuredStates(int curState, int newState) {
13211        return curState | newState;
13212    }
13213
13214    /**
13215     * Version of {@link #resolveSizeAndState(int, int, int)}
13216     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
13217     */
13218    public static int resolveSize(int size, int measureSpec) {
13219        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
13220    }
13221
13222    /**
13223     * Utility to reconcile a desired size and state, with constraints imposed
13224     * by a MeasureSpec.  Will take the desired size, unless a different size
13225     * is imposed by the constraints.  The returned value is a compound integer,
13226     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
13227     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
13228     * size is smaller than the size the view wants to be.
13229     *
13230     * @param size How big the view wants to be
13231     * @param measureSpec Constraints imposed by the parent
13232     * @return Size information bit mask as defined by
13233     * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
13234     */
13235    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
13236        int result = size;
13237        int specMode = MeasureSpec.getMode(measureSpec);
13238        int specSize =  MeasureSpec.getSize(measureSpec);
13239        switch (specMode) {
13240        case MeasureSpec.UNSPECIFIED:
13241            result = size;
13242            break;
13243        case MeasureSpec.AT_MOST:
13244            if (specSize < size) {
13245                result = specSize | MEASURED_STATE_TOO_SMALL;
13246            } else {
13247                result = size;
13248            }
13249            break;
13250        case MeasureSpec.EXACTLY:
13251            result = specSize;
13252            break;
13253        }
13254        return result | (childMeasuredState&MEASURED_STATE_MASK);
13255    }
13256
13257    /**
13258     * Utility to return a default size. Uses the supplied size if the
13259     * MeasureSpec imposed no constraints. Will get larger if allowed
13260     * by the MeasureSpec.
13261     *
13262     * @param size Default size for this view
13263     * @param measureSpec Constraints imposed by the parent
13264     * @return The size this view should be.
13265     */
13266    public static int getDefaultSize(int size, int measureSpec) {
13267        int result = size;
13268        int specMode = MeasureSpec.getMode(measureSpec);
13269        int specSize = MeasureSpec.getSize(measureSpec);
13270
13271        switch (specMode) {
13272        case MeasureSpec.UNSPECIFIED:
13273            result = size;
13274            break;
13275        case MeasureSpec.AT_MOST:
13276        case MeasureSpec.EXACTLY:
13277            result = specSize;
13278            break;
13279        }
13280        return result;
13281    }
13282
13283    /**
13284     * Returns the suggested minimum height that the view should use. This
13285     * returns the maximum of the view's minimum height
13286     * and the background's minimum height
13287     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
13288     * <p>
13289     * When being used in {@link #onMeasure(int, int)}, the caller should still
13290     * ensure the returned height is within the requirements of the parent.
13291     *
13292     * @return The suggested minimum height of the view.
13293     */
13294    protected int getSuggestedMinimumHeight() {
13295        int suggestedMinHeight = mMinHeight;
13296
13297        if (mBGDrawable != null) {
13298            final int bgMinHeight = mBGDrawable.getMinimumHeight();
13299            if (suggestedMinHeight < bgMinHeight) {
13300                suggestedMinHeight = bgMinHeight;
13301            }
13302        }
13303
13304        return suggestedMinHeight;
13305    }
13306
13307    /**
13308     * Returns the suggested minimum width that the view should use. This
13309     * returns the maximum of the view's minimum width)
13310     * and the background's minimum width
13311     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
13312     * <p>
13313     * When being used in {@link #onMeasure(int, int)}, the caller should still
13314     * ensure the returned width is within the requirements of the parent.
13315     *
13316     * @return The suggested minimum width of the view.
13317     */
13318    protected int getSuggestedMinimumWidth() {
13319        int suggestedMinWidth = mMinWidth;
13320
13321        if (mBGDrawable != null) {
13322            final int bgMinWidth = mBGDrawable.getMinimumWidth();
13323            if (suggestedMinWidth < bgMinWidth) {
13324                suggestedMinWidth = bgMinWidth;
13325            }
13326        }
13327
13328        return suggestedMinWidth;
13329    }
13330
13331    /**
13332     * Sets the minimum height of the view. It is not guaranteed the view will
13333     * be able to achieve this minimum height (for example, if its parent layout
13334     * constrains it with less available height).
13335     *
13336     * @param minHeight The minimum height the view will try to be.
13337     */
13338    public void setMinimumHeight(int minHeight) {
13339        mMinHeight = minHeight;
13340    }
13341
13342    /**
13343     * Sets the minimum width of the view. It is not guaranteed the view will
13344     * be able to achieve this minimum width (for example, if its parent layout
13345     * constrains it with less available width).
13346     *
13347     * @param minWidth The minimum width the view will try to be.
13348     */
13349    public void setMinimumWidth(int minWidth) {
13350        mMinWidth = minWidth;
13351    }
13352
13353    /**
13354     * Get the animation currently associated with this view.
13355     *
13356     * @return The animation that is currently playing or
13357     *         scheduled to play for this view.
13358     */
13359    public Animation getAnimation() {
13360        return mCurrentAnimation;
13361    }
13362
13363    /**
13364     * Start the specified animation now.
13365     *
13366     * @param animation the animation to start now
13367     */
13368    public void startAnimation(Animation animation) {
13369        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
13370        setAnimation(animation);
13371        invalidateParentCaches();
13372        invalidate(true);
13373    }
13374
13375    /**
13376     * Cancels any animations for this view.
13377     */
13378    public void clearAnimation() {
13379        if (mCurrentAnimation != null) {
13380            mCurrentAnimation.detach();
13381        }
13382        mCurrentAnimation = null;
13383        invalidateParentIfNeeded();
13384    }
13385
13386    /**
13387     * Sets the next animation to play for this view.
13388     * If you want the animation to play immediately, use
13389     * startAnimation. This method provides allows fine-grained
13390     * control over the start time and invalidation, but you
13391     * must make sure that 1) the animation has a start time set, and
13392     * 2) the view will be invalidated when the animation is supposed to
13393     * start.
13394     *
13395     * @param animation The next animation, or null.
13396     */
13397    public void setAnimation(Animation animation) {
13398        mCurrentAnimation = animation;
13399        if (animation != null) {
13400            animation.reset();
13401        }
13402    }
13403
13404    /**
13405     * Invoked by a parent ViewGroup to notify the start of the animation
13406     * currently associated with this view. If you override this method,
13407     * always call super.onAnimationStart();
13408     *
13409     * @see #setAnimation(android.view.animation.Animation)
13410     * @see #getAnimation()
13411     */
13412    protected void onAnimationStart() {
13413        mPrivateFlags |= ANIMATION_STARTED;
13414    }
13415
13416    /**
13417     * Invoked by a parent ViewGroup to notify the end of the animation
13418     * currently associated with this view. If you override this method,
13419     * always call super.onAnimationEnd();
13420     *
13421     * @see #setAnimation(android.view.animation.Animation)
13422     * @see #getAnimation()
13423     */
13424    protected void onAnimationEnd() {
13425        mPrivateFlags &= ~ANIMATION_STARTED;
13426    }
13427
13428    /**
13429     * Invoked if there is a Transform that involves alpha. Subclass that can
13430     * draw themselves with the specified alpha should return true, and then
13431     * respect that alpha when their onDraw() is called. If this returns false
13432     * then the view may be redirected to draw into an offscreen buffer to
13433     * fulfill the request, which will look fine, but may be slower than if the
13434     * subclass handles it internally. The default implementation returns false.
13435     *
13436     * @param alpha The alpha (0..255) to apply to the view's drawing
13437     * @return true if the view can draw with the specified alpha.
13438     */
13439    protected boolean onSetAlpha(int alpha) {
13440        return false;
13441    }
13442
13443    /**
13444     * This is used by the RootView to perform an optimization when
13445     * the view hierarchy contains one or several SurfaceView.
13446     * SurfaceView is always considered transparent, but its children are not,
13447     * therefore all View objects remove themselves from the global transparent
13448     * region (passed as a parameter to this function).
13449     *
13450     * @param region The transparent region for this ViewAncestor (window).
13451     *
13452     * @return Returns true if the effective visibility of the view at this
13453     * point is opaque, regardless of the transparent region; returns false
13454     * if it is possible for underlying windows to be seen behind the view.
13455     *
13456     * {@hide}
13457     */
13458    public boolean gatherTransparentRegion(Region region) {
13459        final AttachInfo attachInfo = mAttachInfo;
13460        if (region != null && attachInfo != null) {
13461            final int pflags = mPrivateFlags;
13462            if ((pflags & SKIP_DRAW) == 0) {
13463                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
13464                // remove it from the transparent region.
13465                final int[] location = attachInfo.mTransparentLocation;
13466                getLocationInWindow(location);
13467                region.op(location[0], location[1], location[0] + mRight - mLeft,
13468                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
13469            } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) {
13470                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
13471                // exists, so we remove the background drawable's non-transparent
13472                // parts from this transparent region.
13473                applyDrawableToTransparentRegion(mBGDrawable, region);
13474            }
13475        }
13476        return true;
13477    }
13478
13479    /**
13480     * Play a sound effect for this view.
13481     *
13482     * <p>The framework will play sound effects for some built in actions, such as
13483     * clicking, but you may wish to play these effects in your widget,
13484     * for instance, for internal navigation.
13485     *
13486     * <p>The sound effect will only be played if sound effects are enabled by the user, and
13487     * {@link #isSoundEffectsEnabled()} is true.
13488     *
13489     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
13490     */
13491    public void playSoundEffect(int soundConstant) {
13492        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
13493            return;
13494        }
13495        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
13496    }
13497
13498    /**
13499     * BZZZTT!!1!
13500     *
13501     * <p>Provide haptic feedback to the user for this view.
13502     *
13503     * <p>The framework will provide haptic feedback for some built in actions,
13504     * such as long presses, but you may wish to provide feedback for your
13505     * own widget.
13506     *
13507     * <p>The feedback will only be performed if
13508     * {@link #isHapticFeedbackEnabled()} is true.
13509     *
13510     * @param feedbackConstant One of the constants defined in
13511     * {@link HapticFeedbackConstants}
13512     */
13513    public boolean performHapticFeedback(int feedbackConstant) {
13514        return performHapticFeedback(feedbackConstant, 0);
13515    }
13516
13517    /**
13518     * BZZZTT!!1!
13519     *
13520     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
13521     *
13522     * @param feedbackConstant One of the constants defined in
13523     * {@link HapticFeedbackConstants}
13524     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
13525     */
13526    public boolean performHapticFeedback(int feedbackConstant, int flags) {
13527        if (mAttachInfo == null) {
13528            return false;
13529        }
13530        //noinspection SimplifiableIfStatement
13531        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
13532                && !isHapticFeedbackEnabled()) {
13533            return false;
13534        }
13535        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
13536                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
13537    }
13538
13539    /**
13540     * Request that the visibility of the status bar be changed.
13541     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
13542     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
13543     */
13544    public void setSystemUiVisibility(int visibility) {
13545        if (visibility != mSystemUiVisibility) {
13546            mSystemUiVisibility = visibility;
13547            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13548                mParent.recomputeViewAttributes(this);
13549            }
13550        }
13551    }
13552
13553    /**
13554     * Returns the status bar visibility that this view has requested.
13555     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
13556     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
13557     */
13558    public int getSystemUiVisibility() {
13559        return mSystemUiVisibility;
13560    }
13561
13562    /**
13563     * Set a listener to receive callbacks when the visibility of the system bar changes.
13564     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
13565     */
13566    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
13567        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
13568        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
13569            mParent.recomputeViewAttributes(this);
13570        }
13571    }
13572
13573    /**
13574     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
13575     * the view hierarchy.
13576     */
13577    public void dispatchSystemUiVisibilityChanged(int visibility) {
13578        ListenerInfo li = mListenerInfo;
13579        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
13580            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
13581                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
13582        }
13583    }
13584
13585    void updateLocalSystemUiVisibility(int localValue, int localChanges) {
13586        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
13587        if (val != mSystemUiVisibility) {
13588            setSystemUiVisibility(val);
13589        }
13590    }
13591
13592    /**
13593     * Creates an image that the system displays during the drag and drop
13594     * operation. This is called a &quot;drag shadow&quot;. The default implementation
13595     * for a DragShadowBuilder based on a View returns an image that has exactly the same
13596     * appearance as the given View. The default also positions the center of the drag shadow
13597     * directly under the touch point. If no View is provided (the constructor with no parameters
13598     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
13599     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
13600     * default is an invisible drag shadow.
13601     * <p>
13602     * You are not required to use the View you provide to the constructor as the basis of the
13603     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
13604     * anything you want as the drag shadow.
13605     * </p>
13606     * <p>
13607     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
13608     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
13609     *  size and position of the drag shadow. It uses this data to construct a
13610     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
13611     *  so that your application can draw the shadow image in the Canvas.
13612     * </p>
13613     *
13614     * <div class="special reference">
13615     * <h3>Developer Guides</h3>
13616     * <p>For a guide to implementing drag and drop features, read the
13617     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
13618     * </div>
13619     */
13620    public static class DragShadowBuilder {
13621        private final WeakReference<View> mView;
13622
13623        /**
13624         * Constructs a shadow image builder based on a View. By default, the resulting drag
13625         * shadow will have the same appearance and dimensions as the View, with the touch point
13626         * over the center of the View.
13627         * @param view A View. Any View in scope can be used.
13628         */
13629        public DragShadowBuilder(View view) {
13630            mView = new WeakReference<View>(view);
13631        }
13632
13633        /**
13634         * Construct a shadow builder object with no associated View.  This
13635         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
13636         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
13637         * to supply the drag shadow's dimensions and appearance without
13638         * reference to any View object. If they are not overridden, then the result is an
13639         * invisible drag shadow.
13640         */
13641        public DragShadowBuilder() {
13642            mView = new WeakReference<View>(null);
13643        }
13644
13645        /**
13646         * Returns the View object that had been passed to the
13647         * {@link #View.DragShadowBuilder(View)}
13648         * constructor.  If that View parameter was {@code null} or if the
13649         * {@link #View.DragShadowBuilder()}
13650         * constructor was used to instantiate the builder object, this method will return
13651         * null.
13652         *
13653         * @return The View object associate with this builder object.
13654         */
13655        @SuppressWarnings({"JavadocReference"})
13656        final public View getView() {
13657            return mView.get();
13658        }
13659
13660        /**
13661         * Provides the metrics for the shadow image. These include the dimensions of
13662         * the shadow image, and the point within that shadow that should
13663         * be centered under the touch location while dragging.
13664         * <p>
13665         * The default implementation sets the dimensions of the shadow to be the
13666         * same as the dimensions of the View itself and centers the shadow under
13667         * the touch point.
13668         * </p>
13669         *
13670         * @param shadowSize A {@link android.graphics.Point} containing the width and height
13671         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
13672         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
13673         * image.
13674         *
13675         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
13676         * shadow image that should be underneath the touch point during the drag and drop
13677         * operation. Your application must set {@link android.graphics.Point#x} to the
13678         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
13679         */
13680        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
13681            final View view = mView.get();
13682            if (view != null) {
13683                shadowSize.set(view.getWidth(), view.getHeight());
13684                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
13685            } else {
13686                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
13687            }
13688        }
13689
13690        /**
13691         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
13692         * based on the dimensions it received from the
13693         * {@link #onProvideShadowMetrics(Point, Point)} callback.
13694         *
13695         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
13696         */
13697        public void onDrawShadow(Canvas canvas) {
13698            final View view = mView.get();
13699            if (view != null) {
13700                view.draw(canvas);
13701            } else {
13702                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
13703            }
13704        }
13705    }
13706
13707    /**
13708     * Starts a drag and drop operation. When your application calls this method, it passes a
13709     * {@link android.view.View.DragShadowBuilder} object to the system. The
13710     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
13711     * to get metrics for the drag shadow, and then calls the object's
13712     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
13713     * <p>
13714     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
13715     *  drag events to all the View objects in your application that are currently visible. It does
13716     *  this either by calling the View object's drag listener (an implementation of
13717     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
13718     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
13719     *  Both are passed a {@link android.view.DragEvent} object that has a
13720     *  {@link android.view.DragEvent#getAction()} value of
13721     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
13722     * </p>
13723     * <p>
13724     * Your application can invoke startDrag() on any attached View object. The View object does not
13725     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
13726     * be related to the View the user selected for dragging.
13727     * </p>
13728     * @param data A {@link android.content.ClipData} object pointing to the data to be
13729     * transferred by the drag and drop operation.
13730     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
13731     * drag shadow.
13732     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
13733     * drop operation. This Object is put into every DragEvent object sent by the system during the
13734     * current drag.
13735     * <p>
13736     * myLocalState is a lightweight mechanism for the sending information from the dragged View
13737     * to the target Views. For example, it can contain flags that differentiate between a
13738     * a copy operation and a move operation.
13739     * </p>
13740     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
13741     * so the parameter should be set to 0.
13742     * @return {@code true} if the method completes successfully, or
13743     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
13744     * do a drag, and so no drag operation is in progress.
13745     */
13746    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
13747            Object myLocalState, int flags) {
13748        if (ViewDebug.DEBUG_DRAG) {
13749            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
13750        }
13751        boolean okay = false;
13752
13753        Point shadowSize = new Point();
13754        Point shadowTouchPoint = new Point();
13755        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
13756
13757        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
13758                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
13759            throw new IllegalStateException("Drag shadow dimensions must not be negative");
13760        }
13761
13762        if (ViewDebug.DEBUG_DRAG) {
13763            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
13764                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
13765        }
13766        Surface surface = new Surface();
13767        try {
13768            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
13769                    flags, shadowSize.x, shadowSize.y, surface);
13770            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
13771                    + " surface=" + surface);
13772            if (token != null) {
13773                Canvas canvas = surface.lockCanvas(null);
13774                try {
13775                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
13776                    shadowBuilder.onDrawShadow(canvas);
13777                } finally {
13778                    surface.unlockCanvasAndPost(canvas);
13779                }
13780
13781                final ViewRootImpl root = getViewRootImpl();
13782
13783                // Cache the local state object for delivery with DragEvents
13784                root.setLocalDragState(myLocalState);
13785
13786                // repurpose 'shadowSize' for the last touch point
13787                root.getLastTouchPoint(shadowSize);
13788
13789                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
13790                        shadowSize.x, shadowSize.y,
13791                        shadowTouchPoint.x, shadowTouchPoint.y, data);
13792                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
13793
13794                // Off and running!  Release our local surface instance; the drag
13795                // shadow surface is now managed by the system process.
13796                surface.release();
13797            }
13798        } catch (Exception e) {
13799            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
13800            surface.destroy();
13801        }
13802
13803        return okay;
13804    }
13805
13806    /**
13807     * Handles drag events sent by the system following a call to
13808     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
13809     *<p>
13810     * When the system calls this method, it passes a
13811     * {@link android.view.DragEvent} object. A call to
13812     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
13813     * in DragEvent. The method uses these to determine what is happening in the drag and drop
13814     * operation.
13815     * @param event The {@link android.view.DragEvent} sent by the system.
13816     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
13817     * in DragEvent, indicating the type of drag event represented by this object.
13818     * @return {@code true} if the method was successful, otherwise {@code false}.
13819     * <p>
13820     *  The method should return {@code true} in response to an action type of
13821     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
13822     *  operation.
13823     * </p>
13824     * <p>
13825     *  The method should also return {@code true} in response to an action type of
13826     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
13827     *  {@code false} if it didn't.
13828     * </p>
13829     */
13830    public boolean onDragEvent(DragEvent event) {
13831        return false;
13832    }
13833
13834    /**
13835     * Detects if this View is enabled and has a drag event listener.
13836     * If both are true, then it calls the drag event listener with the
13837     * {@link android.view.DragEvent} it received. If the drag event listener returns
13838     * {@code true}, then dispatchDragEvent() returns {@code true}.
13839     * <p>
13840     * For all other cases, the method calls the
13841     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
13842     * method and returns its result.
13843     * </p>
13844     * <p>
13845     * This ensures that a drag event is always consumed, even if the View does not have a drag
13846     * event listener. However, if the View has a listener and the listener returns true, then
13847     * onDragEvent() is not called.
13848     * </p>
13849     */
13850    public boolean dispatchDragEvent(DragEvent event) {
13851        //noinspection SimplifiableIfStatement
13852        ListenerInfo li = mListenerInfo;
13853        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
13854                && li.mOnDragListener.onDrag(this, event)) {
13855            return true;
13856        }
13857        return onDragEvent(event);
13858    }
13859
13860    boolean canAcceptDrag() {
13861        return (mPrivateFlags2 & DRAG_CAN_ACCEPT) != 0;
13862    }
13863
13864    /**
13865     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
13866     * it is ever exposed at all.
13867     * @hide
13868     */
13869    public void onCloseSystemDialogs(String reason) {
13870    }
13871
13872    /**
13873     * Given a Drawable whose bounds have been set to draw into this view,
13874     * update a Region being computed for
13875     * {@link #gatherTransparentRegion(android.graphics.Region)} so
13876     * that any non-transparent parts of the Drawable are removed from the
13877     * given transparent region.
13878     *
13879     * @param dr The Drawable whose transparency is to be applied to the region.
13880     * @param region A Region holding the current transparency information,
13881     * where any parts of the region that are set are considered to be
13882     * transparent.  On return, this region will be modified to have the
13883     * transparency information reduced by the corresponding parts of the
13884     * Drawable that are not transparent.
13885     * {@hide}
13886     */
13887    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
13888        if (DBG) {
13889            Log.i("View", "Getting transparent region for: " + this);
13890        }
13891        final Region r = dr.getTransparentRegion();
13892        final Rect db = dr.getBounds();
13893        final AttachInfo attachInfo = mAttachInfo;
13894        if (r != null && attachInfo != null) {
13895            final int w = getRight()-getLeft();
13896            final int h = getBottom()-getTop();
13897            if (db.left > 0) {
13898                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
13899                r.op(0, 0, db.left, h, Region.Op.UNION);
13900            }
13901            if (db.right < w) {
13902                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
13903                r.op(db.right, 0, w, h, Region.Op.UNION);
13904            }
13905            if (db.top > 0) {
13906                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
13907                r.op(0, 0, w, db.top, Region.Op.UNION);
13908            }
13909            if (db.bottom < h) {
13910                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
13911                r.op(0, db.bottom, w, h, Region.Op.UNION);
13912            }
13913            final int[] location = attachInfo.mTransparentLocation;
13914            getLocationInWindow(location);
13915            r.translate(location[0], location[1]);
13916            region.op(r, Region.Op.INTERSECT);
13917        } else {
13918            region.op(db, Region.Op.DIFFERENCE);
13919        }
13920    }
13921
13922    private void checkForLongClick(int delayOffset) {
13923        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
13924            mHasPerformedLongPress = false;
13925
13926            if (mPendingCheckForLongPress == null) {
13927                mPendingCheckForLongPress = new CheckForLongPress();
13928            }
13929            mPendingCheckForLongPress.rememberWindowAttachCount();
13930            postDelayed(mPendingCheckForLongPress,
13931                    ViewConfiguration.getLongPressTimeout() - delayOffset);
13932        }
13933    }
13934
13935    /**
13936     * Inflate a view from an XML resource.  This convenience method wraps the {@link
13937     * LayoutInflater} class, which provides a full range of options for view inflation.
13938     *
13939     * @param context The Context object for your activity or application.
13940     * @param resource The resource ID to inflate
13941     * @param root A view group that will be the parent.  Used to properly inflate the
13942     * layout_* parameters.
13943     * @see LayoutInflater
13944     */
13945    public static View inflate(Context context, int resource, ViewGroup root) {
13946        LayoutInflater factory = LayoutInflater.from(context);
13947        return factory.inflate(resource, root);
13948    }
13949
13950    /**
13951     * Scroll the view with standard behavior for scrolling beyond the normal
13952     * content boundaries. Views that call this method should override
13953     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
13954     * results of an over-scroll operation.
13955     *
13956     * Views can use this method to handle any touch or fling-based scrolling.
13957     *
13958     * @param deltaX Change in X in pixels
13959     * @param deltaY Change in Y in pixels
13960     * @param scrollX Current X scroll value in pixels before applying deltaX
13961     * @param scrollY Current Y scroll value in pixels before applying deltaY
13962     * @param scrollRangeX Maximum content scroll range along the X axis
13963     * @param scrollRangeY Maximum content scroll range along the Y axis
13964     * @param maxOverScrollX Number of pixels to overscroll by in either direction
13965     *          along the X axis.
13966     * @param maxOverScrollY Number of pixels to overscroll by in either direction
13967     *          along the Y axis.
13968     * @param isTouchEvent true if this scroll operation is the result of a touch event.
13969     * @return true if scrolling was clamped to an over-scroll boundary along either
13970     *          axis, false otherwise.
13971     */
13972    @SuppressWarnings({"UnusedParameters"})
13973    protected boolean overScrollBy(int deltaX, int deltaY,
13974            int scrollX, int scrollY,
13975            int scrollRangeX, int scrollRangeY,
13976            int maxOverScrollX, int maxOverScrollY,
13977            boolean isTouchEvent) {
13978        final int overScrollMode = mOverScrollMode;
13979        final boolean canScrollHorizontal =
13980                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
13981        final boolean canScrollVertical =
13982                computeVerticalScrollRange() > computeVerticalScrollExtent();
13983        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
13984                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
13985        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
13986                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
13987
13988        int newScrollX = scrollX + deltaX;
13989        if (!overScrollHorizontal) {
13990            maxOverScrollX = 0;
13991        }
13992
13993        int newScrollY = scrollY + deltaY;
13994        if (!overScrollVertical) {
13995            maxOverScrollY = 0;
13996        }
13997
13998        // Clamp values if at the limits and record
13999        final int left = -maxOverScrollX;
14000        final int right = maxOverScrollX + scrollRangeX;
14001        final int top = -maxOverScrollY;
14002        final int bottom = maxOverScrollY + scrollRangeY;
14003
14004        boolean clampedX = false;
14005        if (newScrollX > right) {
14006            newScrollX = right;
14007            clampedX = true;
14008        } else if (newScrollX < left) {
14009            newScrollX = left;
14010            clampedX = true;
14011        }
14012
14013        boolean clampedY = false;
14014        if (newScrollY > bottom) {
14015            newScrollY = bottom;
14016            clampedY = true;
14017        } else if (newScrollY < top) {
14018            newScrollY = top;
14019            clampedY = true;
14020        }
14021
14022        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
14023
14024        return clampedX || clampedY;
14025    }
14026
14027    /**
14028     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
14029     * respond to the results of an over-scroll operation.
14030     *
14031     * @param scrollX New X scroll value in pixels
14032     * @param scrollY New Y scroll value in pixels
14033     * @param clampedX True if scrollX was clamped to an over-scroll boundary
14034     * @param clampedY True if scrollY was clamped to an over-scroll boundary
14035     */
14036    protected void onOverScrolled(int scrollX, int scrollY,
14037            boolean clampedX, boolean clampedY) {
14038        // Intentionally empty.
14039    }
14040
14041    /**
14042     * Returns the over-scroll mode for this view. The result will be
14043     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
14044     * (allow over-scrolling only if the view content is larger than the container),
14045     * or {@link #OVER_SCROLL_NEVER}.
14046     *
14047     * @return This view's over-scroll mode.
14048     */
14049    public int getOverScrollMode() {
14050        return mOverScrollMode;
14051    }
14052
14053    /**
14054     * Set the over-scroll mode for this view. Valid over-scroll modes are
14055     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
14056     * (allow over-scrolling only if the view content is larger than the container),
14057     * or {@link #OVER_SCROLL_NEVER}.
14058     *
14059     * Setting the over-scroll mode of a view will have an effect only if the
14060     * view is capable of scrolling.
14061     *
14062     * @param overScrollMode The new over-scroll mode for this view.
14063     */
14064    public void setOverScrollMode(int overScrollMode) {
14065        if (overScrollMode != OVER_SCROLL_ALWAYS &&
14066                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
14067                overScrollMode != OVER_SCROLL_NEVER) {
14068            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
14069        }
14070        mOverScrollMode = overScrollMode;
14071    }
14072
14073    /**
14074     * Gets a scale factor that determines the distance the view should scroll
14075     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
14076     * @return The vertical scroll scale factor.
14077     * @hide
14078     */
14079    protected float getVerticalScrollFactor() {
14080        if (mVerticalScrollFactor == 0) {
14081            TypedValue outValue = new TypedValue();
14082            if (!mContext.getTheme().resolveAttribute(
14083                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
14084                throw new IllegalStateException(
14085                        "Expected theme to define listPreferredItemHeight.");
14086            }
14087            mVerticalScrollFactor = outValue.getDimension(
14088                    mContext.getResources().getDisplayMetrics());
14089        }
14090        return mVerticalScrollFactor;
14091    }
14092
14093    /**
14094     * Gets a scale factor that determines the distance the view should scroll
14095     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
14096     * @return The horizontal scroll scale factor.
14097     * @hide
14098     */
14099    protected float getHorizontalScrollFactor() {
14100        // TODO: Should use something else.
14101        return getVerticalScrollFactor();
14102    }
14103
14104    /**
14105     * Return the value specifying the text direction or policy that was set with
14106     * {@link #setTextDirection(int)}.
14107     *
14108     * @return the defined text direction. It can be one of:
14109     *
14110     * {@link #TEXT_DIRECTION_INHERIT},
14111     * {@link #TEXT_DIRECTION_FIRST_STRONG}
14112     * {@link #TEXT_DIRECTION_ANY_RTL},
14113     * {@link #TEXT_DIRECTION_LTR},
14114     * {@link #TEXT_DIRECTION_RTL},
14115     * {@link #TEXT_DIRECTION_LOCALE},
14116     */
14117    public int getTextDirection() {
14118        return mTextDirection;
14119    }
14120
14121    /**
14122     * Set the text direction.
14123     *
14124     * @param textDirection the direction to set. Should be one of:
14125     *
14126     * {@link #TEXT_DIRECTION_INHERIT},
14127     * {@link #TEXT_DIRECTION_FIRST_STRONG}
14128     * {@link #TEXT_DIRECTION_ANY_RTL},
14129     * {@link #TEXT_DIRECTION_LTR},
14130     * {@link #TEXT_DIRECTION_RTL},
14131     * {@link #TEXT_DIRECTION_LOCALE},
14132     */
14133    public void setTextDirection(int textDirection) {
14134        if (textDirection != mTextDirection) {
14135            mTextDirection = textDirection;
14136            resetResolvedTextDirection();
14137            requestLayout();
14138        }
14139    }
14140
14141    /**
14142     * Return the resolved text direction.
14143     *
14144     * @return the resolved text direction. Return one of:
14145     *
14146     * {@link #TEXT_DIRECTION_FIRST_STRONG}
14147     * {@link #TEXT_DIRECTION_ANY_RTL},
14148     * {@link #TEXT_DIRECTION_LTR},
14149     * {@link #TEXT_DIRECTION_RTL},
14150     * {@link #TEXT_DIRECTION_LOCALE},
14151     */
14152    public int getResolvedTextDirection() {
14153        if (mResolvedTextDirection == TEXT_DIRECTION_INHERIT) {
14154            resolveTextDirection();
14155        }
14156        return mResolvedTextDirection;
14157    }
14158
14159    /**
14160     * Resolve the text direction. Will call {@link View#onResolveTextDirection()} when resolution
14161     * is done.
14162     */
14163    public void resolveTextDirection() {
14164        if (mResolvedTextDirection != TEXT_DIRECTION_INHERIT) {
14165            // Resolution has already been done.
14166            return;
14167        }
14168        if (mTextDirection != TEXT_DIRECTION_INHERIT) {
14169            mResolvedTextDirection = mTextDirection;
14170        } else if (mParent != null && mParent instanceof ViewGroup) {
14171            mResolvedTextDirection = ((ViewGroup) mParent).getResolvedTextDirection();
14172        } else {
14173            mResolvedTextDirection = TEXT_DIRECTION_FIRST_STRONG;
14174        }
14175        onResolveTextDirection();
14176    }
14177
14178    /**
14179     * Called when text direction has been resolved. Subclasses that care about text direction
14180     * resolution should override this method. The default implementation does nothing.
14181     */
14182    public void onResolveTextDirection() {
14183    }
14184
14185    /**
14186     * Reset resolved text direction. Text direction can be resolved with a call to
14187     * getResolvedTextDirection(). Will call {@link View#onResetResolvedTextDirection()} when
14188     * reset is done.
14189     */
14190    public void resetResolvedTextDirection() {
14191        mResolvedTextDirection = TEXT_DIRECTION_INHERIT;
14192        onResetResolvedTextDirection();
14193    }
14194
14195    /**
14196     * Called when text direction is reset. Subclasses that care about text direction reset should
14197     * override this method and do a reset of the text direction of their children. The default
14198     * implementation does nothing.
14199     */
14200    public void onResetResolvedTextDirection() {
14201    }
14202
14203    //
14204    // Properties
14205    //
14206    /**
14207     * A Property wrapper around the <code>alpha</code> functionality handled by the
14208     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
14209     */
14210    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
14211        @Override
14212        public void setValue(View object, float value) {
14213            object.setAlpha(value);
14214        }
14215
14216        @Override
14217        public Float get(View object) {
14218            return object.getAlpha();
14219        }
14220    };
14221
14222    /**
14223     * A Property wrapper around the <code>translationX</code> functionality handled by the
14224     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
14225     */
14226    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
14227        @Override
14228        public void setValue(View object, float value) {
14229            object.setTranslationX(value);
14230        }
14231
14232                @Override
14233        public Float get(View object) {
14234            return object.getTranslationX();
14235        }
14236    };
14237
14238    /**
14239     * A Property wrapper around the <code>translationY</code> functionality handled by the
14240     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
14241     */
14242    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
14243        @Override
14244        public void setValue(View object, float value) {
14245            object.setTranslationY(value);
14246        }
14247
14248        @Override
14249        public Float get(View object) {
14250            return object.getTranslationY();
14251        }
14252    };
14253
14254    /**
14255     * A Property wrapper around the <code>x</code> functionality handled by the
14256     * {@link View#setX(float)} and {@link View#getX()} methods.
14257     */
14258    public static final Property<View, Float> X = new FloatProperty<View>("x") {
14259        @Override
14260        public void setValue(View object, float value) {
14261            object.setX(value);
14262        }
14263
14264        @Override
14265        public Float get(View object) {
14266            return object.getX();
14267        }
14268    };
14269
14270    /**
14271     * A Property wrapper around the <code>y</code> functionality handled by the
14272     * {@link View#setY(float)} and {@link View#getY()} methods.
14273     */
14274    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
14275        @Override
14276        public void setValue(View object, float value) {
14277            object.setY(value);
14278        }
14279
14280        @Override
14281        public Float get(View object) {
14282            return object.getY();
14283        }
14284    };
14285
14286    /**
14287     * A Property wrapper around the <code>rotation</code> functionality handled by the
14288     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
14289     */
14290    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
14291        @Override
14292        public void setValue(View object, float value) {
14293            object.setRotation(value);
14294        }
14295
14296        @Override
14297        public Float get(View object) {
14298            return object.getRotation();
14299        }
14300    };
14301
14302    /**
14303     * A Property wrapper around the <code>rotationX</code> functionality handled by the
14304     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
14305     */
14306    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
14307        @Override
14308        public void setValue(View object, float value) {
14309            object.setRotationX(value);
14310        }
14311
14312        @Override
14313        public Float get(View object) {
14314            return object.getRotationX();
14315        }
14316    };
14317
14318    /**
14319     * A Property wrapper around the <code>rotationY</code> functionality handled by the
14320     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
14321     */
14322    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
14323        @Override
14324        public void setValue(View object, float value) {
14325            object.setRotationY(value);
14326        }
14327
14328        @Override
14329        public Float get(View object) {
14330            return object.getRotationY();
14331        }
14332    };
14333
14334    /**
14335     * A Property wrapper around the <code>scaleX</code> functionality handled by the
14336     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
14337     */
14338    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
14339        @Override
14340        public void setValue(View object, float value) {
14341            object.setScaleX(value);
14342        }
14343
14344        @Override
14345        public Float get(View object) {
14346            return object.getScaleX();
14347        }
14348    };
14349
14350    /**
14351     * A Property wrapper around the <code>scaleY</code> functionality handled by the
14352     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
14353     */
14354    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
14355        @Override
14356        public void setValue(View object, float value) {
14357            object.setScaleY(value);
14358        }
14359
14360        @Override
14361        public Float get(View object) {
14362            return object.getScaleY();
14363        }
14364    };
14365
14366    /**
14367     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
14368     * Each MeasureSpec represents a requirement for either the width or the height.
14369     * A MeasureSpec is comprised of a size and a mode. There are three possible
14370     * modes:
14371     * <dl>
14372     * <dt>UNSPECIFIED</dt>
14373     * <dd>
14374     * The parent has not imposed any constraint on the child. It can be whatever size
14375     * it wants.
14376     * </dd>
14377     *
14378     * <dt>EXACTLY</dt>
14379     * <dd>
14380     * The parent has determined an exact size for the child. The child is going to be
14381     * given those bounds regardless of how big it wants to be.
14382     * </dd>
14383     *
14384     * <dt>AT_MOST</dt>
14385     * <dd>
14386     * The child can be as large as it wants up to the specified size.
14387     * </dd>
14388     * </dl>
14389     *
14390     * MeasureSpecs are implemented as ints to reduce object allocation. This class
14391     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
14392     */
14393    public static class MeasureSpec {
14394        private static final int MODE_SHIFT = 30;
14395        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
14396
14397        /**
14398         * Measure specification mode: The parent has not imposed any constraint
14399         * on the child. It can be whatever size it wants.
14400         */
14401        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
14402
14403        /**
14404         * Measure specification mode: The parent has determined an exact size
14405         * for the child. The child is going to be given those bounds regardless
14406         * of how big it wants to be.
14407         */
14408        public static final int EXACTLY     = 1 << MODE_SHIFT;
14409
14410        /**
14411         * Measure specification mode: The child can be as large as it wants up
14412         * to the specified size.
14413         */
14414        public static final int AT_MOST     = 2 << MODE_SHIFT;
14415
14416        /**
14417         * Creates a measure specification based on the supplied size and mode.
14418         *
14419         * The mode must always be one of the following:
14420         * <ul>
14421         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
14422         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
14423         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
14424         * </ul>
14425         *
14426         * @param size the size of the measure specification
14427         * @param mode the mode of the measure specification
14428         * @return the measure specification based on size and mode
14429         */
14430        public static int makeMeasureSpec(int size, int mode) {
14431            return size + mode;
14432        }
14433
14434        /**
14435         * Extracts the mode from the supplied measure specification.
14436         *
14437         * @param measureSpec the measure specification to extract the mode from
14438         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
14439         *         {@link android.view.View.MeasureSpec#AT_MOST} or
14440         *         {@link android.view.View.MeasureSpec#EXACTLY}
14441         */
14442        public static int getMode(int measureSpec) {
14443            return (measureSpec & MODE_MASK);
14444        }
14445
14446        /**
14447         * Extracts the size from the supplied measure specification.
14448         *
14449         * @param measureSpec the measure specification to extract the size from
14450         * @return the size in pixels defined in the supplied measure specification
14451         */
14452        public static int getSize(int measureSpec) {
14453            return (measureSpec & ~MODE_MASK);
14454        }
14455
14456        /**
14457         * Returns a String representation of the specified measure
14458         * specification.
14459         *
14460         * @param measureSpec the measure specification to convert to a String
14461         * @return a String with the following format: "MeasureSpec: MODE SIZE"
14462         */
14463        public static String toString(int measureSpec) {
14464            int mode = getMode(measureSpec);
14465            int size = getSize(measureSpec);
14466
14467            StringBuilder sb = new StringBuilder("MeasureSpec: ");
14468
14469            if (mode == UNSPECIFIED)
14470                sb.append("UNSPECIFIED ");
14471            else if (mode == EXACTLY)
14472                sb.append("EXACTLY ");
14473            else if (mode == AT_MOST)
14474                sb.append("AT_MOST ");
14475            else
14476                sb.append(mode).append(" ");
14477
14478            sb.append(size);
14479            return sb.toString();
14480        }
14481    }
14482
14483    class CheckForLongPress implements Runnable {
14484
14485        private int mOriginalWindowAttachCount;
14486
14487        public void run() {
14488            if (isPressed() && (mParent != null)
14489                    && mOriginalWindowAttachCount == mWindowAttachCount) {
14490                if (performLongClick()) {
14491                    mHasPerformedLongPress = true;
14492                }
14493            }
14494        }
14495
14496        public void rememberWindowAttachCount() {
14497            mOriginalWindowAttachCount = mWindowAttachCount;
14498        }
14499    }
14500
14501    private final class CheckForTap implements Runnable {
14502        public void run() {
14503            mPrivateFlags &= ~PREPRESSED;
14504            setPressed(true);
14505            checkForLongClick(ViewConfiguration.getTapTimeout());
14506        }
14507    }
14508
14509    private final class PerformClick implements Runnable {
14510        public void run() {
14511            performClick();
14512        }
14513    }
14514
14515    /** @hide */
14516    public void hackTurnOffWindowResizeAnim(boolean off) {
14517        mAttachInfo.mTurnOffWindowResizeAnim = off;
14518    }
14519
14520    /**
14521     * This method returns a ViewPropertyAnimator object, which can be used to animate
14522     * specific properties on this View.
14523     *
14524     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
14525     */
14526    public ViewPropertyAnimator animate() {
14527        if (mAnimator == null) {
14528            mAnimator = new ViewPropertyAnimator(this);
14529        }
14530        return mAnimator;
14531    }
14532
14533    /**
14534     * Interface definition for a callback to be invoked when a key event is
14535     * dispatched to this view. The callback will be invoked before the key
14536     * event is given to the view.
14537     */
14538    public interface OnKeyListener {
14539        /**
14540         * Called when a key is dispatched to a view. This allows listeners to
14541         * get a chance to respond before the target view.
14542         *
14543         * @param v The view the key has been dispatched to.
14544         * @param keyCode The code for the physical key that was pressed
14545         * @param event The KeyEvent object containing full information about
14546         *        the event.
14547         * @return True if the listener has consumed the event, false otherwise.
14548         */
14549        boolean onKey(View v, int keyCode, KeyEvent event);
14550    }
14551
14552    /**
14553     * Interface definition for a callback to be invoked when a touch event is
14554     * dispatched to this view. The callback will be invoked before the touch
14555     * event is given to the view.
14556     */
14557    public interface OnTouchListener {
14558        /**
14559         * Called when a touch event is dispatched to a view. This allows listeners to
14560         * get a chance to respond before the target view.
14561         *
14562         * @param v The view the touch event has been dispatched to.
14563         * @param event The MotionEvent object containing full information about
14564         *        the event.
14565         * @return True if the listener has consumed the event, false otherwise.
14566         */
14567        boolean onTouch(View v, MotionEvent event);
14568    }
14569
14570    /**
14571     * Interface definition for a callback to be invoked when a hover event is
14572     * dispatched to this view. The callback will be invoked before the hover
14573     * event is given to the view.
14574     */
14575    public interface OnHoverListener {
14576        /**
14577         * Called when a hover event is dispatched to a view. This allows listeners to
14578         * get a chance to respond before the target view.
14579         *
14580         * @param v The view the hover event has been dispatched to.
14581         * @param event The MotionEvent object containing full information about
14582         *        the event.
14583         * @return True if the listener has consumed the event, false otherwise.
14584         */
14585        boolean onHover(View v, MotionEvent event);
14586    }
14587
14588    /**
14589     * Interface definition for a callback to be invoked when a generic motion event is
14590     * dispatched to this view. The callback will be invoked before the generic motion
14591     * event is given to the view.
14592     */
14593    public interface OnGenericMotionListener {
14594        /**
14595         * Called when a generic motion event is dispatched to a view. This allows listeners to
14596         * get a chance to respond before the target view.
14597         *
14598         * @param v The view the generic motion event has been dispatched to.
14599         * @param event The MotionEvent object containing full information about
14600         *        the event.
14601         * @return True if the listener has consumed the event, false otherwise.
14602         */
14603        boolean onGenericMotion(View v, MotionEvent event);
14604    }
14605
14606    /**
14607     * Interface definition for a callback to be invoked when a view has been clicked and held.
14608     */
14609    public interface OnLongClickListener {
14610        /**
14611         * Called when a view has been clicked and held.
14612         *
14613         * @param v The view that was clicked and held.
14614         *
14615         * @return true if the callback consumed the long click, false otherwise.
14616         */
14617        boolean onLongClick(View v);
14618    }
14619
14620    /**
14621     * Interface definition for a callback to be invoked when a drag is being dispatched
14622     * to this view.  The callback will be invoked before the hosting view's own
14623     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
14624     * onDrag(event) behavior, it should return 'false' from this callback.
14625     *
14626     * <div class="special reference">
14627     * <h3>Developer Guides</h3>
14628     * <p>For a guide to implementing drag and drop features, read the
14629     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
14630     * </div>
14631     */
14632    public interface OnDragListener {
14633        /**
14634         * Called when a drag event is dispatched to a view. This allows listeners
14635         * to get a chance to override base View behavior.
14636         *
14637         * @param v The View that received the drag event.
14638         * @param event The {@link android.view.DragEvent} object for the drag event.
14639         * @return {@code true} if the drag event was handled successfully, or {@code false}
14640         * if the drag event was not handled. Note that {@code false} will trigger the View
14641         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
14642         */
14643        boolean onDrag(View v, DragEvent event);
14644    }
14645
14646    /**
14647     * Interface definition for a callback to be invoked when the focus state of
14648     * a view changed.
14649     */
14650    public interface OnFocusChangeListener {
14651        /**
14652         * Called when the focus state of a view has changed.
14653         *
14654         * @param v The view whose state has changed.
14655         * @param hasFocus The new focus state of v.
14656         */
14657        void onFocusChange(View v, boolean hasFocus);
14658    }
14659
14660    /**
14661     * Interface definition for a callback to be invoked when a view is clicked.
14662     */
14663    public interface OnClickListener {
14664        /**
14665         * Called when a view has been clicked.
14666         *
14667         * @param v The view that was clicked.
14668         */
14669        void onClick(View v);
14670    }
14671
14672    /**
14673     * Interface definition for a callback to be invoked when the context menu
14674     * for this view is being built.
14675     */
14676    public interface OnCreateContextMenuListener {
14677        /**
14678         * Called when the context menu for this view is being built. It is not
14679         * safe to hold onto the menu after this method returns.
14680         *
14681         * @param menu The context menu that is being built
14682         * @param v The view for which the context menu is being built
14683         * @param menuInfo Extra information about the item for which the
14684         *            context menu should be shown. This information will vary
14685         *            depending on the class of v.
14686         */
14687        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
14688    }
14689
14690    /**
14691     * Interface definition for a callback to be invoked when the status bar changes
14692     * visibility.  This reports <strong>global</strong> changes to the system UI
14693     * state, not just what the application is requesting.
14694     *
14695     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
14696     */
14697    public interface OnSystemUiVisibilityChangeListener {
14698        /**
14699         * Called when the status bar changes visibility because of a call to
14700         * {@link View#setSystemUiVisibility(int)}.
14701         *
14702         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
14703         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  This tells you the
14704         * <strong>global</strong> state of the UI visibility flags, not what your
14705         * app is currently applying.
14706         */
14707        public void onSystemUiVisibilityChange(int visibility);
14708    }
14709
14710    /**
14711     * Interface definition for a callback to be invoked when this view is attached
14712     * or detached from its window.
14713     */
14714    public interface OnAttachStateChangeListener {
14715        /**
14716         * Called when the view is attached to a window.
14717         * @param v The view that was attached
14718         */
14719        public void onViewAttachedToWindow(View v);
14720        /**
14721         * Called when the view is detached from a window.
14722         * @param v The view that was detached
14723         */
14724        public void onViewDetachedFromWindow(View v);
14725    }
14726
14727    private final class UnsetPressedState implements Runnable {
14728        public void run() {
14729            setPressed(false);
14730        }
14731    }
14732
14733    /**
14734     * Base class for derived classes that want to save and restore their own
14735     * state in {@link android.view.View#onSaveInstanceState()}.
14736     */
14737    public static class BaseSavedState extends AbsSavedState {
14738        /**
14739         * Constructor used when reading from a parcel. Reads the state of the superclass.
14740         *
14741         * @param source
14742         */
14743        public BaseSavedState(Parcel source) {
14744            super(source);
14745        }
14746
14747        /**
14748         * Constructor called by derived classes when creating their SavedState objects
14749         *
14750         * @param superState The state of the superclass of this view
14751         */
14752        public BaseSavedState(Parcelable superState) {
14753            super(superState);
14754        }
14755
14756        public static final Parcelable.Creator<BaseSavedState> CREATOR =
14757                new Parcelable.Creator<BaseSavedState>() {
14758            public BaseSavedState createFromParcel(Parcel in) {
14759                return new BaseSavedState(in);
14760            }
14761
14762            public BaseSavedState[] newArray(int size) {
14763                return new BaseSavedState[size];
14764            }
14765        };
14766    }
14767
14768    /**
14769     * A set of information given to a view when it is attached to its parent
14770     * window.
14771     */
14772    static class AttachInfo {
14773        interface Callbacks {
14774            void playSoundEffect(int effectId);
14775            boolean performHapticFeedback(int effectId, boolean always);
14776        }
14777
14778        /**
14779         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
14780         * to a Handler. This class contains the target (View) to invalidate and
14781         * the coordinates of the dirty rectangle.
14782         *
14783         * For performance purposes, this class also implements a pool of up to
14784         * POOL_LIMIT objects that get reused. This reduces memory allocations
14785         * whenever possible.
14786         */
14787        static class InvalidateInfo implements Poolable<InvalidateInfo> {
14788            private static final int POOL_LIMIT = 10;
14789            private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
14790                    Pools.finitePool(new PoolableManager<InvalidateInfo>() {
14791                        public InvalidateInfo newInstance() {
14792                            return new InvalidateInfo();
14793                        }
14794
14795                        public void onAcquired(InvalidateInfo element) {
14796                        }
14797
14798                        public void onReleased(InvalidateInfo element) {
14799                            element.target = null;
14800                        }
14801                    }, POOL_LIMIT)
14802            );
14803
14804            private InvalidateInfo mNext;
14805            private boolean mIsPooled;
14806
14807            View target;
14808
14809            int left;
14810            int top;
14811            int right;
14812            int bottom;
14813
14814            public void setNextPoolable(InvalidateInfo element) {
14815                mNext = element;
14816            }
14817
14818            public InvalidateInfo getNextPoolable() {
14819                return mNext;
14820            }
14821
14822            static InvalidateInfo acquire() {
14823                return sPool.acquire();
14824            }
14825
14826            void release() {
14827                sPool.release(this);
14828            }
14829
14830            public boolean isPooled() {
14831                return mIsPooled;
14832            }
14833
14834            public void setPooled(boolean isPooled) {
14835                mIsPooled = isPooled;
14836            }
14837        }
14838
14839        final IWindowSession mSession;
14840
14841        final IWindow mWindow;
14842
14843        final IBinder mWindowToken;
14844
14845        final Callbacks mRootCallbacks;
14846
14847        HardwareCanvas mHardwareCanvas;
14848
14849        /**
14850         * The top view of the hierarchy.
14851         */
14852        View mRootView;
14853
14854        IBinder mPanelParentWindowToken;
14855        Surface mSurface;
14856
14857        boolean mHardwareAccelerated;
14858        boolean mHardwareAccelerationRequested;
14859        HardwareRenderer mHardwareRenderer;
14860
14861        /**
14862         * Scale factor used by the compatibility mode
14863         */
14864        float mApplicationScale;
14865
14866        /**
14867         * Indicates whether the application is in compatibility mode
14868         */
14869        boolean mScalingRequired;
14870
14871        /**
14872         * If set, ViewAncestor doesn't use its lame animation for when the window resizes.
14873         */
14874        boolean mTurnOffWindowResizeAnim;
14875
14876        /**
14877         * Left position of this view's window
14878         */
14879        int mWindowLeft;
14880
14881        /**
14882         * Top position of this view's window
14883         */
14884        int mWindowTop;
14885
14886        /**
14887         * Indicates whether views need to use 32-bit drawing caches
14888         */
14889        boolean mUse32BitDrawingCache;
14890
14891        /**
14892         * For windows that are full-screen but using insets to layout inside
14893         * of the screen decorations, these are the current insets for the
14894         * content of the window.
14895         */
14896        final Rect mContentInsets = new Rect();
14897
14898        /**
14899         * For windows that are full-screen but using insets to layout inside
14900         * of the screen decorations, these are the current insets for the
14901         * actual visible parts of the window.
14902         */
14903        final Rect mVisibleInsets = new Rect();
14904
14905        /**
14906         * The internal insets given by this window.  This value is
14907         * supplied by the client (through
14908         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
14909         * be given to the window manager when changed to be used in laying
14910         * out windows behind it.
14911         */
14912        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
14913                = new ViewTreeObserver.InternalInsetsInfo();
14914
14915        /**
14916         * All views in the window's hierarchy that serve as scroll containers,
14917         * used to determine if the window can be resized or must be panned
14918         * to adjust for a soft input area.
14919         */
14920        final ArrayList<View> mScrollContainers = new ArrayList<View>();
14921
14922        final KeyEvent.DispatcherState mKeyDispatchState
14923                = new KeyEvent.DispatcherState();
14924
14925        /**
14926         * Indicates whether the view's window currently has the focus.
14927         */
14928        boolean mHasWindowFocus;
14929
14930        /**
14931         * The current visibility of the window.
14932         */
14933        int mWindowVisibility;
14934
14935        /**
14936         * Indicates the time at which drawing started to occur.
14937         */
14938        long mDrawingTime;
14939
14940        /**
14941         * Indicates whether or not ignoring the DIRTY_MASK flags.
14942         */
14943        boolean mIgnoreDirtyState;
14944
14945        /**
14946         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
14947         * to avoid clearing that flag prematurely.
14948         */
14949        boolean mSetIgnoreDirtyState = false;
14950
14951        /**
14952         * Indicates whether the view's window is currently in touch mode.
14953         */
14954        boolean mInTouchMode;
14955
14956        /**
14957         * Indicates that ViewAncestor should trigger a global layout change
14958         * the next time it performs a traversal
14959         */
14960        boolean mRecomputeGlobalAttributes;
14961
14962        /**
14963         * Always report new attributes at next traversal.
14964         */
14965        boolean mForceReportNewAttributes;
14966
14967        /**
14968         * Set during a traveral if any views want to keep the screen on.
14969         */
14970        boolean mKeepScreenOn;
14971
14972        /**
14973         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
14974         */
14975        int mSystemUiVisibility;
14976
14977        /**
14978         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
14979         * attached.
14980         */
14981        boolean mHasSystemUiListeners;
14982
14983        /**
14984         * Set if the visibility of any views has changed.
14985         */
14986        boolean mViewVisibilityChanged;
14987
14988        /**
14989         * Set to true if a view has been scrolled.
14990         */
14991        boolean mViewScrollChanged;
14992
14993        /**
14994         * Global to the view hierarchy used as a temporary for dealing with
14995         * x/y points in the transparent region computations.
14996         */
14997        final int[] mTransparentLocation = new int[2];
14998
14999        /**
15000         * Global to the view hierarchy used as a temporary for dealing with
15001         * x/y points in the ViewGroup.invalidateChild implementation.
15002         */
15003        final int[] mInvalidateChildLocation = new int[2];
15004
15005
15006        /**
15007         * Global to the view hierarchy used as a temporary for dealing with
15008         * x/y location when view is transformed.
15009         */
15010        final float[] mTmpTransformLocation = new float[2];
15011
15012        /**
15013         * The view tree observer used to dispatch global events like
15014         * layout, pre-draw, touch mode change, etc.
15015         */
15016        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
15017
15018        /**
15019         * A Canvas used by the view hierarchy to perform bitmap caching.
15020         */
15021        Canvas mCanvas;
15022
15023        /**
15024         * The view root impl.
15025         */
15026        final ViewRootImpl mViewRootImpl;
15027
15028        /**
15029         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
15030         * handler can be used to pump events in the UI events queue.
15031         */
15032        final Handler mHandler;
15033
15034        /**
15035         * Temporary for use in computing invalidate rectangles while
15036         * calling up the hierarchy.
15037         */
15038        final Rect mTmpInvalRect = new Rect();
15039
15040        /**
15041         * Temporary for use in computing hit areas with transformed views
15042         */
15043        final RectF mTmpTransformRect = new RectF();
15044
15045        /**
15046         * Temporary list for use in collecting focusable descendents of a view.
15047         */
15048        final ArrayList<View> mFocusablesTempList = new ArrayList<View>(24);
15049
15050        /**
15051         * The id of the window for accessibility purposes.
15052         */
15053        int mAccessibilityWindowId = View.NO_ID;
15054
15055        /**
15056         * Creates a new set of attachment information with the specified
15057         * events handler and thread.
15058         *
15059         * @param handler the events handler the view must use
15060         */
15061        AttachInfo(IWindowSession session, IWindow window,
15062                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
15063            mSession = session;
15064            mWindow = window;
15065            mWindowToken = window.asBinder();
15066            mViewRootImpl = viewRootImpl;
15067            mHandler = handler;
15068            mRootCallbacks = effectPlayer;
15069        }
15070    }
15071
15072    /**
15073     * <p>ScrollabilityCache holds various fields used by a View when scrolling
15074     * is supported. This avoids keeping too many unused fields in most
15075     * instances of View.</p>
15076     */
15077    private static class ScrollabilityCache implements Runnable {
15078
15079        /**
15080         * Scrollbars are not visible
15081         */
15082        public static final int OFF = 0;
15083
15084        /**
15085         * Scrollbars are visible
15086         */
15087        public static final int ON = 1;
15088
15089        /**
15090         * Scrollbars are fading away
15091         */
15092        public static final int FADING = 2;
15093
15094        public boolean fadeScrollBars;
15095
15096        public int fadingEdgeLength;
15097        public int scrollBarDefaultDelayBeforeFade;
15098        public int scrollBarFadeDuration;
15099
15100        public int scrollBarSize;
15101        public ScrollBarDrawable scrollBar;
15102        public float[] interpolatorValues;
15103        public View host;
15104
15105        public final Paint paint;
15106        public final Matrix matrix;
15107        public Shader shader;
15108
15109        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
15110
15111        private static final float[] OPAQUE = { 255 };
15112        private static final float[] TRANSPARENT = { 0.0f };
15113
15114        /**
15115         * When fading should start. This time moves into the future every time
15116         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
15117         */
15118        public long fadeStartTime;
15119
15120
15121        /**
15122         * The current state of the scrollbars: ON, OFF, or FADING
15123         */
15124        public int state = OFF;
15125
15126        private int mLastColor;
15127
15128        public ScrollabilityCache(ViewConfiguration configuration, View host) {
15129            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
15130            scrollBarSize = configuration.getScaledScrollBarSize();
15131            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
15132            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
15133
15134            paint = new Paint();
15135            matrix = new Matrix();
15136            // use use a height of 1, and then wack the matrix each time we
15137            // actually use it.
15138            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
15139
15140            paint.setShader(shader);
15141            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
15142            this.host = host;
15143        }
15144
15145        public void setFadeColor(int color) {
15146            if (color != 0 && color != mLastColor) {
15147                mLastColor = color;
15148                color |= 0xFF000000;
15149
15150                shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
15151                        color & 0x00FFFFFF, Shader.TileMode.CLAMP);
15152
15153                paint.setShader(shader);
15154                // Restore the default transfer mode (src_over)
15155                paint.setXfermode(null);
15156            }
15157        }
15158
15159        public void run() {
15160            long now = AnimationUtils.currentAnimationTimeMillis();
15161            if (now >= fadeStartTime) {
15162
15163                // the animation fades the scrollbars out by changing
15164                // the opacity (alpha) from fully opaque to fully
15165                // transparent
15166                int nextFrame = (int) now;
15167                int framesCount = 0;
15168
15169                Interpolator interpolator = scrollBarInterpolator;
15170
15171                // Start opaque
15172                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
15173
15174                // End transparent
15175                nextFrame += scrollBarFadeDuration;
15176                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
15177
15178                state = FADING;
15179
15180                // Kick off the fade animation
15181                host.invalidate(true);
15182            }
15183        }
15184    }
15185
15186    /**
15187     * Resuable callback for sending
15188     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
15189     */
15190    private class SendViewScrolledAccessibilityEvent implements Runnable {
15191        public volatile boolean mIsPending;
15192
15193        public void run() {
15194            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
15195            mIsPending = false;
15196        }
15197    }
15198
15199    /**
15200     * <p>
15201     * This class represents a delegate that can be registered in a {@link View}
15202     * to enhance accessibility support via composition rather via inheritance.
15203     * It is specifically targeted to widget developers that extend basic View
15204     * classes i.e. classes in package android.view, that would like their
15205     * applications to be backwards compatible.
15206     * </p>
15207     * <p>
15208     * A scenario in which a developer would like to use an accessibility delegate
15209     * is overriding a method introduced in a later API version then the minimal API
15210     * version supported by the application. For example, the method
15211     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
15212     * in API version 4 when the accessibility APIs were first introduced. If a
15213     * developer would like his application to run on API version 4 devices (assuming
15214     * all other APIs used by the application are version 4 or lower) and take advantage
15215     * of this method, instead of overriding the method which would break the application's
15216     * backwards compatibility, he can override the corresponding method in this
15217     * delegate and register the delegate in the target View if the API version of
15218     * the system is high enough i.e. the API version is same or higher to the API
15219     * version that introduced
15220     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
15221     * </p>
15222     * <p>
15223     * Here is an example implementation:
15224     * </p>
15225     * <code><pre><p>
15226     * if (Build.VERSION.SDK_INT >= 14) {
15227     *     // If the API version is equal of higher than the version in
15228     *     // which onInitializeAccessibilityNodeInfo was introduced we
15229     *     // register a delegate with a customized implementation.
15230     *     View view = findViewById(R.id.view_id);
15231     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
15232     *         public void onInitializeAccessibilityNodeInfo(View host,
15233     *                 AccessibilityNodeInfo info) {
15234     *             // Let the default implementation populate the info.
15235     *             super.onInitializeAccessibilityNodeInfo(host, info);
15236     *             // Set some other information.
15237     *             info.setEnabled(host.isEnabled());
15238     *         }
15239     *     });
15240     * }
15241     * </code></pre></p>
15242     * <p>
15243     * This delegate contains methods that correspond to the accessibility methods
15244     * in View. If a delegate has been specified the implementation in View hands
15245     * off handling to the corresponding method in this delegate. The default
15246     * implementation the delegate methods behaves exactly as the corresponding
15247     * method in View for the case of no accessibility delegate been set. Hence,
15248     * to customize the behavior of a View method, clients can override only the
15249     * corresponding delegate method without altering the behavior of the rest
15250     * accessibility related methods of the host view.
15251     * </p>
15252     */
15253    public static class AccessibilityDelegate {
15254
15255        /**
15256         * Sends an accessibility event of the given type. If accessibility is not
15257         * enabled this method has no effect.
15258         * <p>
15259         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
15260         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
15261         * been set.
15262         * </p>
15263         *
15264         * @param host The View hosting the delegate.
15265         * @param eventType The type of the event to send.
15266         *
15267         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
15268         */
15269        public void sendAccessibilityEvent(View host, int eventType) {
15270            host.sendAccessibilityEventInternal(eventType);
15271        }
15272
15273        /**
15274         * Sends an accessibility event. This method behaves exactly as
15275         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
15276         * empty {@link AccessibilityEvent} and does not perform a check whether
15277         * accessibility is enabled.
15278         * <p>
15279         * The default implementation behaves as
15280         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
15281         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
15282         * the case of no accessibility delegate been set.
15283         * </p>
15284         *
15285         * @param host The View hosting the delegate.
15286         * @param event The event to send.
15287         *
15288         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
15289         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
15290         */
15291        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
15292            host.sendAccessibilityEventUncheckedInternal(event);
15293        }
15294
15295        /**
15296         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
15297         * to its children for adding their text content to the event.
15298         * <p>
15299         * The default implementation behaves as
15300         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
15301         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
15302         * the case of no accessibility delegate been set.
15303         * </p>
15304         *
15305         * @param host The View hosting the delegate.
15306         * @param event The event.
15307         * @return True if the event population was completed.
15308         *
15309         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
15310         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
15311         */
15312        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
15313            return host.dispatchPopulateAccessibilityEventInternal(event);
15314        }
15315
15316        /**
15317         * Gives a chance to the host View to populate the accessibility event with its
15318         * text content.
15319         * <p>
15320         * The default implementation behaves as
15321         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
15322         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
15323         * the case of no accessibility delegate been set.
15324         * </p>
15325         *
15326         * @param host The View hosting the delegate.
15327         * @param event The accessibility event which to populate.
15328         *
15329         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
15330         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
15331         */
15332        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
15333            host.onPopulateAccessibilityEventInternal(event);
15334        }
15335
15336        /**
15337         * Initializes an {@link AccessibilityEvent} with information about the
15338         * the host View which is the event source.
15339         * <p>
15340         * The default implementation behaves as
15341         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
15342         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
15343         * the case of no accessibility delegate been set.
15344         * </p>
15345         *
15346         * @param host The View hosting the delegate.
15347         * @param event The event to initialize.
15348         *
15349         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
15350         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
15351         */
15352        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
15353            host.onInitializeAccessibilityEventInternal(event);
15354        }
15355
15356        /**
15357         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
15358         * <p>
15359         * The default implementation behaves as
15360         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
15361         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
15362         * the case of no accessibility delegate been set.
15363         * </p>
15364         *
15365         * @param host The View hosting the delegate.
15366         * @param info The instance to initialize.
15367         *
15368         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
15369         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
15370         */
15371        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
15372            host.onInitializeAccessibilityNodeInfoInternal(info);
15373        }
15374
15375        /**
15376         * Called when a child of the host View has requested sending an
15377         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
15378         * to augment the event.
15379         * <p>
15380         * The default implementation behaves as
15381         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
15382         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
15383         * the case of no accessibility delegate been set.
15384         * </p>
15385         *
15386         * @param host The View hosting the delegate.
15387         * @param child The child which requests sending the event.
15388         * @param event The event to be sent.
15389         * @return True if the event should be sent
15390         *
15391         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
15392         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
15393         */
15394        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
15395                AccessibilityEvent event) {
15396            return host.onRequestSendAccessibilityEventInternal(child, event);
15397        }
15398
15399        /**
15400         * Gets the provider for managing a virtual view hierarchy rooted at this View
15401         * and reported to {@link android.accessibilityservice.AccessibilityService}s
15402         * that explore the window content.
15403         * <p>
15404         * The default implementation behaves as
15405         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
15406         * the case of no accessibility delegate been set.
15407         * </p>
15408         *
15409         * @return The provider.
15410         *
15411         * @see AccessibilityNodeProvider
15412         */
15413        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
15414            return null;
15415        }
15416    }
15417}
15418