View.java revision 9dd4c5c6867f8b6de19096d2d68365dccb744c19
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.app.ActivityThread;
20import android.content.ClipData;
21import android.content.Context;
22import android.content.res.Configuration;
23import android.content.res.Resources;
24import android.content.res.TypedArray;
25import android.graphics.Bitmap;
26import android.graphics.Camera;
27import android.graphics.Canvas;
28import android.graphics.Insets;
29import android.graphics.Interpolator;
30import android.graphics.LinearGradient;
31import android.graphics.Matrix;
32import android.graphics.Paint;
33import android.graphics.PixelFormat;
34import android.graphics.Point;
35import android.graphics.PorterDuff;
36import android.graphics.PorterDuffXfermode;
37import android.graphics.Rect;
38import android.graphics.RectF;
39import android.graphics.Region;
40import android.graphics.Shader;
41import android.graphics.drawable.ColorDrawable;
42import android.graphics.drawable.Drawable;
43import android.hardware.display.DisplayManagerGlobal;
44import android.os.Build;
45import android.os.Bundle;
46import android.os.Handler;
47import android.os.IBinder;
48import android.os.Parcel;
49import android.os.Parcelable;
50import android.os.RemoteException;
51import android.os.SystemClock;
52import android.os.SystemProperties;
53import android.text.TextUtils;
54import android.util.AttributeSet;
55import android.util.FloatProperty;
56import android.util.Log;
57import android.util.Pools.SynchronizedPool;
58import android.util.Property;
59import android.util.SparseArray;
60import android.util.TypedValue;
61import android.view.ContextMenu.ContextMenuInfo;
62import android.view.AccessibilityIterators.TextSegmentIterator;
63import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
64import android.view.AccessibilityIterators.WordTextSegmentIterator;
65import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
66import android.view.accessibility.AccessibilityEvent;
67import android.view.accessibility.AccessibilityEventSource;
68import android.view.accessibility.AccessibilityManager;
69import android.view.accessibility.AccessibilityNodeInfo;
70import android.view.accessibility.AccessibilityNodeProvider;
71import android.view.animation.Animation;
72import android.view.animation.AnimationUtils;
73import android.view.animation.Transformation;
74import android.view.inputmethod.EditorInfo;
75import android.view.inputmethod.InputConnection;
76import android.view.inputmethod.InputMethodManager;
77import android.widget.ScrollBarDrawable;
78
79import static android.os.Build.VERSION_CODES.*;
80import static java.lang.Math.max;
81
82import com.android.internal.R;
83import com.android.internal.util.Predicate;
84import com.android.internal.view.menu.MenuBuilder;
85import com.google.android.collect.Lists;
86import com.google.android.collect.Maps;
87
88import java.lang.ref.WeakReference;
89import java.lang.reflect.Field;
90import java.lang.reflect.InvocationTargetException;
91import java.lang.reflect.Method;
92import java.lang.reflect.Modifier;
93import java.util.ArrayList;
94import java.util.Arrays;
95import java.util.Collections;
96import java.util.HashMap;
97import java.util.Locale;
98import java.util.concurrent.CopyOnWriteArrayList;
99import java.util.concurrent.atomic.AtomicInteger;
100
101/**
102 * <p>
103 * This class represents the basic building block for user interface components. A View
104 * occupies a rectangular area on the screen and is responsible for drawing and
105 * event handling. View is the base class for <em>widgets</em>, which are
106 * used to create interactive UI components (buttons, text fields, etc.). The
107 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
108 * are invisible containers that hold other Views (or other ViewGroups) and define
109 * their layout properties.
110 * </p>
111 *
112 * <div class="special reference">
113 * <h3>Developer Guides</h3>
114 * <p>For information about using this class to develop your application's user interface,
115 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
116 * </div>
117 *
118 * <a name="Using"></a>
119 * <h3>Using Views</h3>
120 * <p>
121 * All of the views in a window are arranged in a single tree. You can add views
122 * either from code or by specifying a tree of views in one or more XML layout
123 * files. There are many specialized subclasses of views that act as controls or
124 * are capable of displaying text, images, or other content.
125 * </p>
126 * <p>
127 * Once you have created a tree of views, there are typically a few types of
128 * common operations you may wish to perform:
129 * <ul>
130 * <li><strong>Set properties:</strong> for example setting the text of a
131 * {@link android.widget.TextView}. The available properties and the methods
132 * that set them will vary among the different subclasses of views. Note that
133 * properties that are known at build time can be set in the XML layout
134 * files.</li>
135 * <li><strong>Set focus:</strong> The framework will handled moving focus in
136 * response to user input. To force focus to a specific view, call
137 * {@link #requestFocus}.</li>
138 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
139 * that will be notified when something interesting happens to the view. For
140 * example, all views will let you set a listener to be notified when the view
141 * gains or loses focus. You can register such a listener using
142 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
143 * Other view subclasses offer more specialized listeners. For example, a Button
144 * exposes a listener to notify clients when the button is clicked.</li>
145 * <li><strong>Set visibility:</strong> You can hide or show views using
146 * {@link #setVisibility(int)}.</li>
147 * </ul>
148 * </p>
149 * <p><em>
150 * Note: The Android framework is responsible for measuring, laying out and
151 * drawing views. You should not call methods that perform these actions on
152 * views yourself unless you are actually implementing a
153 * {@link android.view.ViewGroup}.
154 * </em></p>
155 *
156 * <a name="Lifecycle"></a>
157 * <h3>Implementing a Custom View</h3>
158 *
159 * <p>
160 * To implement a custom view, you will usually begin by providing overrides for
161 * some of the standard methods that the framework calls on all views. You do
162 * not need to override all of these methods. In fact, you can start by just
163 * overriding {@link #onDraw(android.graphics.Canvas)}.
164 * <table border="2" width="85%" align="center" cellpadding="5">
165 *     <thead>
166 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
167 *     </thead>
168 *
169 *     <tbody>
170 *     <tr>
171 *         <td rowspan="2">Creation</td>
172 *         <td>Constructors</td>
173 *         <td>There is a form of the constructor that are called when the view
174 *         is created from code and a form that is called when the view is
175 *         inflated from a layout file. The second form should parse and apply
176 *         any attributes defined in the layout file.
177 *         </td>
178 *     </tr>
179 *     <tr>
180 *         <td><code>{@link #onFinishInflate()}</code></td>
181 *         <td>Called after a view and all of its children has been inflated
182 *         from XML.</td>
183 *     </tr>
184 *
185 *     <tr>
186 *         <td rowspan="3">Layout</td>
187 *         <td><code>{@link #onMeasure(int, int)}</code></td>
188 *         <td>Called to determine the size requirements for this view and all
189 *         of its children.
190 *         </td>
191 *     </tr>
192 *     <tr>
193 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
194 *         <td>Called when this view should assign a size and position to all
195 *         of its children.
196 *         </td>
197 *     </tr>
198 *     <tr>
199 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
200 *         <td>Called when the size of this view has changed.
201 *         </td>
202 *     </tr>
203 *
204 *     <tr>
205 *         <td>Drawing</td>
206 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
207 *         <td>Called when the view should render its content.
208 *         </td>
209 *     </tr>
210 *
211 *     <tr>
212 *         <td rowspan="4">Event processing</td>
213 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
214 *         <td>Called when a new hardware key event occurs.
215 *         </td>
216 *     </tr>
217 *     <tr>
218 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
219 *         <td>Called when a hardware key up event occurs.
220 *         </td>
221 *     </tr>
222 *     <tr>
223 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
224 *         <td>Called when a trackball motion event occurs.
225 *         </td>
226 *     </tr>
227 *     <tr>
228 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
229 *         <td>Called when a touch screen motion event occurs.
230 *         </td>
231 *     </tr>
232 *
233 *     <tr>
234 *         <td rowspan="2">Focus</td>
235 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
236 *         <td>Called when the view gains or loses focus.
237 *         </td>
238 *     </tr>
239 *
240 *     <tr>
241 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
242 *         <td>Called when the window containing the view gains or loses focus.
243 *         </td>
244 *     </tr>
245 *
246 *     <tr>
247 *         <td rowspan="3">Attaching</td>
248 *         <td><code>{@link #onAttachedToWindow()}</code></td>
249 *         <td>Called when the view is attached to a window.
250 *         </td>
251 *     </tr>
252 *
253 *     <tr>
254 *         <td><code>{@link #onDetachedFromWindow}</code></td>
255 *         <td>Called when the view is detached from its window.
256 *         </td>
257 *     </tr>
258 *
259 *     <tr>
260 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
261 *         <td>Called when the visibility of the window containing the view
262 *         has changed.
263 *         </td>
264 *     </tr>
265 *     </tbody>
266 *
267 * </table>
268 * </p>
269 *
270 * <a name="IDs"></a>
271 * <h3>IDs</h3>
272 * Views may have an integer id associated with them. These ids are typically
273 * assigned in the layout XML files, and are used to find specific views within
274 * the view tree. A common pattern is to:
275 * <ul>
276 * <li>Define a Button in the layout file and assign it a unique ID.
277 * <pre>
278 * &lt;Button
279 *     android:id="@+id/my_button"
280 *     android:layout_width="wrap_content"
281 *     android:layout_height="wrap_content"
282 *     android:text="@string/my_button_text"/&gt;
283 * </pre></li>
284 * <li>From the onCreate method of an Activity, find the Button
285 * <pre class="prettyprint">
286 *      Button myButton = (Button) findViewById(R.id.my_button);
287 * </pre></li>
288 * </ul>
289 * <p>
290 * View IDs need not be unique throughout the tree, but it is good practice to
291 * ensure that they are at least unique within the part of the tree you are
292 * searching.
293 * </p>
294 *
295 * <a name="Position"></a>
296 * <h3>Position</h3>
297 * <p>
298 * The geometry of a view is that of a rectangle. A view has a location,
299 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
300 * two dimensions, expressed as a width and a height. The unit for location
301 * and dimensions is the pixel.
302 * </p>
303 *
304 * <p>
305 * It is possible to retrieve the location of a view by invoking the methods
306 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
307 * coordinate of the rectangle representing the view. The latter returns the
308 * top, or Y, coordinate of the rectangle representing the view. These methods
309 * both return the location of the view relative to its parent. For instance,
310 * when getLeft() returns 20, that means the view is located 20 pixels to the
311 * right of the left edge of its direct parent.
312 * </p>
313 *
314 * <p>
315 * In addition, several convenience methods are offered to avoid unnecessary
316 * computations, namely {@link #getRight()} and {@link #getBottom()}.
317 * These methods return the coordinates of the right and bottom edges of the
318 * rectangle representing the view. For instance, calling {@link #getRight()}
319 * is similar to the following computation: <code>getLeft() + getWidth()</code>
320 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
321 * </p>
322 *
323 * <a name="SizePaddingMargins"></a>
324 * <h3>Size, padding and margins</h3>
325 * <p>
326 * The size of a view is expressed with a width and a height. A view actually
327 * possess two pairs of width and height values.
328 * </p>
329 *
330 * <p>
331 * The first pair is known as <em>measured width</em> and
332 * <em>measured height</em>. These dimensions define how big a view wants to be
333 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
334 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
335 * and {@link #getMeasuredHeight()}.
336 * </p>
337 *
338 * <p>
339 * The second pair is simply known as <em>width</em> and <em>height</em>, or
340 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
341 * dimensions define the actual size of the view on screen, at drawing time and
342 * after layout. These values may, but do not have to, be different from the
343 * measured width and height. The width and height can be obtained by calling
344 * {@link #getWidth()} and {@link #getHeight()}.
345 * </p>
346 *
347 * <p>
348 * To measure its dimensions, a view takes into account its padding. The padding
349 * is expressed in pixels for the left, top, right and bottom parts of the view.
350 * Padding can be used to offset the content of the view by a specific amount of
351 * pixels. For instance, a left padding of 2 will push the view's content by
352 * 2 pixels to the right of the left edge. Padding can be set using the
353 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
354 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
355 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
356 * {@link #getPaddingEnd()}.
357 * </p>
358 *
359 * <p>
360 * Even though a view can define a padding, it does not provide any support for
361 * margins. However, view groups provide such a support. Refer to
362 * {@link android.view.ViewGroup} and
363 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
364 * </p>
365 *
366 * <a name="Layout"></a>
367 * <h3>Layout</h3>
368 * <p>
369 * Layout is a two pass process: a measure pass and a layout pass. The measuring
370 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
371 * of the view tree. Each view pushes dimension specifications down the tree
372 * during the recursion. At the end of the measure pass, every view has stored
373 * its measurements. The second pass happens in
374 * {@link #layout(int,int,int,int)} and is also top-down. During
375 * this pass each parent is responsible for positioning all of its children
376 * using the sizes computed in the measure pass.
377 * </p>
378 *
379 * <p>
380 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
381 * {@link #getMeasuredHeight()} values must be set, along with those for all of
382 * that view's descendants. A view's measured width and measured height values
383 * must respect the constraints imposed by the view's parents. This guarantees
384 * that at the end of the measure pass, all parents accept all of their
385 * children's measurements. A parent view may call measure() more than once on
386 * its children. For example, the parent may measure each child once with
387 * unspecified dimensions to find out how big they want to be, then call
388 * measure() on them again with actual numbers if the sum of all the children's
389 * unconstrained sizes is too big or too small.
390 * </p>
391 *
392 * <p>
393 * The measure pass uses two classes to communicate dimensions. The
394 * {@link MeasureSpec} class is used by views to tell their parents how they
395 * want to be measured and positioned. The base LayoutParams class just
396 * describes how big the view wants to be for both width and height. For each
397 * dimension, it can specify one of:
398 * <ul>
399 * <li> an exact number
400 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
401 * (minus padding)
402 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
403 * enclose its content (plus padding).
404 * </ul>
405 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
406 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
407 * an X and Y value.
408 * </p>
409 *
410 * <p>
411 * MeasureSpecs are used to push requirements down the tree from parent to
412 * child. A MeasureSpec can be in one of three modes:
413 * <ul>
414 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
415 * of a child view. For example, a LinearLayout may call measure() on its child
416 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
417 * tall the child view wants to be given a width of 240 pixels.
418 * <li>EXACTLY: This is used by the parent to impose an exact size on the
419 * child. The child must use this size, and guarantee that all of its
420 * descendants will fit within this size.
421 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
422 * child. The child must gurantee that it and all of its descendants will fit
423 * within this size.
424 * </ul>
425 * </p>
426 *
427 * <p>
428 * To intiate a layout, call {@link #requestLayout}. This method is typically
429 * called by a view on itself when it believes that is can no longer fit within
430 * its current bounds.
431 * </p>
432 *
433 * <a name="Drawing"></a>
434 * <h3>Drawing</h3>
435 * <p>
436 * Drawing is handled by walking the tree and rendering each view that
437 * intersects the invalid region. Because the tree is traversed in-order,
438 * this means that parents will draw before (i.e., behind) their children, with
439 * siblings drawn in the order they appear in the tree.
440 * If you set a background drawable for a View, then the View will draw it for you
441 * before calling back to its <code>onDraw()</code> method.
442 * </p>
443 *
444 * <p>
445 * Note that the framework will not draw views that are not in the invalid region.
446 * </p>
447 *
448 * <p>
449 * To force a view to draw, call {@link #invalidate()}.
450 * </p>
451 *
452 * <a name="EventHandlingThreading"></a>
453 * <h3>Event Handling and Threading</h3>
454 * <p>
455 * The basic cycle of a view is as follows:
456 * <ol>
457 * <li>An event comes in and is dispatched to the appropriate view. The view
458 * handles the event and notifies any listeners.</li>
459 * <li>If in the course of processing the event, the view's bounds may need
460 * to be changed, the view will call {@link #requestLayout()}.</li>
461 * <li>Similarly, if in the course of processing the event the view's appearance
462 * may need to be changed, the view will call {@link #invalidate()}.</li>
463 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
464 * the framework will take care of measuring, laying out, and drawing the tree
465 * as appropriate.</li>
466 * </ol>
467 * </p>
468 *
469 * <p><em>Note: The entire view tree is single threaded. You must always be on
470 * the UI thread when calling any method on any view.</em>
471 * If you are doing work on other threads and want to update the state of a view
472 * from that thread, you should use a {@link Handler}.
473 * </p>
474 *
475 * <a name="FocusHandling"></a>
476 * <h3>Focus Handling</h3>
477 * <p>
478 * The framework will handle routine focus movement in response to user input.
479 * This includes changing the focus as views are removed or hidden, or as new
480 * views become available. Views indicate their willingness to take focus
481 * through the {@link #isFocusable} method. To change whether a view can take
482 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
483 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
484 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
485 * </p>
486 * <p>
487 * Focus movement is based on an algorithm which finds the nearest neighbor in a
488 * given direction. In rare cases, the default algorithm may not match the
489 * intended behavior of the developer. In these situations, you can provide
490 * explicit overrides by using these XML attributes in the layout file:
491 * <pre>
492 * nextFocusDown
493 * nextFocusLeft
494 * nextFocusRight
495 * nextFocusUp
496 * </pre>
497 * </p>
498 *
499 *
500 * <p>
501 * To get a particular view to take focus, call {@link #requestFocus()}.
502 * </p>
503 *
504 * <a name="TouchMode"></a>
505 * <h3>Touch Mode</h3>
506 * <p>
507 * When a user is navigating a user interface via directional keys such as a D-pad, it is
508 * necessary to give focus to actionable items such as buttons so the user can see
509 * what will take input.  If the device has touch capabilities, however, and the user
510 * begins interacting with the interface by touching it, it is no longer necessary to
511 * always highlight, or give focus to, a particular view.  This motivates a mode
512 * for interaction named 'touch mode'.
513 * </p>
514 * <p>
515 * For a touch capable device, once the user touches the screen, the device
516 * will enter touch mode.  From this point onward, only views for which
517 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
518 * Other views that are touchable, like buttons, will not take focus when touched; they will
519 * only fire the on click listeners.
520 * </p>
521 * <p>
522 * Any time a user hits a directional key, such as a D-pad direction, the view device will
523 * exit touch mode, and find a view to take focus, so that the user may resume interacting
524 * with the user interface without touching the screen again.
525 * </p>
526 * <p>
527 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
528 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
529 * </p>
530 *
531 * <a name="Scrolling"></a>
532 * <h3>Scrolling</h3>
533 * <p>
534 * The framework provides basic support for views that wish to internally
535 * scroll their content. This includes keeping track of the X and Y scroll
536 * offset as well as mechanisms for drawing scrollbars. See
537 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
538 * {@link #awakenScrollBars()} for more details.
539 * </p>
540 *
541 * <a name="Tags"></a>
542 * <h3>Tags</h3>
543 * <p>
544 * Unlike IDs, tags are not used to identify views. Tags are essentially an
545 * extra piece of information that can be associated with a view. They are most
546 * often used as a convenience to store data related to views in the views
547 * themselves rather than by putting them in a separate structure.
548 * </p>
549 *
550 * <a name="Properties"></a>
551 * <h3>Properties</h3>
552 * <p>
553 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
554 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
555 * available both in the {@link Property} form as well as in similarly-named setter/getter
556 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
557 * be used to set persistent state associated with these rendering-related properties on the view.
558 * The properties and methods can also be used in conjunction with
559 * {@link android.animation.Animator Animator}-based animations, described more in the
560 * <a href="#Animation">Animation</a> section.
561 * </p>
562 *
563 * <a name="Animation"></a>
564 * <h3>Animation</h3>
565 * <p>
566 * Starting with Android 3.0, the preferred way of animating views is to use the
567 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
568 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
569 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
570 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
571 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
572 * makes animating these View properties particularly easy and efficient.
573 * </p>
574 * <p>
575 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
576 * You can attach an {@link Animation} object to a view using
577 * {@link #setAnimation(Animation)} or
578 * {@link #startAnimation(Animation)}. The animation can alter the scale,
579 * rotation, translation and alpha of a view over time. If the animation is
580 * attached to a view that has children, the animation will affect the entire
581 * subtree rooted by that node. When an animation is started, the framework will
582 * take care of redrawing the appropriate views until the animation completes.
583 * </p>
584 *
585 * <a name="Security"></a>
586 * <h3>Security</h3>
587 * <p>
588 * Sometimes it is essential that an application be able to verify that an action
589 * is being performed with the full knowledge and consent of the user, such as
590 * granting a permission request, making a purchase or clicking on an advertisement.
591 * Unfortunately, a malicious application could try to spoof the user into
592 * performing these actions, unaware, by concealing the intended purpose of the view.
593 * As a remedy, the framework offers a touch filtering mechanism that can be used to
594 * improve the security of views that provide access to sensitive functionality.
595 * </p><p>
596 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
597 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
598 * will discard touches that are received whenever the view's window is obscured by
599 * another visible window.  As a result, the view will not receive touches whenever a
600 * toast, dialog or other window appears above the view's window.
601 * </p><p>
602 * For more fine-grained control over security, consider overriding the
603 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
604 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
605 * </p>
606 *
607 * @attr ref android.R.styleable#View_alpha
608 * @attr ref android.R.styleable#View_background
609 * @attr ref android.R.styleable#View_clickable
610 * @attr ref android.R.styleable#View_contentDescription
611 * @attr ref android.R.styleable#View_drawingCacheQuality
612 * @attr ref android.R.styleable#View_duplicateParentState
613 * @attr ref android.R.styleable#View_id
614 * @attr ref android.R.styleable#View_requiresFadingEdge
615 * @attr ref android.R.styleable#View_fadeScrollbars
616 * @attr ref android.R.styleable#View_fadingEdgeLength
617 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
618 * @attr ref android.R.styleable#View_fitsSystemWindows
619 * @attr ref android.R.styleable#View_isScrollContainer
620 * @attr ref android.R.styleable#View_focusable
621 * @attr ref android.R.styleable#View_focusableInTouchMode
622 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
623 * @attr ref android.R.styleable#View_keepScreenOn
624 * @attr ref android.R.styleable#View_layerType
625 * @attr ref android.R.styleable#View_layoutDirection
626 * @attr ref android.R.styleable#View_longClickable
627 * @attr ref android.R.styleable#View_minHeight
628 * @attr ref android.R.styleable#View_minWidth
629 * @attr ref android.R.styleable#View_nextFocusDown
630 * @attr ref android.R.styleable#View_nextFocusLeft
631 * @attr ref android.R.styleable#View_nextFocusRight
632 * @attr ref android.R.styleable#View_nextFocusUp
633 * @attr ref android.R.styleable#View_onClick
634 * @attr ref android.R.styleable#View_padding
635 * @attr ref android.R.styleable#View_paddingBottom
636 * @attr ref android.R.styleable#View_paddingLeft
637 * @attr ref android.R.styleable#View_paddingRight
638 * @attr ref android.R.styleable#View_paddingTop
639 * @attr ref android.R.styleable#View_paddingStart
640 * @attr ref android.R.styleable#View_paddingEnd
641 * @attr ref android.R.styleable#View_saveEnabled
642 * @attr ref android.R.styleable#View_rotation
643 * @attr ref android.R.styleable#View_rotationX
644 * @attr ref android.R.styleable#View_rotationY
645 * @attr ref android.R.styleable#View_scaleX
646 * @attr ref android.R.styleable#View_scaleY
647 * @attr ref android.R.styleable#View_scrollX
648 * @attr ref android.R.styleable#View_scrollY
649 * @attr ref android.R.styleable#View_scrollbarSize
650 * @attr ref android.R.styleable#View_scrollbarStyle
651 * @attr ref android.R.styleable#View_scrollbars
652 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
653 * @attr ref android.R.styleable#View_scrollbarFadeDuration
654 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
655 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
656 * @attr ref android.R.styleable#View_scrollbarThumbVertical
657 * @attr ref android.R.styleable#View_scrollbarTrackVertical
658 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
659 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
660 * @attr ref android.R.styleable#View_soundEffectsEnabled
661 * @attr ref android.R.styleable#View_tag
662 * @attr ref android.R.styleable#View_textAlignment
663 * @attr ref android.R.styleable#View_textDirection
664 * @attr ref android.R.styleable#View_transformPivotX
665 * @attr ref android.R.styleable#View_transformPivotY
666 * @attr ref android.R.styleable#View_translationX
667 * @attr ref android.R.styleable#View_translationY
668 * @attr ref android.R.styleable#View_visibility
669 *
670 * @see android.view.ViewGroup
671 */
672public class View implements Drawable.Callback, KeyEvent.Callback,
673        AccessibilityEventSource {
674    private static final boolean DBG = false;
675
676    /**
677     * The logging tag used by this class with android.util.Log.
678     */
679    protected static final String VIEW_LOG_TAG = "View";
680
681    /**
682     * When set to true, apps will draw debugging information about their layouts.
683     *
684     * @hide
685     */
686    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
687
688    /**
689     * Used to mark a View that has no ID.
690     */
691    public static final int NO_ID = -1;
692
693    private static boolean sUseBrokenMakeMeasureSpec = false;
694
695    /**
696     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
697     * calling setFlags.
698     */
699    private static final int NOT_FOCUSABLE = 0x00000000;
700
701    /**
702     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
703     * setFlags.
704     */
705    private static final int FOCUSABLE = 0x00000001;
706
707    /**
708     * Mask for use with setFlags indicating bits used for focus.
709     */
710    private static final int FOCUSABLE_MASK = 0x00000001;
711
712    /**
713     * This view will adjust its padding to fit sytem windows (e.g. status bar)
714     */
715    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
716
717    /**
718     * This view is visible.
719     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
720     * android:visibility}.
721     */
722    public static final int VISIBLE = 0x00000000;
723
724    /**
725     * This view is invisible, but it still takes up space for layout purposes.
726     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
727     * android:visibility}.
728     */
729    public static final int INVISIBLE = 0x00000004;
730
731    /**
732     * This view is invisible, and it doesn't take any space for layout
733     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
734     * android:visibility}.
735     */
736    public static final int GONE = 0x00000008;
737
738    /**
739     * Mask for use with setFlags indicating bits used for visibility.
740     * {@hide}
741     */
742    static final int VISIBILITY_MASK = 0x0000000C;
743
744    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
745
746    /**
747     * This view is enabled. Interpretation varies by subclass.
748     * Use with ENABLED_MASK when calling setFlags.
749     * {@hide}
750     */
751    static final int ENABLED = 0x00000000;
752
753    /**
754     * This view is disabled. Interpretation varies by subclass.
755     * Use with ENABLED_MASK when calling setFlags.
756     * {@hide}
757     */
758    static final int DISABLED = 0x00000020;
759
760   /**
761    * Mask for use with setFlags indicating bits used for indicating whether
762    * this view is enabled
763    * {@hide}
764    */
765    static final int ENABLED_MASK = 0x00000020;
766
767    /**
768     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
769     * called and further optimizations will be performed. It is okay to have
770     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
771     * {@hide}
772     */
773    static final int WILL_NOT_DRAW = 0x00000080;
774
775    /**
776     * Mask for use with setFlags indicating bits used for indicating whether
777     * this view is will draw
778     * {@hide}
779     */
780    static final int DRAW_MASK = 0x00000080;
781
782    /**
783     * <p>This view doesn't show scrollbars.</p>
784     * {@hide}
785     */
786    static final int SCROLLBARS_NONE = 0x00000000;
787
788    /**
789     * <p>This view shows horizontal scrollbars.</p>
790     * {@hide}
791     */
792    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
793
794    /**
795     * <p>This view shows vertical scrollbars.</p>
796     * {@hide}
797     */
798    static final int SCROLLBARS_VERTICAL = 0x00000200;
799
800    /**
801     * <p>Mask for use with setFlags indicating bits used for indicating which
802     * scrollbars are enabled.</p>
803     * {@hide}
804     */
805    static final int SCROLLBARS_MASK = 0x00000300;
806
807    /**
808     * Indicates that the view should filter touches when its window is obscured.
809     * Refer to the class comments for more information about this security feature.
810     * {@hide}
811     */
812    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
813
814    /**
815     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
816     * that they are optional and should be skipped if the window has
817     * requested system UI flags that ignore those insets for layout.
818     */
819    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
820
821    /**
822     * <p>This view doesn't show fading edges.</p>
823     * {@hide}
824     */
825    static final int FADING_EDGE_NONE = 0x00000000;
826
827    /**
828     * <p>This view shows horizontal fading edges.</p>
829     * {@hide}
830     */
831    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
832
833    /**
834     * <p>This view shows vertical fading edges.</p>
835     * {@hide}
836     */
837    static final int FADING_EDGE_VERTICAL = 0x00002000;
838
839    /**
840     * <p>Mask for use with setFlags indicating bits used for indicating which
841     * fading edges are enabled.</p>
842     * {@hide}
843     */
844    static final int FADING_EDGE_MASK = 0x00003000;
845
846    /**
847     * <p>Indicates this view can be clicked. When clickable, a View reacts
848     * to clicks by notifying the OnClickListener.<p>
849     * {@hide}
850     */
851    static final int CLICKABLE = 0x00004000;
852
853    /**
854     * <p>Indicates this view is caching its drawing into a bitmap.</p>
855     * {@hide}
856     */
857    static final int DRAWING_CACHE_ENABLED = 0x00008000;
858
859    /**
860     * <p>Indicates that no icicle should be saved for this view.<p>
861     * {@hide}
862     */
863    static final int SAVE_DISABLED = 0x000010000;
864
865    /**
866     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
867     * property.</p>
868     * {@hide}
869     */
870    static final int SAVE_DISABLED_MASK = 0x000010000;
871
872    /**
873     * <p>Indicates that no drawing cache should ever be created for this view.<p>
874     * {@hide}
875     */
876    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
877
878    /**
879     * <p>Indicates this view can take / keep focus when int touch mode.</p>
880     * {@hide}
881     */
882    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
883
884    /**
885     * <p>Enables low quality mode for the drawing cache.</p>
886     */
887    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
888
889    /**
890     * <p>Enables high quality mode for the drawing cache.</p>
891     */
892    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
893
894    /**
895     * <p>Enables automatic quality mode for the drawing cache.</p>
896     */
897    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
898
899    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
900            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
901    };
902
903    /**
904     * <p>Mask for use with setFlags indicating bits used for the cache
905     * quality property.</p>
906     * {@hide}
907     */
908    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
909
910    /**
911     * <p>
912     * Indicates this view can be long clicked. When long clickable, a View
913     * reacts to long clicks by notifying the OnLongClickListener or showing a
914     * context menu.
915     * </p>
916     * {@hide}
917     */
918    static final int LONG_CLICKABLE = 0x00200000;
919
920    /**
921     * <p>Indicates that this view gets its drawable states from its direct parent
922     * and ignores its original internal states.</p>
923     *
924     * @hide
925     */
926    static final int DUPLICATE_PARENT_STATE = 0x00400000;
927
928    /**
929     * The scrollbar style to display the scrollbars inside the content area,
930     * without increasing the padding. The scrollbars will be overlaid with
931     * translucency on the view's content.
932     */
933    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
934
935    /**
936     * The scrollbar style to display the scrollbars inside the padded area,
937     * increasing the padding of the view. The scrollbars will not overlap the
938     * content area of the view.
939     */
940    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
941
942    /**
943     * The scrollbar style to display the scrollbars at the edge of the view,
944     * without increasing the padding. The scrollbars will be overlaid with
945     * translucency.
946     */
947    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
948
949    /**
950     * The scrollbar style to display the scrollbars at the edge of the view,
951     * increasing the padding of the view. The scrollbars will only overlap the
952     * background, if any.
953     */
954    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
955
956    /**
957     * Mask to check if the scrollbar style is overlay or inset.
958     * {@hide}
959     */
960    static final int SCROLLBARS_INSET_MASK = 0x01000000;
961
962    /**
963     * Mask to check if the scrollbar style is inside or outside.
964     * {@hide}
965     */
966    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
967
968    /**
969     * Mask for scrollbar style.
970     * {@hide}
971     */
972    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
973
974    /**
975     * View flag indicating that the screen should remain on while the
976     * window containing this view is visible to the user.  This effectively
977     * takes care of automatically setting the WindowManager's
978     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
979     */
980    public static final int KEEP_SCREEN_ON = 0x04000000;
981
982    /**
983     * View flag indicating whether this view should have sound effects enabled
984     * for events such as clicking and touching.
985     */
986    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
987
988    /**
989     * View flag indicating whether this view should have haptic feedback
990     * enabled for events such as long presses.
991     */
992    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
993
994    /**
995     * <p>Indicates that the view hierarchy should stop saving state when
996     * it reaches this view.  If state saving is initiated immediately at
997     * the view, it will be allowed.
998     * {@hide}
999     */
1000    static final int PARENT_SAVE_DISABLED = 0x20000000;
1001
1002    /**
1003     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1004     * {@hide}
1005     */
1006    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1007
1008    /**
1009     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1010     * should add all focusable Views regardless if they are focusable in touch mode.
1011     */
1012    public static final int FOCUSABLES_ALL = 0x00000000;
1013
1014    /**
1015     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1016     * should add only Views focusable in touch mode.
1017     */
1018    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1019
1020    /**
1021     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1022     * item.
1023     */
1024    public static final int FOCUS_BACKWARD = 0x00000001;
1025
1026    /**
1027     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1028     * item.
1029     */
1030    public static final int FOCUS_FORWARD = 0x00000002;
1031
1032    /**
1033     * Use with {@link #focusSearch(int)}. Move focus to the left.
1034     */
1035    public static final int FOCUS_LEFT = 0x00000011;
1036
1037    /**
1038     * Use with {@link #focusSearch(int)}. Move focus up.
1039     */
1040    public static final int FOCUS_UP = 0x00000021;
1041
1042    /**
1043     * Use with {@link #focusSearch(int)}. Move focus to the right.
1044     */
1045    public static final int FOCUS_RIGHT = 0x00000042;
1046
1047    /**
1048     * Use with {@link #focusSearch(int)}. Move focus down.
1049     */
1050    public static final int FOCUS_DOWN = 0x00000082;
1051
1052    /**
1053     * Bits of {@link #getMeasuredWidthAndState()} and
1054     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1055     */
1056    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1057
1058    /**
1059     * Bits of {@link #getMeasuredWidthAndState()} and
1060     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1061     */
1062    public static final int MEASURED_STATE_MASK = 0xff000000;
1063
1064    /**
1065     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1066     * for functions that combine both width and height into a single int,
1067     * such as {@link #getMeasuredState()} and the childState argument of
1068     * {@link #resolveSizeAndState(int, int, int)}.
1069     */
1070    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1071
1072    /**
1073     * Bit of {@link #getMeasuredWidthAndState()} and
1074     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1075     * is smaller that the space the view would like to have.
1076     */
1077    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1078
1079    /**
1080     * Base View state sets
1081     */
1082    // Singles
1083    /**
1084     * Indicates the view has no states set. States are used with
1085     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1086     * view depending on its state.
1087     *
1088     * @see android.graphics.drawable.Drawable
1089     * @see #getDrawableState()
1090     */
1091    protected static final int[] EMPTY_STATE_SET;
1092    /**
1093     * Indicates the view is enabled. States are used with
1094     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1095     * view depending on its state.
1096     *
1097     * @see android.graphics.drawable.Drawable
1098     * @see #getDrawableState()
1099     */
1100    protected static final int[] ENABLED_STATE_SET;
1101    /**
1102     * Indicates the view is focused. States are used with
1103     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1104     * view depending on its state.
1105     *
1106     * @see android.graphics.drawable.Drawable
1107     * @see #getDrawableState()
1108     */
1109    protected static final int[] FOCUSED_STATE_SET;
1110    /**
1111     * Indicates the view is selected. States are used with
1112     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1113     * view depending on its state.
1114     *
1115     * @see android.graphics.drawable.Drawable
1116     * @see #getDrawableState()
1117     */
1118    protected static final int[] SELECTED_STATE_SET;
1119    /**
1120     * Indicates the view is pressed. States are used with
1121     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1122     * view depending on its state.
1123     *
1124     * @see android.graphics.drawable.Drawable
1125     * @see #getDrawableState()
1126     * @hide
1127     */
1128    protected static final int[] PRESSED_STATE_SET;
1129    /**
1130     * Indicates the view's window has focus. States are used with
1131     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1132     * view depending on its state.
1133     *
1134     * @see android.graphics.drawable.Drawable
1135     * @see #getDrawableState()
1136     */
1137    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1138    // Doubles
1139    /**
1140     * Indicates the view is enabled and has the focus.
1141     *
1142     * @see #ENABLED_STATE_SET
1143     * @see #FOCUSED_STATE_SET
1144     */
1145    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1146    /**
1147     * Indicates the view is enabled and selected.
1148     *
1149     * @see #ENABLED_STATE_SET
1150     * @see #SELECTED_STATE_SET
1151     */
1152    protected static final int[] ENABLED_SELECTED_STATE_SET;
1153    /**
1154     * Indicates the view is enabled and that its window has focus.
1155     *
1156     * @see #ENABLED_STATE_SET
1157     * @see #WINDOW_FOCUSED_STATE_SET
1158     */
1159    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1160    /**
1161     * Indicates the view is focused and selected.
1162     *
1163     * @see #FOCUSED_STATE_SET
1164     * @see #SELECTED_STATE_SET
1165     */
1166    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1167    /**
1168     * Indicates the view has the focus and that its window has the focus.
1169     *
1170     * @see #FOCUSED_STATE_SET
1171     * @see #WINDOW_FOCUSED_STATE_SET
1172     */
1173    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1174    /**
1175     * Indicates the view is selected and that its window has the focus.
1176     *
1177     * @see #SELECTED_STATE_SET
1178     * @see #WINDOW_FOCUSED_STATE_SET
1179     */
1180    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1181    // Triples
1182    /**
1183     * Indicates the view is enabled, focused and selected.
1184     *
1185     * @see #ENABLED_STATE_SET
1186     * @see #FOCUSED_STATE_SET
1187     * @see #SELECTED_STATE_SET
1188     */
1189    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1190    /**
1191     * Indicates the view is enabled, focused and its window has the focus.
1192     *
1193     * @see #ENABLED_STATE_SET
1194     * @see #FOCUSED_STATE_SET
1195     * @see #WINDOW_FOCUSED_STATE_SET
1196     */
1197    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1198    /**
1199     * Indicates the view is enabled, selected and its window has the focus.
1200     *
1201     * @see #ENABLED_STATE_SET
1202     * @see #SELECTED_STATE_SET
1203     * @see #WINDOW_FOCUSED_STATE_SET
1204     */
1205    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1206    /**
1207     * Indicates the view is focused, selected and its window has the focus.
1208     *
1209     * @see #FOCUSED_STATE_SET
1210     * @see #SELECTED_STATE_SET
1211     * @see #WINDOW_FOCUSED_STATE_SET
1212     */
1213    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1214    /**
1215     * Indicates the view is enabled, focused, selected and its window
1216     * has the focus.
1217     *
1218     * @see #ENABLED_STATE_SET
1219     * @see #FOCUSED_STATE_SET
1220     * @see #SELECTED_STATE_SET
1221     * @see #WINDOW_FOCUSED_STATE_SET
1222     */
1223    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1224    /**
1225     * Indicates the view is pressed and its window has the focus.
1226     *
1227     * @see #PRESSED_STATE_SET
1228     * @see #WINDOW_FOCUSED_STATE_SET
1229     */
1230    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1231    /**
1232     * Indicates the view is pressed and selected.
1233     *
1234     * @see #PRESSED_STATE_SET
1235     * @see #SELECTED_STATE_SET
1236     */
1237    protected static final int[] PRESSED_SELECTED_STATE_SET;
1238    /**
1239     * Indicates the view is pressed, selected and its window has the focus.
1240     *
1241     * @see #PRESSED_STATE_SET
1242     * @see #SELECTED_STATE_SET
1243     * @see #WINDOW_FOCUSED_STATE_SET
1244     */
1245    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1246    /**
1247     * Indicates the view is pressed and focused.
1248     *
1249     * @see #PRESSED_STATE_SET
1250     * @see #FOCUSED_STATE_SET
1251     */
1252    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1253    /**
1254     * Indicates the view is pressed, focused and its window has the focus.
1255     *
1256     * @see #PRESSED_STATE_SET
1257     * @see #FOCUSED_STATE_SET
1258     * @see #WINDOW_FOCUSED_STATE_SET
1259     */
1260    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1261    /**
1262     * Indicates the view is pressed, focused and selected.
1263     *
1264     * @see #PRESSED_STATE_SET
1265     * @see #SELECTED_STATE_SET
1266     * @see #FOCUSED_STATE_SET
1267     */
1268    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1269    /**
1270     * Indicates the view is pressed, focused, selected and its window has the focus.
1271     *
1272     * @see #PRESSED_STATE_SET
1273     * @see #FOCUSED_STATE_SET
1274     * @see #SELECTED_STATE_SET
1275     * @see #WINDOW_FOCUSED_STATE_SET
1276     */
1277    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1278    /**
1279     * Indicates the view is pressed and enabled.
1280     *
1281     * @see #PRESSED_STATE_SET
1282     * @see #ENABLED_STATE_SET
1283     */
1284    protected static final int[] PRESSED_ENABLED_STATE_SET;
1285    /**
1286     * Indicates the view is pressed, enabled and its window has the focus.
1287     *
1288     * @see #PRESSED_STATE_SET
1289     * @see #ENABLED_STATE_SET
1290     * @see #WINDOW_FOCUSED_STATE_SET
1291     */
1292    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1293    /**
1294     * Indicates the view is pressed, enabled and selected.
1295     *
1296     * @see #PRESSED_STATE_SET
1297     * @see #ENABLED_STATE_SET
1298     * @see #SELECTED_STATE_SET
1299     */
1300    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1301    /**
1302     * Indicates the view is pressed, enabled, selected and its window has the
1303     * focus.
1304     *
1305     * @see #PRESSED_STATE_SET
1306     * @see #ENABLED_STATE_SET
1307     * @see #SELECTED_STATE_SET
1308     * @see #WINDOW_FOCUSED_STATE_SET
1309     */
1310    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1311    /**
1312     * Indicates the view is pressed, enabled and focused.
1313     *
1314     * @see #PRESSED_STATE_SET
1315     * @see #ENABLED_STATE_SET
1316     * @see #FOCUSED_STATE_SET
1317     */
1318    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1319    /**
1320     * Indicates the view is pressed, enabled, focused and its window has the
1321     * focus.
1322     *
1323     * @see #PRESSED_STATE_SET
1324     * @see #ENABLED_STATE_SET
1325     * @see #FOCUSED_STATE_SET
1326     * @see #WINDOW_FOCUSED_STATE_SET
1327     */
1328    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1329    /**
1330     * Indicates the view is pressed, enabled, focused and selected.
1331     *
1332     * @see #PRESSED_STATE_SET
1333     * @see #ENABLED_STATE_SET
1334     * @see #SELECTED_STATE_SET
1335     * @see #FOCUSED_STATE_SET
1336     */
1337    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1338    /**
1339     * Indicates the view is pressed, enabled, focused, selected and its window
1340     * has the focus.
1341     *
1342     * @see #PRESSED_STATE_SET
1343     * @see #ENABLED_STATE_SET
1344     * @see #SELECTED_STATE_SET
1345     * @see #FOCUSED_STATE_SET
1346     * @see #WINDOW_FOCUSED_STATE_SET
1347     */
1348    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1349
1350    /**
1351     * The order here is very important to {@link #getDrawableState()}
1352     */
1353    private static final int[][] VIEW_STATE_SETS;
1354
1355    static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1356    static final int VIEW_STATE_SELECTED = 1 << 1;
1357    static final int VIEW_STATE_FOCUSED = 1 << 2;
1358    static final int VIEW_STATE_ENABLED = 1 << 3;
1359    static final int VIEW_STATE_PRESSED = 1 << 4;
1360    static final int VIEW_STATE_ACTIVATED = 1 << 5;
1361    static final int VIEW_STATE_ACCELERATED = 1 << 6;
1362    static final int VIEW_STATE_HOVERED = 1 << 7;
1363    static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1364    static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
1365
1366    static final int[] VIEW_STATE_IDS = new int[] {
1367        R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
1368        R.attr.state_selected,          VIEW_STATE_SELECTED,
1369        R.attr.state_focused,           VIEW_STATE_FOCUSED,
1370        R.attr.state_enabled,           VIEW_STATE_ENABLED,
1371        R.attr.state_pressed,           VIEW_STATE_PRESSED,
1372        R.attr.state_activated,         VIEW_STATE_ACTIVATED,
1373        R.attr.state_accelerated,       VIEW_STATE_ACCELERATED,
1374        R.attr.state_hovered,           VIEW_STATE_HOVERED,
1375        R.attr.state_drag_can_accept,   VIEW_STATE_DRAG_CAN_ACCEPT,
1376        R.attr.state_drag_hovered,      VIEW_STATE_DRAG_HOVERED
1377    };
1378
1379    static {
1380        if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1381            throw new IllegalStateException(
1382                    "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1383        }
1384        int[] orderedIds = new int[VIEW_STATE_IDS.length];
1385        for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
1386            int viewState = R.styleable.ViewDrawableStates[i];
1387            for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
1388                if (VIEW_STATE_IDS[j] == viewState) {
1389                    orderedIds[i * 2] = viewState;
1390                    orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
1391                }
1392            }
1393        }
1394        final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1395        VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1396        for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
1397            int numBits = Integer.bitCount(i);
1398            int[] set = new int[numBits];
1399            int pos = 0;
1400            for (int j = 0; j < orderedIds.length; j += 2) {
1401                if ((i & orderedIds[j+1]) != 0) {
1402                    set[pos++] = orderedIds[j];
1403                }
1404            }
1405            VIEW_STATE_SETS[i] = set;
1406        }
1407
1408        EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1409        WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1410        SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1411        SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1412                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1413        FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1414        FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1415                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1416        FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1417                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1418        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1419                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1420                | VIEW_STATE_FOCUSED];
1421        ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1422        ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1423                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1424        ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1425                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1426        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1427                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1428                | VIEW_STATE_ENABLED];
1429        ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1430                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1431        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1432                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1433                | VIEW_STATE_ENABLED];
1434        ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1435                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1436                | VIEW_STATE_ENABLED];
1437        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1438                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1439                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1440
1441        PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1442        PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1443                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1444        PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1445                VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1446        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1447                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1448                | VIEW_STATE_PRESSED];
1449        PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1450                VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1451        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1452                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1453                | VIEW_STATE_PRESSED];
1454        PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1455                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1456                | VIEW_STATE_PRESSED];
1457        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1458                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1459                | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1460        PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1461                VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1462        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1463                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1464                | VIEW_STATE_PRESSED];
1465        PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1466                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1467                | VIEW_STATE_PRESSED];
1468        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1469                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1470                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1471        PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1472                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1473                | VIEW_STATE_PRESSED];
1474        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1475                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1476                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1477        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1478                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1479                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1480        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1481                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1482                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1483                | VIEW_STATE_PRESSED];
1484    }
1485
1486    /**
1487     * Accessibility event types that are dispatched for text population.
1488     */
1489    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1490            AccessibilityEvent.TYPE_VIEW_CLICKED
1491            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1492            | AccessibilityEvent.TYPE_VIEW_SELECTED
1493            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1494            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1495            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1496            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1497            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1498            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1499            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1500            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1501
1502    /**
1503     * Temporary Rect currently for use in setBackground().  This will probably
1504     * be extended in the future to hold our own class with more than just
1505     * a Rect. :)
1506     */
1507    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1508
1509    /**
1510     * Map used to store views' tags.
1511     */
1512    private SparseArray<Object> mKeyedTags;
1513
1514    /**
1515     * The next available accessibility id.
1516     */
1517    private static int sNextAccessibilityViewId;
1518
1519    /**
1520     * The animation currently associated with this view.
1521     * @hide
1522     */
1523    protected Animation mCurrentAnimation = null;
1524
1525    /**
1526     * Width as measured during measure pass.
1527     * {@hide}
1528     */
1529    @ViewDebug.ExportedProperty(category = "measurement")
1530    int mMeasuredWidth;
1531
1532    /**
1533     * Height as measured during measure pass.
1534     * {@hide}
1535     */
1536    @ViewDebug.ExportedProperty(category = "measurement")
1537    int mMeasuredHeight;
1538
1539    /**
1540     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1541     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1542     * its display list. This flag, used only when hw accelerated, allows us to clear the
1543     * flag while retaining this information until it's needed (at getDisplayList() time and
1544     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1545     *
1546     * {@hide}
1547     */
1548    boolean mRecreateDisplayList = false;
1549
1550    /**
1551     * The view's identifier.
1552     * {@hide}
1553     *
1554     * @see #setId(int)
1555     * @see #getId()
1556     */
1557    @ViewDebug.ExportedProperty(resolveId = true)
1558    int mID = NO_ID;
1559
1560    /**
1561     * The stable ID of this view for accessibility purposes.
1562     */
1563    int mAccessibilityViewId = NO_ID;
1564
1565    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1566
1567    /**
1568     * The view's tag.
1569     * {@hide}
1570     *
1571     * @see #setTag(Object)
1572     * @see #getTag()
1573     */
1574    protected Object mTag;
1575
1576    // for mPrivateFlags:
1577    /** {@hide} */
1578    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1579    /** {@hide} */
1580    static final int PFLAG_FOCUSED                     = 0x00000002;
1581    /** {@hide} */
1582    static final int PFLAG_SELECTED                    = 0x00000004;
1583    /** {@hide} */
1584    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1585    /** {@hide} */
1586    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1587    /** {@hide} */
1588    static final int PFLAG_DRAWN                       = 0x00000020;
1589    /**
1590     * When this flag is set, this view is running an animation on behalf of its
1591     * children and should therefore not cancel invalidate requests, even if they
1592     * lie outside of this view's bounds.
1593     *
1594     * {@hide}
1595     */
1596    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1597    /** {@hide} */
1598    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1599    /** {@hide} */
1600    static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
1601    /** {@hide} */
1602    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1603    /** {@hide} */
1604    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1605    /** {@hide} */
1606    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1607    /** {@hide} */
1608    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1609    /** {@hide} */
1610    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1611
1612    private static final int PFLAG_PRESSED             = 0x00004000;
1613
1614    /** {@hide} */
1615    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1616    /**
1617     * Flag used to indicate that this view should be drawn once more (and only once
1618     * more) after its animation has completed.
1619     * {@hide}
1620     */
1621    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1622
1623    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1624
1625    /**
1626     * Indicates that the View returned true when onSetAlpha() was called and that
1627     * the alpha must be restored.
1628     * {@hide}
1629     */
1630    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1631
1632    /**
1633     * Set by {@link #setScrollContainer(boolean)}.
1634     */
1635    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1636
1637    /**
1638     * Set by {@link #setScrollContainer(boolean)}.
1639     */
1640    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1641
1642    /**
1643     * View flag indicating whether this view was invalidated (fully or partially.)
1644     *
1645     * @hide
1646     */
1647    static final int PFLAG_DIRTY                       = 0x00200000;
1648
1649    /**
1650     * View flag indicating whether this view was invalidated by an opaque
1651     * invalidate request.
1652     *
1653     * @hide
1654     */
1655    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1656
1657    /**
1658     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1659     *
1660     * @hide
1661     */
1662    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1663
1664    /**
1665     * Indicates whether the background is opaque.
1666     *
1667     * @hide
1668     */
1669    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1670
1671    /**
1672     * Indicates whether the scrollbars are opaque.
1673     *
1674     * @hide
1675     */
1676    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1677
1678    /**
1679     * Indicates whether the view is opaque.
1680     *
1681     * @hide
1682     */
1683    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1684
1685    /**
1686     * Indicates a prepressed state;
1687     * the short time between ACTION_DOWN and recognizing
1688     * a 'real' press. Prepressed is used to recognize quick taps
1689     * even when they are shorter than ViewConfiguration.getTapTimeout().
1690     *
1691     * @hide
1692     */
1693    private static final int PFLAG_PREPRESSED          = 0x02000000;
1694
1695    /**
1696     * Indicates whether the view is temporarily detached.
1697     *
1698     * @hide
1699     */
1700    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1701
1702    /**
1703     * Indicates that we should awaken scroll bars once attached
1704     *
1705     * @hide
1706     */
1707    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1708
1709    /**
1710     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1711     * @hide
1712     */
1713    private static final int PFLAG_HOVERED             = 0x10000000;
1714
1715    /**
1716     * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
1717     * for transform operations
1718     *
1719     * @hide
1720     */
1721    private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000;
1722
1723    /** {@hide} */
1724    static final int PFLAG_ACTIVATED                   = 0x40000000;
1725
1726    /**
1727     * Indicates that this view was specifically invalidated, not just dirtied because some
1728     * child view was invalidated. The flag is used to determine when we need to recreate
1729     * a view's display list (as opposed to just returning a reference to its existing
1730     * display list).
1731     *
1732     * @hide
1733     */
1734    static final int PFLAG_INVALIDATED                 = 0x80000000;
1735
1736    /**
1737     * Masks for mPrivateFlags2, as generated by dumpFlags():
1738     *
1739     * -------|-------|-------|-------|
1740     *                                  PFLAG2_TEXT_ALIGNMENT_FLAGS[0]
1741     *                                  PFLAG2_TEXT_DIRECTION_FLAGS[0]
1742     *                                1 PFLAG2_DRAG_CAN_ACCEPT
1743     *                               1  PFLAG2_DRAG_HOVERED
1744     *                               1  PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT
1745     *                              11  PFLAG2_TEXT_DIRECTION_MASK_SHIFT
1746     *                             1 1  PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT
1747     *                             11   PFLAG2_LAYOUT_DIRECTION_MASK
1748     *                             11 1 PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
1749     *                            1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1750     *                            1   1 PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT
1751     *                            1 1   PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT
1752     *                           1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1753     *                           11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1754     *                          1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1755     *                         1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1756     *                         11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1757     *                        1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1758     *                        1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1759     *                        111       PFLAG2_TEXT_DIRECTION_MASK
1760     *                       1          PFLAG2_TEXT_DIRECTION_RESOLVED
1761     *                      1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1762     *                    111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1763     *                   1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1764     *                  1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1765     *                  11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1766     *                 1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1767     *                 1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1768     *                 11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1769     *                 111              PFLAG2_TEXT_ALIGNMENT_MASK
1770     *                1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1771     *               1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1772     *             111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1773     *           11                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1774     *          1                       PFLAG2_HAS_TRANSIENT_STATE
1775     *      1                           PFLAG2_ACCESSIBILITY_FOCUSED
1776     *     1                            PFLAG2_ACCESSIBILITY_STATE_CHANGED
1777     *    1                             PFLAG2_VIEW_QUICK_REJECTED
1778     *   1                              PFLAG2_PADDING_RESOLVED
1779     * -------|-------|-------|-------|
1780     */
1781
1782    /**
1783     * Indicates that this view has reported that it can accept the current drag's content.
1784     * Cleared when the drag operation concludes.
1785     * @hide
1786     */
1787    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1788
1789    /**
1790     * Indicates that this view is currently directly under the drag location in a
1791     * drag-and-drop operation involving content that it can accept.  Cleared when
1792     * the drag exits the view, or when the drag operation concludes.
1793     * @hide
1794     */
1795    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1796
1797    /**
1798     * Horizontal layout direction of this view is from Left to Right.
1799     * Use with {@link #setLayoutDirection}.
1800     */
1801    public static final int LAYOUT_DIRECTION_LTR = 0;
1802
1803    /**
1804     * Horizontal layout direction of this view is from Right to Left.
1805     * Use with {@link #setLayoutDirection}.
1806     */
1807    public static final int LAYOUT_DIRECTION_RTL = 1;
1808
1809    /**
1810     * Horizontal layout direction of this view is inherited from its parent.
1811     * Use with {@link #setLayoutDirection}.
1812     */
1813    public static final int LAYOUT_DIRECTION_INHERIT = 2;
1814
1815    /**
1816     * Horizontal layout direction of this view is from deduced from the default language
1817     * script for the locale. Use with {@link #setLayoutDirection}.
1818     */
1819    public static final int LAYOUT_DIRECTION_LOCALE = 3;
1820
1821    /**
1822     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1823     * @hide
1824     */
1825    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1826
1827    /**
1828     * Mask for use with private flags indicating bits used for horizontal layout direction.
1829     * @hide
1830     */
1831    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1832
1833    /**
1834     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1835     * right-to-left direction.
1836     * @hide
1837     */
1838    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1839
1840    /**
1841     * Indicates whether the view horizontal layout direction has been resolved.
1842     * @hide
1843     */
1844    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1845
1846    /**
1847     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1848     * @hide
1849     */
1850    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1851            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1852
1853    /*
1854     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1855     * flag value.
1856     * @hide
1857     */
1858    private static final int[] LAYOUT_DIRECTION_FLAGS = {
1859            LAYOUT_DIRECTION_LTR,
1860            LAYOUT_DIRECTION_RTL,
1861            LAYOUT_DIRECTION_INHERIT,
1862            LAYOUT_DIRECTION_LOCALE
1863    };
1864
1865    /**
1866     * Default horizontal layout direction.
1867     */
1868    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1869
1870    /**
1871     * Default horizontal layout direction.
1872     * @hide
1873     */
1874    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1875
1876    /**
1877     * Indicates that the view is tracking some sort of transient state
1878     * that the app should not need to be aware of, but that the framework
1879     * should take special care to preserve.
1880     *
1881     * @hide
1882     */
1883    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x1 << 22;
1884
1885    /**
1886     * Text direction is inherited thru {@link ViewGroup}
1887     */
1888    public static final int TEXT_DIRECTION_INHERIT = 0;
1889
1890    /**
1891     * Text direction is using "first strong algorithm". The first strong directional character
1892     * determines the paragraph direction. If there is no strong directional character, the
1893     * paragraph direction is the view's resolved layout direction.
1894     */
1895    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1896
1897    /**
1898     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1899     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1900     * If there are neither, the paragraph direction is the view's resolved layout direction.
1901     */
1902    public static final int TEXT_DIRECTION_ANY_RTL = 2;
1903
1904    /**
1905     * Text direction is forced to LTR.
1906     */
1907    public static final int TEXT_DIRECTION_LTR = 3;
1908
1909    /**
1910     * Text direction is forced to RTL.
1911     */
1912    public static final int TEXT_DIRECTION_RTL = 4;
1913
1914    /**
1915     * Text direction is coming from the system Locale.
1916     */
1917    public static final int TEXT_DIRECTION_LOCALE = 5;
1918
1919    /**
1920     * Default text direction is inherited
1921     */
1922    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
1923
1924    /**
1925     * Default resolved text direction
1926     * @hide
1927     */
1928    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
1929
1930    /**
1931     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
1932     * @hide
1933     */
1934    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
1935
1936    /**
1937     * Mask for use with private flags indicating bits used for text direction.
1938     * @hide
1939     */
1940    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
1941            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
1942
1943    /**
1944     * Array of text direction flags for mapping attribute "textDirection" to correct
1945     * flag value.
1946     * @hide
1947     */
1948    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
1949            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1950            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1951            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1952            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1953            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1954            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
1955    };
1956
1957    /**
1958     * Indicates whether the view text direction has been resolved.
1959     * @hide
1960     */
1961    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
1962            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
1963
1964    /**
1965     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1966     * @hide
1967     */
1968    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
1969
1970    /**
1971     * Mask for use with private flags indicating bits used for resolved text direction.
1972     * @hide
1973     */
1974    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
1975            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
1976
1977    /**
1978     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
1979     * @hide
1980     */
1981    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
1982            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
1983
1984    /*
1985     * Default text alignment. The text alignment of this View is inherited from its parent.
1986     * Use with {@link #setTextAlignment(int)}
1987     */
1988    public static final int TEXT_ALIGNMENT_INHERIT = 0;
1989
1990    /**
1991     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
1992     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
1993     *
1994     * Use with {@link #setTextAlignment(int)}
1995     */
1996    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
1997
1998    /**
1999     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2000     *
2001     * Use with {@link #setTextAlignment(int)}
2002     */
2003    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2004
2005    /**
2006     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2007     *
2008     * Use with {@link #setTextAlignment(int)}
2009     */
2010    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2011
2012    /**
2013     * Center the paragraph, e.g. ALIGN_CENTER.
2014     *
2015     * Use with {@link #setTextAlignment(int)}
2016     */
2017    public static final int TEXT_ALIGNMENT_CENTER = 4;
2018
2019    /**
2020     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2021     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2022     *
2023     * Use with {@link #setTextAlignment(int)}
2024     */
2025    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2026
2027    /**
2028     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2029     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2030     *
2031     * Use with {@link #setTextAlignment(int)}
2032     */
2033    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2034
2035    /**
2036     * Default text alignment is inherited
2037     */
2038    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2039
2040    /**
2041     * Default resolved text alignment
2042     * @hide
2043     */
2044    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2045
2046    /**
2047      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2048      * @hide
2049      */
2050    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2051
2052    /**
2053      * Mask for use with private flags indicating bits used for text alignment.
2054      * @hide
2055      */
2056    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2057
2058    /**
2059     * Array of text direction flags for mapping attribute "textAlignment" to correct
2060     * flag value.
2061     * @hide
2062     */
2063    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2064            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2065            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2066            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2067            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2068            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2069            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2070            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2071    };
2072
2073    /**
2074     * Indicates whether the view text alignment has been resolved.
2075     * @hide
2076     */
2077    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2078
2079    /**
2080     * Bit shift to get the resolved text alignment.
2081     * @hide
2082     */
2083    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2084
2085    /**
2086     * Mask for use with private flags indicating bits used for text alignment.
2087     * @hide
2088     */
2089    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2090            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2091
2092    /**
2093     * Indicates whether if the view text alignment has been resolved to gravity
2094     */
2095    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2096            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2097
2098    // Accessiblity constants for mPrivateFlags2
2099
2100    /**
2101     * Shift for the bits in {@link #mPrivateFlags2} related to the
2102     * "importantForAccessibility" attribute.
2103     */
2104    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2105
2106    /**
2107     * Automatically determine whether a view is important for accessibility.
2108     */
2109    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2110
2111    /**
2112     * The view is important for accessibility.
2113     */
2114    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2115
2116    /**
2117     * The view is not important for accessibility.
2118     */
2119    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2120
2121    /**
2122     * The default whether the view is important for accessibility.
2123     */
2124    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2125
2126    /**
2127     * Mask for obtainig the bits which specify how to determine
2128     * whether a view is important for accessibility.
2129     */
2130    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2131        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO)
2132        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2133
2134    /**
2135     * Flag indicating whether a view has accessibility focus.
2136     */
2137    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x00000040 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2138
2139    /**
2140     * Flag indicating whether a view state for accessibility has changed.
2141     */
2142    static final int PFLAG2_ACCESSIBILITY_STATE_CHANGED = 0x00000080
2143            << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2144
2145    /**
2146     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2147     * is used to check whether later changes to the view's transform should invalidate the
2148     * view to force the quickReject test to run again.
2149     */
2150    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2151
2152    /**
2153     * Flag indicating that start/end padding has been resolved into left/right padding
2154     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2155     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2156     * during measurement. In some special cases this is required such as when an adapter-based
2157     * view measures prospective children without attaching them to a window.
2158     */
2159    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2160
2161    /**
2162     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2163     */
2164    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2165
2166    /**
2167     * Group of bits indicating that RTL properties resolution is done.
2168     */
2169    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2170            PFLAG2_TEXT_DIRECTION_RESOLVED |
2171            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2172            PFLAG2_PADDING_RESOLVED |
2173            PFLAG2_DRAWABLE_RESOLVED;
2174
2175    // There are a couple of flags left in mPrivateFlags2
2176
2177    /* End of masks for mPrivateFlags2 */
2178
2179    /* Masks for mPrivateFlags3 */
2180
2181    /**
2182     * Flag indicating that view has a transform animation set on it. This is used to track whether
2183     * an animation is cleared between successive frames, in order to tell the associated
2184     * DisplayList to clear its animation matrix.
2185     */
2186    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2187
2188    /**
2189     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2190     * animation is cleared between successive frames, in order to tell the associated
2191     * DisplayList to restore its alpha value.
2192     */
2193    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2194
2195
2196    /* End of masks for mPrivateFlags3 */
2197
2198    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2199
2200    /**
2201     * Always allow a user to over-scroll this view, provided it is a
2202     * view that can scroll.
2203     *
2204     * @see #getOverScrollMode()
2205     * @see #setOverScrollMode(int)
2206     */
2207    public static final int OVER_SCROLL_ALWAYS = 0;
2208
2209    /**
2210     * Allow a user to over-scroll this view only if the content is large
2211     * enough to meaningfully scroll, provided it is a view that can scroll.
2212     *
2213     * @see #getOverScrollMode()
2214     * @see #setOverScrollMode(int)
2215     */
2216    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2217
2218    /**
2219     * Never allow a user to over-scroll this view.
2220     *
2221     * @see #getOverScrollMode()
2222     * @see #setOverScrollMode(int)
2223     */
2224    public static final int OVER_SCROLL_NEVER = 2;
2225
2226    /**
2227     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2228     * requested the system UI (status bar) to be visible (the default).
2229     *
2230     * @see #setSystemUiVisibility(int)
2231     */
2232    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2233
2234    /**
2235     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2236     * system UI to enter an unobtrusive "low profile" mode.
2237     *
2238     * <p>This is for use in games, book readers, video players, or any other
2239     * "immersive" application where the usual system chrome is deemed too distracting.
2240     *
2241     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2242     *
2243     * @see #setSystemUiVisibility(int)
2244     */
2245    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2246
2247    /**
2248     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2249     * system navigation be temporarily hidden.
2250     *
2251     * <p>This is an even less obtrusive state than that called for by
2252     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2253     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2254     * those to disappear. This is useful (in conjunction with the
2255     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2256     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2257     * window flags) for displaying content using every last pixel on the display.
2258     *
2259     * <p>There is a limitation: because navigation controls are so important, the least user
2260     * interaction will cause them to reappear immediately.  When this happens, both
2261     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2262     * so that both elements reappear at the same time.
2263     *
2264     * @see #setSystemUiVisibility(int)
2265     */
2266    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2267
2268    /**
2269     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2270     * into the normal fullscreen mode so that its content can take over the screen
2271     * while still allowing the user to interact with the application.
2272     *
2273     * <p>This has the same visual effect as
2274     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2275     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2276     * meaning that non-critical screen decorations (such as the status bar) will be
2277     * hidden while the user is in the View's window, focusing the experience on
2278     * that content.  Unlike the window flag, if you are using ActionBar in
2279     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2280     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2281     * hide the action bar.
2282     *
2283     * <p>This approach to going fullscreen is best used over the window flag when
2284     * it is a transient state -- that is, the application does this at certain
2285     * points in its user interaction where it wants to allow the user to focus
2286     * on content, but not as a continuous state.  For situations where the application
2287     * would like to simply stay full screen the entire time (such as a game that
2288     * wants to take over the screen), the
2289     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2290     * is usually a better approach.  The state set here will be removed by the system
2291     * in various situations (such as the user moving to another application) like
2292     * the other system UI states.
2293     *
2294     * <p>When using this flag, the application should provide some easy facility
2295     * for the user to go out of it.  A common example would be in an e-book
2296     * reader, where tapping on the screen brings back whatever screen and UI
2297     * decorations that had been hidden while the user was immersed in reading
2298     * the book.
2299     *
2300     * @see #setSystemUiVisibility(int)
2301     */
2302    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2303
2304    /**
2305     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2306     * flags, we would like a stable view of the content insets given to
2307     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2308     * will always represent the worst case that the application can expect
2309     * as a continuous state.  In the stock Android UI this is the space for
2310     * the system bar, nav bar, and status bar, but not more transient elements
2311     * such as an input method.
2312     *
2313     * The stable layout your UI sees is based on the system UI modes you can
2314     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2315     * then you will get a stable layout for changes of the
2316     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2317     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2318     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2319     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2320     * with a stable layout.  (Note that you should avoid using
2321     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2322     *
2323     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2324     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2325     * then a hidden status bar will be considered a "stable" state for purposes
2326     * here.  This allows your UI to continually hide the status bar, while still
2327     * using the system UI flags to hide the action bar while still retaining
2328     * a stable layout.  Note that changing the window fullscreen flag will never
2329     * provide a stable layout for a clean transition.
2330     *
2331     * <p>If you are using ActionBar in
2332     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2333     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2334     * insets it adds to those given to the application.
2335     */
2336    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2337
2338    /**
2339     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2340     * to be layed out as if it has requested
2341     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2342     * allows it to avoid artifacts when switching in and out of that mode, at
2343     * the expense that some of its user interface may be covered by screen
2344     * decorations when they are shown.  You can perform layout of your inner
2345     * UI elements to account for the navagation system UI through the
2346     * {@link #fitSystemWindows(Rect)} method.
2347     */
2348    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2349
2350    /**
2351     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2352     * to be layed out as if it has requested
2353     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2354     * allows it to avoid artifacts when switching in and out of that mode, at
2355     * the expense that some of its user interface may be covered by screen
2356     * decorations when they are shown.  You can perform layout of your inner
2357     * UI elements to account for non-fullscreen system UI through the
2358     * {@link #fitSystemWindows(Rect)} method.
2359     */
2360    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2361
2362    /**
2363     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2364     */
2365    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2366
2367    /**
2368     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2369     */
2370    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2371
2372    /**
2373     * @hide
2374     *
2375     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2376     * out of the public fields to keep the undefined bits out of the developer's way.
2377     *
2378     * Flag to make the status bar not expandable.  Unless you also
2379     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2380     */
2381    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2382
2383    /**
2384     * @hide
2385     *
2386     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2387     * out of the public fields to keep the undefined bits out of the developer's way.
2388     *
2389     * Flag to hide notification icons and scrolling ticker text.
2390     */
2391    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2392
2393    /**
2394     * @hide
2395     *
2396     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2397     * out of the public fields to keep the undefined bits out of the developer's way.
2398     *
2399     * Flag to disable incoming notification alerts.  This will not block
2400     * icons, but it will block sound, vibrating and other visual or aural notifications.
2401     */
2402    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2403
2404    /**
2405     * @hide
2406     *
2407     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2408     * out of the public fields to keep the undefined bits out of the developer's way.
2409     *
2410     * Flag to hide only the scrolling ticker.  Note that
2411     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2412     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2413     */
2414    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2415
2416    /**
2417     * @hide
2418     *
2419     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2420     * out of the public fields to keep the undefined bits out of the developer's way.
2421     *
2422     * Flag to hide the center system info area.
2423     */
2424    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2425
2426    /**
2427     * @hide
2428     *
2429     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2430     * out of the public fields to keep the undefined bits out of the developer's way.
2431     *
2432     * Flag to hide only the home button.  Don't use this
2433     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2434     */
2435    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2436
2437    /**
2438     * @hide
2439     *
2440     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2441     * out of the public fields to keep the undefined bits out of the developer's way.
2442     *
2443     * Flag to hide only the back button. Don't use this
2444     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2445     */
2446    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2447
2448    /**
2449     * @hide
2450     *
2451     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2452     * out of the public fields to keep the undefined bits out of the developer's way.
2453     *
2454     * Flag to hide only the clock.  You might use this if your activity has
2455     * its own clock making the status bar's clock redundant.
2456     */
2457    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2458
2459    /**
2460     * @hide
2461     *
2462     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2463     * out of the public fields to keep the undefined bits out of the developer's way.
2464     *
2465     * Flag to hide only the recent apps button. Don't use this
2466     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2467     */
2468    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2469
2470    /**
2471     * @hide
2472     *
2473     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2474     * out of the public fields to keep the undefined bits out of the developer's way.
2475     *
2476     * Flag to disable the global search gesture. Don't use this
2477     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2478     */
2479    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2480
2481    /**
2482     * @hide
2483     */
2484    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
2485
2486    /**
2487     * These are the system UI flags that can be cleared by events outside
2488     * of an application.  Currently this is just the ability to tap on the
2489     * screen while hiding the navigation bar to have it return.
2490     * @hide
2491     */
2492    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2493            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2494            | SYSTEM_UI_FLAG_FULLSCREEN;
2495
2496    /**
2497     * Flags that can impact the layout in relation to system UI.
2498     */
2499    public static final int SYSTEM_UI_LAYOUT_FLAGS =
2500            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2501            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2502
2503    /**
2504     * Find views that render the specified text.
2505     *
2506     * @see #findViewsWithText(ArrayList, CharSequence, int)
2507     */
2508    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2509
2510    /**
2511     * Find find views that contain the specified content description.
2512     *
2513     * @see #findViewsWithText(ArrayList, CharSequence, int)
2514     */
2515    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2516
2517    /**
2518     * Find views that contain {@link AccessibilityNodeProvider}. Such
2519     * a View is a root of virtual view hierarchy and may contain the searched
2520     * text. If this flag is set Views with providers are automatically
2521     * added and it is a responsibility of the client to call the APIs of
2522     * the provider to determine whether the virtual tree rooted at this View
2523     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2524     * represeting the virtual views with this text.
2525     *
2526     * @see #findViewsWithText(ArrayList, CharSequence, int)
2527     *
2528     * @hide
2529     */
2530    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2531
2532    /**
2533     * The undefined cursor position.
2534     *
2535     * @hide
2536     */
2537    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2538
2539    /**
2540     * Indicates that the screen has changed state and is now off.
2541     *
2542     * @see #onScreenStateChanged(int)
2543     */
2544    public static final int SCREEN_STATE_OFF = 0x0;
2545
2546    /**
2547     * Indicates that the screen has changed state and is now on.
2548     *
2549     * @see #onScreenStateChanged(int)
2550     */
2551    public static final int SCREEN_STATE_ON = 0x1;
2552
2553    /**
2554     * Controls the over-scroll mode for this view.
2555     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2556     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2557     * and {@link #OVER_SCROLL_NEVER}.
2558     */
2559    private int mOverScrollMode;
2560
2561    /**
2562     * The parent this view is attached to.
2563     * {@hide}
2564     *
2565     * @see #getParent()
2566     */
2567    protected ViewParent mParent;
2568
2569    /**
2570     * {@hide}
2571     */
2572    AttachInfo mAttachInfo;
2573
2574    /**
2575     * {@hide}
2576     */
2577    @ViewDebug.ExportedProperty(flagMapping = {
2578        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2579                name = "FORCE_LAYOUT"),
2580        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2581                name = "LAYOUT_REQUIRED"),
2582        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2583            name = "DRAWING_CACHE_INVALID", outputIf = false),
2584        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2585        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2586        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2587        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2588    })
2589    int mPrivateFlags;
2590    int mPrivateFlags2;
2591    int mPrivateFlags3;
2592
2593    /**
2594     * This view's request for the visibility of the status bar.
2595     * @hide
2596     */
2597    @ViewDebug.ExportedProperty(flagMapping = {
2598        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2599                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2600                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2601        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2602                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2603                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2604        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2605                                equals = SYSTEM_UI_FLAG_VISIBLE,
2606                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2607    })
2608    int mSystemUiVisibility;
2609
2610    /**
2611     * Reference count for transient state.
2612     * @see #setHasTransientState(boolean)
2613     */
2614    int mTransientStateCount = 0;
2615
2616    /**
2617     * Count of how many windows this view has been attached to.
2618     */
2619    int mWindowAttachCount;
2620
2621    /**
2622     * The layout parameters associated with this view and used by the parent
2623     * {@link android.view.ViewGroup} to determine how this view should be
2624     * laid out.
2625     * {@hide}
2626     */
2627    protected ViewGroup.LayoutParams mLayoutParams;
2628
2629    /**
2630     * The view flags hold various views states.
2631     * {@hide}
2632     */
2633    @ViewDebug.ExportedProperty
2634    int mViewFlags;
2635
2636    static class TransformationInfo {
2637        /**
2638         * The transform matrix for the View. This transform is calculated internally
2639         * based on the rotation, scaleX, and scaleY properties. The identity matrix
2640         * is used by default. Do *not* use this variable directly; instead call
2641         * getMatrix(), which will automatically recalculate the matrix if necessary
2642         * to get the correct matrix based on the latest rotation and scale properties.
2643         */
2644        private final Matrix mMatrix = new Matrix();
2645
2646        /**
2647         * The transform matrix for the View. This transform is calculated internally
2648         * based on the rotation, scaleX, and scaleY properties. The identity matrix
2649         * is used by default. Do *not* use this variable directly; instead call
2650         * getInverseMatrix(), which will automatically recalculate the matrix if necessary
2651         * to get the correct matrix based on the latest rotation and scale properties.
2652         */
2653        private Matrix mInverseMatrix;
2654
2655        /**
2656         * An internal variable that tracks whether we need to recalculate the
2657         * transform matrix, based on whether the rotation or scaleX/Y properties
2658         * have changed since the matrix was last calculated.
2659         */
2660        boolean mMatrixDirty = false;
2661
2662        /**
2663         * An internal variable that tracks whether we need to recalculate the
2664         * transform matrix, based on whether the rotation or scaleX/Y properties
2665         * have changed since the matrix was last calculated.
2666         */
2667        private boolean mInverseMatrixDirty = true;
2668
2669        /**
2670         * A variable that tracks whether we need to recalculate the
2671         * transform matrix, based on whether the rotation or scaleX/Y properties
2672         * have changed since the matrix was last calculated. This variable
2673         * is only valid after a call to updateMatrix() or to a function that
2674         * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
2675         */
2676        private boolean mMatrixIsIdentity = true;
2677
2678        /**
2679         * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
2680         */
2681        private Camera mCamera = null;
2682
2683        /**
2684         * This matrix is used when computing the matrix for 3D rotations.
2685         */
2686        private Matrix matrix3D = null;
2687
2688        /**
2689         * These prev values are used to recalculate a centered pivot point when necessary. The
2690         * pivot point is only used in matrix operations (when rotation, scale, or translation are
2691         * set), so thes values are only used then as well.
2692         */
2693        private int mPrevWidth = -1;
2694        private int mPrevHeight = -1;
2695
2696        /**
2697         * The degrees rotation around the vertical axis through the pivot point.
2698         */
2699        @ViewDebug.ExportedProperty
2700        float mRotationY = 0f;
2701
2702        /**
2703         * The degrees rotation around the horizontal axis through the pivot point.
2704         */
2705        @ViewDebug.ExportedProperty
2706        float mRotationX = 0f;
2707
2708        /**
2709         * The degrees rotation around the pivot point.
2710         */
2711        @ViewDebug.ExportedProperty
2712        float mRotation = 0f;
2713
2714        /**
2715         * The amount of translation of the object away from its left property (post-layout).
2716         */
2717        @ViewDebug.ExportedProperty
2718        float mTranslationX = 0f;
2719
2720        /**
2721         * The amount of translation of the object away from its top property (post-layout).
2722         */
2723        @ViewDebug.ExportedProperty
2724        float mTranslationY = 0f;
2725
2726        /**
2727         * The amount of scale in the x direction around the pivot point. A
2728         * value of 1 means no scaling is applied.
2729         */
2730        @ViewDebug.ExportedProperty
2731        float mScaleX = 1f;
2732
2733        /**
2734         * The amount of scale in the y direction around the pivot point. A
2735         * value of 1 means no scaling is applied.
2736         */
2737        @ViewDebug.ExportedProperty
2738        float mScaleY = 1f;
2739
2740        /**
2741         * The x location of the point around which the view is rotated and scaled.
2742         */
2743        @ViewDebug.ExportedProperty
2744        float mPivotX = 0f;
2745
2746        /**
2747         * The y location of the point around which the view is rotated and scaled.
2748         */
2749        @ViewDebug.ExportedProperty
2750        float mPivotY = 0f;
2751
2752        /**
2753         * The opacity of the View. This is a value from 0 to 1, where 0 means
2754         * completely transparent and 1 means completely opaque.
2755         */
2756        @ViewDebug.ExportedProperty
2757        float mAlpha = 1f;
2758    }
2759
2760    TransformationInfo mTransformationInfo;
2761
2762    private boolean mLastIsOpaque;
2763
2764    /**
2765     * Convenience value to check for float values that are close enough to zero to be considered
2766     * zero.
2767     */
2768    private static final float NONZERO_EPSILON = .001f;
2769
2770    /**
2771     * The distance in pixels from the left edge of this view's parent
2772     * to the left edge of this view.
2773     * {@hide}
2774     */
2775    @ViewDebug.ExportedProperty(category = "layout")
2776    protected int mLeft;
2777    /**
2778     * The distance in pixels from the left edge of this view's parent
2779     * to the right edge of this view.
2780     * {@hide}
2781     */
2782    @ViewDebug.ExportedProperty(category = "layout")
2783    protected int mRight;
2784    /**
2785     * The distance in pixels from the top edge of this view's parent
2786     * to the top edge of this view.
2787     * {@hide}
2788     */
2789    @ViewDebug.ExportedProperty(category = "layout")
2790    protected int mTop;
2791    /**
2792     * The distance in pixels from the top edge of this view's parent
2793     * to the bottom edge of this view.
2794     * {@hide}
2795     */
2796    @ViewDebug.ExportedProperty(category = "layout")
2797    protected int mBottom;
2798
2799    /**
2800     * The offset, in pixels, by which the content of this view is scrolled
2801     * horizontally.
2802     * {@hide}
2803     */
2804    @ViewDebug.ExportedProperty(category = "scrolling")
2805    protected int mScrollX;
2806    /**
2807     * The offset, in pixels, by which the content of this view is scrolled
2808     * vertically.
2809     * {@hide}
2810     */
2811    @ViewDebug.ExportedProperty(category = "scrolling")
2812    protected int mScrollY;
2813
2814    /**
2815     * The left padding in pixels, that is the distance in pixels between the
2816     * left edge of this view and the left edge of its content.
2817     * {@hide}
2818     */
2819    @ViewDebug.ExportedProperty(category = "padding")
2820    protected int mPaddingLeft = 0;
2821    /**
2822     * The right padding in pixels, that is the distance in pixels between the
2823     * right edge of this view and the right edge of its content.
2824     * {@hide}
2825     */
2826    @ViewDebug.ExportedProperty(category = "padding")
2827    protected int mPaddingRight = 0;
2828    /**
2829     * The top padding in pixels, that is the distance in pixels between the
2830     * top edge of this view and the top edge of its content.
2831     * {@hide}
2832     */
2833    @ViewDebug.ExportedProperty(category = "padding")
2834    protected int mPaddingTop;
2835    /**
2836     * The bottom padding in pixels, that is the distance in pixels between the
2837     * bottom edge of this view and the bottom edge of its content.
2838     * {@hide}
2839     */
2840    @ViewDebug.ExportedProperty(category = "padding")
2841    protected int mPaddingBottom;
2842
2843    /**
2844     * The layout insets in pixels, that is the distance in pixels between the
2845     * visible edges of this view its bounds.
2846     */
2847    private Insets mLayoutInsets;
2848
2849    /**
2850     * Briefly describes the view and is primarily used for accessibility support.
2851     */
2852    private CharSequence mContentDescription;
2853
2854    /**
2855     * Specifies the id of a view for which this view serves as a label for
2856     * accessibility purposes.
2857     */
2858    private int mLabelForId = View.NO_ID;
2859
2860    /**
2861     * Predicate for matching labeled view id with its label for
2862     * accessibility purposes.
2863     */
2864    private MatchLabelForPredicate mMatchLabelForPredicate;
2865
2866    /**
2867     * Predicate for matching a view by its id.
2868     */
2869    private MatchIdPredicate mMatchIdPredicate;
2870
2871    /**
2872     * Cache the paddingRight set by the user to append to the scrollbar's size.
2873     *
2874     * @hide
2875     */
2876    @ViewDebug.ExportedProperty(category = "padding")
2877    protected int mUserPaddingRight;
2878
2879    /**
2880     * Cache the paddingBottom set by the user to append to the scrollbar's size.
2881     *
2882     * @hide
2883     */
2884    @ViewDebug.ExportedProperty(category = "padding")
2885    protected int mUserPaddingBottom;
2886
2887    /**
2888     * Cache the paddingLeft set by the user to append to the scrollbar's size.
2889     *
2890     * @hide
2891     */
2892    @ViewDebug.ExportedProperty(category = "padding")
2893    protected int mUserPaddingLeft;
2894
2895    /**
2896     * Cache the paddingStart set by the user to append to the scrollbar's size.
2897     *
2898     */
2899    @ViewDebug.ExportedProperty(category = "padding")
2900    int mUserPaddingStart;
2901
2902    /**
2903     * Cache the paddingEnd set by the user to append to the scrollbar's size.
2904     *
2905     */
2906    @ViewDebug.ExportedProperty(category = "padding")
2907    int mUserPaddingEnd;
2908
2909    /**
2910     * Cache initial left padding.
2911     *
2912     * @hide
2913     */
2914    int mUserPaddingLeftInitial = 0;
2915
2916    /**
2917     * Cache initial right padding.
2918     *
2919     * @hide
2920     */
2921    int mUserPaddingRightInitial = 0;
2922
2923    /**
2924     * Default undefined padding
2925     */
2926    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
2927
2928    /**
2929     * @hide
2930     */
2931    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
2932    /**
2933     * @hide
2934     */
2935    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
2936
2937    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
2938    private Drawable mBackground;
2939
2940    private int mBackgroundResource;
2941    private boolean mBackgroundSizeChanged;
2942
2943    static class ListenerInfo {
2944        /**
2945         * Listener used to dispatch focus change events.
2946         * This field should be made private, so it is hidden from the SDK.
2947         * {@hide}
2948         */
2949        protected OnFocusChangeListener mOnFocusChangeListener;
2950
2951        /**
2952         * Listeners for layout change events.
2953         */
2954        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
2955
2956        /**
2957         * Listeners for attach events.
2958         */
2959        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
2960
2961        /**
2962         * Listener used to dispatch click events.
2963         * This field should be made private, so it is hidden from the SDK.
2964         * {@hide}
2965         */
2966        public OnClickListener mOnClickListener;
2967
2968        /**
2969         * Listener used to dispatch long click events.
2970         * This field should be made private, so it is hidden from the SDK.
2971         * {@hide}
2972         */
2973        protected OnLongClickListener mOnLongClickListener;
2974
2975        /**
2976         * Listener used to build the context menu.
2977         * This field should be made private, so it is hidden from the SDK.
2978         * {@hide}
2979         */
2980        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
2981
2982        private OnKeyListener mOnKeyListener;
2983
2984        private OnTouchListener mOnTouchListener;
2985
2986        private OnHoverListener mOnHoverListener;
2987
2988        private OnGenericMotionListener mOnGenericMotionListener;
2989
2990        private OnDragListener mOnDragListener;
2991
2992        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
2993    }
2994
2995    ListenerInfo mListenerInfo;
2996
2997    /**
2998     * The application environment this view lives in.
2999     * This field should be made private, so it is hidden from the SDK.
3000     * {@hide}
3001     */
3002    protected Context mContext;
3003
3004    private final Resources mResources;
3005
3006    private ScrollabilityCache mScrollCache;
3007
3008    private int[] mDrawableState = null;
3009
3010    /**
3011     * Set to true when drawing cache is enabled and cannot be created.
3012     *
3013     * @hide
3014     */
3015    public boolean mCachingFailed;
3016
3017    private Bitmap mDrawingCache;
3018    private Bitmap mUnscaledDrawingCache;
3019    private HardwareLayer mHardwareLayer;
3020    DisplayList mDisplayList;
3021
3022    /**
3023     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3024     * the user may specify which view to go to next.
3025     */
3026    private int mNextFocusLeftId = View.NO_ID;
3027
3028    /**
3029     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3030     * the user may specify which view to go to next.
3031     */
3032    private int mNextFocusRightId = View.NO_ID;
3033
3034    /**
3035     * When this view has focus and the next focus is {@link #FOCUS_UP},
3036     * the user may specify which view to go to next.
3037     */
3038    private int mNextFocusUpId = View.NO_ID;
3039
3040    /**
3041     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3042     * the user may specify which view to go to next.
3043     */
3044    private int mNextFocusDownId = View.NO_ID;
3045
3046    /**
3047     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3048     * the user may specify which view to go to next.
3049     */
3050    int mNextFocusForwardId = View.NO_ID;
3051
3052    private CheckForLongPress mPendingCheckForLongPress;
3053    private CheckForTap mPendingCheckForTap = null;
3054    private PerformClick mPerformClick;
3055    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3056
3057    private UnsetPressedState mUnsetPressedState;
3058
3059    /**
3060     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3061     * up event while a long press is invoked as soon as the long press duration is reached, so
3062     * a long press could be performed before the tap is checked, in which case the tap's action
3063     * should not be invoked.
3064     */
3065    private boolean mHasPerformedLongPress;
3066
3067    /**
3068     * The minimum height of the view. We'll try our best to have the height
3069     * of this view to at least this amount.
3070     */
3071    @ViewDebug.ExportedProperty(category = "measurement")
3072    private int mMinHeight;
3073
3074    /**
3075     * The minimum width of the view. We'll try our best to have the width
3076     * of this view to at least this amount.
3077     */
3078    @ViewDebug.ExportedProperty(category = "measurement")
3079    private int mMinWidth;
3080
3081    /**
3082     * The delegate to handle touch events that are physically in this view
3083     * but should be handled by another view.
3084     */
3085    private TouchDelegate mTouchDelegate = null;
3086
3087    /**
3088     * Solid color to use as a background when creating the drawing cache. Enables
3089     * the cache to use 16 bit bitmaps instead of 32 bit.
3090     */
3091    private int mDrawingCacheBackgroundColor = 0;
3092
3093    /**
3094     * Special tree observer used when mAttachInfo is null.
3095     */
3096    private ViewTreeObserver mFloatingTreeObserver;
3097
3098    /**
3099     * Cache the touch slop from the context that created the view.
3100     */
3101    private int mTouchSlop;
3102
3103    /**
3104     * Object that handles automatic animation of view properties.
3105     */
3106    private ViewPropertyAnimator mAnimator = null;
3107
3108    /**
3109     * Flag indicating that a drag can cross window boundaries.  When
3110     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3111     * with this flag set, all visible applications will be able to participate
3112     * in the drag operation and receive the dragged content.
3113     *
3114     * @hide
3115     */
3116    public static final int DRAG_FLAG_GLOBAL = 1;
3117
3118    /**
3119     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3120     */
3121    private float mVerticalScrollFactor;
3122
3123    /**
3124     * Position of the vertical scroll bar.
3125     */
3126    private int mVerticalScrollbarPosition;
3127
3128    /**
3129     * Position the scroll bar at the default position as determined by the system.
3130     */
3131    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3132
3133    /**
3134     * Position the scroll bar along the left edge.
3135     */
3136    public static final int SCROLLBAR_POSITION_LEFT = 1;
3137
3138    /**
3139     * Position the scroll bar along the right edge.
3140     */
3141    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3142
3143    /**
3144     * Indicates that the view does not have a layer.
3145     *
3146     * @see #getLayerType()
3147     * @see #setLayerType(int, android.graphics.Paint)
3148     * @see #LAYER_TYPE_SOFTWARE
3149     * @see #LAYER_TYPE_HARDWARE
3150     */
3151    public static final int LAYER_TYPE_NONE = 0;
3152
3153    /**
3154     * <p>Indicates that the view has a software layer. A software layer is backed
3155     * by a bitmap and causes the view to be rendered using Android's software
3156     * rendering pipeline, even if hardware acceleration is enabled.</p>
3157     *
3158     * <p>Software layers have various usages:</p>
3159     * <p>When the application is not using hardware acceleration, a software layer
3160     * is useful to apply a specific color filter and/or blending mode and/or
3161     * translucency to a view and all its children.</p>
3162     * <p>When the application is using hardware acceleration, a software layer
3163     * is useful to render drawing primitives not supported by the hardware
3164     * accelerated pipeline. It can also be used to cache a complex view tree
3165     * into a texture and reduce the complexity of drawing operations. For instance,
3166     * when animating a complex view tree with a translation, a software layer can
3167     * be used to render the view tree only once.</p>
3168     * <p>Software layers should be avoided when the affected view tree updates
3169     * often. Every update will require to re-render the software layer, which can
3170     * potentially be slow (particularly when hardware acceleration is turned on
3171     * since the layer will have to be uploaded into a hardware texture after every
3172     * update.)</p>
3173     *
3174     * @see #getLayerType()
3175     * @see #setLayerType(int, android.graphics.Paint)
3176     * @see #LAYER_TYPE_NONE
3177     * @see #LAYER_TYPE_HARDWARE
3178     */
3179    public static final int LAYER_TYPE_SOFTWARE = 1;
3180
3181    /**
3182     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3183     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3184     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3185     * rendering pipeline, but only if hardware acceleration is turned on for the
3186     * view hierarchy. When hardware acceleration is turned off, hardware layers
3187     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3188     *
3189     * <p>A hardware layer is useful to apply a specific color filter and/or
3190     * blending mode and/or translucency to a view and all its children.</p>
3191     * <p>A hardware layer can be used to cache a complex view tree into a
3192     * texture and reduce the complexity of drawing operations. For instance,
3193     * when animating a complex view tree with a translation, a hardware layer can
3194     * be used to render the view tree only once.</p>
3195     * <p>A hardware layer can also be used to increase the rendering quality when
3196     * rotation transformations are applied on a view. It can also be used to
3197     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3198     *
3199     * @see #getLayerType()
3200     * @see #setLayerType(int, android.graphics.Paint)
3201     * @see #LAYER_TYPE_NONE
3202     * @see #LAYER_TYPE_SOFTWARE
3203     */
3204    public static final int LAYER_TYPE_HARDWARE = 2;
3205
3206    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3207            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3208            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3209            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3210    })
3211    int mLayerType = LAYER_TYPE_NONE;
3212    Paint mLayerPaint;
3213    Rect mLocalDirtyRect;
3214
3215    /**
3216     * Set to true when the view is sending hover accessibility events because it
3217     * is the innermost hovered view.
3218     */
3219    private boolean mSendingHoverAccessibilityEvents;
3220
3221    /**
3222     * Delegate for injecting accessibility functionality.
3223     */
3224    AccessibilityDelegate mAccessibilityDelegate;
3225
3226    /**
3227     * Consistency verifier for debugging purposes.
3228     * @hide
3229     */
3230    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3231            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3232                    new InputEventConsistencyVerifier(this, 0) : null;
3233
3234    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3235
3236    /**
3237     * Simple constructor to use when creating a view from code.
3238     *
3239     * @param context The Context the view is running in, through which it can
3240     *        access the current theme, resources, etc.
3241     */
3242    public View(Context context) {
3243        mContext = context;
3244        mResources = context != null ? context.getResources() : null;
3245        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3246        // Set some flags defaults
3247        mPrivateFlags2 =
3248                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3249                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3250                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3251                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3252                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3253                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3254        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3255        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3256        mUserPaddingStart = UNDEFINED_PADDING;
3257        mUserPaddingEnd = UNDEFINED_PADDING;
3258
3259        if (!sUseBrokenMakeMeasureSpec && context.getApplicationInfo().targetSdkVersion <=
3260                Build.VERSION_CODES.JELLY_BEAN_MR1 ) {
3261            // Older apps may need this compatibility hack for measurement.
3262            sUseBrokenMakeMeasureSpec = true;
3263        }
3264    }
3265
3266    /**
3267     * Constructor that is called when inflating a view from XML. This is called
3268     * when a view is being constructed from an XML file, supplying attributes
3269     * that were specified in the XML file. This version uses a default style of
3270     * 0, so the only attribute values applied are those in the Context's Theme
3271     * and the given AttributeSet.
3272     *
3273     * <p>
3274     * The method onFinishInflate() will be called after all children have been
3275     * added.
3276     *
3277     * @param context The Context the view is running in, through which it can
3278     *        access the current theme, resources, etc.
3279     * @param attrs The attributes of the XML tag that is inflating the view.
3280     * @see #View(Context, AttributeSet, int)
3281     */
3282    public View(Context context, AttributeSet attrs) {
3283        this(context, attrs, 0);
3284    }
3285
3286    /**
3287     * Perform inflation from XML and apply a class-specific base style. This
3288     * constructor of View allows subclasses to use their own base style when
3289     * they are inflating. For example, a Button class's constructor would call
3290     * this version of the super class constructor and supply
3291     * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
3292     * the theme's button style to modify all of the base view attributes (in
3293     * particular its background) as well as the Button class's attributes.
3294     *
3295     * @param context The Context the view is running in, through which it can
3296     *        access the current theme, resources, etc.
3297     * @param attrs The attributes of the XML tag that is inflating the view.
3298     * @param defStyle The default style to apply to this view. If 0, no style
3299     *        will be applied (beyond what is included in the theme). This may
3300     *        either be an attribute resource, whose value will be retrieved
3301     *        from the current theme, or an explicit style resource.
3302     * @see #View(Context, AttributeSet)
3303     */
3304    public View(Context context, AttributeSet attrs, int defStyle) {
3305        this(context);
3306
3307        TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
3308                defStyle, 0);
3309
3310        Drawable background = null;
3311
3312        int leftPadding = -1;
3313        int topPadding = -1;
3314        int rightPadding = -1;
3315        int bottomPadding = -1;
3316        int startPadding = UNDEFINED_PADDING;
3317        int endPadding = UNDEFINED_PADDING;
3318
3319        int padding = -1;
3320
3321        int viewFlagValues = 0;
3322        int viewFlagMasks = 0;
3323
3324        boolean setScrollContainer = false;
3325
3326        int x = 0;
3327        int y = 0;
3328
3329        float tx = 0;
3330        float ty = 0;
3331        float rotation = 0;
3332        float rotationX = 0;
3333        float rotationY = 0;
3334        float sx = 1f;
3335        float sy = 1f;
3336        boolean transformSet = false;
3337
3338        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3339        int overScrollMode = mOverScrollMode;
3340        boolean initializeScrollbars = false;
3341
3342        boolean leftPaddingDefined = false;
3343        boolean rightPaddingDefined = false;
3344        boolean startPaddingDefined = false;
3345        boolean endPaddingDefined = false;
3346
3347        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3348
3349        final int N = a.getIndexCount();
3350        for (int i = 0; i < N; i++) {
3351            int attr = a.getIndex(i);
3352            switch (attr) {
3353                case com.android.internal.R.styleable.View_background:
3354                    background = a.getDrawable(attr);
3355                    break;
3356                case com.android.internal.R.styleable.View_padding:
3357                    padding = a.getDimensionPixelSize(attr, -1);
3358                    mUserPaddingLeftInitial = padding;
3359                    mUserPaddingRightInitial = padding;
3360                    leftPaddingDefined = true;
3361                    rightPaddingDefined = true;
3362                    break;
3363                 case com.android.internal.R.styleable.View_paddingLeft:
3364                    leftPadding = a.getDimensionPixelSize(attr, -1);
3365                    mUserPaddingLeftInitial = leftPadding;
3366                    leftPaddingDefined = true;
3367                    break;
3368                case com.android.internal.R.styleable.View_paddingTop:
3369                    topPadding = a.getDimensionPixelSize(attr, -1);
3370                    break;
3371                case com.android.internal.R.styleable.View_paddingRight:
3372                    rightPadding = a.getDimensionPixelSize(attr, -1);
3373                    mUserPaddingRightInitial = rightPadding;
3374                    rightPaddingDefined = true;
3375                    break;
3376                case com.android.internal.R.styleable.View_paddingBottom:
3377                    bottomPadding = a.getDimensionPixelSize(attr, -1);
3378                    break;
3379                case com.android.internal.R.styleable.View_paddingStart:
3380                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3381                    startPaddingDefined = true;
3382                    break;
3383                case com.android.internal.R.styleable.View_paddingEnd:
3384                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3385                    endPaddingDefined = true;
3386                    break;
3387                case com.android.internal.R.styleable.View_scrollX:
3388                    x = a.getDimensionPixelOffset(attr, 0);
3389                    break;
3390                case com.android.internal.R.styleable.View_scrollY:
3391                    y = a.getDimensionPixelOffset(attr, 0);
3392                    break;
3393                case com.android.internal.R.styleable.View_alpha:
3394                    setAlpha(a.getFloat(attr, 1f));
3395                    break;
3396                case com.android.internal.R.styleable.View_transformPivotX:
3397                    setPivotX(a.getDimensionPixelOffset(attr, 0));
3398                    break;
3399                case com.android.internal.R.styleable.View_transformPivotY:
3400                    setPivotY(a.getDimensionPixelOffset(attr, 0));
3401                    break;
3402                case com.android.internal.R.styleable.View_translationX:
3403                    tx = a.getDimensionPixelOffset(attr, 0);
3404                    transformSet = true;
3405                    break;
3406                case com.android.internal.R.styleable.View_translationY:
3407                    ty = a.getDimensionPixelOffset(attr, 0);
3408                    transformSet = true;
3409                    break;
3410                case com.android.internal.R.styleable.View_rotation:
3411                    rotation = a.getFloat(attr, 0);
3412                    transformSet = true;
3413                    break;
3414                case com.android.internal.R.styleable.View_rotationX:
3415                    rotationX = a.getFloat(attr, 0);
3416                    transformSet = true;
3417                    break;
3418                case com.android.internal.R.styleable.View_rotationY:
3419                    rotationY = a.getFloat(attr, 0);
3420                    transformSet = true;
3421                    break;
3422                case com.android.internal.R.styleable.View_scaleX:
3423                    sx = a.getFloat(attr, 1f);
3424                    transformSet = true;
3425                    break;
3426                case com.android.internal.R.styleable.View_scaleY:
3427                    sy = a.getFloat(attr, 1f);
3428                    transformSet = true;
3429                    break;
3430                case com.android.internal.R.styleable.View_id:
3431                    mID = a.getResourceId(attr, NO_ID);
3432                    break;
3433                case com.android.internal.R.styleable.View_tag:
3434                    mTag = a.getText(attr);
3435                    break;
3436                case com.android.internal.R.styleable.View_fitsSystemWindows:
3437                    if (a.getBoolean(attr, false)) {
3438                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
3439                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3440                    }
3441                    break;
3442                case com.android.internal.R.styleable.View_focusable:
3443                    if (a.getBoolean(attr, false)) {
3444                        viewFlagValues |= FOCUSABLE;
3445                        viewFlagMasks |= FOCUSABLE_MASK;
3446                    }
3447                    break;
3448                case com.android.internal.R.styleable.View_focusableInTouchMode:
3449                    if (a.getBoolean(attr, false)) {
3450                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3451                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3452                    }
3453                    break;
3454                case com.android.internal.R.styleable.View_clickable:
3455                    if (a.getBoolean(attr, false)) {
3456                        viewFlagValues |= CLICKABLE;
3457                        viewFlagMasks |= CLICKABLE;
3458                    }
3459                    break;
3460                case com.android.internal.R.styleable.View_longClickable:
3461                    if (a.getBoolean(attr, false)) {
3462                        viewFlagValues |= LONG_CLICKABLE;
3463                        viewFlagMasks |= LONG_CLICKABLE;
3464                    }
3465                    break;
3466                case com.android.internal.R.styleable.View_saveEnabled:
3467                    if (!a.getBoolean(attr, true)) {
3468                        viewFlagValues |= SAVE_DISABLED;
3469                        viewFlagMasks |= SAVE_DISABLED_MASK;
3470                    }
3471                    break;
3472                case com.android.internal.R.styleable.View_duplicateParentState:
3473                    if (a.getBoolean(attr, false)) {
3474                        viewFlagValues |= DUPLICATE_PARENT_STATE;
3475                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
3476                    }
3477                    break;
3478                case com.android.internal.R.styleable.View_visibility:
3479                    final int visibility = a.getInt(attr, 0);
3480                    if (visibility != 0) {
3481                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
3482                        viewFlagMasks |= VISIBILITY_MASK;
3483                    }
3484                    break;
3485                case com.android.internal.R.styleable.View_layoutDirection:
3486                    // Clear any layout direction flags (included resolved bits) already set
3487                    mPrivateFlags2 &=
3488                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3489                    // Set the layout direction flags depending on the value of the attribute
3490                    final int layoutDirection = a.getInt(attr, -1);
3491                    final int value = (layoutDirection != -1) ?
3492                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3493                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3494                    break;
3495                case com.android.internal.R.styleable.View_drawingCacheQuality:
3496                    final int cacheQuality = a.getInt(attr, 0);
3497                    if (cacheQuality != 0) {
3498                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3499                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3500                    }
3501                    break;
3502                case com.android.internal.R.styleable.View_contentDescription:
3503                    setContentDescription(a.getString(attr));
3504                    break;
3505                case com.android.internal.R.styleable.View_labelFor:
3506                    setLabelFor(a.getResourceId(attr, NO_ID));
3507                    break;
3508                case com.android.internal.R.styleable.View_soundEffectsEnabled:
3509                    if (!a.getBoolean(attr, true)) {
3510                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3511                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3512                    }
3513                    break;
3514                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3515                    if (!a.getBoolean(attr, true)) {
3516                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3517                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3518                    }
3519                    break;
3520                case R.styleable.View_scrollbars:
3521                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3522                    if (scrollbars != SCROLLBARS_NONE) {
3523                        viewFlagValues |= scrollbars;
3524                        viewFlagMasks |= SCROLLBARS_MASK;
3525                        initializeScrollbars = true;
3526                    }
3527                    break;
3528                //noinspection deprecation
3529                case R.styleable.View_fadingEdge:
3530                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3531                        // Ignore the attribute starting with ICS
3532                        break;
3533                    }
3534                    // With builds < ICS, fall through and apply fading edges
3535                case R.styleable.View_requiresFadingEdge:
3536                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3537                    if (fadingEdge != FADING_EDGE_NONE) {
3538                        viewFlagValues |= fadingEdge;
3539                        viewFlagMasks |= FADING_EDGE_MASK;
3540                        initializeFadingEdge(a);
3541                    }
3542                    break;
3543                case R.styleable.View_scrollbarStyle:
3544                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3545                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3546                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3547                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3548                    }
3549                    break;
3550                case R.styleable.View_isScrollContainer:
3551                    setScrollContainer = true;
3552                    if (a.getBoolean(attr, false)) {
3553                        setScrollContainer(true);
3554                    }
3555                    break;
3556                case com.android.internal.R.styleable.View_keepScreenOn:
3557                    if (a.getBoolean(attr, false)) {
3558                        viewFlagValues |= KEEP_SCREEN_ON;
3559                        viewFlagMasks |= KEEP_SCREEN_ON;
3560                    }
3561                    break;
3562                case R.styleable.View_filterTouchesWhenObscured:
3563                    if (a.getBoolean(attr, false)) {
3564                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3565                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3566                    }
3567                    break;
3568                case R.styleable.View_nextFocusLeft:
3569                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3570                    break;
3571                case R.styleable.View_nextFocusRight:
3572                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3573                    break;
3574                case R.styleable.View_nextFocusUp:
3575                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3576                    break;
3577                case R.styleable.View_nextFocusDown:
3578                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3579                    break;
3580                case R.styleable.View_nextFocusForward:
3581                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3582                    break;
3583                case R.styleable.View_minWidth:
3584                    mMinWidth = a.getDimensionPixelSize(attr, 0);
3585                    break;
3586                case R.styleable.View_minHeight:
3587                    mMinHeight = a.getDimensionPixelSize(attr, 0);
3588                    break;
3589                case R.styleable.View_onClick:
3590                    if (context.isRestricted()) {
3591                        throw new IllegalStateException("The android:onClick attribute cannot "
3592                                + "be used within a restricted context");
3593                    }
3594
3595                    final String handlerName = a.getString(attr);
3596                    if (handlerName != null) {
3597                        setOnClickListener(new OnClickListener() {
3598                            private Method mHandler;
3599
3600                            public void onClick(View v) {
3601                                if (mHandler == null) {
3602                                    try {
3603                                        mHandler = getContext().getClass().getMethod(handlerName,
3604                                                View.class);
3605                                    } catch (NoSuchMethodException e) {
3606                                        int id = getId();
3607                                        String idText = id == NO_ID ? "" : " with id '"
3608                                                + getContext().getResources().getResourceEntryName(
3609                                                    id) + "'";
3610                                        throw new IllegalStateException("Could not find a method " +
3611                                                handlerName + "(View) in the activity "
3612                                                + getContext().getClass() + " for onClick handler"
3613                                                + " on view " + View.this.getClass() + idText, e);
3614                                    }
3615                                }
3616
3617                                try {
3618                                    mHandler.invoke(getContext(), View.this);
3619                                } catch (IllegalAccessException e) {
3620                                    throw new IllegalStateException("Could not execute non "
3621                                            + "public method of the activity", e);
3622                                } catch (InvocationTargetException e) {
3623                                    throw new IllegalStateException("Could not execute "
3624                                            + "method of the activity", e);
3625                                }
3626                            }
3627                        });
3628                    }
3629                    break;
3630                case R.styleable.View_overScrollMode:
3631                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3632                    break;
3633                case R.styleable.View_verticalScrollbarPosition:
3634                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3635                    break;
3636                case R.styleable.View_layerType:
3637                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3638                    break;
3639                case R.styleable.View_textDirection:
3640                    // Clear any text direction flag already set
3641                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
3642                    // Set the text direction flags depending on the value of the attribute
3643                    final int textDirection = a.getInt(attr, -1);
3644                    if (textDirection != -1) {
3645                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
3646                    }
3647                    break;
3648                case R.styleable.View_textAlignment:
3649                    // Clear any text alignment flag already set
3650                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
3651                    // Set the text alignment flag depending on the value of the attribute
3652                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
3653                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
3654                    break;
3655                case R.styleable.View_importantForAccessibility:
3656                    setImportantForAccessibility(a.getInt(attr,
3657                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
3658                    break;
3659            }
3660        }
3661
3662        setOverScrollMode(overScrollMode);
3663
3664        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
3665        // the resolved layout direction). Those cached values will be used later during padding
3666        // resolution.
3667        mUserPaddingStart = startPadding;
3668        mUserPaddingEnd = endPadding;
3669
3670        if (background != null) {
3671            setBackground(background);
3672        }
3673
3674        if (padding >= 0) {
3675            leftPadding = padding;
3676            topPadding = padding;
3677            rightPadding = padding;
3678            bottomPadding = padding;
3679            mUserPaddingLeftInitial = padding;
3680            mUserPaddingRightInitial = padding;
3681        }
3682
3683        if (isRtlCompatibilityMode()) {
3684            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
3685            // left / right padding are used if defined (meaning here nothing to do). If they are not
3686            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
3687            // start / end and resolve them as left / right (layout direction is not taken into account).
3688            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
3689            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
3690            // defined.
3691            if (!leftPaddingDefined && startPaddingDefined) {
3692                leftPadding = startPadding;
3693            }
3694            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
3695            if (!rightPaddingDefined && endPaddingDefined) {
3696                rightPadding = endPadding;
3697            }
3698            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
3699        } else {
3700            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
3701            // values defined. Otherwise, left /right values are used.
3702            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
3703            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
3704            // defined.
3705            if (leftPaddingDefined) {
3706                mUserPaddingLeftInitial = leftPadding;
3707            }
3708            if (rightPaddingDefined) {
3709                mUserPaddingRightInitial = rightPadding;
3710            }
3711        }
3712
3713        internalSetPadding(
3714                mUserPaddingLeftInitial,
3715                topPadding >= 0 ? topPadding : mPaddingTop,
3716                mUserPaddingRightInitial,
3717                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
3718
3719        if (viewFlagMasks != 0) {
3720            setFlags(viewFlagValues, viewFlagMasks);
3721        }
3722
3723        if (initializeScrollbars) {
3724            initializeScrollbars(a);
3725        }
3726
3727        a.recycle();
3728
3729        // Needs to be called after mViewFlags is set
3730        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3731            recomputePadding();
3732        }
3733
3734        if (x != 0 || y != 0) {
3735            scrollTo(x, y);
3736        }
3737
3738        if (transformSet) {
3739            setTranslationX(tx);
3740            setTranslationY(ty);
3741            setRotation(rotation);
3742            setRotationX(rotationX);
3743            setRotationY(rotationY);
3744            setScaleX(sx);
3745            setScaleY(sy);
3746        }
3747
3748        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
3749            setScrollContainer(true);
3750        }
3751
3752        computeOpaqueFlags();
3753    }
3754
3755    /**
3756     * Non-public constructor for use in testing
3757     */
3758    View() {
3759        mResources = null;
3760    }
3761
3762    public String toString() {
3763        StringBuilder out = new StringBuilder(128);
3764        out.append(getClass().getName());
3765        out.append('{');
3766        out.append(Integer.toHexString(System.identityHashCode(this)));
3767        out.append(' ');
3768        switch (mViewFlags&VISIBILITY_MASK) {
3769            case VISIBLE: out.append('V'); break;
3770            case INVISIBLE: out.append('I'); break;
3771            case GONE: out.append('G'); break;
3772            default: out.append('.'); break;
3773        }
3774        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
3775        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
3776        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
3777        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
3778        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
3779        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
3780        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
3781        out.append(' ');
3782        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
3783        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
3784        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
3785        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
3786            out.append('p');
3787        } else {
3788            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
3789        }
3790        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
3791        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
3792        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
3793        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
3794        out.append(' ');
3795        out.append(mLeft);
3796        out.append(',');
3797        out.append(mTop);
3798        out.append('-');
3799        out.append(mRight);
3800        out.append(',');
3801        out.append(mBottom);
3802        final int id = getId();
3803        if (id != NO_ID) {
3804            out.append(" #");
3805            out.append(Integer.toHexString(id));
3806            final Resources r = mResources;
3807            if (id != 0 && r != null) {
3808                try {
3809                    String pkgname;
3810                    switch (id&0xff000000) {
3811                        case 0x7f000000:
3812                            pkgname="app";
3813                            break;
3814                        case 0x01000000:
3815                            pkgname="android";
3816                            break;
3817                        default:
3818                            pkgname = r.getResourcePackageName(id);
3819                            break;
3820                    }
3821                    String typename = r.getResourceTypeName(id);
3822                    String entryname = r.getResourceEntryName(id);
3823                    out.append(" ");
3824                    out.append(pkgname);
3825                    out.append(":");
3826                    out.append(typename);
3827                    out.append("/");
3828                    out.append(entryname);
3829                } catch (Resources.NotFoundException e) {
3830                }
3831            }
3832        }
3833        out.append("}");
3834        return out.toString();
3835    }
3836
3837    /**
3838     * <p>
3839     * Initializes the fading edges from a given set of styled attributes. This
3840     * method should be called by subclasses that need fading edges and when an
3841     * instance of these subclasses is created programmatically rather than
3842     * being inflated from XML. This method is automatically called when the XML
3843     * is inflated.
3844     * </p>
3845     *
3846     * @param a the styled attributes set to initialize the fading edges from
3847     */
3848    protected void initializeFadingEdge(TypedArray a) {
3849        initScrollCache();
3850
3851        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
3852                R.styleable.View_fadingEdgeLength,
3853                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
3854    }
3855
3856    /**
3857     * Returns the size of the vertical faded edges used to indicate that more
3858     * content in this view is visible.
3859     *
3860     * @return The size in pixels of the vertical faded edge or 0 if vertical
3861     *         faded edges are not enabled for this view.
3862     * @attr ref android.R.styleable#View_fadingEdgeLength
3863     */
3864    public int getVerticalFadingEdgeLength() {
3865        if (isVerticalFadingEdgeEnabled()) {
3866            ScrollabilityCache cache = mScrollCache;
3867            if (cache != null) {
3868                return cache.fadingEdgeLength;
3869            }
3870        }
3871        return 0;
3872    }
3873
3874    /**
3875     * Set the size of the faded edge used to indicate that more content in this
3876     * view is available.  Will not change whether the fading edge is enabled; use
3877     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
3878     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
3879     * for the vertical or horizontal fading edges.
3880     *
3881     * @param length The size in pixels of the faded edge used to indicate that more
3882     *        content in this view is visible.
3883     */
3884    public void setFadingEdgeLength(int length) {
3885        initScrollCache();
3886        mScrollCache.fadingEdgeLength = length;
3887    }
3888
3889    /**
3890     * Returns the size of the horizontal faded edges used to indicate that more
3891     * content in this view is visible.
3892     *
3893     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
3894     *         faded edges are not enabled for this view.
3895     * @attr ref android.R.styleable#View_fadingEdgeLength
3896     */
3897    public int getHorizontalFadingEdgeLength() {
3898        if (isHorizontalFadingEdgeEnabled()) {
3899            ScrollabilityCache cache = mScrollCache;
3900            if (cache != null) {
3901                return cache.fadingEdgeLength;
3902            }
3903        }
3904        return 0;
3905    }
3906
3907    /**
3908     * Returns the width of the vertical scrollbar.
3909     *
3910     * @return The width in pixels of the vertical scrollbar or 0 if there
3911     *         is no vertical scrollbar.
3912     */
3913    public int getVerticalScrollbarWidth() {
3914        ScrollabilityCache cache = mScrollCache;
3915        if (cache != null) {
3916            ScrollBarDrawable scrollBar = cache.scrollBar;
3917            if (scrollBar != null) {
3918                int size = scrollBar.getSize(true);
3919                if (size <= 0) {
3920                    size = cache.scrollBarSize;
3921                }
3922                return size;
3923            }
3924            return 0;
3925        }
3926        return 0;
3927    }
3928
3929    /**
3930     * Returns the height of the horizontal scrollbar.
3931     *
3932     * @return The height in pixels of the horizontal scrollbar or 0 if
3933     *         there is no horizontal scrollbar.
3934     */
3935    protected int getHorizontalScrollbarHeight() {
3936        ScrollabilityCache cache = mScrollCache;
3937        if (cache != null) {
3938            ScrollBarDrawable scrollBar = cache.scrollBar;
3939            if (scrollBar != null) {
3940                int size = scrollBar.getSize(false);
3941                if (size <= 0) {
3942                    size = cache.scrollBarSize;
3943                }
3944                return size;
3945            }
3946            return 0;
3947        }
3948        return 0;
3949    }
3950
3951    /**
3952     * <p>
3953     * Initializes the scrollbars from a given set of styled attributes. This
3954     * method should be called by subclasses that need scrollbars and when an
3955     * instance of these subclasses is created programmatically rather than
3956     * being inflated from XML. This method is automatically called when the XML
3957     * is inflated.
3958     * </p>
3959     *
3960     * @param a the styled attributes set to initialize the scrollbars from
3961     */
3962    protected void initializeScrollbars(TypedArray a) {
3963        initScrollCache();
3964
3965        final ScrollabilityCache scrollabilityCache = mScrollCache;
3966
3967        if (scrollabilityCache.scrollBar == null) {
3968            scrollabilityCache.scrollBar = new ScrollBarDrawable();
3969        }
3970
3971        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
3972
3973        if (!fadeScrollbars) {
3974            scrollabilityCache.state = ScrollabilityCache.ON;
3975        }
3976        scrollabilityCache.fadeScrollBars = fadeScrollbars;
3977
3978
3979        scrollabilityCache.scrollBarFadeDuration = a.getInt(
3980                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
3981                        .getScrollBarFadeDuration());
3982        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
3983                R.styleable.View_scrollbarDefaultDelayBeforeFade,
3984                ViewConfiguration.getScrollDefaultDelay());
3985
3986
3987        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
3988                com.android.internal.R.styleable.View_scrollbarSize,
3989                ViewConfiguration.get(mContext).getScaledScrollBarSize());
3990
3991        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
3992        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
3993
3994        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
3995        if (thumb != null) {
3996            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
3997        }
3998
3999        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4000                false);
4001        if (alwaysDraw) {
4002            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4003        }
4004
4005        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4006        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4007
4008        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4009        if (thumb != null) {
4010            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4011        }
4012
4013        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4014                false);
4015        if (alwaysDraw) {
4016            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4017        }
4018
4019        // Apply layout direction to the new Drawables if needed
4020        final int layoutDirection = getLayoutDirection();
4021        if (track != null) {
4022            track.setLayoutDirection(layoutDirection);
4023        }
4024        if (thumb != null) {
4025            thumb.setLayoutDirection(layoutDirection);
4026        }
4027
4028        // Re-apply user/background padding so that scrollbar(s) get added
4029        resolvePadding();
4030    }
4031
4032    /**
4033     * <p>
4034     * Initalizes the scrollability cache if necessary.
4035     * </p>
4036     */
4037    private void initScrollCache() {
4038        if (mScrollCache == null) {
4039            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4040        }
4041    }
4042
4043    private ScrollabilityCache getScrollCache() {
4044        initScrollCache();
4045        return mScrollCache;
4046    }
4047
4048    /**
4049     * Set the position of the vertical scroll bar. Should be one of
4050     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4051     * {@link #SCROLLBAR_POSITION_RIGHT}.
4052     *
4053     * @param position Where the vertical scroll bar should be positioned.
4054     */
4055    public void setVerticalScrollbarPosition(int position) {
4056        if (mVerticalScrollbarPosition != position) {
4057            mVerticalScrollbarPosition = position;
4058            computeOpaqueFlags();
4059            resolvePadding();
4060        }
4061    }
4062
4063    /**
4064     * @return The position where the vertical scroll bar will show, if applicable.
4065     * @see #setVerticalScrollbarPosition(int)
4066     */
4067    public int getVerticalScrollbarPosition() {
4068        return mVerticalScrollbarPosition;
4069    }
4070
4071    ListenerInfo getListenerInfo() {
4072        if (mListenerInfo != null) {
4073            return mListenerInfo;
4074        }
4075        mListenerInfo = new ListenerInfo();
4076        return mListenerInfo;
4077    }
4078
4079    /**
4080     * Register a callback to be invoked when focus of this view changed.
4081     *
4082     * @param l The callback that will run.
4083     */
4084    public void setOnFocusChangeListener(OnFocusChangeListener l) {
4085        getListenerInfo().mOnFocusChangeListener = l;
4086    }
4087
4088    /**
4089     * Add a listener that will be called when the bounds of the view change due to
4090     * layout processing.
4091     *
4092     * @param listener The listener that will be called when layout bounds change.
4093     */
4094    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4095        ListenerInfo li = getListenerInfo();
4096        if (li.mOnLayoutChangeListeners == null) {
4097            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4098        }
4099        if (!li.mOnLayoutChangeListeners.contains(listener)) {
4100            li.mOnLayoutChangeListeners.add(listener);
4101        }
4102    }
4103
4104    /**
4105     * Remove a listener for layout changes.
4106     *
4107     * @param listener The listener for layout bounds change.
4108     */
4109    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4110        ListenerInfo li = mListenerInfo;
4111        if (li == null || li.mOnLayoutChangeListeners == null) {
4112            return;
4113        }
4114        li.mOnLayoutChangeListeners.remove(listener);
4115    }
4116
4117    /**
4118     * Add a listener for attach state changes.
4119     *
4120     * This listener will be called whenever this view is attached or detached
4121     * from a window. Remove the listener using
4122     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4123     *
4124     * @param listener Listener to attach
4125     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4126     */
4127    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4128        ListenerInfo li = getListenerInfo();
4129        if (li.mOnAttachStateChangeListeners == null) {
4130            li.mOnAttachStateChangeListeners
4131                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4132        }
4133        li.mOnAttachStateChangeListeners.add(listener);
4134    }
4135
4136    /**
4137     * Remove a listener for attach state changes. The listener will receive no further
4138     * notification of window attach/detach events.
4139     *
4140     * @param listener Listener to remove
4141     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4142     */
4143    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4144        ListenerInfo li = mListenerInfo;
4145        if (li == null || li.mOnAttachStateChangeListeners == null) {
4146            return;
4147        }
4148        li.mOnAttachStateChangeListeners.remove(listener);
4149    }
4150
4151    /**
4152     * Returns the focus-change callback registered for this view.
4153     *
4154     * @return The callback, or null if one is not registered.
4155     */
4156    public OnFocusChangeListener getOnFocusChangeListener() {
4157        ListenerInfo li = mListenerInfo;
4158        return li != null ? li.mOnFocusChangeListener : null;
4159    }
4160
4161    /**
4162     * Register a callback to be invoked when this view is clicked. If this view is not
4163     * clickable, it becomes clickable.
4164     *
4165     * @param l The callback that will run
4166     *
4167     * @see #setClickable(boolean)
4168     */
4169    public void setOnClickListener(OnClickListener l) {
4170        if (!isClickable()) {
4171            setClickable(true);
4172        }
4173        getListenerInfo().mOnClickListener = l;
4174    }
4175
4176    /**
4177     * Return whether this view has an attached OnClickListener.  Returns
4178     * true if there is a listener, false if there is none.
4179     */
4180    public boolean hasOnClickListeners() {
4181        ListenerInfo li = mListenerInfo;
4182        return (li != null && li.mOnClickListener != null);
4183    }
4184
4185    /**
4186     * Register a callback to be invoked when this view is clicked and held. If this view is not
4187     * long clickable, it becomes long clickable.
4188     *
4189     * @param l The callback that will run
4190     *
4191     * @see #setLongClickable(boolean)
4192     */
4193    public void setOnLongClickListener(OnLongClickListener l) {
4194        if (!isLongClickable()) {
4195            setLongClickable(true);
4196        }
4197        getListenerInfo().mOnLongClickListener = l;
4198    }
4199
4200    /**
4201     * Register a callback to be invoked when the context menu for this view is
4202     * being built. If this view is not long clickable, it becomes long clickable.
4203     *
4204     * @param l The callback that will run
4205     *
4206     */
4207    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4208        if (!isLongClickable()) {
4209            setLongClickable(true);
4210        }
4211        getListenerInfo().mOnCreateContextMenuListener = l;
4212    }
4213
4214    /**
4215     * Call this view's OnClickListener, if it is defined.  Performs all normal
4216     * actions associated with clicking: reporting accessibility event, playing
4217     * a sound, etc.
4218     *
4219     * @return True there was an assigned OnClickListener that was called, false
4220     *         otherwise is returned.
4221     */
4222    public boolean performClick() {
4223        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4224
4225        ListenerInfo li = mListenerInfo;
4226        if (li != null && li.mOnClickListener != null) {
4227            playSoundEffect(SoundEffectConstants.CLICK);
4228            li.mOnClickListener.onClick(this);
4229            return true;
4230        }
4231
4232        return false;
4233    }
4234
4235    /**
4236     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
4237     * this only calls the listener, and does not do any associated clicking
4238     * actions like reporting an accessibility event.
4239     *
4240     * @return True there was an assigned OnClickListener that was called, false
4241     *         otherwise is returned.
4242     */
4243    public boolean callOnClick() {
4244        ListenerInfo li = mListenerInfo;
4245        if (li != null && li.mOnClickListener != null) {
4246            li.mOnClickListener.onClick(this);
4247            return true;
4248        }
4249        return false;
4250    }
4251
4252    /**
4253     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4254     * OnLongClickListener did not consume the event.
4255     *
4256     * @return True if one of the above receivers consumed the event, false otherwise.
4257     */
4258    public boolean performLongClick() {
4259        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4260
4261        boolean handled = false;
4262        ListenerInfo li = mListenerInfo;
4263        if (li != null && li.mOnLongClickListener != null) {
4264            handled = li.mOnLongClickListener.onLongClick(View.this);
4265        }
4266        if (!handled) {
4267            handled = showContextMenu();
4268        }
4269        if (handled) {
4270            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4271        }
4272        return handled;
4273    }
4274
4275    /**
4276     * Performs button-related actions during a touch down event.
4277     *
4278     * @param event The event.
4279     * @return True if the down was consumed.
4280     *
4281     * @hide
4282     */
4283    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4284        if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4285            if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4286                return true;
4287            }
4288        }
4289        return false;
4290    }
4291
4292    /**
4293     * Bring up the context menu for this view.
4294     *
4295     * @return Whether a context menu was displayed.
4296     */
4297    public boolean showContextMenu() {
4298        return getParent().showContextMenuForChild(this);
4299    }
4300
4301    /**
4302     * Bring up the context menu for this view, referring to the item under the specified point.
4303     *
4304     * @param x The referenced x coordinate.
4305     * @param y The referenced y coordinate.
4306     * @param metaState The keyboard modifiers that were pressed.
4307     * @return Whether a context menu was displayed.
4308     *
4309     * @hide
4310     */
4311    public boolean showContextMenu(float x, float y, int metaState) {
4312        return showContextMenu();
4313    }
4314
4315    /**
4316     * Start an action mode.
4317     *
4318     * @param callback Callback that will control the lifecycle of the action mode
4319     * @return The new action mode if it is started, null otherwise
4320     *
4321     * @see ActionMode
4322     */
4323    public ActionMode startActionMode(ActionMode.Callback callback) {
4324        ViewParent parent = getParent();
4325        if (parent == null) return null;
4326        return parent.startActionModeForChild(this, callback);
4327    }
4328
4329    /**
4330     * Register a callback to be invoked when a hardware key is pressed in this view.
4331     * Key presses in software input methods will generally not trigger the methods of
4332     * this listener.
4333     * @param l the key listener to attach to this view
4334     */
4335    public void setOnKeyListener(OnKeyListener l) {
4336        getListenerInfo().mOnKeyListener = l;
4337    }
4338
4339    /**
4340     * Register a callback to be invoked when a touch event is sent to this view.
4341     * @param l the touch listener to attach to this view
4342     */
4343    public void setOnTouchListener(OnTouchListener l) {
4344        getListenerInfo().mOnTouchListener = l;
4345    }
4346
4347    /**
4348     * Register a callback to be invoked when a generic motion event is sent to this view.
4349     * @param l the generic motion listener to attach to this view
4350     */
4351    public void setOnGenericMotionListener(OnGenericMotionListener l) {
4352        getListenerInfo().mOnGenericMotionListener = l;
4353    }
4354
4355    /**
4356     * Register a callback to be invoked when a hover event is sent to this view.
4357     * @param l the hover listener to attach to this view
4358     */
4359    public void setOnHoverListener(OnHoverListener l) {
4360        getListenerInfo().mOnHoverListener = l;
4361    }
4362
4363    /**
4364     * Register a drag event listener callback object for this View. The parameter is
4365     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4366     * View, the system calls the
4367     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4368     * @param l An implementation of {@link android.view.View.OnDragListener}.
4369     */
4370    public void setOnDragListener(OnDragListener l) {
4371        getListenerInfo().mOnDragListener = l;
4372    }
4373
4374    /**
4375     * Give this view focus. This will cause
4376     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
4377     *
4378     * Note: this does not check whether this {@link View} should get focus, it just
4379     * gives it focus no matter what.  It should only be called internally by framework
4380     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4381     *
4382     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4383     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
4384     *        focus moved when requestFocus() is called. It may not always
4385     *        apply, in which case use the default View.FOCUS_DOWN.
4386     * @param previouslyFocusedRect The rectangle of the view that had focus
4387     *        prior in this View's coordinate system.
4388     */
4389    void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
4390        if (DBG) {
4391            System.out.println(this + " requestFocus()");
4392        }
4393
4394        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4395            mPrivateFlags |= PFLAG_FOCUSED;
4396
4397            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
4398
4399            if (mParent != null) {
4400                mParent.requestChildFocus(this, this);
4401            }
4402
4403            if (mAttachInfo != null) {
4404                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
4405            }
4406
4407            onFocusChanged(true, direction, previouslyFocusedRect);
4408            refreshDrawableState();
4409
4410            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4411                notifyAccessibilityStateChanged();
4412            }
4413        }
4414    }
4415
4416    /**
4417     * Request that a rectangle of this view be visible on the screen,
4418     * scrolling if necessary just enough.
4419     *
4420     * <p>A View should call this if it maintains some notion of which part
4421     * of its content is interesting.  For example, a text editing view
4422     * should call this when its cursor moves.
4423     *
4424     * @param rectangle The rectangle.
4425     * @return Whether any parent scrolled.
4426     */
4427    public boolean requestRectangleOnScreen(Rect rectangle) {
4428        return requestRectangleOnScreen(rectangle, false);
4429    }
4430
4431    /**
4432     * Request that a rectangle of this view be visible on the screen,
4433     * scrolling if necessary just enough.
4434     *
4435     * <p>A View should call this if it maintains some notion of which part
4436     * of its content is interesting.  For example, a text editing view
4437     * should call this when its cursor moves.
4438     *
4439     * <p>When <code>immediate</code> is set to true, scrolling will not be
4440     * animated.
4441     *
4442     * @param rectangle The rectangle.
4443     * @param immediate True to forbid animated scrolling, false otherwise
4444     * @return Whether any parent scrolled.
4445     */
4446    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
4447        if (mParent == null) {
4448            return false;
4449        }
4450
4451        View child = this;
4452
4453        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
4454        position.set(rectangle);
4455
4456        ViewParent parent = mParent;
4457        boolean scrolled = false;
4458        while (parent != null) {
4459            rectangle.set((int) position.left, (int) position.top,
4460                    (int) position.right, (int) position.bottom);
4461
4462            scrolled |= parent.requestChildRectangleOnScreen(child,
4463                    rectangle, immediate);
4464
4465            if (!child.hasIdentityMatrix()) {
4466                child.getMatrix().mapRect(position);
4467            }
4468
4469            position.offset(child.mLeft, child.mTop);
4470
4471            if (!(parent instanceof View)) {
4472                break;
4473            }
4474
4475            View parentView = (View) parent;
4476
4477            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
4478
4479            child = parentView;
4480            parent = child.getParent();
4481        }
4482
4483        return scrolled;
4484    }
4485
4486    /**
4487     * Called when this view wants to give up focus. If focus is cleared
4488     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
4489     * <p>
4490     * <strong>Note:</strong> When a View clears focus the framework is trying
4491     * to give focus to the first focusable View from the top. Hence, if this
4492     * View is the first from the top that can take focus, then all callbacks
4493     * related to clearing focus will be invoked after wich the framework will
4494     * give focus to this view.
4495     * </p>
4496     */
4497    public void clearFocus() {
4498        if (DBG) {
4499            System.out.println(this + " clearFocus()");
4500        }
4501
4502        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4503            mPrivateFlags &= ~PFLAG_FOCUSED;
4504
4505            if (mParent != null) {
4506                mParent.clearChildFocus(this);
4507            }
4508
4509            onFocusChanged(false, 0, null);
4510
4511            refreshDrawableState();
4512
4513            if (!rootViewRequestFocus()) {
4514                notifyGlobalFocusCleared(this);
4515            }
4516
4517            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4518                notifyAccessibilityStateChanged();
4519            }
4520        }
4521    }
4522
4523    void notifyGlobalFocusCleared(View oldFocus) {
4524        if (oldFocus != null && mAttachInfo != null) {
4525            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
4526        }
4527    }
4528
4529    boolean rootViewRequestFocus() {
4530        View root = getRootView();
4531        if (root != null) {
4532            return root.requestFocus();
4533        }
4534        return false;
4535    }
4536
4537    /**
4538     * Called internally by the view system when a new view is getting focus.
4539     * This is what clears the old focus.
4540     */
4541    void unFocus() {
4542        if (DBG) {
4543            System.out.println(this + " unFocus()");
4544        }
4545
4546        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4547            mPrivateFlags &= ~PFLAG_FOCUSED;
4548
4549            onFocusChanged(false, 0, null);
4550            refreshDrawableState();
4551
4552            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4553                notifyAccessibilityStateChanged();
4554            }
4555        }
4556    }
4557
4558    /**
4559     * Returns true if this view has focus iteself, or is the ancestor of the
4560     * view that has focus.
4561     *
4562     * @return True if this view has or contains focus, false otherwise.
4563     */
4564    @ViewDebug.ExportedProperty(category = "focus")
4565    public boolean hasFocus() {
4566        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
4567    }
4568
4569    /**
4570     * Returns true if this view is focusable or if it contains a reachable View
4571     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
4572     * is a View whose parents do not block descendants focus.
4573     *
4574     * Only {@link #VISIBLE} views are considered focusable.
4575     *
4576     * @return True if the view is focusable or if the view contains a focusable
4577     *         View, false otherwise.
4578     *
4579     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
4580     */
4581    public boolean hasFocusable() {
4582        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
4583    }
4584
4585    /**
4586     * Called by the view system when the focus state of this view changes.
4587     * When the focus change event is caused by directional navigation, direction
4588     * and previouslyFocusedRect provide insight into where the focus is coming from.
4589     * When overriding, be sure to call up through to the super class so that
4590     * the standard focus handling will occur.
4591     *
4592     * @param gainFocus True if the View has focus; false otherwise.
4593     * @param direction The direction focus has moved when requestFocus()
4594     *                  is called to give this view focus. Values are
4595     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
4596     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
4597     *                  It may not always apply, in which case use the default.
4598     * @param previouslyFocusedRect The rectangle, in this view's coordinate
4599     *        system, of the previously focused view.  If applicable, this will be
4600     *        passed in as finer grained information about where the focus is coming
4601     *        from (in addition to direction).  Will be <code>null</code> otherwise.
4602     */
4603    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
4604        if (gainFocus) {
4605            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4606                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
4607            }
4608        }
4609
4610        InputMethodManager imm = InputMethodManager.peekInstance();
4611        if (!gainFocus) {
4612            if (isPressed()) {
4613                setPressed(false);
4614            }
4615            if (imm != null && mAttachInfo != null
4616                    && mAttachInfo.mHasWindowFocus) {
4617                imm.focusOut(this);
4618            }
4619            onFocusLost();
4620        } else if (imm != null && mAttachInfo != null
4621                && mAttachInfo.mHasWindowFocus) {
4622            imm.focusIn(this);
4623        }
4624
4625        invalidate(true);
4626        ListenerInfo li = mListenerInfo;
4627        if (li != null && li.mOnFocusChangeListener != null) {
4628            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
4629        }
4630
4631        if (mAttachInfo != null) {
4632            mAttachInfo.mKeyDispatchState.reset(this);
4633        }
4634    }
4635
4636    /**
4637     * Sends an accessibility event of the given type. If accessibility is
4638     * not enabled this method has no effect. The default implementation calls
4639     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
4640     * to populate information about the event source (this View), then calls
4641     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
4642     * populate the text content of the event source including its descendants,
4643     * and last calls
4644     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
4645     * on its parent to resuest sending of the event to interested parties.
4646     * <p>
4647     * If an {@link AccessibilityDelegate} has been specified via calling
4648     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4649     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
4650     * responsible for handling this call.
4651     * </p>
4652     *
4653     * @param eventType The type of the event to send, as defined by several types from
4654     * {@link android.view.accessibility.AccessibilityEvent}, such as
4655     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
4656     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
4657     *
4658     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4659     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4660     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
4661     * @see AccessibilityDelegate
4662     */
4663    public void sendAccessibilityEvent(int eventType) {
4664        if (mAccessibilityDelegate != null) {
4665            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
4666        } else {
4667            sendAccessibilityEventInternal(eventType);
4668        }
4669    }
4670
4671    /**
4672     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
4673     * {@link AccessibilityEvent} to make an announcement which is related to some
4674     * sort of a context change for which none of the events representing UI transitions
4675     * is a good fit. For example, announcing a new page in a book. If accessibility
4676     * is not enabled this method does nothing.
4677     *
4678     * @param text The announcement text.
4679     */
4680    public void announceForAccessibility(CharSequence text) {
4681        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
4682            AccessibilityEvent event = AccessibilityEvent.obtain(
4683                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
4684            onInitializeAccessibilityEvent(event);
4685            event.getText().add(text);
4686            event.setContentDescription(null);
4687            mParent.requestSendAccessibilityEvent(this, event);
4688        }
4689    }
4690
4691    /**
4692     * @see #sendAccessibilityEvent(int)
4693     *
4694     * Note: Called from the default {@link AccessibilityDelegate}.
4695     */
4696    void sendAccessibilityEventInternal(int eventType) {
4697        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4698            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
4699        }
4700    }
4701
4702    /**
4703     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
4704     * takes as an argument an empty {@link AccessibilityEvent} and does not
4705     * perform a check whether accessibility is enabled.
4706     * <p>
4707     * If an {@link AccessibilityDelegate} has been specified via calling
4708     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4709     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
4710     * is responsible for handling this call.
4711     * </p>
4712     *
4713     * @param event The event to send.
4714     *
4715     * @see #sendAccessibilityEvent(int)
4716     */
4717    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
4718        if (mAccessibilityDelegate != null) {
4719            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
4720        } else {
4721            sendAccessibilityEventUncheckedInternal(event);
4722        }
4723    }
4724
4725    /**
4726     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
4727     *
4728     * Note: Called from the default {@link AccessibilityDelegate}.
4729     */
4730    void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
4731        if (!isShown()) {
4732            return;
4733        }
4734        onInitializeAccessibilityEvent(event);
4735        // Only a subset of accessibility events populates text content.
4736        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
4737            dispatchPopulateAccessibilityEvent(event);
4738        }
4739        // In the beginning we called #isShown(), so we know that getParent() is not null.
4740        getParent().requestSendAccessibilityEvent(this, event);
4741    }
4742
4743    /**
4744     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
4745     * to its children for adding their text content to the event. Note that the
4746     * event text is populated in a separate dispatch path since we add to the
4747     * event not only the text of the source but also the text of all its descendants.
4748     * A typical implementation will call
4749     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
4750     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4751     * on each child. Override this method if custom population of the event text
4752     * content is required.
4753     * <p>
4754     * If an {@link AccessibilityDelegate} has been specified via calling
4755     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4756     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
4757     * is responsible for handling this call.
4758     * </p>
4759     * <p>
4760     * <em>Note:</em> Accessibility events of certain types are not dispatched for
4761     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
4762     * </p>
4763     *
4764     * @param event The event.
4765     *
4766     * @return True if the event population was completed.
4767     */
4768    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
4769        if (mAccessibilityDelegate != null) {
4770            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
4771        } else {
4772            return dispatchPopulateAccessibilityEventInternal(event);
4773        }
4774    }
4775
4776    /**
4777     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4778     *
4779     * Note: Called from the default {@link AccessibilityDelegate}.
4780     */
4781    boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4782        onPopulateAccessibilityEvent(event);
4783        return false;
4784    }
4785
4786    /**
4787     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4788     * giving a chance to this View to populate the accessibility event with its
4789     * text content. While this method is free to modify event
4790     * attributes other than text content, doing so should normally be performed in
4791     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
4792     * <p>
4793     * Example: Adding formatted date string to an accessibility event in addition
4794     *          to the text added by the super implementation:
4795     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
4796     *     super.onPopulateAccessibilityEvent(event);
4797     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
4798     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
4799     *         mCurrentDate.getTimeInMillis(), flags);
4800     *     event.getText().add(selectedDateUtterance);
4801     * }</pre>
4802     * <p>
4803     * If an {@link AccessibilityDelegate} has been specified via calling
4804     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4805     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
4806     * is responsible for handling this call.
4807     * </p>
4808     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4809     * information to the event, in case the default implementation has basic information to add.
4810     * </p>
4811     *
4812     * @param event The accessibility event which to populate.
4813     *
4814     * @see #sendAccessibilityEvent(int)
4815     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4816     */
4817    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
4818        if (mAccessibilityDelegate != null) {
4819            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
4820        } else {
4821            onPopulateAccessibilityEventInternal(event);
4822        }
4823    }
4824
4825    /**
4826     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
4827     *
4828     * Note: Called from the default {@link AccessibilityDelegate}.
4829     */
4830    void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4831
4832    }
4833
4834    /**
4835     * Initializes an {@link AccessibilityEvent} with information about
4836     * this View which is the event source. In other words, the source of
4837     * an accessibility event is the view whose state change triggered firing
4838     * the event.
4839     * <p>
4840     * Example: Setting the password property of an event in addition
4841     *          to properties set by the super implementation:
4842     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4843     *     super.onInitializeAccessibilityEvent(event);
4844     *     event.setPassword(true);
4845     * }</pre>
4846     * <p>
4847     * If an {@link AccessibilityDelegate} has been specified via calling
4848     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4849     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
4850     * is responsible for handling this call.
4851     * </p>
4852     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4853     * information to the event, in case the default implementation has basic information to add.
4854     * </p>
4855     * @param event The event to initialize.
4856     *
4857     * @see #sendAccessibilityEvent(int)
4858     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4859     */
4860    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4861        if (mAccessibilityDelegate != null) {
4862            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
4863        } else {
4864            onInitializeAccessibilityEventInternal(event);
4865        }
4866    }
4867
4868    /**
4869     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4870     *
4871     * Note: Called from the default {@link AccessibilityDelegate}.
4872     */
4873    void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
4874        event.setSource(this);
4875        event.setClassName(View.class.getName());
4876        event.setPackageName(getContext().getPackageName());
4877        event.setEnabled(isEnabled());
4878        event.setContentDescription(mContentDescription);
4879
4880        switch (event.getEventType()) {
4881            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
4882                ArrayList<View> focusablesTempList = (mAttachInfo != null)
4883                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
4884                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
4885                event.setItemCount(focusablesTempList.size());
4886                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
4887                if (mAttachInfo != null) {
4888                    focusablesTempList.clear();
4889                }
4890            } break;
4891            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
4892                CharSequence text = getIterableTextForAccessibility();
4893                if (text != null && text.length() > 0) {
4894                    event.setFromIndex(getAccessibilitySelectionStart());
4895                    event.setToIndex(getAccessibilitySelectionEnd());
4896                    event.setItemCount(text.length());
4897                }
4898            } break;
4899        }
4900    }
4901
4902    /**
4903     * Returns an {@link AccessibilityNodeInfo} representing this view from the
4904     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
4905     * This method is responsible for obtaining an accessibility node info from a
4906     * pool of reusable instances and calling
4907     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
4908     * initialize the former.
4909     * <p>
4910     * Note: The client is responsible for recycling the obtained instance by calling
4911     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
4912     * </p>
4913     *
4914     * @return A populated {@link AccessibilityNodeInfo}.
4915     *
4916     * @see AccessibilityNodeInfo
4917     */
4918    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
4919        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
4920        if (provider != null) {
4921            return provider.createAccessibilityNodeInfo(View.NO_ID);
4922        } else {
4923            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
4924            onInitializeAccessibilityNodeInfo(info);
4925            return info;
4926        }
4927    }
4928
4929    /**
4930     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
4931     * The base implementation sets:
4932     * <ul>
4933     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
4934     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
4935     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
4936     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
4937     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
4938     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
4939     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
4940     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
4941     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
4942     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
4943     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
4944     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
4945     * </ul>
4946     * <p>
4947     * Subclasses should override this method, call the super implementation,
4948     * and set additional attributes.
4949     * </p>
4950     * <p>
4951     * If an {@link AccessibilityDelegate} has been specified via calling
4952     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4953     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
4954     * is responsible for handling this call.
4955     * </p>
4956     *
4957     * @param info The instance to initialize.
4958     */
4959    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
4960        if (mAccessibilityDelegate != null) {
4961            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
4962        } else {
4963            onInitializeAccessibilityNodeInfoInternal(info);
4964        }
4965    }
4966
4967    /**
4968     * Gets the location of this view in screen coordintates.
4969     *
4970     * @param outRect The output location
4971     */
4972    void getBoundsOnScreen(Rect outRect) {
4973        if (mAttachInfo == null) {
4974            return;
4975        }
4976
4977        RectF position = mAttachInfo.mTmpTransformRect;
4978        position.set(0, 0, mRight - mLeft, mBottom - mTop);
4979
4980        if (!hasIdentityMatrix()) {
4981            getMatrix().mapRect(position);
4982        }
4983
4984        position.offset(mLeft, mTop);
4985
4986        ViewParent parent = mParent;
4987        while (parent instanceof View) {
4988            View parentView = (View) parent;
4989
4990            position.offset(-parentView.mScrollX, -parentView.mScrollY);
4991
4992            if (!parentView.hasIdentityMatrix()) {
4993                parentView.getMatrix().mapRect(position);
4994            }
4995
4996            position.offset(parentView.mLeft, parentView.mTop);
4997
4998            parent = parentView.mParent;
4999        }
5000
5001        if (parent instanceof ViewRootImpl) {
5002            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
5003            position.offset(0, -viewRootImpl.mCurScrollY);
5004        }
5005
5006        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
5007
5008        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
5009                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
5010    }
5011
5012    /**
5013     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
5014     *
5015     * Note: Called from the default {@link AccessibilityDelegate}.
5016     */
5017    void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
5018        Rect bounds = mAttachInfo.mTmpInvalRect;
5019
5020        getDrawingRect(bounds);
5021        info.setBoundsInParent(bounds);
5022
5023        getBoundsOnScreen(bounds);
5024        info.setBoundsInScreen(bounds);
5025
5026        ViewParent parent = getParentForAccessibility();
5027        if (parent instanceof View) {
5028            info.setParent((View) parent);
5029        }
5030
5031        if (mID != View.NO_ID) {
5032            View rootView = getRootView();
5033            if (rootView == null) {
5034                rootView = this;
5035            }
5036            View label = rootView.findLabelForView(this, mID);
5037            if (label != null) {
5038                info.setLabeledBy(label);
5039            }
5040
5041            if ((mAttachInfo.mAccessibilityFetchFlags
5042                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0) {
5043                String viewId = null;
5044                try {
5045                    viewId = getResources().getResourceName(mID);
5046                } catch (Resources.NotFoundException nfe) {
5047                    /* ignore */
5048                }
5049                if (viewId == null) {
5050                    try {
5051                        viewId = ((Context) ActivityThread.currentActivityThread()
5052                                .getSystemContext()).getResources().getResourceName(mID);
5053                    } catch (Resources.NotFoundException nfe) {
5054                        /* ignore */
5055                    }
5056                }
5057                info.setViewIdResourceName(viewId);
5058            }
5059        }
5060
5061        if (mLabelForId != View.NO_ID) {
5062            View rootView = getRootView();
5063            if (rootView == null) {
5064                rootView = this;
5065            }
5066            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
5067            if (labeled != null) {
5068                info.setLabelFor(labeled);
5069            }
5070        }
5071
5072        info.setVisibleToUser(isVisibleToUser());
5073
5074        info.setPackageName(mContext.getPackageName());
5075        info.setClassName(View.class.getName());
5076        info.setContentDescription(getContentDescription());
5077
5078        info.setEnabled(isEnabled());
5079        info.setClickable(isClickable());
5080        info.setFocusable(isFocusable());
5081        info.setFocused(isFocused());
5082        info.setAccessibilityFocused(isAccessibilityFocused());
5083        info.setSelected(isSelected());
5084        info.setLongClickable(isLongClickable());
5085
5086        // TODO: These make sense only if we are in an AdapterView but all
5087        // views can be selected. Maybe from accessibility perspective
5088        // we should report as selectable view in an AdapterView.
5089        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
5090        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
5091
5092        if (isFocusable()) {
5093            if (isFocused()) {
5094                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
5095            } else {
5096                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
5097            }
5098        }
5099
5100        if (!isAccessibilityFocused()) {
5101            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
5102        } else {
5103            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
5104        }
5105
5106        if (isClickable() && isEnabled()) {
5107            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
5108        }
5109
5110        if (isLongClickable() && isEnabled()) {
5111            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
5112        }
5113
5114        CharSequence text = getIterableTextForAccessibility();
5115        if (text != null && text.length() > 0) {
5116            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
5117
5118            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
5119            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
5120            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
5121            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
5122                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
5123                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
5124        }
5125    }
5126
5127    private View findLabelForView(View view, int labeledId) {
5128        if (mMatchLabelForPredicate == null) {
5129            mMatchLabelForPredicate = new MatchLabelForPredicate();
5130        }
5131        mMatchLabelForPredicate.mLabeledId = labeledId;
5132        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
5133    }
5134
5135    /**
5136     * Computes whether this view is visible to the user. Such a view is
5137     * attached, visible, all its predecessors are visible, it is not clipped
5138     * entirely by its predecessors, and has an alpha greater than zero.
5139     *
5140     * @return Whether the view is visible on the screen.
5141     *
5142     * @hide
5143     */
5144    protected boolean isVisibleToUser() {
5145        return isVisibleToUser(null);
5146    }
5147
5148    /**
5149     * Computes whether the given portion of this view is visible to the user.
5150     * Such a view is attached, visible, all its predecessors are visible,
5151     * has an alpha greater than zero, and the specified portion is not
5152     * clipped entirely by its predecessors.
5153     *
5154     * @param boundInView the portion of the view to test; coordinates should be relative; may be
5155     *                    <code>null</code>, and the entire view will be tested in this case.
5156     *                    When <code>true</code> is returned by the function, the actual visible
5157     *                    region will be stored in this parameter; that is, if boundInView is fully
5158     *                    contained within the view, no modification will be made, otherwise regions
5159     *                    outside of the visible area of the view will be clipped.
5160     *
5161     * @return Whether the specified portion of the view is visible on the screen.
5162     *
5163     * @hide
5164     */
5165    protected boolean isVisibleToUser(Rect boundInView) {
5166        if (mAttachInfo != null) {
5167            // Attached to invisible window means this view is not visible.
5168            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
5169                return false;
5170            }
5171            // An invisible predecessor or one with alpha zero means
5172            // that this view is not visible to the user.
5173            Object current = this;
5174            while (current instanceof View) {
5175                View view = (View) current;
5176                // We have attach info so this view is attached and there is no
5177                // need to check whether we reach to ViewRootImpl on the way up.
5178                if (view.getAlpha() <= 0 || view.getVisibility() != VISIBLE) {
5179                    return false;
5180                }
5181                current = view.mParent;
5182            }
5183            // Check if the view is entirely covered by its predecessors.
5184            Rect visibleRect = mAttachInfo.mTmpInvalRect;
5185            Point offset = mAttachInfo.mPoint;
5186            if (!getGlobalVisibleRect(visibleRect, offset)) {
5187                return false;
5188            }
5189            // Check if the visible portion intersects the rectangle of interest.
5190            if (boundInView != null) {
5191                visibleRect.offset(-offset.x, -offset.y);
5192                return boundInView.intersect(visibleRect);
5193            }
5194            return true;
5195        }
5196        return false;
5197    }
5198
5199    /**
5200     * Returns the delegate for implementing accessibility support via
5201     * composition. For more details see {@link AccessibilityDelegate}.
5202     *
5203     * @return The delegate, or null if none set.
5204     *
5205     * @hide
5206     */
5207    public AccessibilityDelegate getAccessibilityDelegate() {
5208        return mAccessibilityDelegate;
5209    }
5210
5211    /**
5212     * Sets a delegate for implementing accessibility support via composition as
5213     * opposed to inheritance. The delegate's primary use is for implementing
5214     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
5215     *
5216     * @param delegate The delegate instance.
5217     *
5218     * @see AccessibilityDelegate
5219     */
5220    public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
5221        mAccessibilityDelegate = delegate;
5222    }
5223
5224    /**
5225     * Gets the provider for managing a virtual view hierarchy rooted at this View
5226     * and reported to {@link android.accessibilityservice.AccessibilityService}s
5227     * that explore the window content.
5228     * <p>
5229     * If this method returns an instance, this instance is responsible for managing
5230     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
5231     * View including the one representing the View itself. Similarly the returned
5232     * instance is responsible for performing accessibility actions on any virtual
5233     * view or the root view itself.
5234     * </p>
5235     * <p>
5236     * If an {@link AccessibilityDelegate} has been specified via calling
5237     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5238     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
5239     * is responsible for handling this call.
5240     * </p>
5241     *
5242     * @return The provider.
5243     *
5244     * @see AccessibilityNodeProvider
5245     */
5246    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
5247        if (mAccessibilityDelegate != null) {
5248            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
5249        } else {
5250            return null;
5251        }
5252    }
5253
5254    /**
5255     * Gets the unique identifier of this view on the screen for accessibility purposes.
5256     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
5257     *
5258     * @return The view accessibility id.
5259     *
5260     * @hide
5261     */
5262    public int getAccessibilityViewId() {
5263        if (mAccessibilityViewId == NO_ID) {
5264            mAccessibilityViewId = sNextAccessibilityViewId++;
5265        }
5266        return mAccessibilityViewId;
5267    }
5268
5269    /**
5270     * Gets the unique identifier of the window in which this View reseides.
5271     *
5272     * @return The window accessibility id.
5273     *
5274     * @hide
5275     */
5276    public int getAccessibilityWindowId() {
5277        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
5278    }
5279
5280    /**
5281     * Gets the {@link View} description. It briefly describes the view and is
5282     * primarily used for accessibility support. Set this property to enable
5283     * better accessibility support for your application. This is especially
5284     * true for views that do not have textual representation (For example,
5285     * ImageButton).
5286     *
5287     * @return The content description.
5288     *
5289     * @attr ref android.R.styleable#View_contentDescription
5290     */
5291    @ViewDebug.ExportedProperty(category = "accessibility")
5292    public CharSequence getContentDescription() {
5293        return mContentDescription;
5294    }
5295
5296    /**
5297     * Sets the {@link View} description. It briefly describes the view and is
5298     * primarily used for accessibility support. Set this property to enable
5299     * better accessibility support for your application. This is especially
5300     * true for views that do not have textual representation (For example,
5301     * ImageButton).
5302     *
5303     * @param contentDescription The content description.
5304     *
5305     * @attr ref android.R.styleable#View_contentDescription
5306     */
5307    @RemotableViewMethod
5308    public void setContentDescription(CharSequence contentDescription) {
5309        if (mContentDescription == null) {
5310            if (contentDescription == null) {
5311                return;
5312            }
5313        } else if (mContentDescription.equals(contentDescription)) {
5314            return;
5315        }
5316        mContentDescription = contentDescription;
5317        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
5318        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
5319             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
5320        }
5321        notifyAccessibilityStateChanged();
5322    }
5323
5324    /**
5325     * Gets the id of a view for which this view serves as a label for
5326     * accessibility purposes.
5327     *
5328     * @return The labeled view id.
5329     */
5330    @ViewDebug.ExportedProperty(category = "accessibility")
5331    public int getLabelFor() {
5332        return mLabelForId;
5333    }
5334
5335    /**
5336     * Sets the id of a view for which this view serves as a label for
5337     * accessibility purposes.
5338     *
5339     * @param id The labeled view id.
5340     */
5341    @RemotableViewMethod
5342    public void setLabelFor(int id) {
5343        mLabelForId = id;
5344        if (mLabelForId != View.NO_ID
5345                && mID == View.NO_ID) {
5346            mID = generateViewId();
5347        }
5348    }
5349
5350    /**
5351     * Invoked whenever this view loses focus, either by losing window focus or by losing
5352     * focus within its window. This method can be used to clear any state tied to the
5353     * focus. For instance, if a button is held pressed with the trackball and the window
5354     * loses focus, this method can be used to cancel the press.
5355     *
5356     * Subclasses of View overriding this method should always call super.onFocusLost().
5357     *
5358     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
5359     * @see #onWindowFocusChanged(boolean)
5360     *
5361     * @hide pending API council approval
5362     */
5363    protected void onFocusLost() {
5364        resetPressedState();
5365    }
5366
5367    private void resetPressedState() {
5368        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
5369            return;
5370        }
5371
5372        if (isPressed()) {
5373            setPressed(false);
5374
5375            if (!mHasPerformedLongPress) {
5376                removeLongPressCallback();
5377            }
5378        }
5379    }
5380
5381    /**
5382     * Returns true if this view has focus
5383     *
5384     * @return True if this view has focus, false otherwise.
5385     */
5386    @ViewDebug.ExportedProperty(category = "focus")
5387    public boolean isFocused() {
5388        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5389    }
5390
5391    /**
5392     * Find the view in the hierarchy rooted at this view that currently has
5393     * focus.
5394     *
5395     * @return The view that currently has focus, or null if no focused view can
5396     *         be found.
5397     */
5398    public View findFocus() {
5399        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
5400    }
5401
5402    /**
5403     * Indicates whether this view is one of the set of scrollable containers in
5404     * its window.
5405     *
5406     * @return whether this view is one of the set of scrollable containers in
5407     * its window
5408     *
5409     * @attr ref android.R.styleable#View_isScrollContainer
5410     */
5411    public boolean isScrollContainer() {
5412        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
5413    }
5414
5415    /**
5416     * Change whether this view is one of the set of scrollable containers in
5417     * its window.  This will be used to determine whether the window can
5418     * resize or must pan when a soft input area is open -- scrollable
5419     * containers allow the window to use resize mode since the container
5420     * will appropriately shrink.
5421     *
5422     * @attr ref android.R.styleable#View_isScrollContainer
5423     */
5424    public void setScrollContainer(boolean isScrollContainer) {
5425        if (isScrollContainer) {
5426            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
5427                mAttachInfo.mScrollContainers.add(this);
5428                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
5429            }
5430            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
5431        } else {
5432            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
5433                mAttachInfo.mScrollContainers.remove(this);
5434            }
5435            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
5436        }
5437    }
5438
5439    /**
5440     * Returns the quality of the drawing cache.
5441     *
5442     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5443     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5444     *
5445     * @see #setDrawingCacheQuality(int)
5446     * @see #setDrawingCacheEnabled(boolean)
5447     * @see #isDrawingCacheEnabled()
5448     *
5449     * @attr ref android.R.styleable#View_drawingCacheQuality
5450     */
5451    public int getDrawingCacheQuality() {
5452        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
5453    }
5454
5455    /**
5456     * Set the drawing cache quality of this view. This value is used only when the
5457     * drawing cache is enabled
5458     *
5459     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5460     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5461     *
5462     * @see #getDrawingCacheQuality()
5463     * @see #setDrawingCacheEnabled(boolean)
5464     * @see #isDrawingCacheEnabled()
5465     *
5466     * @attr ref android.R.styleable#View_drawingCacheQuality
5467     */
5468    public void setDrawingCacheQuality(int quality) {
5469        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
5470    }
5471
5472    /**
5473     * Returns whether the screen should remain on, corresponding to the current
5474     * value of {@link #KEEP_SCREEN_ON}.
5475     *
5476     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
5477     *
5478     * @see #setKeepScreenOn(boolean)
5479     *
5480     * @attr ref android.R.styleable#View_keepScreenOn
5481     */
5482    public boolean getKeepScreenOn() {
5483        return (mViewFlags & KEEP_SCREEN_ON) != 0;
5484    }
5485
5486    /**
5487     * Controls whether the screen should remain on, modifying the
5488     * value of {@link #KEEP_SCREEN_ON}.
5489     *
5490     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
5491     *
5492     * @see #getKeepScreenOn()
5493     *
5494     * @attr ref android.R.styleable#View_keepScreenOn
5495     */
5496    public void setKeepScreenOn(boolean keepScreenOn) {
5497        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
5498    }
5499
5500    /**
5501     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5502     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5503     *
5504     * @attr ref android.R.styleable#View_nextFocusLeft
5505     */
5506    public int getNextFocusLeftId() {
5507        return mNextFocusLeftId;
5508    }
5509
5510    /**
5511     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5512     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
5513     * decide automatically.
5514     *
5515     * @attr ref android.R.styleable#View_nextFocusLeft
5516     */
5517    public void setNextFocusLeftId(int nextFocusLeftId) {
5518        mNextFocusLeftId = nextFocusLeftId;
5519    }
5520
5521    /**
5522     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5523     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5524     *
5525     * @attr ref android.R.styleable#View_nextFocusRight
5526     */
5527    public int getNextFocusRightId() {
5528        return mNextFocusRightId;
5529    }
5530
5531    /**
5532     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5533     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
5534     * decide automatically.
5535     *
5536     * @attr ref android.R.styleable#View_nextFocusRight
5537     */
5538    public void setNextFocusRightId(int nextFocusRightId) {
5539        mNextFocusRightId = nextFocusRightId;
5540    }
5541
5542    /**
5543     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5544     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5545     *
5546     * @attr ref android.R.styleable#View_nextFocusUp
5547     */
5548    public int getNextFocusUpId() {
5549        return mNextFocusUpId;
5550    }
5551
5552    /**
5553     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5554     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
5555     * decide automatically.
5556     *
5557     * @attr ref android.R.styleable#View_nextFocusUp
5558     */
5559    public void setNextFocusUpId(int nextFocusUpId) {
5560        mNextFocusUpId = nextFocusUpId;
5561    }
5562
5563    /**
5564     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5565     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5566     *
5567     * @attr ref android.R.styleable#View_nextFocusDown
5568     */
5569    public int getNextFocusDownId() {
5570        return mNextFocusDownId;
5571    }
5572
5573    /**
5574     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5575     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
5576     * decide automatically.
5577     *
5578     * @attr ref android.R.styleable#View_nextFocusDown
5579     */
5580    public void setNextFocusDownId(int nextFocusDownId) {
5581        mNextFocusDownId = nextFocusDownId;
5582    }
5583
5584    /**
5585     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5586     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5587     *
5588     * @attr ref android.R.styleable#View_nextFocusForward
5589     */
5590    public int getNextFocusForwardId() {
5591        return mNextFocusForwardId;
5592    }
5593
5594    /**
5595     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5596     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
5597     * decide automatically.
5598     *
5599     * @attr ref android.R.styleable#View_nextFocusForward
5600     */
5601    public void setNextFocusForwardId(int nextFocusForwardId) {
5602        mNextFocusForwardId = nextFocusForwardId;
5603    }
5604
5605    /**
5606     * Returns the visibility of this view and all of its ancestors
5607     *
5608     * @return True if this view and all of its ancestors are {@link #VISIBLE}
5609     */
5610    public boolean isShown() {
5611        View current = this;
5612        //noinspection ConstantConditions
5613        do {
5614            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
5615                return false;
5616            }
5617            ViewParent parent = current.mParent;
5618            if (parent == null) {
5619                return false; // We are not attached to the view root
5620            }
5621            if (!(parent instanceof View)) {
5622                return true;
5623            }
5624            current = (View) parent;
5625        } while (current != null);
5626
5627        return false;
5628    }
5629
5630    /**
5631     * Called by the view hierarchy when the content insets for a window have
5632     * changed, to allow it to adjust its content to fit within those windows.
5633     * The content insets tell you the space that the status bar, input method,
5634     * and other system windows infringe on the application's window.
5635     *
5636     * <p>You do not normally need to deal with this function, since the default
5637     * window decoration given to applications takes care of applying it to the
5638     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
5639     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
5640     * and your content can be placed under those system elements.  You can then
5641     * use this method within your view hierarchy if you have parts of your UI
5642     * which you would like to ensure are not being covered.
5643     *
5644     * <p>The default implementation of this method simply applies the content
5645     * inset's to the view's padding, consuming that content (modifying the
5646     * insets to be 0), and returning true.  This behavior is off by default, but can
5647     * be enabled through {@link #setFitsSystemWindows(boolean)}.
5648     *
5649     * <p>This function's traversal down the hierarchy is depth-first.  The same content
5650     * insets object is propagated down the hierarchy, so any changes made to it will
5651     * be seen by all following views (including potentially ones above in
5652     * the hierarchy since this is a depth-first traversal).  The first view
5653     * that returns true will abort the entire traversal.
5654     *
5655     * <p>The default implementation works well for a situation where it is
5656     * used with a container that covers the entire window, allowing it to
5657     * apply the appropriate insets to its content on all edges.  If you need
5658     * a more complicated layout (such as two different views fitting system
5659     * windows, one on the top of the window, and one on the bottom),
5660     * you can override the method and handle the insets however you would like.
5661     * Note that the insets provided by the framework are always relative to the
5662     * far edges of the window, not accounting for the location of the called view
5663     * within that window.  (In fact when this method is called you do not yet know
5664     * where the layout will place the view, as it is done before layout happens.)
5665     *
5666     * <p>Note: unlike many View methods, there is no dispatch phase to this
5667     * call.  If you are overriding it in a ViewGroup and want to allow the
5668     * call to continue to your children, you must be sure to call the super
5669     * implementation.
5670     *
5671     * <p>Here is a sample layout that makes use of fitting system windows
5672     * to have controls for a video view placed inside of the window decorations
5673     * that it hides and shows.  This can be used with code like the second
5674     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
5675     *
5676     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
5677     *
5678     * @param insets Current content insets of the window.  Prior to
5679     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
5680     * the insets or else you and Android will be unhappy.
5681     *
5682     * @return Return true if this view applied the insets and it should not
5683     * continue propagating further down the hierarchy, false otherwise.
5684     * @see #getFitsSystemWindows()
5685     * @see #setFitsSystemWindows(boolean)
5686     * @see #setSystemUiVisibility(int)
5687     */
5688    protected boolean fitSystemWindows(Rect insets) {
5689        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
5690            mUserPaddingStart = UNDEFINED_PADDING;
5691            mUserPaddingEnd = UNDEFINED_PADDING;
5692            if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
5693                    || mAttachInfo == null
5694                    || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
5695                internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
5696                return true;
5697            } else {
5698                internalSetPadding(0, 0, 0, 0);
5699                return false;
5700            }
5701        }
5702        return false;
5703    }
5704
5705    /**
5706     * Sets whether or not this view should account for system screen decorations
5707     * such as the status bar and inset its content; that is, controlling whether
5708     * the default implementation of {@link #fitSystemWindows(Rect)} will be
5709     * executed.  See that method for more details.
5710     *
5711     * <p>Note that if you are providing your own implementation of
5712     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
5713     * flag to true -- your implementation will be overriding the default
5714     * implementation that checks this flag.
5715     *
5716     * @param fitSystemWindows If true, then the default implementation of
5717     * {@link #fitSystemWindows(Rect)} will be executed.
5718     *
5719     * @attr ref android.R.styleable#View_fitsSystemWindows
5720     * @see #getFitsSystemWindows()
5721     * @see #fitSystemWindows(Rect)
5722     * @see #setSystemUiVisibility(int)
5723     */
5724    public void setFitsSystemWindows(boolean fitSystemWindows) {
5725        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
5726    }
5727
5728    /**
5729     * Check for state of {@link #setFitsSystemWindows(boolean). If this method
5730     * returns true, the default implementation of {@link #fitSystemWindows(Rect)}
5731     * will be executed.
5732     *
5733     * @return Returns true if the default implementation of
5734     * {@link #fitSystemWindows(Rect)} will be executed.
5735     *
5736     * @attr ref android.R.styleable#View_fitsSystemWindows
5737     * @see #setFitsSystemWindows()
5738     * @see #fitSystemWindows(Rect)
5739     * @see #setSystemUiVisibility(int)
5740     */
5741    public boolean getFitsSystemWindows() {
5742        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
5743    }
5744
5745    /** @hide */
5746    public boolean fitsSystemWindows() {
5747        return getFitsSystemWindows();
5748    }
5749
5750    /**
5751     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
5752     */
5753    public void requestFitSystemWindows() {
5754        if (mParent != null) {
5755            mParent.requestFitSystemWindows();
5756        }
5757    }
5758
5759    /**
5760     * For use by PhoneWindow to make its own system window fitting optional.
5761     * @hide
5762     */
5763    public void makeOptionalFitsSystemWindows() {
5764        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
5765    }
5766
5767    /**
5768     * Returns the visibility status for this view.
5769     *
5770     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5771     * @attr ref android.R.styleable#View_visibility
5772     */
5773    @ViewDebug.ExportedProperty(mapping = {
5774        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
5775        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
5776        @ViewDebug.IntToString(from = GONE,      to = "GONE")
5777    })
5778    public int getVisibility() {
5779        return mViewFlags & VISIBILITY_MASK;
5780    }
5781
5782    /**
5783     * Set the enabled state of this view.
5784     *
5785     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5786     * @attr ref android.R.styleable#View_visibility
5787     */
5788    @RemotableViewMethod
5789    public void setVisibility(int visibility) {
5790        setFlags(visibility, VISIBILITY_MASK);
5791        if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
5792    }
5793
5794    /**
5795     * Returns the enabled status for this view. The interpretation of the
5796     * enabled state varies by subclass.
5797     *
5798     * @return True if this view is enabled, false otherwise.
5799     */
5800    @ViewDebug.ExportedProperty
5801    public boolean isEnabled() {
5802        return (mViewFlags & ENABLED_MASK) == ENABLED;
5803    }
5804
5805    /**
5806     * Set the enabled state of this view. The interpretation of the enabled
5807     * state varies by subclass.
5808     *
5809     * @param enabled True if this view is enabled, false otherwise.
5810     */
5811    @RemotableViewMethod
5812    public void setEnabled(boolean enabled) {
5813        if (enabled == isEnabled()) return;
5814
5815        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
5816
5817        /*
5818         * The View most likely has to change its appearance, so refresh
5819         * the drawable state.
5820         */
5821        refreshDrawableState();
5822
5823        // Invalidate too, since the default behavior for views is to be
5824        // be drawn at 50% alpha rather than to change the drawable.
5825        invalidate(true);
5826    }
5827
5828    /**
5829     * Set whether this view can receive the focus.
5830     *
5831     * Setting this to false will also ensure that this view is not focusable
5832     * in touch mode.
5833     *
5834     * @param focusable If true, this view can receive the focus.
5835     *
5836     * @see #setFocusableInTouchMode(boolean)
5837     * @attr ref android.R.styleable#View_focusable
5838     */
5839    public void setFocusable(boolean focusable) {
5840        if (!focusable) {
5841            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
5842        }
5843        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
5844    }
5845
5846    /**
5847     * Set whether this view can receive focus while in touch mode.
5848     *
5849     * Setting this to true will also ensure that this view is focusable.
5850     *
5851     * @param focusableInTouchMode If true, this view can receive the focus while
5852     *   in touch mode.
5853     *
5854     * @see #setFocusable(boolean)
5855     * @attr ref android.R.styleable#View_focusableInTouchMode
5856     */
5857    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
5858        // Focusable in touch mode should always be set before the focusable flag
5859        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
5860        // which, in touch mode, will not successfully request focus on this view
5861        // because the focusable in touch mode flag is not set
5862        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
5863        if (focusableInTouchMode) {
5864            setFlags(FOCUSABLE, FOCUSABLE_MASK);
5865        }
5866    }
5867
5868    /**
5869     * Set whether this view should have sound effects enabled for events such as
5870     * clicking and touching.
5871     *
5872     * <p>You may wish to disable sound effects for a view if you already play sounds,
5873     * for instance, a dial key that plays dtmf tones.
5874     *
5875     * @param soundEffectsEnabled whether sound effects are enabled for this view.
5876     * @see #isSoundEffectsEnabled()
5877     * @see #playSoundEffect(int)
5878     * @attr ref android.R.styleable#View_soundEffectsEnabled
5879     */
5880    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
5881        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
5882    }
5883
5884    /**
5885     * @return whether this view should have sound effects enabled for events such as
5886     *     clicking and touching.
5887     *
5888     * @see #setSoundEffectsEnabled(boolean)
5889     * @see #playSoundEffect(int)
5890     * @attr ref android.R.styleable#View_soundEffectsEnabled
5891     */
5892    @ViewDebug.ExportedProperty
5893    public boolean isSoundEffectsEnabled() {
5894        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
5895    }
5896
5897    /**
5898     * Set whether this view should have haptic feedback for events such as
5899     * long presses.
5900     *
5901     * <p>You may wish to disable haptic feedback if your view already controls
5902     * its own haptic feedback.
5903     *
5904     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
5905     * @see #isHapticFeedbackEnabled()
5906     * @see #performHapticFeedback(int)
5907     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5908     */
5909    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
5910        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
5911    }
5912
5913    /**
5914     * @return whether this view should have haptic feedback enabled for events
5915     * long presses.
5916     *
5917     * @see #setHapticFeedbackEnabled(boolean)
5918     * @see #performHapticFeedback(int)
5919     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5920     */
5921    @ViewDebug.ExportedProperty
5922    public boolean isHapticFeedbackEnabled() {
5923        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
5924    }
5925
5926    /**
5927     * Returns the layout direction for this view.
5928     *
5929     * @return One of {@link #LAYOUT_DIRECTION_LTR},
5930     *   {@link #LAYOUT_DIRECTION_RTL},
5931     *   {@link #LAYOUT_DIRECTION_INHERIT} or
5932     *   {@link #LAYOUT_DIRECTION_LOCALE}.
5933     *
5934     * @attr ref android.R.styleable#View_layoutDirection
5935     *
5936     * @hide
5937     */
5938    @ViewDebug.ExportedProperty(category = "layout", mapping = {
5939        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
5940        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
5941        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
5942        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
5943    })
5944    public int getRawLayoutDirection() {
5945        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
5946    }
5947
5948    /**
5949     * Set the layout direction for this view. This will propagate a reset of layout direction
5950     * resolution to the view's children and resolve layout direction for this view.
5951     *
5952     * @param layoutDirection the layout direction to set. Should be one of:
5953     *
5954     * {@link #LAYOUT_DIRECTION_LTR},
5955     * {@link #LAYOUT_DIRECTION_RTL},
5956     * {@link #LAYOUT_DIRECTION_INHERIT},
5957     * {@link #LAYOUT_DIRECTION_LOCALE}.
5958     *
5959     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
5960     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
5961     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
5962     *
5963     * @attr ref android.R.styleable#View_layoutDirection
5964     */
5965    @RemotableViewMethod
5966    public void setLayoutDirection(int layoutDirection) {
5967        if (getRawLayoutDirection() != layoutDirection) {
5968            // Reset the current layout direction and the resolved one
5969            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
5970            resetRtlProperties();
5971            // Set the new layout direction (filtered)
5972            mPrivateFlags2 |=
5973                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
5974            // We need to resolve all RTL properties as they all depend on layout direction
5975            resolveRtlPropertiesIfNeeded();
5976            requestLayout();
5977            invalidate(true);
5978        }
5979    }
5980
5981    /**
5982     * Returns the resolved layout direction for this view.
5983     *
5984     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
5985     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
5986     *
5987     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
5988     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
5989     *
5990     * @attr ref android.R.styleable#View_layoutDirection
5991     */
5992    @ViewDebug.ExportedProperty(category = "layout", mapping = {
5993        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
5994        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
5995    })
5996    public int getLayoutDirection() {
5997        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
5998        if (targetSdkVersion < JELLY_BEAN_MR1) {
5999            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
6000            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
6001        }
6002        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
6003                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
6004    }
6005
6006    /**
6007     * Indicates whether or not this view's layout is right-to-left. This is resolved from
6008     * layout attribute and/or the inherited value from the parent
6009     *
6010     * @return true if the layout is right-to-left.
6011     *
6012     * @hide
6013     */
6014    @ViewDebug.ExportedProperty(category = "layout")
6015    public boolean isLayoutRtl() {
6016        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
6017    }
6018
6019    /**
6020     * Indicates whether the view is currently tracking transient state that the
6021     * app should not need to concern itself with saving and restoring, but that
6022     * the framework should take special note to preserve when possible.
6023     *
6024     * <p>A view with transient state cannot be trivially rebound from an external
6025     * data source, such as an adapter binding item views in a list. This may be
6026     * because the view is performing an animation, tracking user selection
6027     * of content, or similar.</p>
6028     *
6029     * @return true if the view has transient state
6030     */
6031    @ViewDebug.ExportedProperty(category = "layout")
6032    public boolean hasTransientState() {
6033        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
6034    }
6035
6036    /**
6037     * Set whether this view is currently tracking transient state that the
6038     * framework should attempt to preserve when possible. This flag is reference counted,
6039     * so every call to setHasTransientState(true) should be paired with a later call
6040     * to setHasTransientState(false).
6041     *
6042     * <p>A view with transient state cannot be trivially rebound from an external
6043     * data source, such as an adapter binding item views in a list. This may be
6044     * because the view is performing an animation, tracking user selection
6045     * of content, or similar.</p>
6046     *
6047     * @param hasTransientState true if this view has transient state
6048     */
6049    public void setHasTransientState(boolean hasTransientState) {
6050        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
6051                mTransientStateCount - 1;
6052        if (mTransientStateCount < 0) {
6053            mTransientStateCount = 0;
6054            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
6055                    "unmatched pair of setHasTransientState calls");
6056        }
6057        if ((hasTransientState && mTransientStateCount == 1) ||
6058                (!hasTransientState && mTransientStateCount == 0)) {
6059            // update flag if we've just incremented up from 0 or decremented down to 0
6060            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
6061                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
6062            if (mParent != null) {
6063                try {
6064                    mParent.childHasTransientStateChanged(this, hasTransientState);
6065                } catch (AbstractMethodError e) {
6066                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
6067                            " does not fully implement ViewParent", e);
6068                }
6069            }
6070        }
6071    }
6072
6073    /**
6074     * If this view doesn't do any drawing on its own, set this flag to
6075     * allow further optimizations. By default, this flag is not set on
6076     * View, but could be set on some View subclasses such as ViewGroup.
6077     *
6078     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
6079     * you should clear this flag.
6080     *
6081     * @param willNotDraw whether or not this View draw on its own
6082     */
6083    public void setWillNotDraw(boolean willNotDraw) {
6084        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
6085    }
6086
6087    /**
6088     * Returns whether or not this View draws on its own.
6089     *
6090     * @return true if this view has nothing to draw, false otherwise
6091     */
6092    @ViewDebug.ExportedProperty(category = "drawing")
6093    public boolean willNotDraw() {
6094        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
6095    }
6096
6097    /**
6098     * When a View's drawing cache is enabled, drawing is redirected to an
6099     * offscreen bitmap. Some views, like an ImageView, must be able to
6100     * bypass this mechanism if they already draw a single bitmap, to avoid
6101     * unnecessary usage of the memory.
6102     *
6103     * @param willNotCacheDrawing true if this view does not cache its
6104     *        drawing, false otherwise
6105     */
6106    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
6107        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
6108    }
6109
6110    /**
6111     * Returns whether or not this View can cache its drawing or not.
6112     *
6113     * @return true if this view does not cache its drawing, false otherwise
6114     */
6115    @ViewDebug.ExportedProperty(category = "drawing")
6116    public boolean willNotCacheDrawing() {
6117        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
6118    }
6119
6120    /**
6121     * Indicates whether this view reacts to click events or not.
6122     *
6123     * @return true if the view is clickable, false otherwise
6124     *
6125     * @see #setClickable(boolean)
6126     * @attr ref android.R.styleable#View_clickable
6127     */
6128    @ViewDebug.ExportedProperty
6129    public boolean isClickable() {
6130        return (mViewFlags & CLICKABLE) == CLICKABLE;
6131    }
6132
6133    /**
6134     * Enables or disables click events for this view. When a view
6135     * is clickable it will change its state to "pressed" on every click.
6136     * Subclasses should set the view clickable to visually react to
6137     * user's clicks.
6138     *
6139     * @param clickable true to make the view clickable, false otherwise
6140     *
6141     * @see #isClickable()
6142     * @attr ref android.R.styleable#View_clickable
6143     */
6144    public void setClickable(boolean clickable) {
6145        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
6146    }
6147
6148    /**
6149     * Indicates whether this view reacts to long click events or not.
6150     *
6151     * @return true if the view is long clickable, false otherwise
6152     *
6153     * @see #setLongClickable(boolean)
6154     * @attr ref android.R.styleable#View_longClickable
6155     */
6156    public boolean isLongClickable() {
6157        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
6158    }
6159
6160    /**
6161     * Enables or disables long click events for this view. When a view is long
6162     * clickable it reacts to the user holding down the button for a longer
6163     * duration than a tap. This event can either launch the listener or a
6164     * context menu.
6165     *
6166     * @param longClickable true to make the view long clickable, false otherwise
6167     * @see #isLongClickable()
6168     * @attr ref android.R.styleable#View_longClickable
6169     */
6170    public void setLongClickable(boolean longClickable) {
6171        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
6172    }
6173
6174    /**
6175     * Sets the pressed state for this view.
6176     *
6177     * @see #isClickable()
6178     * @see #setClickable(boolean)
6179     *
6180     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
6181     *        the View's internal state from a previously set "pressed" state.
6182     */
6183    public void setPressed(boolean pressed) {
6184        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
6185
6186        if (pressed) {
6187            mPrivateFlags |= PFLAG_PRESSED;
6188        } else {
6189            mPrivateFlags &= ~PFLAG_PRESSED;
6190        }
6191
6192        if (needsRefresh) {
6193            refreshDrawableState();
6194        }
6195        dispatchSetPressed(pressed);
6196    }
6197
6198    /**
6199     * Dispatch setPressed to all of this View's children.
6200     *
6201     * @see #setPressed(boolean)
6202     *
6203     * @param pressed The new pressed state
6204     */
6205    protected void dispatchSetPressed(boolean pressed) {
6206    }
6207
6208    /**
6209     * Indicates whether the view is currently in pressed state. Unless
6210     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
6211     * the pressed state.
6212     *
6213     * @see #setPressed(boolean)
6214     * @see #isClickable()
6215     * @see #setClickable(boolean)
6216     *
6217     * @return true if the view is currently pressed, false otherwise
6218     */
6219    public boolean isPressed() {
6220        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
6221    }
6222
6223    /**
6224     * Indicates whether this view will save its state (that is,
6225     * whether its {@link #onSaveInstanceState} method will be called).
6226     *
6227     * @return Returns true if the view state saving is enabled, else false.
6228     *
6229     * @see #setSaveEnabled(boolean)
6230     * @attr ref android.R.styleable#View_saveEnabled
6231     */
6232    public boolean isSaveEnabled() {
6233        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
6234    }
6235
6236    /**
6237     * Controls whether the saving of this view's state is
6238     * enabled (that is, whether its {@link #onSaveInstanceState} method
6239     * will be called).  Note that even if freezing is enabled, the
6240     * view still must have an id assigned to it (via {@link #setId(int)})
6241     * for its state to be saved.  This flag can only disable the
6242     * saving of this view; any child views may still have their state saved.
6243     *
6244     * @param enabled Set to false to <em>disable</em> state saving, or true
6245     * (the default) to allow it.
6246     *
6247     * @see #isSaveEnabled()
6248     * @see #setId(int)
6249     * @see #onSaveInstanceState()
6250     * @attr ref android.R.styleable#View_saveEnabled
6251     */
6252    public void setSaveEnabled(boolean enabled) {
6253        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
6254    }
6255
6256    /**
6257     * Gets whether the framework should discard touches when the view's
6258     * window is obscured by another visible window.
6259     * Refer to the {@link View} security documentation for more details.
6260     *
6261     * @return True if touch filtering is enabled.
6262     *
6263     * @see #setFilterTouchesWhenObscured(boolean)
6264     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
6265     */
6266    @ViewDebug.ExportedProperty
6267    public boolean getFilterTouchesWhenObscured() {
6268        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
6269    }
6270
6271    /**
6272     * Sets whether the framework should discard touches when the view's
6273     * window is obscured by another visible window.
6274     * Refer to the {@link View} security documentation for more details.
6275     *
6276     * @param enabled True if touch filtering should be enabled.
6277     *
6278     * @see #getFilterTouchesWhenObscured
6279     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
6280     */
6281    public void setFilterTouchesWhenObscured(boolean enabled) {
6282        setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
6283                FILTER_TOUCHES_WHEN_OBSCURED);
6284    }
6285
6286    /**
6287     * Indicates whether the entire hierarchy under this view will save its
6288     * state when a state saving traversal occurs from its parent.  The default
6289     * is true; if false, these views will not be saved unless
6290     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
6291     *
6292     * @return Returns true if the view state saving from parent is enabled, else false.
6293     *
6294     * @see #setSaveFromParentEnabled(boolean)
6295     */
6296    public boolean isSaveFromParentEnabled() {
6297        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
6298    }
6299
6300    /**
6301     * Controls whether the entire hierarchy under this view will save its
6302     * state when a state saving traversal occurs from its parent.  The default
6303     * is true; if false, these views will not be saved unless
6304     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
6305     *
6306     * @param enabled Set to false to <em>disable</em> state saving, or true
6307     * (the default) to allow it.
6308     *
6309     * @see #isSaveFromParentEnabled()
6310     * @see #setId(int)
6311     * @see #onSaveInstanceState()
6312     */
6313    public void setSaveFromParentEnabled(boolean enabled) {
6314        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
6315    }
6316
6317
6318    /**
6319     * Returns whether this View is able to take focus.
6320     *
6321     * @return True if this view can take focus, or false otherwise.
6322     * @attr ref android.R.styleable#View_focusable
6323     */
6324    @ViewDebug.ExportedProperty(category = "focus")
6325    public final boolean isFocusable() {
6326        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
6327    }
6328
6329    /**
6330     * When a view is focusable, it may not want to take focus when in touch mode.
6331     * For example, a button would like focus when the user is navigating via a D-pad
6332     * so that the user can click on it, but once the user starts touching the screen,
6333     * the button shouldn't take focus
6334     * @return Whether the view is focusable in touch mode.
6335     * @attr ref android.R.styleable#View_focusableInTouchMode
6336     */
6337    @ViewDebug.ExportedProperty
6338    public final boolean isFocusableInTouchMode() {
6339        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
6340    }
6341
6342    /**
6343     * Find the nearest view in the specified direction that can take focus.
6344     * This does not actually give focus to that view.
6345     *
6346     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6347     *
6348     * @return The nearest focusable in the specified direction, or null if none
6349     *         can be found.
6350     */
6351    public View focusSearch(int direction) {
6352        if (mParent != null) {
6353            return mParent.focusSearch(this, direction);
6354        } else {
6355            return null;
6356        }
6357    }
6358
6359    /**
6360     * This method is the last chance for the focused view and its ancestors to
6361     * respond to an arrow key. This is called when the focused view did not
6362     * consume the key internally, nor could the view system find a new view in
6363     * the requested direction to give focus to.
6364     *
6365     * @param focused The currently focused view.
6366     * @param direction The direction focus wants to move. One of FOCUS_UP,
6367     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
6368     * @return True if the this view consumed this unhandled move.
6369     */
6370    public boolean dispatchUnhandledMove(View focused, int direction) {
6371        return false;
6372    }
6373
6374    /**
6375     * If a user manually specified the next view id for a particular direction,
6376     * use the root to look up the view.
6377     * @param root The root view of the hierarchy containing this view.
6378     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
6379     * or FOCUS_BACKWARD.
6380     * @return The user specified next view, or null if there is none.
6381     */
6382    View findUserSetNextFocus(View root, int direction) {
6383        switch (direction) {
6384            case FOCUS_LEFT:
6385                if (mNextFocusLeftId == View.NO_ID) return null;
6386                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
6387            case FOCUS_RIGHT:
6388                if (mNextFocusRightId == View.NO_ID) return null;
6389                return findViewInsideOutShouldExist(root, mNextFocusRightId);
6390            case FOCUS_UP:
6391                if (mNextFocusUpId == View.NO_ID) return null;
6392                return findViewInsideOutShouldExist(root, mNextFocusUpId);
6393            case FOCUS_DOWN:
6394                if (mNextFocusDownId == View.NO_ID) return null;
6395                return findViewInsideOutShouldExist(root, mNextFocusDownId);
6396            case FOCUS_FORWARD:
6397                if (mNextFocusForwardId == View.NO_ID) return null;
6398                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
6399            case FOCUS_BACKWARD: {
6400                if (mID == View.NO_ID) return null;
6401                final int id = mID;
6402                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
6403                    @Override
6404                    public boolean apply(View t) {
6405                        return t.mNextFocusForwardId == id;
6406                    }
6407                });
6408            }
6409        }
6410        return null;
6411    }
6412
6413    private View findViewInsideOutShouldExist(View root, int id) {
6414        if (mMatchIdPredicate == null) {
6415            mMatchIdPredicate = new MatchIdPredicate();
6416        }
6417        mMatchIdPredicate.mId = id;
6418        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
6419        if (result == null) {
6420            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
6421        }
6422        return result;
6423    }
6424
6425    /**
6426     * Find and return all focusable views that are descendants of this view,
6427     * possibly including this view if it is focusable itself.
6428     *
6429     * @param direction The direction of the focus
6430     * @return A list of focusable views
6431     */
6432    public ArrayList<View> getFocusables(int direction) {
6433        ArrayList<View> result = new ArrayList<View>(24);
6434        addFocusables(result, direction);
6435        return result;
6436    }
6437
6438    /**
6439     * Add any focusable views that are descendants of this view (possibly
6440     * including this view if it is focusable itself) to views.  If we are in touch mode,
6441     * only add views that are also focusable in touch mode.
6442     *
6443     * @param views Focusable views found so far
6444     * @param direction The direction of the focus
6445     */
6446    public void addFocusables(ArrayList<View> views, int direction) {
6447        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
6448    }
6449
6450    /**
6451     * Adds any focusable views that are descendants of this view (possibly
6452     * including this view if it is focusable itself) to views. This method
6453     * adds all focusable views regardless if we are in touch mode or
6454     * only views focusable in touch mode if we are in touch mode or
6455     * only views that can take accessibility focus if accessibility is enabeld
6456     * depending on the focusable mode paramater.
6457     *
6458     * @param views Focusable views found so far or null if all we are interested is
6459     *        the number of focusables.
6460     * @param direction The direction of the focus.
6461     * @param focusableMode The type of focusables to be added.
6462     *
6463     * @see #FOCUSABLES_ALL
6464     * @see #FOCUSABLES_TOUCH_MODE
6465     */
6466    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
6467        if (views == null) {
6468            return;
6469        }
6470        if (!isFocusable()) {
6471            return;
6472        }
6473        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
6474                && isInTouchMode() && !isFocusableInTouchMode()) {
6475            return;
6476        }
6477        views.add(this);
6478    }
6479
6480    /**
6481     * Finds the Views that contain given text. The containment is case insensitive.
6482     * The search is performed by either the text that the View renders or the content
6483     * description that describes the view for accessibility purposes and the view does
6484     * not render or both. Clients can specify how the search is to be performed via
6485     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
6486     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
6487     *
6488     * @param outViews The output list of matching Views.
6489     * @param searched The text to match against.
6490     *
6491     * @see #FIND_VIEWS_WITH_TEXT
6492     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
6493     * @see #setContentDescription(CharSequence)
6494     */
6495    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
6496        if (getAccessibilityNodeProvider() != null) {
6497            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
6498                outViews.add(this);
6499            }
6500        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
6501                && (searched != null && searched.length() > 0)
6502                && (mContentDescription != null && mContentDescription.length() > 0)) {
6503            String searchedLowerCase = searched.toString().toLowerCase();
6504            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
6505            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
6506                outViews.add(this);
6507            }
6508        }
6509    }
6510
6511    /**
6512     * Find and return all touchable views that are descendants of this view,
6513     * possibly including this view if it is touchable itself.
6514     *
6515     * @return A list of touchable views
6516     */
6517    public ArrayList<View> getTouchables() {
6518        ArrayList<View> result = new ArrayList<View>();
6519        addTouchables(result);
6520        return result;
6521    }
6522
6523    /**
6524     * Add any touchable views that are descendants of this view (possibly
6525     * including this view if it is touchable itself) to views.
6526     *
6527     * @param views Touchable views found so far
6528     */
6529    public void addTouchables(ArrayList<View> views) {
6530        final int viewFlags = mViewFlags;
6531
6532        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
6533                && (viewFlags & ENABLED_MASK) == ENABLED) {
6534            views.add(this);
6535        }
6536    }
6537
6538    /**
6539     * Returns whether this View is accessibility focused.
6540     *
6541     * @return True if this View is accessibility focused.
6542     */
6543    boolean isAccessibilityFocused() {
6544        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
6545    }
6546
6547    /**
6548     * Call this to try to give accessibility focus to this view.
6549     *
6550     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
6551     * returns false or the view is no visible or the view already has accessibility
6552     * focus.
6553     *
6554     * See also {@link #focusSearch(int)}, which is what you call to say that you
6555     * have focus, and you want your parent to look for the next one.
6556     *
6557     * @return Whether this view actually took accessibility focus.
6558     *
6559     * @hide
6560     */
6561    public boolean requestAccessibilityFocus() {
6562        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
6563        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
6564            return false;
6565        }
6566        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6567            return false;
6568        }
6569        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
6570            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
6571            ViewRootImpl viewRootImpl = getViewRootImpl();
6572            if (viewRootImpl != null) {
6573                viewRootImpl.setAccessibilityFocus(this, null);
6574            }
6575            invalidate();
6576            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
6577            notifyAccessibilityStateChanged();
6578            return true;
6579        }
6580        return false;
6581    }
6582
6583    /**
6584     * Call this to try to clear accessibility focus of this view.
6585     *
6586     * See also {@link #focusSearch(int)}, which is what you call to say that you
6587     * have focus, and you want your parent to look for the next one.
6588     *
6589     * @hide
6590     */
6591    public void clearAccessibilityFocus() {
6592        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
6593            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
6594            invalidate();
6595            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
6596            notifyAccessibilityStateChanged();
6597        }
6598        // Clear the global reference of accessibility focus if this
6599        // view or any of its descendants had accessibility focus.
6600        ViewRootImpl viewRootImpl = getViewRootImpl();
6601        if (viewRootImpl != null) {
6602            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
6603            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
6604                viewRootImpl.setAccessibilityFocus(null, null);
6605            }
6606        }
6607    }
6608
6609    private void sendAccessibilityHoverEvent(int eventType) {
6610        // Since we are not delivering to a client accessibility events from not
6611        // important views (unless the clinet request that) we need to fire the
6612        // event from the deepest view exposed to the client. As a consequence if
6613        // the user crosses a not exposed view the client will see enter and exit
6614        // of the exposed predecessor followed by and enter and exit of that same
6615        // predecessor when entering and exiting the not exposed descendant. This
6616        // is fine since the client has a clear idea which view is hovered at the
6617        // price of a couple more events being sent. This is a simple and
6618        // working solution.
6619        View source = this;
6620        while (true) {
6621            if (source.includeForAccessibility()) {
6622                source.sendAccessibilityEvent(eventType);
6623                return;
6624            }
6625            ViewParent parent = source.getParent();
6626            if (parent instanceof View) {
6627                source = (View) parent;
6628            } else {
6629                return;
6630            }
6631        }
6632    }
6633
6634    /**
6635     * Clears accessibility focus without calling any callback methods
6636     * normally invoked in {@link #clearAccessibilityFocus()}. This method
6637     * is used for clearing accessibility focus when giving this focus to
6638     * another view.
6639     */
6640    void clearAccessibilityFocusNoCallbacks() {
6641        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
6642            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
6643            invalidate();
6644        }
6645    }
6646
6647    /**
6648     * Call this to try to give focus to a specific view or to one of its
6649     * descendants.
6650     *
6651     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6652     * false), or if it is focusable and it is not focusable in touch mode
6653     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
6654     *
6655     * See also {@link #focusSearch(int)}, which is what you call to say that you
6656     * have focus, and you want your parent to look for the next one.
6657     *
6658     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
6659     * {@link #FOCUS_DOWN} and <code>null</code>.
6660     *
6661     * @return Whether this view or one of its descendants actually took focus.
6662     */
6663    public final boolean requestFocus() {
6664        return requestFocus(View.FOCUS_DOWN);
6665    }
6666
6667    /**
6668     * Call this to try to give focus to a specific view or to one of its
6669     * descendants and give it a hint about what direction focus is heading.
6670     *
6671     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6672     * false), or if it is focusable and it is not focusable in touch mode
6673     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
6674     *
6675     * See also {@link #focusSearch(int)}, which is what you call to say that you
6676     * have focus, and you want your parent to look for the next one.
6677     *
6678     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
6679     * <code>null</code> set for the previously focused rectangle.
6680     *
6681     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6682     * @return Whether this view or one of its descendants actually took focus.
6683     */
6684    public final boolean requestFocus(int direction) {
6685        return requestFocus(direction, null);
6686    }
6687
6688    /**
6689     * Call this to try to give focus to a specific view or to one of its descendants
6690     * and give it hints about the direction and a specific rectangle that the focus
6691     * is coming from.  The rectangle can help give larger views a finer grained hint
6692     * about where focus is coming from, and therefore, where to show selection, or
6693     * forward focus change internally.
6694     *
6695     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6696     * false), or if it is focusable and it is not focusable in touch mode
6697     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
6698     *
6699     * A View will not take focus if it is not visible.
6700     *
6701     * A View will not take focus if one of its parents has
6702     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
6703     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
6704     *
6705     * See also {@link #focusSearch(int)}, which is what you call to say that you
6706     * have focus, and you want your parent to look for the next one.
6707     *
6708     * You may wish to override this method if your custom {@link View} has an internal
6709     * {@link View} that it wishes to forward the request to.
6710     *
6711     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6712     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
6713     *        to give a finer grained hint about where focus is coming from.  May be null
6714     *        if there is no hint.
6715     * @return Whether this view or one of its descendants actually took focus.
6716     */
6717    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
6718        return requestFocusNoSearch(direction, previouslyFocusedRect);
6719    }
6720
6721    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
6722        // need to be focusable
6723        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
6724                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6725            return false;
6726        }
6727
6728        // need to be focusable in touch mode if in touch mode
6729        if (isInTouchMode() &&
6730            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
6731               return false;
6732        }
6733
6734        // need to not have any parents blocking us
6735        if (hasAncestorThatBlocksDescendantFocus()) {
6736            return false;
6737        }
6738
6739        handleFocusGainInternal(direction, previouslyFocusedRect);
6740        return true;
6741    }
6742
6743    /**
6744     * Call this to try to give focus to a specific view or to one of its descendants. This is a
6745     * special variant of {@link #requestFocus() } that will allow views that are not focuable in
6746     * touch mode to request focus when they are touched.
6747     *
6748     * @return Whether this view or one of its descendants actually took focus.
6749     *
6750     * @see #isInTouchMode()
6751     *
6752     */
6753    public final boolean requestFocusFromTouch() {
6754        // Leave touch mode if we need to
6755        if (isInTouchMode()) {
6756            ViewRootImpl viewRoot = getViewRootImpl();
6757            if (viewRoot != null) {
6758                viewRoot.ensureTouchMode(false);
6759            }
6760        }
6761        return requestFocus(View.FOCUS_DOWN);
6762    }
6763
6764    /**
6765     * @return Whether any ancestor of this view blocks descendant focus.
6766     */
6767    private boolean hasAncestorThatBlocksDescendantFocus() {
6768        ViewParent ancestor = mParent;
6769        while (ancestor instanceof ViewGroup) {
6770            final ViewGroup vgAncestor = (ViewGroup) ancestor;
6771            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
6772                return true;
6773            } else {
6774                ancestor = vgAncestor.getParent();
6775            }
6776        }
6777        return false;
6778    }
6779
6780    /**
6781     * Gets the mode for determining whether this View is important for accessibility
6782     * which is if it fires accessibility events and if it is reported to
6783     * accessibility services that query the screen.
6784     *
6785     * @return The mode for determining whether a View is important for accessibility.
6786     *
6787     * @attr ref android.R.styleable#View_importantForAccessibility
6788     *
6789     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6790     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6791     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6792     */
6793    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
6794            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
6795            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
6796            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
6797        })
6798    public int getImportantForAccessibility() {
6799        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
6800                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
6801    }
6802
6803    /**
6804     * Sets how to determine whether this view is important for accessibility
6805     * which is if it fires accessibility events and if it is reported to
6806     * accessibility services that query the screen.
6807     *
6808     * @param mode How to determine whether this view is important for accessibility.
6809     *
6810     * @attr ref android.R.styleable#View_importantForAccessibility
6811     *
6812     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6813     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6814     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6815     */
6816    public void setImportantForAccessibility(int mode) {
6817        if (mode != getImportantForAccessibility()) {
6818            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
6819            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
6820                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
6821            notifyAccessibilityStateChanged();
6822        }
6823    }
6824
6825    /**
6826     * Gets whether this view should be exposed for accessibility.
6827     *
6828     * @return Whether the view is exposed for accessibility.
6829     *
6830     * @hide
6831     */
6832    public boolean isImportantForAccessibility() {
6833        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
6834                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
6835        switch (mode) {
6836            case IMPORTANT_FOR_ACCESSIBILITY_YES:
6837                return true;
6838            case IMPORTANT_FOR_ACCESSIBILITY_NO:
6839                return false;
6840            case IMPORTANT_FOR_ACCESSIBILITY_AUTO:
6841                return isActionableForAccessibility() || hasListenersForAccessibility()
6842                        || getAccessibilityNodeProvider() != null;
6843            default:
6844                throw new IllegalArgumentException("Unknow important for accessibility mode: "
6845                        + mode);
6846        }
6847    }
6848
6849    /**
6850     * Gets the parent for accessibility purposes. Note that the parent for
6851     * accessibility is not necessary the immediate parent. It is the first
6852     * predecessor that is important for accessibility.
6853     *
6854     * @return The parent for accessibility purposes.
6855     */
6856    public ViewParent getParentForAccessibility() {
6857        if (mParent instanceof View) {
6858            View parentView = (View) mParent;
6859            if (parentView.includeForAccessibility()) {
6860                return mParent;
6861            } else {
6862                return mParent.getParentForAccessibility();
6863            }
6864        }
6865        return null;
6866    }
6867
6868    /**
6869     * Adds the children of a given View for accessibility. Since some Views are
6870     * not important for accessibility the children for accessibility are not
6871     * necessarily direct children of the riew, rather they are the first level of
6872     * descendants important for accessibility.
6873     *
6874     * @param children The list of children for accessibility.
6875     */
6876    public void addChildrenForAccessibility(ArrayList<View> children) {
6877        if (includeForAccessibility()) {
6878            children.add(this);
6879        }
6880    }
6881
6882    /**
6883     * Whether to regard this view for accessibility. A view is regarded for
6884     * accessibility if it is important for accessibility or the querying
6885     * accessibility service has explicitly requested that view not
6886     * important for accessibility are regarded.
6887     *
6888     * @return Whether to regard the view for accessibility.
6889     *
6890     * @hide
6891     */
6892    public boolean includeForAccessibility() {
6893        if (mAttachInfo != null) {
6894            return (mAttachInfo.mAccessibilityFetchFlags
6895                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
6896                    || isImportantForAccessibility();
6897        }
6898        return false;
6899    }
6900
6901    /**
6902     * Returns whether the View is considered actionable from
6903     * accessibility perspective. Such view are important for
6904     * accessibility.
6905     *
6906     * @return True if the view is actionable for accessibility.
6907     *
6908     * @hide
6909     */
6910    public boolean isActionableForAccessibility() {
6911        return (isClickable() || isLongClickable() || isFocusable());
6912    }
6913
6914    /**
6915     * Returns whether the View has registered callbacks wich makes it
6916     * important for accessibility.
6917     *
6918     * @return True if the view is actionable for accessibility.
6919     */
6920    private boolean hasListenersForAccessibility() {
6921        ListenerInfo info = getListenerInfo();
6922        return mTouchDelegate != null || info.mOnKeyListener != null
6923                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
6924                || info.mOnHoverListener != null || info.mOnDragListener != null;
6925    }
6926
6927    /**
6928     * Notifies accessibility services that some view's important for
6929     * accessibility state has changed. Note that such notifications
6930     * are made at most once every
6931     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
6932     * to avoid unnecessary load to the system. Also once a view has
6933     * made a notifucation this method is a NOP until the notification has
6934     * been sent to clients.
6935     *
6936     * @hide
6937     *
6938     * TODO: Makse sure this method is called for any view state change
6939     *       that is interesting for accessilility purposes.
6940     */
6941    public void notifyAccessibilityStateChanged() {
6942        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
6943            return;
6944        }
6945        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_STATE_CHANGED) == 0) {
6946            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_STATE_CHANGED;
6947            if (mParent != null) {
6948                mParent.childAccessibilityStateChanged(this);
6949            }
6950        }
6951    }
6952
6953    /**
6954     * Reset the state indicating the this view has requested clients
6955     * interested in its accessibility state to be notified.
6956     *
6957     * @hide
6958     */
6959    public void resetAccessibilityStateChanged() {
6960        mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_STATE_CHANGED;
6961    }
6962
6963    /**
6964     * Performs the specified accessibility action on the view. For
6965     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
6966     * <p>
6967     * If an {@link AccessibilityDelegate} has been specified via calling
6968     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6969     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
6970     * is responsible for handling this call.
6971     * </p>
6972     *
6973     * @param action The action to perform.
6974     * @param arguments Optional action arguments.
6975     * @return Whether the action was performed.
6976     */
6977    public boolean performAccessibilityAction(int action, Bundle arguments) {
6978      if (mAccessibilityDelegate != null) {
6979          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
6980      } else {
6981          return performAccessibilityActionInternal(action, arguments);
6982      }
6983    }
6984
6985   /**
6986    * @see #performAccessibilityAction(int, Bundle)
6987    *
6988    * Note: Called from the default {@link AccessibilityDelegate}.
6989    */
6990    boolean performAccessibilityActionInternal(int action, Bundle arguments) {
6991        switch (action) {
6992            case AccessibilityNodeInfo.ACTION_CLICK: {
6993                if (isClickable()) {
6994                    performClick();
6995                    return true;
6996                }
6997            } break;
6998            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
6999                if (isLongClickable()) {
7000                    performLongClick();
7001                    return true;
7002                }
7003            } break;
7004            case AccessibilityNodeInfo.ACTION_FOCUS: {
7005                if (!hasFocus()) {
7006                    // Get out of touch mode since accessibility
7007                    // wants to move focus around.
7008                    getViewRootImpl().ensureTouchMode(false);
7009                    return requestFocus();
7010                }
7011            } break;
7012            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
7013                if (hasFocus()) {
7014                    clearFocus();
7015                    return !isFocused();
7016                }
7017            } break;
7018            case AccessibilityNodeInfo.ACTION_SELECT: {
7019                if (!isSelected()) {
7020                    setSelected(true);
7021                    return isSelected();
7022                }
7023            } break;
7024            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
7025                if (isSelected()) {
7026                    setSelected(false);
7027                    return !isSelected();
7028                }
7029            } break;
7030            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
7031                if (!isAccessibilityFocused()) {
7032                    return requestAccessibilityFocus();
7033                }
7034            } break;
7035            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
7036                if (isAccessibilityFocused()) {
7037                    clearAccessibilityFocus();
7038                    return true;
7039                }
7040            } break;
7041            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
7042                if (arguments != null) {
7043                    final int granularity = arguments.getInt(
7044                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
7045                    final boolean extendSelection = arguments.getBoolean(
7046                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
7047                    return nextAtGranularity(granularity, extendSelection);
7048                }
7049            } break;
7050            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
7051                if (arguments != null) {
7052                    final int granularity = arguments.getInt(
7053                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
7054                    final boolean extendSelection = arguments.getBoolean(
7055                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
7056                    return previousAtGranularity(granularity, extendSelection);
7057                }
7058            } break;
7059            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
7060                CharSequence text = getIterableTextForAccessibility();
7061                if (text == null) {
7062                    return false;
7063                }
7064                final int start = (arguments != null) ? arguments.getInt(
7065                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
7066                final int end = (arguments != null) ? arguments.getInt(
7067                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
7068                // Only cursor position can be specified (selection length == 0)
7069                if ((getAccessibilitySelectionStart() != start
7070                        || getAccessibilitySelectionEnd() != end)
7071                        && (start == end)) {
7072                    setAccessibilitySelection(start, end);
7073                    notifyAccessibilityStateChanged();
7074                    return true;
7075                }
7076            } break;
7077        }
7078        return false;
7079    }
7080
7081    private boolean nextAtGranularity(int granularity, boolean extendSelection) {
7082        CharSequence text = getIterableTextForAccessibility();
7083        if (text == null || text.length() == 0) {
7084            return false;
7085        }
7086        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
7087        if (iterator == null) {
7088            return false;
7089        }
7090        int current = getAccessibilitySelectionEnd();
7091        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
7092            current = 0;
7093        }
7094        final int[] range = iterator.following(current);
7095        if (range == null) {
7096            return false;
7097        }
7098        final int start = range[0];
7099        final int end = range[1];
7100        if (extendSelection && isAccessibilitySelectionExtendable()) {
7101            int selectionStart = getAccessibilitySelectionStart();
7102            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
7103                selectionStart = start;
7104            }
7105            setAccessibilitySelection(selectionStart, end);
7106        } else {
7107            setAccessibilitySelection(end, end);
7108        }
7109        sendViewTextTraversedAtGranularityEvent(
7110                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
7111                granularity, start, end);
7112        return true;
7113    }
7114
7115    private boolean previousAtGranularity(int granularity, boolean extendSelection) {
7116        CharSequence text = getIterableTextForAccessibility();
7117        if (text == null || text.length() == 0) {
7118            return false;
7119        }
7120        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
7121        if (iterator == null) {
7122            return false;
7123        }
7124        int current = getAccessibilitySelectionStart();
7125        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
7126            current = text.length();
7127        }
7128        final int[] range = iterator.preceding(current);
7129        if (range == null) {
7130            return false;
7131        }
7132        final int start = range[0];
7133        final int end = range[1];
7134        if (extendSelection && isAccessibilitySelectionExtendable()) {
7135            int selectionEnd = getAccessibilitySelectionEnd();
7136            if (selectionEnd == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
7137                selectionEnd = end;
7138            }
7139            setAccessibilitySelection(start, selectionEnd);
7140        } else {
7141            setAccessibilitySelection(start, start);
7142        }
7143        sendViewTextTraversedAtGranularityEvent(
7144                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
7145                granularity, start, end);
7146        return true;
7147    }
7148
7149    /**
7150     * Gets the text reported for accessibility purposes.
7151     *
7152     * @return The accessibility text.
7153     *
7154     * @hide
7155     */
7156    public CharSequence getIterableTextForAccessibility() {
7157        return getContentDescription();
7158    }
7159
7160    /**
7161     * Gets whether accessibility selection can be extended.
7162     *
7163     * @return If selection is extensible.
7164     *
7165     * @hide
7166     */
7167    public boolean isAccessibilitySelectionExtendable() {
7168        return false;
7169    }
7170
7171    /**
7172     * @hide
7173     */
7174    public int getAccessibilitySelectionStart() {
7175        return mAccessibilityCursorPosition;
7176    }
7177
7178    /**
7179     * @hide
7180     */
7181    public int getAccessibilitySelectionEnd() {
7182        return getAccessibilitySelectionStart();
7183    }
7184
7185    /**
7186     * @hide
7187     */
7188    public void setAccessibilitySelection(int start, int end) {
7189        if (start ==  end && end == mAccessibilityCursorPosition) {
7190            return;
7191        }
7192        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
7193            mAccessibilityCursorPosition = start;
7194        } else {
7195            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
7196        }
7197        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
7198    }
7199
7200    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
7201            int fromIndex, int toIndex) {
7202        if (mParent == null) {
7203            return;
7204        }
7205        AccessibilityEvent event = AccessibilityEvent.obtain(
7206                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
7207        onInitializeAccessibilityEvent(event);
7208        onPopulateAccessibilityEvent(event);
7209        event.setFromIndex(fromIndex);
7210        event.setToIndex(toIndex);
7211        event.setAction(action);
7212        event.setMovementGranularity(granularity);
7213        mParent.requestSendAccessibilityEvent(this, event);
7214    }
7215
7216    /**
7217     * @hide
7218     */
7219    public TextSegmentIterator getIteratorForGranularity(int granularity) {
7220        switch (granularity) {
7221            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
7222                CharSequence text = getIterableTextForAccessibility();
7223                if (text != null && text.length() > 0) {
7224                    CharacterTextSegmentIterator iterator =
7225                        CharacterTextSegmentIterator.getInstance(
7226                                mContext.getResources().getConfiguration().locale);
7227                    iterator.initialize(text.toString());
7228                    return iterator;
7229                }
7230            } break;
7231            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
7232                CharSequence text = getIterableTextForAccessibility();
7233                if (text != null && text.length() > 0) {
7234                    WordTextSegmentIterator iterator =
7235                        WordTextSegmentIterator.getInstance(
7236                                mContext.getResources().getConfiguration().locale);
7237                    iterator.initialize(text.toString());
7238                    return iterator;
7239                }
7240            } break;
7241            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
7242                CharSequence text = getIterableTextForAccessibility();
7243                if (text != null && text.length() > 0) {
7244                    ParagraphTextSegmentIterator iterator =
7245                        ParagraphTextSegmentIterator.getInstance();
7246                    iterator.initialize(text.toString());
7247                    return iterator;
7248                }
7249            } break;
7250        }
7251        return null;
7252    }
7253
7254    /**
7255     * @hide
7256     */
7257    public void dispatchStartTemporaryDetach() {
7258        clearAccessibilityFocus();
7259        clearDisplayList();
7260
7261        onStartTemporaryDetach();
7262    }
7263
7264    /**
7265     * This is called when a container is going to temporarily detach a child, with
7266     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
7267     * It will either be followed by {@link #onFinishTemporaryDetach()} or
7268     * {@link #onDetachedFromWindow()} when the container is done.
7269     */
7270    public void onStartTemporaryDetach() {
7271        removeUnsetPressCallback();
7272        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
7273    }
7274
7275    /**
7276     * @hide
7277     */
7278    public void dispatchFinishTemporaryDetach() {
7279        onFinishTemporaryDetach();
7280    }
7281
7282    /**
7283     * Called after {@link #onStartTemporaryDetach} when the container is done
7284     * changing the view.
7285     */
7286    public void onFinishTemporaryDetach() {
7287    }
7288
7289    /**
7290     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
7291     * for this view's window.  Returns null if the view is not currently attached
7292     * to the window.  Normally you will not need to use this directly, but
7293     * just use the standard high-level event callbacks like
7294     * {@link #onKeyDown(int, KeyEvent)}.
7295     */
7296    public KeyEvent.DispatcherState getKeyDispatcherState() {
7297        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
7298    }
7299
7300    /**
7301     * Dispatch a key event before it is processed by any input method
7302     * associated with the view hierarchy.  This can be used to intercept
7303     * key events in special situations before the IME consumes them; a
7304     * typical example would be handling the BACK key to update the application's
7305     * UI instead of allowing the IME to see it and close itself.
7306     *
7307     * @param event The key event to be dispatched.
7308     * @return True if the event was handled, false otherwise.
7309     */
7310    public boolean dispatchKeyEventPreIme(KeyEvent event) {
7311        return onKeyPreIme(event.getKeyCode(), event);
7312    }
7313
7314    /**
7315     * Dispatch a key event to the next view on the focus path. This path runs
7316     * from the top of the view tree down to the currently focused view. If this
7317     * view has focus, it will dispatch to itself. Otherwise it will dispatch
7318     * the next node down the focus path. This method also fires any key
7319     * listeners.
7320     *
7321     * @param event The key event to be dispatched.
7322     * @return True if the event was handled, false otherwise.
7323     */
7324    public boolean dispatchKeyEvent(KeyEvent event) {
7325        if (mInputEventConsistencyVerifier != null) {
7326            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
7327        }
7328
7329        // Give any attached key listener a first crack at the event.
7330        //noinspection SimplifiableIfStatement
7331        ListenerInfo li = mListenerInfo;
7332        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
7333                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
7334            return true;
7335        }
7336
7337        if (event.dispatch(this, mAttachInfo != null
7338                ? mAttachInfo.mKeyDispatchState : null, this)) {
7339            return true;
7340        }
7341
7342        if (mInputEventConsistencyVerifier != null) {
7343            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7344        }
7345        return false;
7346    }
7347
7348    /**
7349     * Dispatches a key shortcut event.
7350     *
7351     * @param event The key event to be dispatched.
7352     * @return True if the event was handled by the view, false otherwise.
7353     */
7354    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7355        return onKeyShortcut(event.getKeyCode(), event);
7356    }
7357
7358    /**
7359     * Pass the touch screen motion event down to the target view, or this
7360     * view if it is the target.
7361     *
7362     * @param event The motion event to be dispatched.
7363     * @return True if the event was handled by the view, false otherwise.
7364     */
7365    public boolean dispatchTouchEvent(MotionEvent event) {
7366        if (mInputEventConsistencyVerifier != null) {
7367            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
7368        }
7369
7370        if (onFilterTouchEventForSecurity(event)) {
7371            //noinspection SimplifiableIfStatement
7372            ListenerInfo li = mListenerInfo;
7373            if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
7374                    && li.mOnTouchListener.onTouch(this, event)) {
7375                return true;
7376            }
7377
7378            if (onTouchEvent(event)) {
7379                return true;
7380            }
7381        }
7382
7383        if (mInputEventConsistencyVerifier != null) {
7384            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7385        }
7386        return false;
7387    }
7388
7389    /**
7390     * Filter the touch event to apply security policies.
7391     *
7392     * @param event The motion event to be filtered.
7393     * @return True if the event should be dispatched, false if the event should be dropped.
7394     *
7395     * @see #getFilterTouchesWhenObscured
7396     */
7397    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
7398        //noinspection RedundantIfStatement
7399        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
7400                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
7401            // Window is obscured, drop this touch.
7402            return false;
7403        }
7404        return true;
7405    }
7406
7407    /**
7408     * Pass a trackball motion event down to the focused view.
7409     *
7410     * @param event The motion event to be dispatched.
7411     * @return True if the event was handled by the view, false otherwise.
7412     */
7413    public boolean dispatchTrackballEvent(MotionEvent event) {
7414        if (mInputEventConsistencyVerifier != null) {
7415            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
7416        }
7417
7418        return onTrackballEvent(event);
7419    }
7420
7421    /**
7422     * Dispatch a generic motion event.
7423     * <p>
7424     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
7425     * are delivered to the view under the pointer.  All other generic motion events are
7426     * delivered to the focused view.  Hover events are handled specially and are delivered
7427     * to {@link #onHoverEvent(MotionEvent)}.
7428     * </p>
7429     *
7430     * @param event The motion event to be dispatched.
7431     * @return True if the event was handled by the view, false otherwise.
7432     */
7433    public boolean dispatchGenericMotionEvent(MotionEvent event) {
7434        if (mInputEventConsistencyVerifier != null) {
7435            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
7436        }
7437
7438        final int source = event.getSource();
7439        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
7440            final int action = event.getAction();
7441            if (action == MotionEvent.ACTION_HOVER_ENTER
7442                    || action == MotionEvent.ACTION_HOVER_MOVE
7443                    || action == MotionEvent.ACTION_HOVER_EXIT) {
7444                if (dispatchHoverEvent(event)) {
7445                    return true;
7446                }
7447            } else if (dispatchGenericPointerEvent(event)) {
7448                return true;
7449            }
7450        } else if (dispatchGenericFocusedEvent(event)) {
7451            return true;
7452        }
7453
7454        if (dispatchGenericMotionEventInternal(event)) {
7455            return true;
7456        }
7457
7458        if (mInputEventConsistencyVerifier != null) {
7459            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7460        }
7461        return false;
7462    }
7463
7464    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
7465        //noinspection SimplifiableIfStatement
7466        ListenerInfo li = mListenerInfo;
7467        if (li != null && li.mOnGenericMotionListener != null
7468                && (mViewFlags & ENABLED_MASK) == ENABLED
7469                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
7470            return true;
7471        }
7472
7473        if (onGenericMotionEvent(event)) {
7474            return true;
7475        }
7476
7477        if (mInputEventConsistencyVerifier != null) {
7478            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7479        }
7480        return false;
7481    }
7482
7483    /**
7484     * Dispatch a hover event.
7485     * <p>
7486     * Do not call this method directly.
7487     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
7488     * </p>
7489     *
7490     * @param event The motion event to be dispatched.
7491     * @return True if the event was handled by the view, false otherwise.
7492     */
7493    protected boolean dispatchHoverEvent(MotionEvent event) {
7494        //noinspection SimplifiableIfStatement
7495        ListenerInfo li = mListenerInfo;
7496        if (li != null && li.mOnHoverListener != null
7497                && (mViewFlags & ENABLED_MASK) == ENABLED
7498                && li.mOnHoverListener.onHover(this, event)) {
7499            return true;
7500        }
7501
7502        return onHoverEvent(event);
7503    }
7504
7505    /**
7506     * Returns true if the view has a child to which it has recently sent
7507     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
7508     * it does not have a hovered child, then it must be the innermost hovered view.
7509     * @hide
7510     */
7511    protected boolean hasHoveredChild() {
7512        return false;
7513    }
7514
7515    /**
7516     * Dispatch a generic motion event to the view under the first pointer.
7517     * <p>
7518     * Do not call this method directly.
7519     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
7520     * </p>
7521     *
7522     * @param event The motion event to be dispatched.
7523     * @return True if the event was handled by the view, false otherwise.
7524     */
7525    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
7526        return false;
7527    }
7528
7529    /**
7530     * Dispatch a generic motion event to the currently focused view.
7531     * <p>
7532     * Do not call this method directly.
7533     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
7534     * </p>
7535     *
7536     * @param event The motion event to be dispatched.
7537     * @return True if the event was handled by the view, false otherwise.
7538     */
7539    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
7540        return false;
7541    }
7542
7543    /**
7544     * Dispatch a pointer event.
7545     * <p>
7546     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
7547     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
7548     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
7549     * and should not be expected to handle other pointing device features.
7550     * </p>
7551     *
7552     * @param event The motion event to be dispatched.
7553     * @return True if the event was handled by the view, false otherwise.
7554     * @hide
7555     */
7556    public final boolean dispatchPointerEvent(MotionEvent event) {
7557        if (event.isTouchEvent()) {
7558            return dispatchTouchEvent(event);
7559        } else {
7560            return dispatchGenericMotionEvent(event);
7561        }
7562    }
7563
7564    /**
7565     * Called when the window containing this view gains or loses window focus.
7566     * ViewGroups should override to route to their children.
7567     *
7568     * @param hasFocus True if the window containing this view now has focus,
7569     *        false otherwise.
7570     */
7571    public void dispatchWindowFocusChanged(boolean hasFocus) {
7572        onWindowFocusChanged(hasFocus);
7573    }
7574
7575    /**
7576     * Called when the window containing this view gains or loses focus.  Note
7577     * that this is separate from view focus: to receive key events, both
7578     * your view and its window must have focus.  If a window is displayed
7579     * on top of yours that takes input focus, then your own window will lose
7580     * focus but the view focus will remain unchanged.
7581     *
7582     * @param hasWindowFocus True if the window containing this view now has
7583     *        focus, false otherwise.
7584     */
7585    public void onWindowFocusChanged(boolean hasWindowFocus) {
7586        InputMethodManager imm = InputMethodManager.peekInstance();
7587        if (!hasWindowFocus) {
7588            if (isPressed()) {
7589                setPressed(false);
7590            }
7591            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
7592                imm.focusOut(this);
7593            }
7594            removeLongPressCallback();
7595            removeTapCallback();
7596            onFocusLost();
7597        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
7598            imm.focusIn(this);
7599        }
7600        refreshDrawableState();
7601    }
7602
7603    /**
7604     * Returns true if this view is in a window that currently has window focus.
7605     * Note that this is not the same as the view itself having focus.
7606     *
7607     * @return True if this view is in a window that currently has window focus.
7608     */
7609    public boolean hasWindowFocus() {
7610        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
7611    }
7612
7613    /**
7614     * Dispatch a view visibility change down the view hierarchy.
7615     * ViewGroups should override to route to their children.
7616     * @param changedView The view whose visibility changed. Could be 'this' or
7617     * an ancestor view.
7618     * @param visibility The new visibility of changedView: {@link #VISIBLE},
7619     * {@link #INVISIBLE} or {@link #GONE}.
7620     */
7621    protected void dispatchVisibilityChanged(View changedView, int visibility) {
7622        onVisibilityChanged(changedView, visibility);
7623    }
7624
7625    /**
7626     * Called when the visibility of the view or an ancestor of the view is changed.
7627     * @param changedView The view whose visibility changed. Could be 'this' or
7628     * an ancestor view.
7629     * @param visibility The new visibility of changedView: {@link #VISIBLE},
7630     * {@link #INVISIBLE} or {@link #GONE}.
7631     */
7632    protected void onVisibilityChanged(View changedView, int visibility) {
7633        if (visibility == VISIBLE) {
7634            if (mAttachInfo != null) {
7635                initialAwakenScrollBars();
7636            } else {
7637                mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
7638            }
7639        }
7640    }
7641
7642    /**
7643     * Dispatch a hint about whether this view is displayed. For instance, when
7644     * a View moves out of the screen, it might receives a display hint indicating
7645     * the view is not displayed. Applications should not <em>rely</em> on this hint
7646     * as there is no guarantee that they will receive one.
7647     *
7648     * @param hint A hint about whether or not this view is displayed:
7649     * {@link #VISIBLE} or {@link #INVISIBLE}.
7650     */
7651    public void dispatchDisplayHint(int hint) {
7652        onDisplayHint(hint);
7653    }
7654
7655    /**
7656     * Gives this view a hint about whether is displayed or not. For instance, when
7657     * a View moves out of the screen, it might receives a display hint indicating
7658     * the view is not displayed. Applications should not <em>rely</em> on this hint
7659     * as there is no guarantee that they will receive one.
7660     *
7661     * @param hint A hint about whether or not this view is displayed:
7662     * {@link #VISIBLE} or {@link #INVISIBLE}.
7663     */
7664    protected void onDisplayHint(int hint) {
7665    }
7666
7667    /**
7668     * Dispatch a window visibility change down the view hierarchy.
7669     * ViewGroups should override to route to their children.
7670     *
7671     * @param visibility The new visibility of the window.
7672     *
7673     * @see #onWindowVisibilityChanged(int)
7674     */
7675    public void dispatchWindowVisibilityChanged(int visibility) {
7676        onWindowVisibilityChanged(visibility);
7677    }
7678
7679    /**
7680     * Called when the window containing has change its visibility
7681     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
7682     * that this tells you whether or not your window is being made visible
7683     * to the window manager; this does <em>not</em> tell you whether or not
7684     * your window is obscured by other windows on the screen, even if it
7685     * is itself visible.
7686     *
7687     * @param visibility The new visibility of the window.
7688     */
7689    protected void onWindowVisibilityChanged(int visibility) {
7690        if (visibility == VISIBLE) {
7691            initialAwakenScrollBars();
7692        }
7693    }
7694
7695    /**
7696     * Returns the current visibility of the window this view is attached to
7697     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
7698     *
7699     * @return Returns the current visibility of the view's window.
7700     */
7701    public int getWindowVisibility() {
7702        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
7703    }
7704
7705    /**
7706     * Retrieve the overall visible display size in which the window this view is
7707     * attached to has been positioned in.  This takes into account screen
7708     * decorations above the window, for both cases where the window itself
7709     * is being position inside of them or the window is being placed under
7710     * then and covered insets are used for the window to position its content
7711     * inside.  In effect, this tells you the available area where content can
7712     * be placed and remain visible to users.
7713     *
7714     * <p>This function requires an IPC back to the window manager to retrieve
7715     * the requested information, so should not be used in performance critical
7716     * code like drawing.
7717     *
7718     * @param outRect Filled in with the visible display frame.  If the view
7719     * is not attached to a window, this is simply the raw display size.
7720     */
7721    public void getWindowVisibleDisplayFrame(Rect outRect) {
7722        if (mAttachInfo != null) {
7723            try {
7724                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
7725            } catch (RemoteException e) {
7726                return;
7727            }
7728            // XXX This is really broken, and probably all needs to be done
7729            // in the window manager, and we need to know more about whether
7730            // we want the area behind or in front of the IME.
7731            final Rect insets = mAttachInfo.mVisibleInsets;
7732            outRect.left += insets.left;
7733            outRect.top += insets.top;
7734            outRect.right -= insets.right;
7735            outRect.bottom -= insets.bottom;
7736            return;
7737        }
7738        // The view is not attached to a display so we don't have a context.
7739        // Make a best guess about the display size.
7740        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
7741        d.getRectSize(outRect);
7742    }
7743
7744    /**
7745     * Dispatch a notification about a resource configuration change down
7746     * the view hierarchy.
7747     * ViewGroups should override to route to their children.
7748     *
7749     * @param newConfig The new resource configuration.
7750     *
7751     * @see #onConfigurationChanged(android.content.res.Configuration)
7752     */
7753    public void dispatchConfigurationChanged(Configuration newConfig) {
7754        onConfigurationChanged(newConfig);
7755    }
7756
7757    /**
7758     * Called when the current configuration of the resources being used
7759     * by the application have changed.  You can use this to decide when
7760     * to reload resources that can changed based on orientation and other
7761     * configuration characterstics.  You only need to use this if you are
7762     * not relying on the normal {@link android.app.Activity} mechanism of
7763     * recreating the activity instance upon a configuration change.
7764     *
7765     * @param newConfig The new resource configuration.
7766     */
7767    protected void onConfigurationChanged(Configuration newConfig) {
7768    }
7769
7770    /**
7771     * Private function to aggregate all per-view attributes in to the view
7772     * root.
7773     */
7774    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7775        performCollectViewAttributes(attachInfo, visibility);
7776    }
7777
7778    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7779        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
7780            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
7781                attachInfo.mKeepScreenOn = true;
7782            }
7783            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
7784            ListenerInfo li = mListenerInfo;
7785            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
7786                attachInfo.mHasSystemUiListeners = true;
7787            }
7788        }
7789    }
7790
7791    void needGlobalAttributesUpdate(boolean force) {
7792        final AttachInfo ai = mAttachInfo;
7793        if (ai != null && !ai.mRecomputeGlobalAttributes) {
7794            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
7795                    || ai.mHasSystemUiListeners) {
7796                ai.mRecomputeGlobalAttributes = true;
7797            }
7798        }
7799    }
7800
7801    /**
7802     * Returns whether the device is currently in touch mode.  Touch mode is entered
7803     * once the user begins interacting with the device by touch, and affects various
7804     * things like whether focus is always visible to the user.
7805     *
7806     * @return Whether the device is in touch mode.
7807     */
7808    @ViewDebug.ExportedProperty
7809    public boolean isInTouchMode() {
7810        if (mAttachInfo != null) {
7811            return mAttachInfo.mInTouchMode;
7812        } else {
7813            return ViewRootImpl.isInTouchMode();
7814        }
7815    }
7816
7817    /**
7818     * Returns the context the view is running in, through which it can
7819     * access the current theme, resources, etc.
7820     *
7821     * @return The view's Context.
7822     */
7823    @ViewDebug.CapturedViewProperty
7824    public final Context getContext() {
7825        return mContext;
7826    }
7827
7828    /**
7829     * Handle a key event before it is processed by any input method
7830     * associated with the view hierarchy.  This can be used to intercept
7831     * key events in special situations before the IME consumes them; a
7832     * typical example would be handling the BACK key to update the application's
7833     * UI instead of allowing the IME to see it and close itself.
7834     *
7835     * @param keyCode The value in event.getKeyCode().
7836     * @param event Description of the key event.
7837     * @return If you handled the event, return true. If you want to allow the
7838     *         event to be handled by the next receiver, return false.
7839     */
7840    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
7841        return false;
7842    }
7843
7844    /**
7845     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
7846     * KeyEvent.Callback.onKeyDown()}: perform press of the view
7847     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
7848     * is released, if the view is enabled and clickable.
7849     *
7850     * <p>Key presses in software keyboards will generally NOT trigger this listener,
7851     * although some may elect to do so in some situations. Do not rely on this to
7852     * catch software key presses.
7853     *
7854     * @param keyCode A key code that represents the button pressed, from
7855     *                {@link android.view.KeyEvent}.
7856     * @param event   The KeyEvent object that defines the button action.
7857     */
7858    public boolean onKeyDown(int keyCode, KeyEvent event) {
7859        boolean result = false;
7860
7861        switch (keyCode) {
7862            case KeyEvent.KEYCODE_DPAD_CENTER:
7863            case KeyEvent.KEYCODE_ENTER: {
7864                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7865                    return true;
7866                }
7867                // Long clickable items don't necessarily have to be clickable
7868                if (((mViewFlags & CLICKABLE) == CLICKABLE ||
7869                        (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
7870                        (event.getRepeatCount() == 0)) {
7871                    setPressed(true);
7872                    checkForLongClick(0);
7873                    return true;
7874                }
7875                break;
7876            }
7877        }
7878        return result;
7879    }
7880
7881    /**
7882     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
7883     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
7884     * the event).
7885     * <p>Key presses in software keyboards will generally NOT trigger this listener,
7886     * although some may elect to do so in some situations. Do not rely on this to
7887     * catch software key presses.
7888     */
7889    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
7890        return false;
7891    }
7892
7893    /**
7894     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
7895     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
7896     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
7897     * {@link KeyEvent#KEYCODE_ENTER} is released.
7898     * <p>Key presses in software keyboards will generally NOT trigger this listener,
7899     * although some may elect to do so in some situations. Do not rely on this to
7900     * catch software key presses.
7901     *
7902     * @param keyCode A key code that represents the button pressed, from
7903     *                {@link android.view.KeyEvent}.
7904     * @param event   The KeyEvent object that defines the button action.
7905     */
7906    public boolean onKeyUp(int keyCode, KeyEvent event) {
7907        boolean result = false;
7908
7909        switch (keyCode) {
7910            case KeyEvent.KEYCODE_DPAD_CENTER:
7911            case KeyEvent.KEYCODE_ENTER: {
7912                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7913                    return true;
7914                }
7915                if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
7916                    setPressed(false);
7917
7918                    if (!mHasPerformedLongPress) {
7919                        // This is a tap, so remove the longpress check
7920                        removeLongPressCallback();
7921
7922                        result = performClick();
7923                    }
7924                }
7925                break;
7926            }
7927        }
7928        return result;
7929    }
7930
7931    /**
7932     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
7933     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
7934     * the event).
7935     * <p>Key presses in software keyboards will generally NOT trigger this listener,
7936     * although some may elect to do so in some situations. Do not rely on this to
7937     * catch software key presses.
7938     *
7939     * @param keyCode     A key code that represents the button pressed, from
7940     *                    {@link android.view.KeyEvent}.
7941     * @param repeatCount The number of times the action was made.
7942     * @param event       The KeyEvent object that defines the button action.
7943     */
7944    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
7945        return false;
7946    }
7947
7948    /**
7949     * Called on the focused view when a key shortcut event is not handled.
7950     * Override this method to implement local key shortcuts for the View.
7951     * Key shortcuts can also be implemented by setting the
7952     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
7953     *
7954     * @param keyCode The value in event.getKeyCode().
7955     * @param event Description of the key event.
7956     * @return If you handled the event, return true. If you want to allow the
7957     *         event to be handled by the next receiver, return false.
7958     */
7959    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
7960        return false;
7961    }
7962
7963    /**
7964     * Check whether the called view is a text editor, in which case it
7965     * would make sense to automatically display a soft input window for
7966     * it.  Subclasses should override this if they implement
7967     * {@link #onCreateInputConnection(EditorInfo)} to return true if
7968     * a call on that method would return a non-null InputConnection, and
7969     * they are really a first-class editor that the user would normally
7970     * start typing on when the go into a window containing your view.
7971     *
7972     * <p>The default implementation always returns false.  This does
7973     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
7974     * will not be called or the user can not otherwise perform edits on your
7975     * view; it is just a hint to the system that this is not the primary
7976     * purpose of this view.
7977     *
7978     * @return Returns true if this view is a text editor, else false.
7979     */
7980    public boolean onCheckIsTextEditor() {
7981        return false;
7982    }
7983
7984    /**
7985     * Create a new InputConnection for an InputMethod to interact
7986     * with the view.  The default implementation returns null, since it doesn't
7987     * support input methods.  You can override this to implement such support.
7988     * This is only needed for views that take focus and text input.
7989     *
7990     * <p>When implementing this, you probably also want to implement
7991     * {@link #onCheckIsTextEditor()} to indicate you will return a
7992     * non-null InputConnection.
7993     *
7994     * @param outAttrs Fill in with attribute information about the connection.
7995     */
7996    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
7997        return null;
7998    }
7999
8000    /**
8001     * Called by the {@link android.view.inputmethod.InputMethodManager}
8002     * when a view who is not the current
8003     * input connection target is trying to make a call on the manager.  The
8004     * default implementation returns false; you can override this to return
8005     * true for certain views if you are performing InputConnection proxying
8006     * to them.
8007     * @param view The View that is making the InputMethodManager call.
8008     * @return Return true to allow the call, false to reject.
8009     */
8010    public boolean checkInputConnectionProxy(View view) {
8011        return false;
8012    }
8013
8014    /**
8015     * Show the context menu for this view. It is not safe to hold on to the
8016     * menu after returning from this method.
8017     *
8018     * You should normally not overload this method. Overload
8019     * {@link #onCreateContextMenu(ContextMenu)} or define an
8020     * {@link OnCreateContextMenuListener} to add items to the context menu.
8021     *
8022     * @param menu The context menu to populate
8023     */
8024    public void createContextMenu(ContextMenu menu) {
8025        ContextMenuInfo menuInfo = getContextMenuInfo();
8026
8027        // Sets the current menu info so all items added to menu will have
8028        // my extra info set.
8029        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
8030
8031        onCreateContextMenu(menu);
8032        ListenerInfo li = mListenerInfo;
8033        if (li != null && li.mOnCreateContextMenuListener != null) {
8034            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
8035        }
8036
8037        // Clear the extra information so subsequent items that aren't mine don't
8038        // have my extra info.
8039        ((MenuBuilder)menu).setCurrentMenuInfo(null);
8040
8041        if (mParent != null) {
8042            mParent.createContextMenu(menu);
8043        }
8044    }
8045
8046    /**
8047     * Views should implement this if they have extra information to associate
8048     * with the context menu. The return result is supplied as a parameter to
8049     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
8050     * callback.
8051     *
8052     * @return Extra information about the item for which the context menu
8053     *         should be shown. This information will vary across different
8054     *         subclasses of View.
8055     */
8056    protected ContextMenuInfo getContextMenuInfo() {
8057        return null;
8058    }
8059
8060    /**
8061     * Views should implement this if the view itself is going to add items to
8062     * the context menu.
8063     *
8064     * @param menu the context menu to populate
8065     */
8066    protected void onCreateContextMenu(ContextMenu menu) {
8067    }
8068
8069    /**
8070     * Implement this method to handle trackball motion events.  The
8071     * <em>relative</em> movement of the trackball since the last event
8072     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
8073     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
8074     * that a movement of 1 corresponds to the user pressing one DPAD key (so
8075     * they will often be fractional values, representing the more fine-grained
8076     * movement information available from a trackball).
8077     *
8078     * @param event The motion event.
8079     * @return True if the event was handled, false otherwise.
8080     */
8081    public boolean onTrackballEvent(MotionEvent event) {
8082        return false;
8083    }
8084
8085    /**
8086     * Implement this method to handle generic motion events.
8087     * <p>
8088     * Generic motion events describe joystick movements, mouse hovers, track pad
8089     * touches, scroll wheel movements and other input events.  The
8090     * {@link MotionEvent#getSource() source} of the motion event specifies
8091     * the class of input that was received.  Implementations of this method
8092     * must examine the bits in the source before processing the event.
8093     * The following code example shows how this is done.
8094     * </p><p>
8095     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8096     * are delivered to the view under the pointer.  All other generic motion events are
8097     * delivered to the focused view.
8098     * </p>
8099     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
8100     *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
8101     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
8102     *             // process the joystick movement...
8103     *             return true;
8104     *         }
8105     *     }
8106     *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_POINTER) != 0) {
8107     *         switch (event.getAction()) {
8108     *             case MotionEvent.ACTION_HOVER_MOVE:
8109     *                 // process the mouse hover movement...
8110     *                 return true;
8111     *             case MotionEvent.ACTION_SCROLL:
8112     *                 // process the scroll wheel movement...
8113     *                 return true;
8114     *         }
8115     *     }
8116     *     return super.onGenericMotionEvent(event);
8117     * }</pre>
8118     *
8119     * @param event The generic motion event being processed.
8120     * @return True if the event was handled, false otherwise.
8121     */
8122    public boolean onGenericMotionEvent(MotionEvent event) {
8123        return false;
8124    }
8125
8126    /**
8127     * Implement this method to handle hover events.
8128     * <p>
8129     * This method is called whenever a pointer is hovering into, over, or out of the
8130     * bounds of a view and the view is not currently being touched.
8131     * Hover events are represented as pointer events with action
8132     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
8133     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
8134     * </p>
8135     * <ul>
8136     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
8137     * when the pointer enters the bounds of the view.</li>
8138     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
8139     * when the pointer has already entered the bounds of the view and has moved.</li>
8140     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
8141     * when the pointer has exited the bounds of the view or when the pointer is
8142     * about to go down due to a button click, tap, or similar user action that
8143     * causes the view to be touched.</li>
8144     * </ul>
8145     * <p>
8146     * The view should implement this method to return true to indicate that it is
8147     * handling the hover event, such as by changing its drawable state.
8148     * </p><p>
8149     * The default implementation calls {@link #setHovered} to update the hovered state
8150     * of the view when a hover enter or hover exit event is received, if the view
8151     * is enabled and is clickable.  The default implementation also sends hover
8152     * accessibility events.
8153     * </p>
8154     *
8155     * @param event The motion event that describes the hover.
8156     * @return True if the view handled the hover event.
8157     *
8158     * @see #isHovered
8159     * @see #setHovered
8160     * @see #onHoverChanged
8161     */
8162    public boolean onHoverEvent(MotionEvent event) {
8163        // The root view may receive hover (or touch) events that are outside the bounds of
8164        // the window.  This code ensures that we only send accessibility events for
8165        // hovers that are actually within the bounds of the root view.
8166        final int action = event.getActionMasked();
8167        if (!mSendingHoverAccessibilityEvents) {
8168            if ((action == MotionEvent.ACTION_HOVER_ENTER
8169                    || action == MotionEvent.ACTION_HOVER_MOVE)
8170                    && !hasHoveredChild()
8171                    && pointInView(event.getX(), event.getY())) {
8172                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
8173                mSendingHoverAccessibilityEvents = true;
8174            }
8175        } else {
8176            if (action == MotionEvent.ACTION_HOVER_EXIT
8177                    || (action == MotionEvent.ACTION_MOVE
8178                            && !pointInView(event.getX(), event.getY()))) {
8179                mSendingHoverAccessibilityEvents = false;
8180                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
8181                // If the window does not have input focus we take away accessibility
8182                // focus as soon as the user stop hovering over the view.
8183                if (mAttachInfo != null && !mAttachInfo.mHasWindowFocus) {
8184                    getViewRootImpl().setAccessibilityFocus(null, null);
8185                }
8186            }
8187        }
8188
8189        if (isHoverable()) {
8190            switch (action) {
8191                case MotionEvent.ACTION_HOVER_ENTER:
8192                    setHovered(true);
8193                    break;
8194                case MotionEvent.ACTION_HOVER_EXIT:
8195                    setHovered(false);
8196                    break;
8197            }
8198
8199            // Dispatch the event to onGenericMotionEvent before returning true.
8200            // This is to provide compatibility with existing applications that
8201            // handled HOVER_MOVE events in onGenericMotionEvent and that would
8202            // break because of the new default handling for hoverable views
8203            // in onHoverEvent.
8204            // Note that onGenericMotionEvent will be called by default when
8205            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
8206            return dispatchGenericMotionEventInternal(event);
8207        }
8208
8209        return false;
8210    }
8211
8212    /**
8213     * Returns true if the view should handle {@link #onHoverEvent}
8214     * by calling {@link #setHovered} to change its hovered state.
8215     *
8216     * @return True if the view is hoverable.
8217     */
8218    private boolean isHoverable() {
8219        final int viewFlags = mViewFlags;
8220        if ((viewFlags & ENABLED_MASK) == DISABLED) {
8221            return false;
8222        }
8223
8224        return (viewFlags & CLICKABLE) == CLICKABLE
8225                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8226    }
8227
8228    /**
8229     * Returns true if the view is currently hovered.
8230     *
8231     * @return True if the view is currently hovered.
8232     *
8233     * @see #setHovered
8234     * @see #onHoverChanged
8235     */
8236    @ViewDebug.ExportedProperty
8237    public boolean isHovered() {
8238        return (mPrivateFlags & PFLAG_HOVERED) != 0;
8239    }
8240
8241    /**
8242     * Sets whether the view is currently hovered.
8243     * <p>
8244     * Calling this method also changes the drawable state of the view.  This
8245     * enables the view to react to hover by using different drawable resources
8246     * to change its appearance.
8247     * </p><p>
8248     * The {@link #onHoverChanged} method is called when the hovered state changes.
8249     * </p>
8250     *
8251     * @param hovered True if the view is hovered.
8252     *
8253     * @see #isHovered
8254     * @see #onHoverChanged
8255     */
8256    public void setHovered(boolean hovered) {
8257        if (hovered) {
8258            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
8259                mPrivateFlags |= PFLAG_HOVERED;
8260                refreshDrawableState();
8261                onHoverChanged(true);
8262            }
8263        } else {
8264            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
8265                mPrivateFlags &= ~PFLAG_HOVERED;
8266                refreshDrawableState();
8267                onHoverChanged(false);
8268            }
8269        }
8270    }
8271
8272    /**
8273     * Implement this method to handle hover state changes.
8274     * <p>
8275     * This method is called whenever the hover state changes as a result of a
8276     * call to {@link #setHovered}.
8277     * </p>
8278     *
8279     * @param hovered The current hover state, as returned by {@link #isHovered}.
8280     *
8281     * @see #isHovered
8282     * @see #setHovered
8283     */
8284    public void onHoverChanged(boolean hovered) {
8285    }
8286
8287    /**
8288     * Implement this method to handle touch screen motion events.
8289     *
8290     * @param event The motion event.
8291     * @return True if the event was handled, false otherwise.
8292     */
8293    public boolean onTouchEvent(MotionEvent event) {
8294        final int viewFlags = mViewFlags;
8295
8296        if ((viewFlags & ENABLED_MASK) == DISABLED) {
8297            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
8298                setPressed(false);
8299            }
8300            // A disabled view that is clickable still consumes the touch
8301            // events, it just doesn't respond to them.
8302            return (((viewFlags & CLICKABLE) == CLICKABLE ||
8303                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
8304        }
8305
8306        if (mTouchDelegate != null) {
8307            if (mTouchDelegate.onTouchEvent(event)) {
8308                return true;
8309            }
8310        }
8311
8312        if (((viewFlags & CLICKABLE) == CLICKABLE ||
8313                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
8314            switch (event.getAction()) {
8315                case MotionEvent.ACTION_UP:
8316                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
8317                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
8318                        // take focus if we don't have it already and we should in
8319                        // touch mode.
8320                        boolean focusTaken = false;
8321                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
8322                            focusTaken = requestFocus();
8323                        }
8324
8325                        if (prepressed) {
8326                            // The button is being released before we actually
8327                            // showed it as pressed.  Make it show the pressed
8328                            // state now (before scheduling the click) to ensure
8329                            // the user sees it.
8330                            setPressed(true);
8331                       }
8332
8333                        if (!mHasPerformedLongPress) {
8334                            // This is a tap, so remove the longpress check
8335                            removeLongPressCallback();
8336
8337                            // Only perform take click actions if we were in the pressed state
8338                            if (!focusTaken) {
8339                                // Use a Runnable and post this rather than calling
8340                                // performClick directly. This lets other visual state
8341                                // of the view update before click actions start.
8342                                if (mPerformClick == null) {
8343                                    mPerformClick = new PerformClick();
8344                                }
8345                                if (!post(mPerformClick)) {
8346                                    performClick();
8347                                }
8348                            }
8349                        }
8350
8351                        if (mUnsetPressedState == null) {
8352                            mUnsetPressedState = new UnsetPressedState();
8353                        }
8354
8355                        if (prepressed) {
8356                            postDelayed(mUnsetPressedState,
8357                                    ViewConfiguration.getPressedStateDuration());
8358                        } else if (!post(mUnsetPressedState)) {
8359                            // If the post failed, unpress right now
8360                            mUnsetPressedState.run();
8361                        }
8362                        removeTapCallback();
8363                    }
8364                    break;
8365
8366                case MotionEvent.ACTION_DOWN:
8367                    mHasPerformedLongPress = false;
8368
8369                    if (performButtonActionOnTouchDown(event)) {
8370                        break;
8371                    }
8372
8373                    // Walk up the hierarchy to determine if we're inside a scrolling container.
8374                    boolean isInScrollingContainer = isInScrollingContainer();
8375
8376                    // For views inside a scrolling container, delay the pressed feedback for
8377                    // a short period in case this is a scroll.
8378                    if (isInScrollingContainer) {
8379                        mPrivateFlags |= PFLAG_PREPRESSED;
8380                        if (mPendingCheckForTap == null) {
8381                            mPendingCheckForTap = new CheckForTap();
8382                        }
8383                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
8384                    } else {
8385                        // Not inside a scrolling container, so show the feedback right away
8386                        setPressed(true);
8387                        checkForLongClick(0);
8388                    }
8389                    break;
8390
8391                case MotionEvent.ACTION_CANCEL:
8392                    setPressed(false);
8393                    removeTapCallback();
8394                    removeLongPressCallback();
8395                    break;
8396
8397                case MotionEvent.ACTION_MOVE:
8398                    final int x = (int) event.getX();
8399                    final int y = (int) event.getY();
8400
8401                    // Be lenient about moving outside of buttons
8402                    if (!pointInView(x, y, mTouchSlop)) {
8403                        // Outside button
8404                        removeTapCallback();
8405                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
8406                            // Remove any future long press/tap checks
8407                            removeLongPressCallback();
8408
8409                            setPressed(false);
8410                        }
8411                    }
8412                    break;
8413            }
8414            return true;
8415        }
8416
8417        return false;
8418    }
8419
8420    /**
8421     * @hide
8422     */
8423    public boolean isInScrollingContainer() {
8424        ViewParent p = getParent();
8425        while (p != null && p instanceof ViewGroup) {
8426            if (((ViewGroup) p).shouldDelayChildPressedState()) {
8427                return true;
8428            }
8429            p = p.getParent();
8430        }
8431        return false;
8432    }
8433
8434    /**
8435     * Remove the longpress detection timer.
8436     */
8437    private void removeLongPressCallback() {
8438        if (mPendingCheckForLongPress != null) {
8439          removeCallbacks(mPendingCheckForLongPress);
8440        }
8441    }
8442
8443    /**
8444     * Remove the pending click action
8445     */
8446    private void removePerformClickCallback() {
8447        if (mPerformClick != null) {
8448            removeCallbacks(mPerformClick);
8449        }
8450    }
8451
8452    /**
8453     * Remove the prepress detection timer.
8454     */
8455    private void removeUnsetPressCallback() {
8456        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
8457            setPressed(false);
8458            removeCallbacks(mUnsetPressedState);
8459        }
8460    }
8461
8462    /**
8463     * Remove the tap detection timer.
8464     */
8465    private void removeTapCallback() {
8466        if (mPendingCheckForTap != null) {
8467            mPrivateFlags &= ~PFLAG_PREPRESSED;
8468            removeCallbacks(mPendingCheckForTap);
8469        }
8470    }
8471
8472    /**
8473     * Cancels a pending long press.  Your subclass can use this if you
8474     * want the context menu to come up if the user presses and holds
8475     * at the same place, but you don't want it to come up if they press
8476     * and then move around enough to cause scrolling.
8477     */
8478    public void cancelLongPress() {
8479        removeLongPressCallback();
8480
8481        /*
8482         * The prepressed state handled by the tap callback is a display
8483         * construct, but the tap callback will post a long press callback
8484         * less its own timeout. Remove it here.
8485         */
8486        removeTapCallback();
8487    }
8488
8489    /**
8490     * Remove the pending callback for sending a
8491     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
8492     */
8493    private void removeSendViewScrolledAccessibilityEventCallback() {
8494        if (mSendViewScrolledAccessibilityEvent != null) {
8495            removeCallbacks(mSendViewScrolledAccessibilityEvent);
8496            mSendViewScrolledAccessibilityEvent.mIsPending = false;
8497        }
8498    }
8499
8500    /**
8501     * Sets the TouchDelegate for this View.
8502     */
8503    public void setTouchDelegate(TouchDelegate delegate) {
8504        mTouchDelegate = delegate;
8505    }
8506
8507    /**
8508     * Gets the TouchDelegate for this View.
8509     */
8510    public TouchDelegate getTouchDelegate() {
8511        return mTouchDelegate;
8512    }
8513
8514    /**
8515     * Set flags controlling behavior of this view.
8516     *
8517     * @param flags Constant indicating the value which should be set
8518     * @param mask Constant indicating the bit range that should be changed
8519     */
8520    void setFlags(int flags, int mask) {
8521        int old = mViewFlags;
8522        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
8523
8524        int changed = mViewFlags ^ old;
8525        if (changed == 0) {
8526            return;
8527        }
8528        int privateFlags = mPrivateFlags;
8529
8530        /* Check if the FOCUSABLE bit has changed */
8531        if (((changed & FOCUSABLE_MASK) != 0) &&
8532                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
8533            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
8534                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
8535                /* Give up focus if we are no longer focusable */
8536                clearFocus();
8537            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
8538                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
8539                /*
8540                 * Tell the view system that we are now available to take focus
8541                 * if no one else already has it.
8542                 */
8543                if (mParent != null) mParent.focusableViewAvailable(this);
8544            }
8545            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8546                notifyAccessibilityStateChanged();
8547            }
8548        }
8549
8550        if ((flags & VISIBILITY_MASK) == VISIBLE) {
8551            if ((changed & VISIBILITY_MASK) != 0) {
8552                /*
8553                 * If this view is becoming visible, invalidate it in case it changed while
8554                 * it was not visible. Marking it drawn ensures that the invalidation will
8555                 * go through.
8556                 */
8557                mPrivateFlags |= PFLAG_DRAWN;
8558                invalidate(true);
8559
8560                needGlobalAttributesUpdate(true);
8561
8562                // a view becoming visible is worth notifying the parent
8563                // about in case nothing has focus.  even if this specific view
8564                // isn't focusable, it may contain something that is, so let
8565                // the root view try to give this focus if nothing else does.
8566                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
8567                    mParent.focusableViewAvailable(this);
8568                }
8569            }
8570        }
8571
8572        /* Check if the GONE bit has changed */
8573        if ((changed & GONE) != 0) {
8574            needGlobalAttributesUpdate(false);
8575            requestLayout();
8576
8577            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
8578                if (hasFocus()) clearFocus();
8579                clearAccessibilityFocus();
8580                destroyDrawingCache();
8581                if (mParent instanceof View) {
8582                    // GONE views noop invalidation, so invalidate the parent
8583                    ((View) mParent).invalidate(true);
8584                }
8585                // Mark the view drawn to ensure that it gets invalidated properly the next
8586                // time it is visible and gets invalidated
8587                mPrivateFlags |= PFLAG_DRAWN;
8588            }
8589            if (mAttachInfo != null) {
8590                mAttachInfo.mViewVisibilityChanged = true;
8591            }
8592        }
8593
8594        /* Check if the VISIBLE bit has changed */
8595        if ((changed & INVISIBLE) != 0) {
8596            needGlobalAttributesUpdate(false);
8597            /*
8598             * If this view is becoming invisible, set the DRAWN flag so that
8599             * the next invalidate() will not be skipped.
8600             */
8601            mPrivateFlags |= PFLAG_DRAWN;
8602
8603            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
8604                // root view becoming invisible shouldn't clear focus and accessibility focus
8605                if (getRootView() != this) {
8606                    clearFocus();
8607                    clearAccessibilityFocus();
8608                }
8609            }
8610            if (mAttachInfo != null) {
8611                mAttachInfo.mViewVisibilityChanged = true;
8612            }
8613        }
8614
8615        if ((changed & VISIBILITY_MASK) != 0) {
8616            if (mParent instanceof ViewGroup) {
8617                ((ViewGroup) mParent).onChildVisibilityChanged(this,
8618                        (changed & VISIBILITY_MASK), (flags & VISIBILITY_MASK));
8619                ((View) mParent).invalidate(true);
8620            } else if (mParent != null) {
8621                mParent.invalidateChild(this, null);
8622            }
8623            dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
8624        }
8625
8626        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
8627            destroyDrawingCache();
8628        }
8629
8630        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
8631            destroyDrawingCache();
8632            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
8633            invalidateParentCaches();
8634        }
8635
8636        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
8637            destroyDrawingCache();
8638            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
8639        }
8640
8641        if ((changed & DRAW_MASK) != 0) {
8642            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
8643                if (mBackground != null) {
8644                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
8645                    mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
8646                } else {
8647                    mPrivateFlags |= PFLAG_SKIP_DRAW;
8648                }
8649            } else {
8650                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
8651            }
8652            requestLayout();
8653            invalidate(true);
8654        }
8655
8656        if ((changed & KEEP_SCREEN_ON) != 0) {
8657            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
8658                mParent.recomputeViewAttributes(this);
8659            }
8660        }
8661
8662        if (AccessibilityManager.getInstance(mContext).isEnabled()
8663                && ((changed & FOCUSABLE) != 0 || (changed & CLICKABLE) != 0
8664                        || (changed & LONG_CLICKABLE) != 0 || (changed & ENABLED) != 0)) {
8665            notifyAccessibilityStateChanged();
8666        }
8667    }
8668
8669    /**
8670     * Change the view's z order in the tree, so it's on top of other sibling
8671     * views
8672     */
8673    public void bringToFront() {
8674        if (mParent != null) {
8675            mParent.bringChildToFront(this);
8676        }
8677    }
8678
8679    /**
8680     * This is called in response to an internal scroll in this view (i.e., the
8681     * view scrolled its own contents). This is typically as a result of
8682     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
8683     * called.
8684     *
8685     * @param l Current horizontal scroll origin.
8686     * @param t Current vertical scroll origin.
8687     * @param oldl Previous horizontal scroll origin.
8688     * @param oldt Previous vertical scroll origin.
8689     */
8690    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
8691        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8692            postSendViewScrolledAccessibilityEventCallback();
8693        }
8694
8695        mBackgroundSizeChanged = true;
8696
8697        final AttachInfo ai = mAttachInfo;
8698        if (ai != null) {
8699            ai.mViewScrollChanged = true;
8700        }
8701    }
8702
8703    /**
8704     * Interface definition for a callback to be invoked when the layout bounds of a view
8705     * changes due to layout processing.
8706     */
8707    public interface OnLayoutChangeListener {
8708        /**
8709         * Called when the focus state of a view has changed.
8710         *
8711         * @param v The view whose state has changed.
8712         * @param left The new value of the view's left property.
8713         * @param top The new value of the view's top property.
8714         * @param right The new value of the view's right property.
8715         * @param bottom The new value of the view's bottom property.
8716         * @param oldLeft The previous value of the view's left property.
8717         * @param oldTop The previous value of the view's top property.
8718         * @param oldRight The previous value of the view's right property.
8719         * @param oldBottom The previous value of the view's bottom property.
8720         */
8721        void onLayoutChange(View v, int left, int top, int right, int bottom,
8722            int oldLeft, int oldTop, int oldRight, int oldBottom);
8723    }
8724
8725    /**
8726     * This is called during layout when the size of this view has changed. If
8727     * you were just added to the view hierarchy, you're called with the old
8728     * values of 0.
8729     *
8730     * @param w Current width of this view.
8731     * @param h Current height of this view.
8732     * @param oldw Old width of this view.
8733     * @param oldh Old height of this view.
8734     */
8735    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
8736    }
8737
8738    /**
8739     * Called by draw to draw the child views. This may be overridden
8740     * by derived classes to gain control just before its children are drawn
8741     * (but after its own view has been drawn).
8742     * @param canvas the canvas on which to draw the view
8743     */
8744    protected void dispatchDraw(Canvas canvas) {
8745
8746    }
8747
8748    /**
8749     * Gets the parent of this view. Note that the parent is a
8750     * ViewParent and not necessarily a View.
8751     *
8752     * @return Parent of this view.
8753     */
8754    public final ViewParent getParent() {
8755        return mParent;
8756    }
8757
8758    /**
8759     * Set the horizontal scrolled position of your view. This will cause a call to
8760     * {@link #onScrollChanged(int, int, int, int)} and the view will be
8761     * invalidated.
8762     * @param value the x position to scroll to
8763     */
8764    public void setScrollX(int value) {
8765        scrollTo(value, mScrollY);
8766    }
8767
8768    /**
8769     * Set the vertical scrolled position of your view. This will cause a call to
8770     * {@link #onScrollChanged(int, int, int, int)} and the view will be
8771     * invalidated.
8772     * @param value the y position to scroll to
8773     */
8774    public void setScrollY(int value) {
8775        scrollTo(mScrollX, value);
8776    }
8777
8778    /**
8779     * Return the scrolled left position of this view. This is the left edge of
8780     * the displayed part of your view. You do not need to draw any pixels
8781     * farther left, since those are outside of the frame of your view on
8782     * screen.
8783     *
8784     * @return The left edge of the displayed part of your view, in pixels.
8785     */
8786    public final int getScrollX() {
8787        return mScrollX;
8788    }
8789
8790    /**
8791     * Return the scrolled top position of this view. This is the top edge of
8792     * the displayed part of your view. You do not need to draw any pixels above
8793     * it, since those are outside of the frame of your view on screen.
8794     *
8795     * @return The top edge of the displayed part of your view, in pixels.
8796     */
8797    public final int getScrollY() {
8798        return mScrollY;
8799    }
8800
8801    /**
8802     * Return the width of the your view.
8803     *
8804     * @return The width of your view, in pixels.
8805     */
8806    @ViewDebug.ExportedProperty(category = "layout")
8807    public final int getWidth() {
8808        return mRight - mLeft;
8809    }
8810
8811    /**
8812     * Return the height of your view.
8813     *
8814     * @return The height of your view, in pixels.
8815     */
8816    @ViewDebug.ExportedProperty(category = "layout")
8817    public final int getHeight() {
8818        return mBottom - mTop;
8819    }
8820
8821    /**
8822     * Return the visible drawing bounds of your view. Fills in the output
8823     * rectangle with the values from getScrollX(), getScrollY(),
8824     * getWidth(), and getHeight(). These bounds do not account for any
8825     * transformation properties currently set on the view, such as
8826     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
8827     *
8828     * @param outRect The (scrolled) drawing bounds of the view.
8829     */
8830    public void getDrawingRect(Rect outRect) {
8831        outRect.left = mScrollX;
8832        outRect.top = mScrollY;
8833        outRect.right = mScrollX + (mRight - mLeft);
8834        outRect.bottom = mScrollY + (mBottom - mTop);
8835    }
8836
8837    /**
8838     * Like {@link #getMeasuredWidthAndState()}, but only returns the
8839     * raw width component (that is the result is masked by
8840     * {@link #MEASURED_SIZE_MASK}).
8841     *
8842     * @return The raw measured width of this view.
8843     */
8844    public final int getMeasuredWidth() {
8845        return mMeasuredWidth & MEASURED_SIZE_MASK;
8846    }
8847
8848    /**
8849     * Return the full width measurement information for this view as computed
8850     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
8851     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
8852     * This should be used during measurement and layout calculations only. Use
8853     * {@link #getWidth()} to see how wide a view is after layout.
8854     *
8855     * @return The measured width of this view as a bit mask.
8856     */
8857    public final int getMeasuredWidthAndState() {
8858        return mMeasuredWidth;
8859    }
8860
8861    /**
8862     * Like {@link #getMeasuredHeightAndState()}, but only returns the
8863     * raw width component (that is the result is masked by
8864     * {@link #MEASURED_SIZE_MASK}).
8865     *
8866     * @return The raw measured height of this view.
8867     */
8868    public final int getMeasuredHeight() {
8869        return mMeasuredHeight & MEASURED_SIZE_MASK;
8870    }
8871
8872    /**
8873     * Return the full height measurement information for this view as computed
8874     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
8875     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
8876     * This should be used during measurement and layout calculations only. Use
8877     * {@link #getHeight()} to see how wide a view is after layout.
8878     *
8879     * @return The measured width of this view as a bit mask.
8880     */
8881    public final int getMeasuredHeightAndState() {
8882        return mMeasuredHeight;
8883    }
8884
8885    /**
8886     * Return only the state bits of {@link #getMeasuredWidthAndState()}
8887     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
8888     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
8889     * and the height component is at the shifted bits
8890     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
8891     */
8892    public final int getMeasuredState() {
8893        return (mMeasuredWidth&MEASURED_STATE_MASK)
8894                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
8895                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
8896    }
8897
8898    /**
8899     * The transform matrix of this view, which is calculated based on the current
8900     * roation, scale, and pivot properties.
8901     *
8902     * @see #getRotation()
8903     * @see #getScaleX()
8904     * @see #getScaleY()
8905     * @see #getPivotX()
8906     * @see #getPivotY()
8907     * @return The current transform matrix for the view
8908     */
8909    public Matrix getMatrix() {
8910        if (mTransformationInfo != null) {
8911            updateMatrix();
8912            return mTransformationInfo.mMatrix;
8913        }
8914        return Matrix.IDENTITY_MATRIX;
8915    }
8916
8917    /**
8918     * Utility function to determine if the value is far enough away from zero to be
8919     * considered non-zero.
8920     * @param value A floating point value to check for zero-ness
8921     * @return whether the passed-in value is far enough away from zero to be considered non-zero
8922     */
8923    private static boolean nonzero(float value) {
8924        return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
8925    }
8926
8927    /**
8928     * Returns true if the transform matrix is the identity matrix.
8929     * Recomputes the matrix if necessary.
8930     *
8931     * @return True if the transform matrix is the identity matrix, false otherwise.
8932     */
8933    final boolean hasIdentityMatrix() {
8934        if (mTransformationInfo != null) {
8935            updateMatrix();
8936            return mTransformationInfo.mMatrixIsIdentity;
8937        }
8938        return true;
8939    }
8940
8941    void ensureTransformationInfo() {
8942        if (mTransformationInfo == null) {
8943            mTransformationInfo = new TransformationInfo();
8944        }
8945    }
8946
8947    /**
8948     * Recomputes the transform matrix if necessary.
8949     */
8950    private void updateMatrix() {
8951        final TransformationInfo info = mTransformationInfo;
8952        if (info == null) {
8953            return;
8954        }
8955        if (info.mMatrixDirty) {
8956            // transform-related properties have changed since the last time someone
8957            // asked for the matrix; recalculate it with the current values
8958
8959            // Figure out if we need to update the pivot point
8960            if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
8961                if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
8962                    info.mPrevWidth = mRight - mLeft;
8963                    info.mPrevHeight = mBottom - mTop;
8964                    info.mPivotX = info.mPrevWidth / 2f;
8965                    info.mPivotY = info.mPrevHeight / 2f;
8966                }
8967            }
8968            info.mMatrix.reset();
8969            if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
8970                info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
8971                info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
8972                info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
8973            } else {
8974                if (info.mCamera == null) {
8975                    info.mCamera = new Camera();
8976                    info.matrix3D = new Matrix();
8977                }
8978                info.mCamera.save();
8979                info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
8980                info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
8981                info.mCamera.getMatrix(info.matrix3D);
8982                info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
8983                info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
8984                        info.mPivotY + info.mTranslationY);
8985                info.mMatrix.postConcat(info.matrix3D);
8986                info.mCamera.restore();
8987            }
8988            info.mMatrixDirty = false;
8989            info.mMatrixIsIdentity = info.mMatrix.isIdentity();
8990            info.mInverseMatrixDirty = true;
8991        }
8992    }
8993
8994   /**
8995     * Utility method to retrieve the inverse of the current mMatrix property.
8996     * We cache the matrix to avoid recalculating it when transform properties
8997     * have not changed.
8998     *
8999     * @return The inverse of the current matrix of this view.
9000     */
9001    final Matrix getInverseMatrix() {
9002        final TransformationInfo info = mTransformationInfo;
9003        if (info != null) {
9004            updateMatrix();
9005            if (info.mInverseMatrixDirty) {
9006                if (info.mInverseMatrix == null) {
9007                    info.mInverseMatrix = new Matrix();
9008                }
9009                info.mMatrix.invert(info.mInverseMatrix);
9010                info.mInverseMatrixDirty = false;
9011            }
9012            return info.mInverseMatrix;
9013        }
9014        return Matrix.IDENTITY_MATRIX;
9015    }
9016
9017    /**
9018     * Gets the distance along the Z axis from the camera to this view.
9019     *
9020     * @see #setCameraDistance(float)
9021     *
9022     * @return The distance along the Z axis.
9023     */
9024    public float getCameraDistance() {
9025        ensureTransformationInfo();
9026        final float dpi = mResources.getDisplayMetrics().densityDpi;
9027        final TransformationInfo info = mTransformationInfo;
9028        if (info.mCamera == null) {
9029            info.mCamera = new Camera();
9030            info.matrix3D = new Matrix();
9031        }
9032        return -(info.mCamera.getLocationZ() * dpi);
9033    }
9034
9035    /**
9036     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
9037     * views are drawn) from the camera to this view. The camera's distance
9038     * affects 3D transformations, for instance rotations around the X and Y
9039     * axis. If the rotationX or rotationY properties are changed and this view is
9040     * large (more than half the size of the screen), it is recommended to always
9041     * use a camera distance that's greater than the height (X axis rotation) or
9042     * the width (Y axis rotation) of this view.</p>
9043     *
9044     * <p>The distance of the camera from the view plane can have an affect on the
9045     * perspective distortion of the view when it is rotated around the x or y axis.
9046     * For example, a large distance will result in a large viewing angle, and there
9047     * will not be much perspective distortion of the view as it rotates. A short
9048     * distance may cause much more perspective distortion upon rotation, and can
9049     * also result in some drawing artifacts if the rotated view ends up partially
9050     * behind the camera (which is why the recommendation is to use a distance at
9051     * least as far as the size of the view, if the view is to be rotated.)</p>
9052     *
9053     * <p>The distance is expressed in "depth pixels." The default distance depends
9054     * on the screen density. For instance, on a medium density display, the
9055     * default distance is 1280. On a high density display, the default distance
9056     * is 1920.</p>
9057     *
9058     * <p>If you want to specify a distance that leads to visually consistent
9059     * results across various densities, use the following formula:</p>
9060     * <pre>
9061     * float scale = context.getResources().getDisplayMetrics().density;
9062     * view.setCameraDistance(distance * scale);
9063     * </pre>
9064     *
9065     * <p>The density scale factor of a high density display is 1.5,
9066     * and 1920 = 1280 * 1.5.</p>
9067     *
9068     * @param distance The distance in "depth pixels", if negative the opposite
9069     *        value is used
9070     *
9071     * @see #setRotationX(float)
9072     * @see #setRotationY(float)
9073     */
9074    public void setCameraDistance(float distance) {
9075        invalidateViewProperty(true, false);
9076
9077        ensureTransformationInfo();
9078        final float dpi = mResources.getDisplayMetrics().densityDpi;
9079        final TransformationInfo info = mTransformationInfo;
9080        if (info.mCamera == null) {
9081            info.mCamera = new Camera();
9082            info.matrix3D = new Matrix();
9083        }
9084
9085        info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
9086        info.mMatrixDirty = true;
9087
9088        invalidateViewProperty(false, false);
9089        if (mDisplayList != null) {
9090            mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
9091        }
9092        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9093            // View was rejected last time it was drawn by its parent; this may have changed
9094            invalidateParentIfNeeded();
9095        }
9096    }
9097
9098    /**
9099     * The degrees that the view is rotated around the pivot point.
9100     *
9101     * @see #setRotation(float)
9102     * @see #getPivotX()
9103     * @see #getPivotY()
9104     *
9105     * @return The degrees of rotation.
9106     */
9107    @ViewDebug.ExportedProperty(category = "drawing")
9108    public float getRotation() {
9109        return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
9110    }
9111
9112    /**
9113     * Sets the degrees that the view is rotated around the pivot point. Increasing values
9114     * result in clockwise rotation.
9115     *
9116     * @param rotation The degrees of rotation.
9117     *
9118     * @see #getRotation()
9119     * @see #getPivotX()
9120     * @see #getPivotY()
9121     * @see #setRotationX(float)
9122     * @see #setRotationY(float)
9123     *
9124     * @attr ref android.R.styleable#View_rotation
9125     */
9126    public void setRotation(float rotation) {
9127        ensureTransformationInfo();
9128        final TransformationInfo info = mTransformationInfo;
9129        if (info.mRotation != rotation) {
9130            // Double-invalidation is necessary to capture view's old and new areas
9131            invalidateViewProperty(true, false);
9132            info.mRotation = rotation;
9133            info.mMatrixDirty = true;
9134            invalidateViewProperty(false, true);
9135            if (mDisplayList != null) {
9136                mDisplayList.setRotation(rotation);
9137            }
9138            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9139                // View was rejected last time it was drawn by its parent; this may have changed
9140                invalidateParentIfNeeded();
9141            }
9142        }
9143    }
9144
9145    /**
9146     * The degrees that the view is rotated around the vertical axis through the pivot point.
9147     *
9148     * @see #getPivotX()
9149     * @see #getPivotY()
9150     * @see #setRotationY(float)
9151     *
9152     * @return The degrees of Y rotation.
9153     */
9154    @ViewDebug.ExportedProperty(category = "drawing")
9155    public float getRotationY() {
9156        return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
9157    }
9158
9159    /**
9160     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
9161     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
9162     * down the y axis.
9163     *
9164     * When rotating large views, it is recommended to adjust the camera distance
9165     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
9166     *
9167     * @param rotationY The degrees of Y rotation.
9168     *
9169     * @see #getRotationY()
9170     * @see #getPivotX()
9171     * @see #getPivotY()
9172     * @see #setRotation(float)
9173     * @see #setRotationX(float)
9174     * @see #setCameraDistance(float)
9175     *
9176     * @attr ref android.R.styleable#View_rotationY
9177     */
9178    public void setRotationY(float rotationY) {
9179        ensureTransformationInfo();
9180        final TransformationInfo info = mTransformationInfo;
9181        if (info.mRotationY != rotationY) {
9182            invalidateViewProperty(true, false);
9183            info.mRotationY = rotationY;
9184            info.mMatrixDirty = true;
9185            invalidateViewProperty(false, true);
9186            if (mDisplayList != null) {
9187                mDisplayList.setRotationY(rotationY);
9188            }
9189            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9190                // View was rejected last time it was drawn by its parent; this may have changed
9191                invalidateParentIfNeeded();
9192            }
9193        }
9194    }
9195
9196    /**
9197     * The degrees that the view is rotated around the horizontal axis through the pivot point.
9198     *
9199     * @see #getPivotX()
9200     * @see #getPivotY()
9201     * @see #setRotationX(float)
9202     *
9203     * @return The degrees of X rotation.
9204     */
9205    @ViewDebug.ExportedProperty(category = "drawing")
9206    public float getRotationX() {
9207        return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
9208    }
9209
9210    /**
9211     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
9212     * Increasing values result in clockwise rotation from the viewpoint of looking down the
9213     * x axis.
9214     *
9215     * When rotating large views, it is recommended to adjust the camera distance
9216     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
9217     *
9218     * @param rotationX The degrees of X rotation.
9219     *
9220     * @see #getRotationX()
9221     * @see #getPivotX()
9222     * @see #getPivotY()
9223     * @see #setRotation(float)
9224     * @see #setRotationY(float)
9225     * @see #setCameraDistance(float)
9226     *
9227     * @attr ref android.R.styleable#View_rotationX
9228     */
9229    public void setRotationX(float rotationX) {
9230        ensureTransformationInfo();
9231        final TransformationInfo info = mTransformationInfo;
9232        if (info.mRotationX != rotationX) {
9233            invalidateViewProperty(true, false);
9234            info.mRotationX = rotationX;
9235            info.mMatrixDirty = true;
9236            invalidateViewProperty(false, true);
9237            if (mDisplayList != null) {
9238                mDisplayList.setRotationX(rotationX);
9239            }
9240            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9241                // View was rejected last time it was drawn by its parent; this may have changed
9242                invalidateParentIfNeeded();
9243            }
9244        }
9245    }
9246
9247    /**
9248     * The amount that the view is scaled in x around the pivot point, as a proportion of
9249     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
9250     *
9251     * <p>By default, this is 1.0f.
9252     *
9253     * @see #getPivotX()
9254     * @see #getPivotY()
9255     * @return The scaling factor.
9256     */
9257    @ViewDebug.ExportedProperty(category = "drawing")
9258    public float getScaleX() {
9259        return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
9260    }
9261
9262    /**
9263     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
9264     * the view's unscaled width. A value of 1 means that no scaling is applied.
9265     *
9266     * @param scaleX The scaling factor.
9267     * @see #getPivotX()
9268     * @see #getPivotY()
9269     *
9270     * @attr ref android.R.styleable#View_scaleX
9271     */
9272    public void setScaleX(float scaleX) {
9273        ensureTransformationInfo();
9274        final TransformationInfo info = mTransformationInfo;
9275        if (info.mScaleX != scaleX) {
9276            invalidateViewProperty(true, false);
9277            info.mScaleX = scaleX;
9278            info.mMatrixDirty = true;
9279            invalidateViewProperty(false, true);
9280            if (mDisplayList != null) {
9281                mDisplayList.setScaleX(scaleX);
9282            }
9283            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9284                // View was rejected last time it was drawn by its parent; this may have changed
9285                invalidateParentIfNeeded();
9286            }
9287        }
9288    }
9289
9290    /**
9291     * The amount that the view is scaled in y around the pivot point, as a proportion of
9292     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
9293     *
9294     * <p>By default, this is 1.0f.
9295     *
9296     * @see #getPivotX()
9297     * @see #getPivotY()
9298     * @return The scaling factor.
9299     */
9300    @ViewDebug.ExportedProperty(category = "drawing")
9301    public float getScaleY() {
9302        return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
9303    }
9304
9305    /**
9306     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
9307     * the view's unscaled width. A value of 1 means that no scaling is applied.
9308     *
9309     * @param scaleY The scaling factor.
9310     * @see #getPivotX()
9311     * @see #getPivotY()
9312     *
9313     * @attr ref android.R.styleable#View_scaleY
9314     */
9315    public void setScaleY(float scaleY) {
9316        ensureTransformationInfo();
9317        final TransformationInfo info = mTransformationInfo;
9318        if (info.mScaleY != scaleY) {
9319            invalidateViewProperty(true, false);
9320            info.mScaleY = scaleY;
9321            info.mMatrixDirty = true;
9322            invalidateViewProperty(false, true);
9323            if (mDisplayList != null) {
9324                mDisplayList.setScaleY(scaleY);
9325            }
9326            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9327                // View was rejected last time it was drawn by its parent; this may have changed
9328                invalidateParentIfNeeded();
9329            }
9330        }
9331    }
9332
9333    /**
9334     * The x location of the point around which the view is {@link #setRotation(float) rotated}
9335     * and {@link #setScaleX(float) scaled}.
9336     *
9337     * @see #getRotation()
9338     * @see #getScaleX()
9339     * @see #getScaleY()
9340     * @see #getPivotY()
9341     * @return The x location of the pivot point.
9342     *
9343     * @attr ref android.R.styleable#View_transformPivotX
9344     */
9345    @ViewDebug.ExportedProperty(category = "drawing")
9346    public float getPivotX() {
9347        return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
9348    }
9349
9350    /**
9351     * Sets the x location of the point around which the view is
9352     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
9353     * By default, the pivot point is centered on the object.
9354     * Setting this property disables this behavior and causes the view to use only the
9355     * explicitly set pivotX and pivotY values.
9356     *
9357     * @param pivotX The x location of the pivot point.
9358     * @see #getRotation()
9359     * @see #getScaleX()
9360     * @see #getScaleY()
9361     * @see #getPivotY()
9362     *
9363     * @attr ref android.R.styleable#View_transformPivotX
9364     */
9365    public void setPivotX(float pivotX) {
9366        ensureTransformationInfo();
9367        mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
9368        final TransformationInfo info = mTransformationInfo;
9369        if (info.mPivotX != pivotX) {
9370            invalidateViewProperty(true, false);
9371            info.mPivotX = pivotX;
9372            info.mMatrixDirty = true;
9373            invalidateViewProperty(false, true);
9374            if (mDisplayList != null) {
9375                mDisplayList.setPivotX(pivotX);
9376            }
9377            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9378                // View was rejected last time it was drawn by its parent; this may have changed
9379                invalidateParentIfNeeded();
9380            }
9381        }
9382    }
9383
9384    /**
9385     * The y location of the point around which the view is {@link #setRotation(float) rotated}
9386     * and {@link #setScaleY(float) scaled}.
9387     *
9388     * @see #getRotation()
9389     * @see #getScaleX()
9390     * @see #getScaleY()
9391     * @see #getPivotY()
9392     * @return The y location of the pivot point.
9393     *
9394     * @attr ref android.R.styleable#View_transformPivotY
9395     */
9396    @ViewDebug.ExportedProperty(category = "drawing")
9397    public float getPivotY() {
9398        return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
9399    }
9400
9401    /**
9402     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
9403     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
9404     * Setting this property disables this behavior and causes the view to use only the
9405     * explicitly set pivotX and pivotY values.
9406     *
9407     * @param pivotY The y location of the pivot point.
9408     * @see #getRotation()
9409     * @see #getScaleX()
9410     * @see #getScaleY()
9411     * @see #getPivotY()
9412     *
9413     * @attr ref android.R.styleable#View_transformPivotY
9414     */
9415    public void setPivotY(float pivotY) {
9416        ensureTransformationInfo();
9417        mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
9418        final TransformationInfo info = mTransformationInfo;
9419        if (info.mPivotY != pivotY) {
9420            invalidateViewProperty(true, false);
9421            info.mPivotY = pivotY;
9422            info.mMatrixDirty = true;
9423            invalidateViewProperty(false, true);
9424            if (mDisplayList != null) {
9425                mDisplayList.setPivotY(pivotY);
9426            }
9427            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9428                // View was rejected last time it was drawn by its parent; this may have changed
9429                invalidateParentIfNeeded();
9430            }
9431        }
9432    }
9433
9434    /**
9435     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
9436     * completely transparent and 1 means the view is completely opaque.
9437     *
9438     * <p>By default this is 1.0f.
9439     * @return The opacity of the view.
9440     */
9441    @ViewDebug.ExportedProperty(category = "drawing")
9442    public float getAlpha() {
9443        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
9444    }
9445
9446    /**
9447     * Returns whether this View has content which overlaps. This function, intended to be
9448     * overridden by specific View types, is an optimization when alpha is set on a view. If
9449     * rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer
9450     * and then composited it into place, which can be expensive. If the view has no overlapping
9451     * rendering, the view can draw each primitive with the appropriate alpha value directly.
9452     * An example of overlapping rendering is a TextView with a background image, such as a
9453     * Button. An example of non-overlapping rendering is a TextView with no background, or
9454     * an ImageView with only the foreground image. The default implementation returns true;
9455     * subclasses should override if they have cases which can be optimized.
9456     *
9457     * @return true if the content in this view might overlap, false otherwise.
9458     */
9459    public boolean hasOverlappingRendering() {
9460        return true;
9461    }
9462
9463    /**
9464     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
9465     * completely transparent and 1 means the view is completely opaque.</p>
9466     *
9467     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
9468     * responsible for applying the opacity itself. Otherwise, calling this method is
9469     * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
9470     * setting a hardware layer.</p>
9471     *
9472     * <p>Note that setting alpha to a translucent value (0 < alpha < 1) may have
9473     * performance implications. It is generally best to use the alpha property sparingly and
9474     * transiently, as in the case of fading animations.</p>
9475     *
9476     * @param alpha The opacity of the view.
9477     *
9478     * @see #setLayerType(int, android.graphics.Paint)
9479     *
9480     * @attr ref android.R.styleable#View_alpha
9481     */
9482    public void setAlpha(float alpha) {
9483        ensureTransformationInfo();
9484        if (mTransformationInfo.mAlpha != alpha) {
9485            mTransformationInfo.mAlpha = alpha;
9486            if (onSetAlpha((int) (alpha * 255))) {
9487                mPrivateFlags |= PFLAG_ALPHA_SET;
9488                // subclass is handling alpha - don't optimize rendering cache invalidation
9489                invalidateParentCaches();
9490                invalidate(true);
9491            } else {
9492                mPrivateFlags &= ~PFLAG_ALPHA_SET;
9493                invalidateViewProperty(true, false);
9494                if (mDisplayList != null) {
9495                    mDisplayList.setAlpha(alpha);
9496                }
9497            }
9498        }
9499    }
9500
9501    /**
9502     * Faster version of setAlpha() which performs the same steps except there are
9503     * no calls to invalidate(). The caller of this function should perform proper invalidation
9504     * on the parent and this object. The return value indicates whether the subclass handles
9505     * alpha (the return value for onSetAlpha()).
9506     *
9507     * @param alpha The new value for the alpha property
9508     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
9509     *         the new value for the alpha property is different from the old value
9510     */
9511    boolean setAlphaNoInvalidation(float alpha) {
9512        ensureTransformationInfo();
9513        if (mTransformationInfo.mAlpha != alpha) {
9514            mTransformationInfo.mAlpha = alpha;
9515            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
9516            if (subclassHandlesAlpha) {
9517                mPrivateFlags |= PFLAG_ALPHA_SET;
9518                return true;
9519            } else {
9520                mPrivateFlags &= ~PFLAG_ALPHA_SET;
9521                if (mDisplayList != null) {
9522                    mDisplayList.setAlpha(alpha);
9523                }
9524            }
9525        }
9526        return false;
9527    }
9528
9529    /**
9530     * Top position of this view relative to its parent.
9531     *
9532     * @return The top of this view, in pixels.
9533     */
9534    @ViewDebug.CapturedViewProperty
9535    public final int getTop() {
9536        return mTop;
9537    }
9538
9539    /**
9540     * Sets the top position of this view relative to its parent. This method is meant to be called
9541     * by the layout system and should not generally be called otherwise, because the property
9542     * may be changed at any time by the layout.
9543     *
9544     * @param top The top of this view, in pixels.
9545     */
9546    public final void setTop(int top) {
9547        if (top != mTop) {
9548            updateMatrix();
9549            final boolean matrixIsIdentity = mTransformationInfo == null
9550                    || mTransformationInfo.mMatrixIsIdentity;
9551            if (matrixIsIdentity) {
9552                if (mAttachInfo != null) {
9553                    int minTop;
9554                    int yLoc;
9555                    if (top < mTop) {
9556                        minTop = top;
9557                        yLoc = top - mTop;
9558                    } else {
9559                        minTop = mTop;
9560                        yLoc = 0;
9561                    }
9562                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
9563                }
9564            } else {
9565                // Double-invalidation is necessary to capture view's old and new areas
9566                invalidate(true);
9567            }
9568
9569            int width = mRight - mLeft;
9570            int oldHeight = mBottom - mTop;
9571
9572            mTop = top;
9573            if (mDisplayList != null) {
9574                mDisplayList.setTop(mTop);
9575            }
9576
9577            onSizeChanged(width, mBottom - mTop, width, oldHeight);
9578
9579            if (!matrixIsIdentity) {
9580                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9581                    // A change in dimension means an auto-centered pivot point changes, too
9582                    mTransformationInfo.mMatrixDirty = true;
9583                }
9584                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9585                invalidate(true);
9586            }
9587            mBackgroundSizeChanged = true;
9588            invalidateParentIfNeeded();
9589            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9590                // View was rejected last time it was drawn by its parent; this may have changed
9591                invalidateParentIfNeeded();
9592            }
9593        }
9594    }
9595
9596    /**
9597     * Bottom position of this view relative to its parent.
9598     *
9599     * @return The bottom of this view, in pixels.
9600     */
9601    @ViewDebug.CapturedViewProperty
9602    public final int getBottom() {
9603        return mBottom;
9604    }
9605
9606    /**
9607     * True if this view has changed since the last time being drawn.
9608     *
9609     * @return The dirty state of this view.
9610     */
9611    public boolean isDirty() {
9612        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
9613    }
9614
9615    /**
9616     * Sets the bottom position of this view relative to its parent. This method is meant to be
9617     * called by the layout system and should not generally be called otherwise, because the
9618     * property may be changed at any time by the layout.
9619     *
9620     * @param bottom The bottom of this view, in pixels.
9621     */
9622    public final void setBottom(int bottom) {
9623        if (bottom != mBottom) {
9624            updateMatrix();
9625            final boolean matrixIsIdentity = mTransformationInfo == null
9626                    || mTransformationInfo.mMatrixIsIdentity;
9627            if (matrixIsIdentity) {
9628                if (mAttachInfo != null) {
9629                    int maxBottom;
9630                    if (bottom < mBottom) {
9631                        maxBottom = mBottom;
9632                    } else {
9633                        maxBottom = bottom;
9634                    }
9635                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
9636                }
9637            } else {
9638                // Double-invalidation is necessary to capture view's old and new areas
9639                invalidate(true);
9640            }
9641
9642            int width = mRight - mLeft;
9643            int oldHeight = mBottom - mTop;
9644
9645            mBottom = bottom;
9646            if (mDisplayList != null) {
9647                mDisplayList.setBottom(mBottom);
9648            }
9649
9650            onSizeChanged(width, mBottom - mTop, width, oldHeight);
9651
9652            if (!matrixIsIdentity) {
9653                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9654                    // A change in dimension means an auto-centered pivot point changes, too
9655                    mTransformationInfo.mMatrixDirty = true;
9656                }
9657                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9658                invalidate(true);
9659            }
9660            mBackgroundSizeChanged = true;
9661            invalidateParentIfNeeded();
9662            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9663                // View was rejected last time it was drawn by its parent; this may have changed
9664                invalidateParentIfNeeded();
9665            }
9666        }
9667    }
9668
9669    /**
9670     * Left position of this view relative to its parent.
9671     *
9672     * @return The left edge of this view, in pixels.
9673     */
9674    @ViewDebug.CapturedViewProperty
9675    public final int getLeft() {
9676        return mLeft;
9677    }
9678
9679    /**
9680     * Sets the left position of this view relative to its parent. This method is meant to be called
9681     * by the layout system and should not generally be called otherwise, because the property
9682     * may be changed at any time by the layout.
9683     *
9684     * @param left The bottom of this view, in pixels.
9685     */
9686    public final void setLeft(int left) {
9687        if (left != mLeft) {
9688            updateMatrix();
9689            final boolean matrixIsIdentity = mTransformationInfo == null
9690                    || mTransformationInfo.mMatrixIsIdentity;
9691            if (matrixIsIdentity) {
9692                if (mAttachInfo != null) {
9693                    int minLeft;
9694                    int xLoc;
9695                    if (left < mLeft) {
9696                        minLeft = left;
9697                        xLoc = left - mLeft;
9698                    } else {
9699                        minLeft = mLeft;
9700                        xLoc = 0;
9701                    }
9702                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
9703                }
9704            } else {
9705                // Double-invalidation is necessary to capture view's old and new areas
9706                invalidate(true);
9707            }
9708
9709            int oldWidth = mRight - mLeft;
9710            int height = mBottom - mTop;
9711
9712            mLeft = left;
9713            if (mDisplayList != null) {
9714                mDisplayList.setLeft(left);
9715            }
9716
9717            onSizeChanged(mRight - mLeft, height, oldWidth, height);
9718
9719            if (!matrixIsIdentity) {
9720                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9721                    // A change in dimension means an auto-centered pivot point changes, too
9722                    mTransformationInfo.mMatrixDirty = true;
9723                }
9724                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9725                invalidate(true);
9726            }
9727            mBackgroundSizeChanged = true;
9728            invalidateParentIfNeeded();
9729            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9730                // View was rejected last time it was drawn by its parent; this may have changed
9731                invalidateParentIfNeeded();
9732            }
9733        }
9734    }
9735
9736    /**
9737     * Right position of this view relative to its parent.
9738     *
9739     * @return The right edge of this view, in pixels.
9740     */
9741    @ViewDebug.CapturedViewProperty
9742    public final int getRight() {
9743        return mRight;
9744    }
9745
9746    /**
9747     * Sets the right position of this view relative to its parent. This method is meant to be called
9748     * by the layout system and should not generally be called otherwise, because the property
9749     * may be changed at any time by the layout.
9750     *
9751     * @param right The bottom of this view, in pixels.
9752     */
9753    public final void setRight(int right) {
9754        if (right != mRight) {
9755            updateMatrix();
9756            final boolean matrixIsIdentity = mTransformationInfo == null
9757                    || mTransformationInfo.mMatrixIsIdentity;
9758            if (matrixIsIdentity) {
9759                if (mAttachInfo != null) {
9760                    int maxRight;
9761                    if (right < mRight) {
9762                        maxRight = mRight;
9763                    } else {
9764                        maxRight = right;
9765                    }
9766                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
9767                }
9768            } else {
9769                // Double-invalidation is necessary to capture view's old and new areas
9770                invalidate(true);
9771            }
9772
9773            int oldWidth = mRight - mLeft;
9774            int height = mBottom - mTop;
9775
9776            mRight = right;
9777            if (mDisplayList != null) {
9778                mDisplayList.setRight(mRight);
9779            }
9780
9781            onSizeChanged(mRight - mLeft, height, oldWidth, height);
9782
9783            if (!matrixIsIdentity) {
9784                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9785                    // A change in dimension means an auto-centered pivot point changes, too
9786                    mTransformationInfo.mMatrixDirty = true;
9787                }
9788                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9789                invalidate(true);
9790            }
9791            mBackgroundSizeChanged = true;
9792            invalidateParentIfNeeded();
9793            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9794                // View was rejected last time it was drawn by its parent; this may have changed
9795                invalidateParentIfNeeded();
9796            }
9797        }
9798    }
9799
9800    /**
9801     * The visual x position of this view, in pixels. This is equivalent to the
9802     * {@link #setTranslationX(float) translationX} property plus the current
9803     * {@link #getLeft() left} property.
9804     *
9805     * @return The visual x position of this view, in pixels.
9806     */
9807    @ViewDebug.ExportedProperty(category = "drawing")
9808    public float getX() {
9809        return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
9810    }
9811
9812    /**
9813     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
9814     * {@link #setTranslationX(float) translationX} property to be the difference between
9815     * the x value passed in and the current {@link #getLeft() left} property.
9816     *
9817     * @param x The visual x position of this view, in pixels.
9818     */
9819    public void setX(float x) {
9820        setTranslationX(x - mLeft);
9821    }
9822
9823    /**
9824     * The visual y position of this view, in pixels. This is equivalent to the
9825     * {@link #setTranslationY(float) translationY} property plus the current
9826     * {@link #getTop() top} property.
9827     *
9828     * @return The visual y position of this view, in pixels.
9829     */
9830    @ViewDebug.ExportedProperty(category = "drawing")
9831    public float getY() {
9832        return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
9833    }
9834
9835    /**
9836     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
9837     * {@link #setTranslationY(float) translationY} property to be the difference between
9838     * the y value passed in and the current {@link #getTop() top} property.
9839     *
9840     * @param y The visual y position of this view, in pixels.
9841     */
9842    public void setY(float y) {
9843        setTranslationY(y - mTop);
9844    }
9845
9846
9847    /**
9848     * The horizontal location of this view relative to its {@link #getLeft() left} position.
9849     * This position is post-layout, in addition to wherever the object's
9850     * layout placed it.
9851     *
9852     * @return The horizontal position of this view relative to its left position, in pixels.
9853     */
9854    @ViewDebug.ExportedProperty(category = "drawing")
9855    public float getTranslationX() {
9856        return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
9857    }
9858
9859    /**
9860     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
9861     * This effectively positions the object post-layout, in addition to wherever the object's
9862     * layout placed it.
9863     *
9864     * @param translationX The horizontal position of this view relative to its left position,
9865     * in pixels.
9866     *
9867     * @attr ref android.R.styleable#View_translationX
9868     */
9869    public void setTranslationX(float translationX) {
9870        ensureTransformationInfo();
9871        final TransformationInfo info = mTransformationInfo;
9872        if (info.mTranslationX != translationX) {
9873            // Double-invalidation is necessary to capture view's old and new areas
9874            invalidateViewProperty(true, false);
9875            info.mTranslationX = translationX;
9876            info.mMatrixDirty = true;
9877            invalidateViewProperty(false, true);
9878            if (mDisplayList != null) {
9879                mDisplayList.setTranslationX(translationX);
9880            }
9881            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9882                // View was rejected last time it was drawn by its parent; this may have changed
9883                invalidateParentIfNeeded();
9884            }
9885        }
9886    }
9887
9888    /**
9889     * The horizontal location of this view relative to its {@link #getTop() top} position.
9890     * This position is post-layout, in addition to wherever the object's
9891     * layout placed it.
9892     *
9893     * @return The vertical position of this view relative to its top position,
9894     * in pixels.
9895     */
9896    @ViewDebug.ExportedProperty(category = "drawing")
9897    public float getTranslationY() {
9898        return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
9899    }
9900
9901    /**
9902     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
9903     * This effectively positions the object post-layout, in addition to wherever the object's
9904     * layout placed it.
9905     *
9906     * @param translationY The vertical position of this view relative to its top position,
9907     * in pixels.
9908     *
9909     * @attr ref android.R.styleable#View_translationY
9910     */
9911    public void setTranslationY(float translationY) {
9912        ensureTransformationInfo();
9913        final TransformationInfo info = mTransformationInfo;
9914        if (info.mTranslationY != translationY) {
9915            invalidateViewProperty(true, false);
9916            info.mTranslationY = translationY;
9917            info.mMatrixDirty = true;
9918            invalidateViewProperty(false, true);
9919            if (mDisplayList != null) {
9920                mDisplayList.setTranslationY(translationY);
9921            }
9922            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9923                // View was rejected last time it was drawn by its parent; this may have changed
9924                invalidateParentIfNeeded();
9925            }
9926        }
9927    }
9928
9929    /**
9930     * Hit rectangle in parent's coordinates
9931     *
9932     * @param outRect The hit rectangle of the view.
9933     */
9934    public void getHitRect(Rect outRect) {
9935        updateMatrix();
9936        final TransformationInfo info = mTransformationInfo;
9937        if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
9938            outRect.set(mLeft, mTop, mRight, mBottom);
9939        } else {
9940            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
9941            tmpRect.set(-info.mPivotX, -info.mPivotY,
9942                    getWidth() - info.mPivotX, getHeight() - info.mPivotY);
9943            info.mMatrix.mapRect(tmpRect);
9944            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
9945                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
9946        }
9947    }
9948
9949    /**
9950     * Determines whether the given point, in local coordinates is inside the view.
9951     */
9952    /*package*/ final boolean pointInView(float localX, float localY) {
9953        return localX >= 0 && localX < (mRight - mLeft)
9954                && localY >= 0 && localY < (mBottom - mTop);
9955    }
9956
9957    /**
9958     * Utility method to determine whether the given point, in local coordinates,
9959     * is inside the view, where the area of the view is expanded by the slop factor.
9960     * This method is called while processing touch-move events to determine if the event
9961     * is still within the view.
9962     */
9963    private boolean pointInView(float localX, float localY, float slop) {
9964        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
9965                localY < ((mBottom - mTop) + slop);
9966    }
9967
9968    /**
9969     * When a view has focus and the user navigates away from it, the next view is searched for
9970     * starting from the rectangle filled in by this method.
9971     *
9972     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
9973     * of the view.  However, if your view maintains some idea of internal selection,
9974     * such as a cursor, or a selected row or column, you should override this method and
9975     * fill in a more specific rectangle.
9976     *
9977     * @param r The rectangle to fill in, in this view's coordinates.
9978     */
9979    public void getFocusedRect(Rect r) {
9980        getDrawingRect(r);
9981    }
9982
9983    /**
9984     * If some part of this view is not clipped by any of its parents, then
9985     * return that area in r in global (root) coordinates. To convert r to local
9986     * coordinates (without taking possible View rotations into account), offset
9987     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
9988     * If the view is completely clipped or translated out, return false.
9989     *
9990     * @param r If true is returned, r holds the global coordinates of the
9991     *        visible portion of this view.
9992     * @param globalOffset If true is returned, globalOffset holds the dx,dy
9993     *        between this view and its root. globalOffet may be null.
9994     * @return true if r is non-empty (i.e. part of the view is visible at the
9995     *         root level.
9996     */
9997    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
9998        int width = mRight - mLeft;
9999        int height = mBottom - mTop;
10000        if (width > 0 && height > 0) {
10001            r.set(0, 0, width, height);
10002            if (globalOffset != null) {
10003                globalOffset.set(-mScrollX, -mScrollY);
10004            }
10005            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
10006        }
10007        return false;
10008    }
10009
10010    public final boolean getGlobalVisibleRect(Rect r) {
10011        return getGlobalVisibleRect(r, null);
10012    }
10013
10014    public final boolean getLocalVisibleRect(Rect r) {
10015        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
10016        if (getGlobalVisibleRect(r, offset)) {
10017            r.offset(-offset.x, -offset.y); // make r local
10018            return true;
10019        }
10020        return false;
10021    }
10022
10023    /**
10024     * Offset this view's vertical location by the specified number of pixels.
10025     *
10026     * @param offset the number of pixels to offset the view by
10027     */
10028    public void offsetTopAndBottom(int offset) {
10029        if (offset != 0) {
10030            updateMatrix();
10031            final boolean matrixIsIdentity = mTransformationInfo == null
10032                    || mTransformationInfo.mMatrixIsIdentity;
10033            if (matrixIsIdentity) {
10034                if (mDisplayList != null) {
10035                    invalidateViewProperty(false, false);
10036                } else {
10037                    final ViewParent p = mParent;
10038                    if (p != null && mAttachInfo != null) {
10039                        final Rect r = mAttachInfo.mTmpInvalRect;
10040                        int minTop;
10041                        int maxBottom;
10042                        int yLoc;
10043                        if (offset < 0) {
10044                            minTop = mTop + offset;
10045                            maxBottom = mBottom;
10046                            yLoc = offset;
10047                        } else {
10048                            minTop = mTop;
10049                            maxBottom = mBottom + offset;
10050                            yLoc = 0;
10051                        }
10052                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
10053                        p.invalidateChild(this, r);
10054                    }
10055                }
10056            } else {
10057                invalidateViewProperty(false, false);
10058            }
10059
10060            mTop += offset;
10061            mBottom += offset;
10062            if (mDisplayList != null) {
10063                mDisplayList.offsetTopBottom(offset);
10064                invalidateViewProperty(false, false);
10065            } else {
10066                if (!matrixIsIdentity) {
10067                    invalidateViewProperty(false, true);
10068                }
10069                invalidateParentIfNeeded();
10070            }
10071        }
10072    }
10073
10074    /**
10075     * Offset this view's horizontal location by the specified amount of pixels.
10076     *
10077     * @param offset the numer of pixels to offset the view by
10078     */
10079    public void offsetLeftAndRight(int offset) {
10080        if (offset != 0) {
10081            updateMatrix();
10082            final boolean matrixIsIdentity = mTransformationInfo == null
10083                    || mTransformationInfo.mMatrixIsIdentity;
10084            if (matrixIsIdentity) {
10085                if (mDisplayList != null) {
10086                    invalidateViewProperty(false, false);
10087                } else {
10088                    final ViewParent p = mParent;
10089                    if (p != null && mAttachInfo != null) {
10090                        final Rect r = mAttachInfo.mTmpInvalRect;
10091                        int minLeft;
10092                        int maxRight;
10093                        if (offset < 0) {
10094                            minLeft = mLeft + offset;
10095                            maxRight = mRight;
10096                        } else {
10097                            minLeft = mLeft;
10098                            maxRight = mRight + offset;
10099                        }
10100                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
10101                        p.invalidateChild(this, r);
10102                    }
10103                }
10104            } else {
10105                invalidateViewProperty(false, false);
10106            }
10107
10108            mLeft += offset;
10109            mRight += offset;
10110            if (mDisplayList != null) {
10111                mDisplayList.offsetLeftRight(offset);
10112                invalidateViewProperty(false, false);
10113            } else {
10114                if (!matrixIsIdentity) {
10115                    invalidateViewProperty(false, true);
10116                }
10117                invalidateParentIfNeeded();
10118            }
10119        }
10120    }
10121
10122    /**
10123     * Get the LayoutParams associated with this view. All views should have
10124     * layout parameters. These supply parameters to the <i>parent</i> of this
10125     * view specifying how it should be arranged. There are many subclasses of
10126     * ViewGroup.LayoutParams, and these correspond to the different subclasses
10127     * of ViewGroup that are responsible for arranging their children.
10128     *
10129     * This method may return null if this View is not attached to a parent
10130     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
10131     * was not invoked successfully. When a View is attached to a parent
10132     * ViewGroup, this method must not return null.
10133     *
10134     * @return The LayoutParams associated with this view, or null if no
10135     *         parameters have been set yet
10136     */
10137    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
10138    public ViewGroup.LayoutParams getLayoutParams() {
10139        return mLayoutParams;
10140    }
10141
10142    /**
10143     * Set the layout parameters associated with this view. These supply
10144     * parameters to the <i>parent</i> of this view specifying how it should be
10145     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
10146     * correspond to the different subclasses of ViewGroup that are responsible
10147     * for arranging their children.
10148     *
10149     * @param params The layout parameters for this view, cannot be null
10150     */
10151    public void setLayoutParams(ViewGroup.LayoutParams params) {
10152        if (params == null) {
10153            throw new NullPointerException("Layout parameters cannot be null");
10154        }
10155        mLayoutParams = params;
10156        resolveLayoutParams();
10157        if (mParent instanceof ViewGroup) {
10158            ((ViewGroup) mParent).onSetLayoutParams(this, params);
10159        }
10160        requestLayout();
10161    }
10162
10163    /**
10164     * Resolve the layout parameters depending on the resolved layout direction
10165     *
10166     * @hide
10167     */
10168    public void resolveLayoutParams() {
10169        if (mLayoutParams != null) {
10170            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
10171        }
10172    }
10173
10174    /**
10175     * Set the scrolled position of your view. This will cause a call to
10176     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10177     * invalidated.
10178     * @param x the x position to scroll to
10179     * @param y the y position to scroll to
10180     */
10181    public void scrollTo(int x, int y) {
10182        if (mScrollX != x || mScrollY != y) {
10183            int oldX = mScrollX;
10184            int oldY = mScrollY;
10185            mScrollX = x;
10186            mScrollY = y;
10187            invalidateParentCaches();
10188            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
10189            if (!awakenScrollBars()) {
10190                postInvalidateOnAnimation();
10191            }
10192        }
10193    }
10194
10195    /**
10196     * Move the scrolled position of your view. This will cause a call to
10197     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10198     * invalidated.
10199     * @param x the amount of pixels to scroll by horizontally
10200     * @param y the amount of pixels to scroll by vertically
10201     */
10202    public void scrollBy(int x, int y) {
10203        scrollTo(mScrollX + x, mScrollY + y);
10204    }
10205
10206    /**
10207     * <p>Trigger the scrollbars to draw. When invoked this method starts an
10208     * animation to fade the scrollbars out after a default delay. If a subclass
10209     * provides animated scrolling, the start delay should equal the duration
10210     * of the scrolling animation.</p>
10211     *
10212     * <p>The animation starts only if at least one of the scrollbars is
10213     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
10214     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
10215     * this method returns true, and false otherwise. If the animation is
10216     * started, this method calls {@link #invalidate()}; in that case the
10217     * caller should not call {@link #invalidate()}.</p>
10218     *
10219     * <p>This method should be invoked every time a subclass directly updates
10220     * the scroll parameters.</p>
10221     *
10222     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
10223     * and {@link #scrollTo(int, int)}.</p>
10224     *
10225     * @return true if the animation is played, false otherwise
10226     *
10227     * @see #awakenScrollBars(int)
10228     * @see #scrollBy(int, int)
10229     * @see #scrollTo(int, int)
10230     * @see #isHorizontalScrollBarEnabled()
10231     * @see #isVerticalScrollBarEnabled()
10232     * @see #setHorizontalScrollBarEnabled(boolean)
10233     * @see #setVerticalScrollBarEnabled(boolean)
10234     */
10235    protected boolean awakenScrollBars() {
10236        return mScrollCache != null &&
10237                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
10238    }
10239
10240    /**
10241     * Trigger the scrollbars to draw.
10242     * This method differs from awakenScrollBars() only in its default duration.
10243     * initialAwakenScrollBars() will show the scroll bars for longer than
10244     * usual to give the user more of a chance to notice them.
10245     *
10246     * @return true if the animation is played, false otherwise.
10247     */
10248    private boolean initialAwakenScrollBars() {
10249        return mScrollCache != null &&
10250                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
10251    }
10252
10253    /**
10254     * <p>
10255     * Trigger the scrollbars to draw. When invoked this method starts an
10256     * animation to fade the scrollbars out after a fixed delay. If a subclass
10257     * provides animated scrolling, the start delay should equal the duration of
10258     * the scrolling animation.
10259     * </p>
10260     *
10261     * <p>
10262     * The animation starts only if at least one of the scrollbars is enabled,
10263     * as specified by {@link #isHorizontalScrollBarEnabled()} and
10264     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
10265     * this method returns true, and false otherwise. If the animation is
10266     * started, this method calls {@link #invalidate()}; in that case the caller
10267     * should not call {@link #invalidate()}.
10268     * </p>
10269     *
10270     * <p>
10271     * This method should be invoked everytime a subclass directly updates the
10272     * scroll parameters.
10273     * </p>
10274     *
10275     * @param startDelay the delay, in milliseconds, after which the animation
10276     *        should start; when the delay is 0, the animation starts
10277     *        immediately
10278     * @return true if the animation is played, false otherwise
10279     *
10280     * @see #scrollBy(int, int)
10281     * @see #scrollTo(int, int)
10282     * @see #isHorizontalScrollBarEnabled()
10283     * @see #isVerticalScrollBarEnabled()
10284     * @see #setHorizontalScrollBarEnabled(boolean)
10285     * @see #setVerticalScrollBarEnabled(boolean)
10286     */
10287    protected boolean awakenScrollBars(int startDelay) {
10288        return awakenScrollBars(startDelay, true);
10289    }
10290
10291    /**
10292     * <p>
10293     * Trigger the scrollbars to draw. When invoked this method starts an
10294     * animation to fade the scrollbars out after a fixed delay. If a subclass
10295     * provides animated scrolling, the start delay should equal the duration of
10296     * the scrolling animation.
10297     * </p>
10298     *
10299     * <p>
10300     * The animation starts only if at least one of the scrollbars is enabled,
10301     * as specified by {@link #isHorizontalScrollBarEnabled()} and
10302     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
10303     * this method returns true, and false otherwise. If the animation is
10304     * started, this method calls {@link #invalidate()} if the invalidate parameter
10305     * is set to true; in that case the caller
10306     * should not call {@link #invalidate()}.
10307     * </p>
10308     *
10309     * <p>
10310     * This method should be invoked everytime a subclass directly updates the
10311     * scroll parameters.
10312     * </p>
10313     *
10314     * @param startDelay the delay, in milliseconds, after which the animation
10315     *        should start; when the delay is 0, the animation starts
10316     *        immediately
10317     *
10318     * @param invalidate Wheter this method should call invalidate
10319     *
10320     * @return true if the animation is played, false otherwise
10321     *
10322     * @see #scrollBy(int, int)
10323     * @see #scrollTo(int, int)
10324     * @see #isHorizontalScrollBarEnabled()
10325     * @see #isVerticalScrollBarEnabled()
10326     * @see #setHorizontalScrollBarEnabled(boolean)
10327     * @see #setVerticalScrollBarEnabled(boolean)
10328     */
10329    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
10330        final ScrollabilityCache scrollCache = mScrollCache;
10331
10332        if (scrollCache == null || !scrollCache.fadeScrollBars) {
10333            return false;
10334        }
10335
10336        if (scrollCache.scrollBar == null) {
10337            scrollCache.scrollBar = new ScrollBarDrawable();
10338        }
10339
10340        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
10341
10342            if (invalidate) {
10343                // Invalidate to show the scrollbars
10344                postInvalidateOnAnimation();
10345            }
10346
10347            if (scrollCache.state == ScrollabilityCache.OFF) {
10348                // FIXME: this is copied from WindowManagerService.
10349                // We should get this value from the system when it
10350                // is possible to do so.
10351                final int KEY_REPEAT_FIRST_DELAY = 750;
10352                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
10353            }
10354
10355            // Tell mScrollCache when we should start fading. This may
10356            // extend the fade start time if one was already scheduled
10357            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
10358            scrollCache.fadeStartTime = fadeStartTime;
10359            scrollCache.state = ScrollabilityCache.ON;
10360
10361            // Schedule our fader to run, unscheduling any old ones first
10362            if (mAttachInfo != null) {
10363                mAttachInfo.mHandler.removeCallbacks(scrollCache);
10364                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
10365            }
10366
10367            return true;
10368        }
10369
10370        return false;
10371    }
10372
10373    /**
10374     * Do not invalidate views which are not visible and which are not running an animation. They
10375     * will not get drawn and they should not set dirty flags as if they will be drawn
10376     */
10377    private boolean skipInvalidate() {
10378        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
10379                (!(mParent instanceof ViewGroup) ||
10380                        !((ViewGroup) mParent).isViewTransitioning(this));
10381    }
10382    /**
10383     * Mark the area defined by dirty as needing to be drawn. If the view is
10384     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
10385     * in the future. This must be called from a UI thread. To call from a non-UI
10386     * thread, call {@link #postInvalidate()}.
10387     *
10388     * WARNING: This method is destructive to dirty.
10389     * @param dirty the rectangle representing the bounds of the dirty region
10390     */
10391    public void invalidate(Rect dirty) {
10392        if (skipInvalidate()) {
10393            return;
10394        }
10395        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10396                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
10397                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
10398            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10399            mPrivateFlags |= PFLAG_INVALIDATED;
10400            mPrivateFlags |= PFLAG_DIRTY;
10401            final ViewParent p = mParent;
10402            final AttachInfo ai = mAttachInfo;
10403            //noinspection PointlessBooleanExpression,ConstantConditions
10404            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10405                if (p != null && ai != null && ai.mHardwareAccelerated) {
10406                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10407                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
10408                    p.invalidateChild(this, null);
10409                    return;
10410                }
10411            }
10412            if (p != null && ai != null) {
10413                final int scrollX = mScrollX;
10414                final int scrollY = mScrollY;
10415                final Rect r = ai.mTmpInvalRect;
10416                r.set(dirty.left - scrollX, dirty.top - scrollY,
10417                        dirty.right - scrollX, dirty.bottom - scrollY);
10418                mParent.invalidateChild(this, r);
10419            }
10420        }
10421    }
10422
10423    /**
10424     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn.
10425     * The coordinates of the dirty rect are relative to the view.
10426     * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
10427     * will be called at some point in the future. This must be called from
10428     * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
10429     * @param l the left position of the dirty region
10430     * @param t the top position of the dirty region
10431     * @param r the right position of the dirty region
10432     * @param b the bottom position of the dirty region
10433     */
10434    public void invalidate(int l, int t, int r, int b) {
10435        if (skipInvalidate()) {
10436            return;
10437        }
10438        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10439                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
10440                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
10441            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10442            mPrivateFlags |= PFLAG_INVALIDATED;
10443            mPrivateFlags |= PFLAG_DIRTY;
10444            final ViewParent p = mParent;
10445            final AttachInfo ai = mAttachInfo;
10446            //noinspection PointlessBooleanExpression,ConstantConditions
10447            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10448                if (p != null && ai != null && ai.mHardwareAccelerated) {
10449                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10450                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
10451                    p.invalidateChild(this, null);
10452                    return;
10453                }
10454            }
10455            if (p != null && ai != null && l < r && t < b) {
10456                final int scrollX = mScrollX;
10457                final int scrollY = mScrollY;
10458                final Rect tmpr = ai.mTmpInvalRect;
10459                tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
10460                p.invalidateChild(this, tmpr);
10461            }
10462        }
10463    }
10464
10465    /**
10466     * Invalidate the whole view. If the view is visible,
10467     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
10468     * the future. This must be called from a UI thread. To call from a non-UI thread,
10469     * call {@link #postInvalidate()}.
10470     */
10471    public void invalidate() {
10472        invalidate(true);
10473    }
10474
10475    /**
10476     * This is where the invalidate() work actually happens. A full invalidate()
10477     * causes the drawing cache to be invalidated, but this function can be called with
10478     * invalidateCache set to false to skip that invalidation step for cases that do not
10479     * need it (for example, a component that remains at the same dimensions with the same
10480     * content).
10481     *
10482     * @param invalidateCache Whether the drawing cache for this view should be invalidated as
10483     * well. This is usually true for a full invalidate, but may be set to false if the
10484     * View's contents or dimensions have not changed.
10485     */
10486    void invalidate(boolean invalidateCache) {
10487        if (skipInvalidate()) {
10488            return;
10489        }
10490        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10491                (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
10492                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
10493            mLastIsOpaque = isOpaque();
10494            mPrivateFlags &= ~PFLAG_DRAWN;
10495            mPrivateFlags |= PFLAG_DIRTY;
10496            if (invalidateCache) {
10497                mPrivateFlags |= PFLAG_INVALIDATED;
10498                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10499            }
10500            final AttachInfo ai = mAttachInfo;
10501            final ViewParent p = mParent;
10502            //noinspection PointlessBooleanExpression,ConstantConditions
10503            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10504                if (p != null && ai != null && ai.mHardwareAccelerated) {
10505                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10506                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
10507                    p.invalidateChild(this, null);
10508                    return;
10509                }
10510            }
10511
10512            if (p != null && ai != null) {
10513                final Rect r = ai.mTmpInvalRect;
10514                r.set(0, 0, mRight - mLeft, mBottom - mTop);
10515                // Don't call invalidate -- we don't want to internally scroll
10516                // our own bounds
10517                p.invalidateChild(this, r);
10518            }
10519        }
10520    }
10521
10522    /**
10523     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
10524     * set any flags or handle all of the cases handled by the default invalidation methods.
10525     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
10526     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
10527     * walk up the hierarchy, transforming the dirty rect as necessary.
10528     *
10529     * The method also handles normal invalidation logic if display list properties are not
10530     * being used in this view. The invalidateParent and forceRedraw flags are used by that
10531     * backup approach, to handle these cases used in the various property-setting methods.
10532     *
10533     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
10534     * are not being used in this view
10535     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
10536     * list properties are not being used in this view
10537     */
10538    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
10539        if (mDisplayList == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) {
10540            if (invalidateParent) {
10541                invalidateParentCaches();
10542            }
10543            if (forceRedraw) {
10544                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10545            }
10546            invalidate(false);
10547        } else {
10548            final AttachInfo ai = mAttachInfo;
10549            final ViewParent p = mParent;
10550            if (p != null && ai != null) {
10551                final Rect r = ai.mTmpInvalRect;
10552                r.set(0, 0, mRight - mLeft, mBottom - mTop);
10553                if (mParent instanceof ViewGroup) {
10554                    ((ViewGroup) mParent).invalidateChildFast(this, r);
10555                } else {
10556                    mParent.invalidateChild(this, r);
10557                }
10558            }
10559        }
10560    }
10561
10562    /**
10563     * Utility method to transform a given Rect by the current matrix of this view.
10564     */
10565    void transformRect(final Rect rect) {
10566        if (!getMatrix().isIdentity()) {
10567            RectF boundingRect = mAttachInfo.mTmpTransformRect;
10568            boundingRect.set(rect);
10569            getMatrix().mapRect(boundingRect);
10570            rect.set((int) (boundingRect.left - 0.5f),
10571                    (int) (boundingRect.top - 0.5f),
10572                    (int) (boundingRect.right + 0.5f),
10573                    (int) (boundingRect.bottom + 0.5f));
10574        }
10575    }
10576
10577    /**
10578     * Used to indicate that the parent of this view should clear its caches. This functionality
10579     * is used to force the parent to rebuild its display list (when hardware-accelerated),
10580     * which is necessary when various parent-managed properties of the view change, such as
10581     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
10582     * clears the parent caches and does not causes an invalidate event.
10583     *
10584     * @hide
10585     */
10586    protected void invalidateParentCaches() {
10587        if (mParent instanceof View) {
10588            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
10589        }
10590    }
10591
10592    /**
10593     * Used to indicate that the parent of this view should be invalidated. This functionality
10594     * is used to force the parent to rebuild its display list (when hardware-accelerated),
10595     * which is necessary when various parent-managed properties of the view change, such as
10596     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
10597     * an invalidation event to the parent.
10598     *
10599     * @hide
10600     */
10601    protected void invalidateParentIfNeeded() {
10602        if (isHardwareAccelerated() && mParent instanceof View) {
10603            ((View) mParent).invalidate(true);
10604        }
10605    }
10606
10607    /**
10608     * Indicates whether this View is opaque. An opaque View guarantees that it will
10609     * draw all the pixels overlapping its bounds using a fully opaque color.
10610     *
10611     * Subclasses of View should override this method whenever possible to indicate
10612     * whether an instance is opaque. Opaque Views are treated in a special way by
10613     * the View hierarchy, possibly allowing it to perform optimizations during
10614     * invalidate/draw passes.
10615     *
10616     * @return True if this View is guaranteed to be fully opaque, false otherwise.
10617     */
10618    @ViewDebug.ExportedProperty(category = "drawing")
10619    public boolean isOpaque() {
10620        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
10621                ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f);
10622    }
10623
10624    /**
10625     * @hide
10626     */
10627    protected void computeOpaqueFlags() {
10628        // Opaque if:
10629        //   - Has a background
10630        //   - Background is opaque
10631        //   - Doesn't have scrollbars or scrollbars are inside overlay
10632
10633        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
10634            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
10635        } else {
10636            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
10637        }
10638
10639        final int flags = mViewFlags;
10640        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
10641                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
10642            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
10643        } else {
10644            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
10645        }
10646    }
10647
10648    /**
10649     * @hide
10650     */
10651    protected boolean hasOpaqueScrollbars() {
10652        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
10653    }
10654
10655    /**
10656     * @return A handler associated with the thread running the View. This
10657     * handler can be used to pump events in the UI events queue.
10658     */
10659    public Handler getHandler() {
10660        if (mAttachInfo != null) {
10661            return mAttachInfo.mHandler;
10662        }
10663        return null;
10664    }
10665
10666    /**
10667     * Gets the view root associated with the View.
10668     * @return The view root, or null if none.
10669     * @hide
10670     */
10671    public ViewRootImpl getViewRootImpl() {
10672        if (mAttachInfo != null) {
10673            return mAttachInfo.mViewRootImpl;
10674        }
10675        return null;
10676    }
10677
10678    /**
10679     * <p>Causes the Runnable to be added to the message queue.
10680     * The runnable will be run on the user interface thread.</p>
10681     *
10682     * @param action The Runnable that will be executed.
10683     *
10684     * @return Returns true if the Runnable was successfully placed in to the
10685     *         message queue.  Returns false on failure, usually because the
10686     *         looper processing the message queue is exiting.
10687     *
10688     * @see #postDelayed
10689     * @see #removeCallbacks
10690     */
10691    public boolean post(Runnable action) {
10692        final AttachInfo attachInfo = mAttachInfo;
10693        if (attachInfo != null) {
10694            return attachInfo.mHandler.post(action);
10695        }
10696        // Assume that post will succeed later
10697        ViewRootImpl.getRunQueue().post(action);
10698        return true;
10699    }
10700
10701    /**
10702     * <p>Causes the Runnable to be added to the message queue, to be run
10703     * after the specified amount of time elapses.
10704     * The runnable will be run on the user interface thread.</p>
10705     *
10706     * @param action The Runnable that will be executed.
10707     * @param delayMillis The delay (in milliseconds) until the Runnable
10708     *        will be executed.
10709     *
10710     * @return true if the Runnable was successfully placed in to the
10711     *         message queue.  Returns false on failure, usually because the
10712     *         looper processing the message queue is exiting.  Note that a
10713     *         result of true does not mean the Runnable will be processed --
10714     *         if the looper is quit before the delivery time of the message
10715     *         occurs then the message will be dropped.
10716     *
10717     * @see #post
10718     * @see #removeCallbacks
10719     */
10720    public boolean postDelayed(Runnable action, long delayMillis) {
10721        final AttachInfo attachInfo = mAttachInfo;
10722        if (attachInfo != null) {
10723            return attachInfo.mHandler.postDelayed(action, delayMillis);
10724        }
10725        // Assume that post will succeed later
10726        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10727        return true;
10728    }
10729
10730    /**
10731     * <p>Causes the Runnable to execute on the next animation time step.
10732     * The runnable will be run on the user interface thread.</p>
10733     *
10734     * @param action The Runnable that will be executed.
10735     *
10736     * @see #postOnAnimationDelayed
10737     * @see #removeCallbacks
10738     */
10739    public void postOnAnimation(Runnable action) {
10740        final AttachInfo attachInfo = mAttachInfo;
10741        if (attachInfo != null) {
10742            attachInfo.mViewRootImpl.mChoreographer.postCallback(
10743                    Choreographer.CALLBACK_ANIMATION, action, null);
10744        } else {
10745            // Assume that post will succeed later
10746            ViewRootImpl.getRunQueue().post(action);
10747        }
10748    }
10749
10750    /**
10751     * <p>Causes the Runnable to execute on the next animation time step,
10752     * after the specified amount of time elapses.
10753     * The runnable will be run on the user interface thread.</p>
10754     *
10755     * @param action The Runnable that will be executed.
10756     * @param delayMillis The delay (in milliseconds) until the Runnable
10757     *        will be executed.
10758     *
10759     * @see #postOnAnimation
10760     * @see #removeCallbacks
10761     */
10762    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
10763        final AttachInfo attachInfo = mAttachInfo;
10764        if (attachInfo != null) {
10765            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
10766                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
10767        } else {
10768            // Assume that post will succeed later
10769            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10770        }
10771    }
10772
10773    /**
10774     * <p>Removes the specified Runnable from the message queue.</p>
10775     *
10776     * @param action The Runnable to remove from the message handling queue
10777     *
10778     * @return true if this view could ask the Handler to remove the Runnable,
10779     *         false otherwise. When the returned value is true, the Runnable
10780     *         may or may not have been actually removed from the message queue
10781     *         (for instance, if the Runnable was not in the queue already.)
10782     *
10783     * @see #post
10784     * @see #postDelayed
10785     * @see #postOnAnimation
10786     * @see #postOnAnimationDelayed
10787     */
10788    public boolean removeCallbacks(Runnable action) {
10789        if (action != null) {
10790            final AttachInfo attachInfo = mAttachInfo;
10791            if (attachInfo != null) {
10792                attachInfo.mHandler.removeCallbacks(action);
10793                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
10794                        Choreographer.CALLBACK_ANIMATION, action, null);
10795            } else {
10796                // Assume that post will succeed later
10797                ViewRootImpl.getRunQueue().removeCallbacks(action);
10798            }
10799        }
10800        return true;
10801    }
10802
10803    /**
10804     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
10805     * Use this to invalidate the View from a non-UI thread.</p>
10806     *
10807     * <p>This method can be invoked from outside of the UI thread
10808     * only when this View is attached to a window.</p>
10809     *
10810     * @see #invalidate()
10811     * @see #postInvalidateDelayed(long)
10812     */
10813    public void postInvalidate() {
10814        postInvalidateDelayed(0);
10815    }
10816
10817    /**
10818     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10819     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
10820     *
10821     * <p>This method can be invoked from outside of the UI thread
10822     * only when this View is attached to a window.</p>
10823     *
10824     * @param left The left coordinate of the rectangle to invalidate.
10825     * @param top The top coordinate of the rectangle to invalidate.
10826     * @param right The right coordinate of the rectangle to invalidate.
10827     * @param bottom The bottom coordinate of the rectangle to invalidate.
10828     *
10829     * @see #invalidate(int, int, int, int)
10830     * @see #invalidate(Rect)
10831     * @see #postInvalidateDelayed(long, int, int, int, int)
10832     */
10833    public void postInvalidate(int left, int top, int right, int bottom) {
10834        postInvalidateDelayed(0, left, top, right, bottom);
10835    }
10836
10837    /**
10838     * <p>Cause an invalidate to happen on a subsequent cycle through the event
10839     * loop. Waits for the specified amount of time.</p>
10840     *
10841     * <p>This method can be invoked from outside of the UI thread
10842     * only when this View is attached to a window.</p>
10843     *
10844     * @param delayMilliseconds the duration in milliseconds to delay the
10845     *         invalidation by
10846     *
10847     * @see #invalidate()
10848     * @see #postInvalidate()
10849     */
10850    public void postInvalidateDelayed(long delayMilliseconds) {
10851        // We try only with the AttachInfo because there's no point in invalidating
10852        // if we are not attached to our window
10853        final AttachInfo attachInfo = mAttachInfo;
10854        if (attachInfo != null) {
10855            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
10856        }
10857    }
10858
10859    /**
10860     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10861     * through the event loop. Waits for the specified amount of time.</p>
10862     *
10863     * <p>This method can be invoked from outside of the UI thread
10864     * only when this View is attached to a window.</p>
10865     *
10866     * @param delayMilliseconds the duration in milliseconds to delay the
10867     *         invalidation by
10868     * @param left The left coordinate of the rectangle to invalidate.
10869     * @param top The top coordinate of the rectangle to invalidate.
10870     * @param right The right coordinate of the rectangle to invalidate.
10871     * @param bottom The bottom coordinate of the rectangle to invalidate.
10872     *
10873     * @see #invalidate(int, int, int, int)
10874     * @see #invalidate(Rect)
10875     * @see #postInvalidate(int, int, int, int)
10876     */
10877    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
10878            int right, int bottom) {
10879
10880        // We try only with the AttachInfo because there's no point in invalidating
10881        // if we are not attached to our window
10882        final AttachInfo attachInfo = mAttachInfo;
10883        if (attachInfo != null) {
10884            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
10885            info.target = this;
10886            info.left = left;
10887            info.top = top;
10888            info.right = right;
10889            info.bottom = bottom;
10890
10891            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
10892        }
10893    }
10894
10895    /**
10896     * <p>Cause an invalidate to happen on the next animation time step, typically the
10897     * next display frame.</p>
10898     *
10899     * <p>This method can be invoked from outside of the UI thread
10900     * only when this View is attached to a window.</p>
10901     *
10902     * @see #invalidate()
10903     */
10904    public void postInvalidateOnAnimation() {
10905        // We try only with the AttachInfo because there's no point in invalidating
10906        // if we are not attached to our window
10907        final AttachInfo attachInfo = mAttachInfo;
10908        if (attachInfo != null) {
10909            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
10910        }
10911    }
10912
10913    /**
10914     * <p>Cause an invalidate of the specified area to happen on the next animation
10915     * time step, typically the next display frame.</p>
10916     *
10917     * <p>This method can be invoked from outside of the UI thread
10918     * only when this View is attached to a window.</p>
10919     *
10920     * @param left The left coordinate of the rectangle to invalidate.
10921     * @param top The top coordinate of the rectangle to invalidate.
10922     * @param right The right coordinate of the rectangle to invalidate.
10923     * @param bottom The bottom coordinate of the rectangle to invalidate.
10924     *
10925     * @see #invalidate(int, int, int, int)
10926     * @see #invalidate(Rect)
10927     */
10928    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
10929        // We try only with the AttachInfo because there's no point in invalidating
10930        // if we are not attached to our window
10931        final AttachInfo attachInfo = mAttachInfo;
10932        if (attachInfo != null) {
10933            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
10934            info.target = this;
10935            info.left = left;
10936            info.top = top;
10937            info.right = right;
10938            info.bottom = bottom;
10939
10940            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
10941        }
10942    }
10943
10944    /**
10945     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
10946     * This event is sent at most once every
10947     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
10948     */
10949    private void postSendViewScrolledAccessibilityEventCallback() {
10950        if (mSendViewScrolledAccessibilityEvent == null) {
10951            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
10952        }
10953        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
10954            mSendViewScrolledAccessibilityEvent.mIsPending = true;
10955            postDelayed(mSendViewScrolledAccessibilityEvent,
10956                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
10957        }
10958    }
10959
10960    /**
10961     * Called by a parent to request that a child update its values for mScrollX
10962     * and mScrollY if necessary. This will typically be done if the child is
10963     * animating a scroll using a {@link android.widget.Scroller Scroller}
10964     * object.
10965     */
10966    public void computeScroll() {
10967    }
10968
10969    /**
10970     * <p>Indicate whether the horizontal edges are faded when the view is
10971     * scrolled horizontally.</p>
10972     *
10973     * @return true if the horizontal edges should are faded on scroll, false
10974     *         otherwise
10975     *
10976     * @see #setHorizontalFadingEdgeEnabled(boolean)
10977     *
10978     * @attr ref android.R.styleable#View_requiresFadingEdge
10979     */
10980    public boolean isHorizontalFadingEdgeEnabled() {
10981        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
10982    }
10983
10984    /**
10985     * <p>Define whether the horizontal edges should be faded when this view
10986     * is scrolled horizontally.</p>
10987     *
10988     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
10989     *                                    be faded when the view is scrolled
10990     *                                    horizontally
10991     *
10992     * @see #isHorizontalFadingEdgeEnabled()
10993     *
10994     * @attr ref android.R.styleable#View_requiresFadingEdge
10995     */
10996    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
10997        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
10998            if (horizontalFadingEdgeEnabled) {
10999                initScrollCache();
11000            }
11001
11002            mViewFlags ^= FADING_EDGE_HORIZONTAL;
11003        }
11004    }
11005
11006    /**
11007     * <p>Indicate whether the vertical edges are faded when the view is
11008     * scrolled horizontally.</p>
11009     *
11010     * @return true if the vertical edges should are faded on scroll, false
11011     *         otherwise
11012     *
11013     * @see #setVerticalFadingEdgeEnabled(boolean)
11014     *
11015     * @attr ref android.R.styleable#View_requiresFadingEdge
11016     */
11017    public boolean isVerticalFadingEdgeEnabled() {
11018        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
11019    }
11020
11021    /**
11022     * <p>Define whether the vertical edges should be faded when this view
11023     * is scrolled vertically.</p>
11024     *
11025     * @param verticalFadingEdgeEnabled true if the vertical edges should
11026     *                                  be faded when the view is scrolled
11027     *                                  vertically
11028     *
11029     * @see #isVerticalFadingEdgeEnabled()
11030     *
11031     * @attr ref android.R.styleable#View_requiresFadingEdge
11032     */
11033    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
11034        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
11035            if (verticalFadingEdgeEnabled) {
11036                initScrollCache();
11037            }
11038
11039            mViewFlags ^= FADING_EDGE_VERTICAL;
11040        }
11041    }
11042
11043    /**
11044     * Returns the strength, or intensity, of the top faded edge. The strength is
11045     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
11046     * returns 0.0 or 1.0 but no value in between.
11047     *
11048     * Subclasses should override this method to provide a smoother fade transition
11049     * when scrolling occurs.
11050     *
11051     * @return the intensity of the top fade as a float between 0.0f and 1.0f
11052     */
11053    protected float getTopFadingEdgeStrength() {
11054        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
11055    }
11056
11057    /**
11058     * Returns the strength, or intensity, of the bottom faded edge. The strength is
11059     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
11060     * returns 0.0 or 1.0 but no value in between.
11061     *
11062     * Subclasses should override this method to provide a smoother fade transition
11063     * when scrolling occurs.
11064     *
11065     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
11066     */
11067    protected float getBottomFadingEdgeStrength() {
11068        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
11069                computeVerticalScrollRange() ? 1.0f : 0.0f;
11070    }
11071
11072    /**
11073     * Returns the strength, or intensity, of the left faded edge. The strength is
11074     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
11075     * returns 0.0 or 1.0 but no value in between.
11076     *
11077     * Subclasses should override this method to provide a smoother fade transition
11078     * when scrolling occurs.
11079     *
11080     * @return the intensity of the left fade as a float between 0.0f and 1.0f
11081     */
11082    protected float getLeftFadingEdgeStrength() {
11083        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
11084    }
11085
11086    /**
11087     * Returns the strength, or intensity, of the right faded edge. The strength is
11088     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
11089     * returns 0.0 or 1.0 but no value in between.
11090     *
11091     * Subclasses should override this method to provide a smoother fade transition
11092     * when scrolling occurs.
11093     *
11094     * @return the intensity of the right fade as a float between 0.0f and 1.0f
11095     */
11096    protected float getRightFadingEdgeStrength() {
11097        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
11098                computeHorizontalScrollRange() ? 1.0f : 0.0f;
11099    }
11100
11101    /**
11102     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
11103     * scrollbar is not drawn by default.</p>
11104     *
11105     * @return true if the horizontal scrollbar should be painted, false
11106     *         otherwise
11107     *
11108     * @see #setHorizontalScrollBarEnabled(boolean)
11109     */
11110    public boolean isHorizontalScrollBarEnabled() {
11111        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
11112    }
11113
11114    /**
11115     * <p>Define whether the horizontal scrollbar should be drawn or not. The
11116     * scrollbar is not drawn by default.</p>
11117     *
11118     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
11119     *                                   be painted
11120     *
11121     * @see #isHorizontalScrollBarEnabled()
11122     */
11123    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
11124        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
11125            mViewFlags ^= SCROLLBARS_HORIZONTAL;
11126            computeOpaqueFlags();
11127            resolvePadding();
11128        }
11129    }
11130
11131    /**
11132     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
11133     * scrollbar is not drawn by default.</p>
11134     *
11135     * @return true if the vertical scrollbar should be painted, false
11136     *         otherwise
11137     *
11138     * @see #setVerticalScrollBarEnabled(boolean)
11139     */
11140    public boolean isVerticalScrollBarEnabled() {
11141        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
11142    }
11143
11144    /**
11145     * <p>Define whether the vertical scrollbar should be drawn or not. The
11146     * scrollbar is not drawn by default.</p>
11147     *
11148     * @param verticalScrollBarEnabled true if the vertical scrollbar should
11149     *                                 be painted
11150     *
11151     * @see #isVerticalScrollBarEnabled()
11152     */
11153    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
11154        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
11155            mViewFlags ^= SCROLLBARS_VERTICAL;
11156            computeOpaqueFlags();
11157            resolvePadding();
11158        }
11159    }
11160
11161    /**
11162     * @hide
11163     */
11164    protected void recomputePadding() {
11165        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
11166    }
11167
11168    /**
11169     * Define whether scrollbars will fade when the view is not scrolling.
11170     *
11171     * @param fadeScrollbars wheter to enable fading
11172     *
11173     * @attr ref android.R.styleable#View_fadeScrollbars
11174     */
11175    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
11176        initScrollCache();
11177        final ScrollabilityCache scrollabilityCache = mScrollCache;
11178        scrollabilityCache.fadeScrollBars = fadeScrollbars;
11179        if (fadeScrollbars) {
11180            scrollabilityCache.state = ScrollabilityCache.OFF;
11181        } else {
11182            scrollabilityCache.state = ScrollabilityCache.ON;
11183        }
11184    }
11185
11186    /**
11187     *
11188     * Returns true if scrollbars will fade when this view is not scrolling
11189     *
11190     * @return true if scrollbar fading is enabled
11191     *
11192     * @attr ref android.R.styleable#View_fadeScrollbars
11193     */
11194    public boolean isScrollbarFadingEnabled() {
11195        return mScrollCache != null && mScrollCache.fadeScrollBars;
11196    }
11197
11198    /**
11199     *
11200     * Returns the delay before scrollbars fade.
11201     *
11202     * @return the delay before scrollbars fade
11203     *
11204     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
11205     */
11206    public int getScrollBarDefaultDelayBeforeFade() {
11207        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
11208                mScrollCache.scrollBarDefaultDelayBeforeFade;
11209    }
11210
11211    /**
11212     * Define the delay before scrollbars fade.
11213     *
11214     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
11215     *
11216     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
11217     */
11218    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
11219        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
11220    }
11221
11222    /**
11223     *
11224     * Returns the scrollbar fade duration.
11225     *
11226     * @return the scrollbar fade duration
11227     *
11228     * @attr ref android.R.styleable#View_scrollbarFadeDuration
11229     */
11230    public int getScrollBarFadeDuration() {
11231        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
11232                mScrollCache.scrollBarFadeDuration;
11233    }
11234
11235    /**
11236     * Define the scrollbar fade duration.
11237     *
11238     * @param scrollBarFadeDuration - the scrollbar fade duration
11239     *
11240     * @attr ref android.R.styleable#View_scrollbarFadeDuration
11241     */
11242    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
11243        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
11244    }
11245
11246    /**
11247     *
11248     * Returns the scrollbar size.
11249     *
11250     * @return the scrollbar size
11251     *
11252     * @attr ref android.R.styleable#View_scrollbarSize
11253     */
11254    public int getScrollBarSize() {
11255        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
11256                mScrollCache.scrollBarSize;
11257    }
11258
11259    /**
11260     * Define the scrollbar size.
11261     *
11262     * @param scrollBarSize - the scrollbar size
11263     *
11264     * @attr ref android.R.styleable#View_scrollbarSize
11265     */
11266    public void setScrollBarSize(int scrollBarSize) {
11267        getScrollCache().scrollBarSize = scrollBarSize;
11268    }
11269
11270    /**
11271     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
11272     * inset. When inset, they add to the padding of the view. And the scrollbars
11273     * can be drawn inside the padding area or on the edge of the view. For example,
11274     * if a view has a background drawable and you want to draw the scrollbars
11275     * inside the padding specified by the drawable, you can use
11276     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
11277     * appear at the edge of the view, ignoring the padding, then you can use
11278     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
11279     * @param style the style of the scrollbars. Should be one of
11280     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
11281     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
11282     * @see #SCROLLBARS_INSIDE_OVERLAY
11283     * @see #SCROLLBARS_INSIDE_INSET
11284     * @see #SCROLLBARS_OUTSIDE_OVERLAY
11285     * @see #SCROLLBARS_OUTSIDE_INSET
11286     *
11287     * @attr ref android.R.styleable#View_scrollbarStyle
11288     */
11289    public void setScrollBarStyle(int style) {
11290        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
11291            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
11292            computeOpaqueFlags();
11293            resolvePadding();
11294        }
11295    }
11296
11297    /**
11298     * <p>Returns the current scrollbar style.</p>
11299     * @return the current scrollbar style
11300     * @see #SCROLLBARS_INSIDE_OVERLAY
11301     * @see #SCROLLBARS_INSIDE_INSET
11302     * @see #SCROLLBARS_OUTSIDE_OVERLAY
11303     * @see #SCROLLBARS_OUTSIDE_INSET
11304     *
11305     * @attr ref android.R.styleable#View_scrollbarStyle
11306     */
11307    @ViewDebug.ExportedProperty(mapping = {
11308            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
11309            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
11310            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
11311            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
11312    })
11313    public int getScrollBarStyle() {
11314        return mViewFlags & SCROLLBARS_STYLE_MASK;
11315    }
11316
11317    /**
11318     * <p>Compute the horizontal range that the horizontal scrollbar
11319     * represents.</p>
11320     *
11321     * <p>The range is expressed in arbitrary units that must be the same as the
11322     * units used by {@link #computeHorizontalScrollExtent()} and
11323     * {@link #computeHorizontalScrollOffset()}.</p>
11324     *
11325     * <p>The default range is the drawing width of this view.</p>
11326     *
11327     * @return the total horizontal range represented by the horizontal
11328     *         scrollbar
11329     *
11330     * @see #computeHorizontalScrollExtent()
11331     * @see #computeHorizontalScrollOffset()
11332     * @see android.widget.ScrollBarDrawable
11333     */
11334    protected int computeHorizontalScrollRange() {
11335        return getWidth();
11336    }
11337
11338    /**
11339     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
11340     * within the horizontal range. This value is used to compute the position
11341     * of the thumb within the scrollbar's track.</p>
11342     *
11343     * <p>The range is expressed in arbitrary units that must be the same as the
11344     * units used by {@link #computeHorizontalScrollRange()} and
11345     * {@link #computeHorizontalScrollExtent()}.</p>
11346     *
11347     * <p>The default offset is the scroll offset of this view.</p>
11348     *
11349     * @return the horizontal offset of the scrollbar's thumb
11350     *
11351     * @see #computeHorizontalScrollRange()
11352     * @see #computeHorizontalScrollExtent()
11353     * @see android.widget.ScrollBarDrawable
11354     */
11355    protected int computeHorizontalScrollOffset() {
11356        return mScrollX;
11357    }
11358
11359    /**
11360     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
11361     * within the horizontal range. This value is used to compute the length
11362     * of the thumb within the scrollbar's track.</p>
11363     *
11364     * <p>The range is expressed in arbitrary units that must be the same as the
11365     * units used by {@link #computeHorizontalScrollRange()} and
11366     * {@link #computeHorizontalScrollOffset()}.</p>
11367     *
11368     * <p>The default extent is the drawing width of this view.</p>
11369     *
11370     * @return the horizontal extent of the scrollbar's thumb
11371     *
11372     * @see #computeHorizontalScrollRange()
11373     * @see #computeHorizontalScrollOffset()
11374     * @see android.widget.ScrollBarDrawable
11375     */
11376    protected int computeHorizontalScrollExtent() {
11377        return getWidth();
11378    }
11379
11380    /**
11381     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
11382     *
11383     * <p>The range is expressed in arbitrary units that must be the same as the
11384     * units used by {@link #computeVerticalScrollExtent()} and
11385     * {@link #computeVerticalScrollOffset()}.</p>
11386     *
11387     * @return the total vertical range represented by the vertical scrollbar
11388     *
11389     * <p>The default range is the drawing height of this view.</p>
11390     *
11391     * @see #computeVerticalScrollExtent()
11392     * @see #computeVerticalScrollOffset()
11393     * @see android.widget.ScrollBarDrawable
11394     */
11395    protected int computeVerticalScrollRange() {
11396        return getHeight();
11397    }
11398
11399    /**
11400     * <p>Compute the vertical offset of the vertical scrollbar's thumb
11401     * within the horizontal range. This value is used to compute the position
11402     * of the thumb within the scrollbar's track.</p>
11403     *
11404     * <p>The range is expressed in arbitrary units that must be the same as the
11405     * units used by {@link #computeVerticalScrollRange()} and
11406     * {@link #computeVerticalScrollExtent()}.</p>
11407     *
11408     * <p>The default offset is the scroll offset of this view.</p>
11409     *
11410     * @return the vertical offset of the scrollbar's thumb
11411     *
11412     * @see #computeVerticalScrollRange()
11413     * @see #computeVerticalScrollExtent()
11414     * @see android.widget.ScrollBarDrawable
11415     */
11416    protected int computeVerticalScrollOffset() {
11417        return mScrollY;
11418    }
11419
11420    /**
11421     * <p>Compute the vertical extent of the horizontal scrollbar's thumb
11422     * within the vertical range. This value is used to compute the length
11423     * of the thumb within the scrollbar's track.</p>
11424     *
11425     * <p>The range is expressed in arbitrary units that must be the same as the
11426     * units used by {@link #computeVerticalScrollRange()} and
11427     * {@link #computeVerticalScrollOffset()}.</p>
11428     *
11429     * <p>The default extent is the drawing height of this view.</p>
11430     *
11431     * @return the vertical extent of the scrollbar's thumb
11432     *
11433     * @see #computeVerticalScrollRange()
11434     * @see #computeVerticalScrollOffset()
11435     * @see android.widget.ScrollBarDrawable
11436     */
11437    protected int computeVerticalScrollExtent() {
11438        return getHeight();
11439    }
11440
11441    /**
11442     * Check if this view can be scrolled horizontally in a certain direction.
11443     *
11444     * @param direction Negative to check scrolling left, positive to check scrolling right.
11445     * @return true if this view can be scrolled in the specified direction, false otherwise.
11446     */
11447    public boolean canScrollHorizontally(int direction) {
11448        final int offset = computeHorizontalScrollOffset();
11449        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
11450        if (range == 0) return false;
11451        if (direction < 0) {
11452            return offset > 0;
11453        } else {
11454            return offset < range - 1;
11455        }
11456    }
11457
11458    /**
11459     * Check if this view can be scrolled vertically in a certain direction.
11460     *
11461     * @param direction Negative to check scrolling up, positive to check scrolling down.
11462     * @return true if this view can be scrolled in the specified direction, false otherwise.
11463     */
11464    public boolean canScrollVertically(int direction) {
11465        final int offset = computeVerticalScrollOffset();
11466        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
11467        if (range == 0) return false;
11468        if (direction < 0) {
11469            return offset > 0;
11470        } else {
11471            return offset < range - 1;
11472        }
11473    }
11474
11475    /**
11476     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
11477     * scrollbars are painted only if they have been awakened first.</p>
11478     *
11479     * @param canvas the canvas on which to draw the scrollbars
11480     *
11481     * @see #awakenScrollBars(int)
11482     */
11483    protected final void onDrawScrollBars(Canvas canvas) {
11484        // scrollbars are drawn only when the animation is running
11485        final ScrollabilityCache cache = mScrollCache;
11486        if (cache != null) {
11487
11488            int state = cache.state;
11489
11490            if (state == ScrollabilityCache.OFF) {
11491                return;
11492            }
11493
11494            boolean invalidate = false;
11495
11496            if (state == ScrollabilityCache.FADING) {
11497                // We're fading -- get our fade interpolation
11498                if (cache.interpolatorValues == null) {
11499                    cache.interpolatorValues = new float[1];
11500                }
11501
11502                float[] values = cache.interpolatorValues;
11503
11504                // Stops the animation if we're done
11505                if (cache.scrollBarInterpolator.timeToValues(values) ==
11506                        Interpolator.Result.FREEZE_END) {
11507                    cache.state = ScrollabilityCache.OFF;
11508                } else {
11509                    cache.scrollBar.setAlpha(Math.round(values[0]));
11510                }
11511
11512                // This will make the scroll bars inval themselves after
11513                // drawing. We only want this when we're fading so that
11514                // we prevent excessive redraws
11515                invalidate = true;
11516            } else {
11517                // We're just on -- but we may have been fading before so
11518                // reset alpha
11519                cache.scrollBar.setAlpha(255);
11520            }
11521
11522
11523            final int viewFlags = mViewFlags;
11524
11525            final boolean drawHorizontalScrollBar =
11526                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
11527            final boolean drawVerticalScrollBar =
11528                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
11529                && !isVerticalScrollBarHidden();
11530
11531            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
11532                final int width = mRight - mLeft;
11533                final int height = mBottom - mTop;
11534
11535                final ScrollBarDrawable scrollBar = cache.scrollBar;
11536
11537                final int scrollX = mScrollX;
11538                final int scrollY = mScrollY;
11539                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
11540
11541                int left, top, right, bottom;
11542
11543                if (drawHorizontalScrollBar) {
11544                    int size = scrollBar.getSize(false);
11545                    if (size <= 0) {
11546                        size = cache.scrollBarSize;
11547                    }
11548
11549                    scrollBar.setParameters(computeHorizontalScrollRange(),
11550                                            computeHorizontalScrollOffset(),
11551                                            computeHorizontalScrollExtent(), false);
11552                    final int verticalScrollBarGap = drawVerticalScrollBar ?
11553                            getVerticalScrollbarWidth() : 0;
11554                    top = scrollY + height - size - (mUserPaddingBottom & inside);
11555                    left = scrollX + (mPaddingLeft & inside);
11556                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
11557                    bottom = top + size;
11558                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
11559                    if (invalidate) {
11560                        invalidate(left, top, right, bottom);
11561                    }
11562                }
11563
11564                if (drawVerticalScrollBar) {
11565                    int size = scrollBar.getSize(true);
11566                    if (size <= 0) {
11567                        size = cache.scrollBarSize;
11568                    }
11569
11570                    scrollBar.setParameters(computeVerticalScrollRange(),
11571                                            computeVerticalScrollOffset(),
11572                                            computeVerticalScrollExtent(), true);
11573                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
11574                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
11575                        verticalScrollbarPosition = isLayoutRtl() ?
11576                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
11577                    }
11578                    switch (verticalScrollbarPosition) {
11579                        default:
11580                        case SCROLLBAR_POSITION_RIGHT:
11581                            left = scrollX + width - size - (mUserPaddingRight & inside);
11582                            break;
11583                        case SCROLLBAR_POSITION_LEFT:
11584                            left = scrollX + (mUserPaddingLeft & inside);
11585                            break;
11586                    }
11587                    top = scrollY + (mPaddingTop & inside);
11588                    right = left + size;
11589                    bottom = scrollY + height - (mUserPaddingBottom & inside);
11590                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
11591                    if (invalidate) {
11592                        invalidate(left, top, right, bottom);
11593                    }
11594                }
11595            }
11596        }
11597    }
11598
11599    /**
11600     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
11601     * FastScroller is visible.
11602     * @return whether to temporarily hide the vertical scrollbar
11603     * @hide
11604     */
11605    protected boolean isVerticalScrollBarHidden() {
11606        return false;
11607    }
11608
11609    /**
11610     * <p>Draw the horizontal scrollbar if
11611     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
11612     *
11613     * @param canvas the canvas on which to draw the scrollbar
11614     * @param scrollBar the scrollbar's drawable
11615     *
11616     * @see #isHorizontalScrollBarEnabled()
11617     * @see #computeHorizontalScrollRange()
11618     * @see #computeHorizontalScrollExtent()
11619     * @see #computeHorizontalScrollOffset()
11620     * @see android.widget.ScrollBarDrawable
11621     * @hide
11622     */
11623    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
11624            int l, int t, int r, int b) {
11625        scrollBar.setBounds(l, t, r, b);
11626        scrollBar.draw(canvas);
11627    }
11628
11629    /**
11630     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
11631     * returns true.</p>
11632     *
11633     * @param canvas the canvas on which to draw the scrollbar
11634     * @param scrollBar the scrollbar's drawable
11635     *
11636     * @see #isVerticalScrollBarEnabled()
11637     * @see #computeVerticalScrollRange()
11638     * @see #computeVerticalScrollExtent()
11639     * @see #computeVerticalScrollOffset()
11640     * @see android.widget.ScrollBarDrawable
11641     * @hide
11642     */
11643    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
11644            int l, int t, int r, int b) {
11645        scrollBar.setBounds(l, t, r, b);
11646        scrollBar.draw(canvas);
11647    }
11648
11649    /**
11650     * Implement this to do your drawing.
11651     *
11652     * @param canvas the canvas on which the background will be drawn
11653     */
11654    protected void onDraw(Canvas canvas) {
11655    }
11656
11657    /*
11658     * Caller is responsible for calling requestLayout if necessary.
11659     * (This allows addViewInLayout to not request a new layout.)
11660     */
11661    void assignParent(ViewParent parent) {
11662        if (mParent == null) {
11663            mParent = parent;
11664        } else if (parent == null) {
11665            mParent = null;
11666        } else {
11667            throw new RuntimeException("view " + this + " being added, but"
11668                    + " it already has a parent");
11669        }
11670    }
11671
11672    /**
11673     * This is called when the view is attached to a window.  At this point it
11674     * has a Surface and will start drawing.  Note that this function is
11675     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
11676     * however it may be called any time before the first onDraw -- including
11677     * before or after {@link #onMeasure(int, int)}.
11678     *
11679     * @see #onDetachedFromWindow()
11680     */
11681    protected void onAttachedToWindow() {
11682        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
11683            mParent.requestTransparentRegion(this);
11684        }
11685
11686        if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
11687            initialAwakenScrollBars();
11688            mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
11689        }
11690
11691        jumpDrawablesToCurrentState();
11692
11693        clearAccessibilityFocus();
11694        if (isFocused()) {
11695            InputMethodManager imm = InputMethodManager.peekInstance();
11696            imm.focusIn(this);
11697        }
11698
11699        if (mDisplayList != null) {
11700            mDisplayList.setDirty(false);
11701        }
11702    }
11703
11704    /**
11705     * Resolve all RTL related properties.
11706     *
11707     * @hide
11708     */
11709    public void resolveRtlPropertiesIfNeeded() {
11710        if (!needRtlPropertiesResolution()) return;
11711
11712        // Order is important here: LayoutDirection MUST be resolved first
11713        if (!isLayoutDirectionResolved()) {
11714            resolveLayoutDirection();
11715            resolveLayoutParams();
11716        }
11717        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
11718        if (!isTextDirectionResolved()) {
11719            resolveTextDirection();
11720        }
11721        if (!isTextAlignmentResolved()) {
11722            resolveTextAlignment();
11723        }
11724        if (!isPaddingResolved()) {
11725            resolvePadding();
11726        }
11727        if (!isDrawablesResolved()) {
11728            resolveDrawables();
11729        }
11730        onRtlPropertiesChanged(getLayoutDirection());
11731    }
11732
11733    /**
11734     * Reset resolution of all RTL related properties.
11735     *
11736     * @hide
11737     */
11738    public void resetRtlProperties() {
11739        resetResolvedLayoutDirection();
11740        resetResolvedTextDirection();
11741        resetResolvedTextAlignment();
11742        resetResolvedPadding();
11743        resetResolvedDrawables();
11744    }
11745
11746    /**
11747     * @see #onScreenStateChanged(int)
11748     */
11749    void dispatchScreenStateChanged(int screenState) {
11750        onScreenStateChanged(screenState);
11751    }
11752
11753    /**
11754     * This method is called whenever the state of the screen this view is
11755     * attached to changes. A state change will usually occurs when the screen
11756     * turns on or off (whether it happens automatically or the user does it
11757     * manually.)
11758     *
11759     * @param screenState The new state of the screen. Can be either
11760     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
11761     */
11762    public void onScreenStateChanged(int screenState) {
11763    }
11764
11765    /**
11766     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
11767     */
11768    private boolean hasRtlSupport() {
11769        return mContext.getApplicationInfo().hasRtlSupport();
11770    }
11771
11772    /**
11773     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
11774     * RTL not supported)
11775     */
11776    private boolean isRtlCompatibilityMode() {
11777        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
11778        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
11779    }
11780
11781    /**
11782     * @return true if RTL properties need resolution.
11783     */
11784    private boolean needRtlPropertiesResolution() {
11785        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
11786    }
11787
11788    /**
11789     * Called when any RTL property (layout direction or text direction or text alignment) has
11790     * been changed.
11791     *
11792     * Subclasses need to override this method to take care of cached information that depends on the
11793     * resolved layout direction, or to inform child views that inherit their layout direction.
11794     *
11795     * The default implementation does nothing.
11796     *
11797     * @param layoutDirection the direction of the layout
11798     *
11799     * @see #LAYOUT_DIRECTION_LTR
11800     * @see #LAYOUT_DIRECTION_RTL
11801     */
11802    public void onRtlPropertiesChanged(int layoutDirection) {
11803    }
11804
11805    /**
11806     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
11807     * that the parent directionality can and will be resolved before its children.
11808     *
11809     * @return true if resolution has been done, false otherwise.
11810     *
11811     * @hide
11812     */
11813    public boolean resolveLayoutDirection() {
11814        // Clear any previous layout direction resolution
11815        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
11816
11817        if (hasRtlSupport()) {
11818            // Set resolved depending on layout direction
11819            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
11820                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
11821                case LAYOUT_DIRECTION_INHERIT:
11822                    // We cannot resolve yet. LTR is by default and let the resolution happen again
11823                    // later to get the correct resolved value
11824                    if (!canResolveLayoutDirection()) return false;
11825
11826                    // Parent has not yet resolved, LTR is still the default
11827                    if (!mParent.isLayoutDirectionResolved()) return false;
11828
11829                    if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
11830                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
11831                    }
11832                    break;
11833                case LAYOUT_DIRECTION_RTL:
11834                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
11835                    break;
11836                case LAYOUT_DIRECTION_LOCALE:
11837                    if((LAYOUT_DIRECTION_RTL ==
11838                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
11839                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
11840                    }
11841                    break;
11842                default:
11843                    // Nothing to do, LTR by default
11844            }
11845        }
11846
11847        // Set to resolved
11848        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
11849        return true;
11850    }
11851
11852    /**
11853     * Check if layout direction resolution can be done.
11854     *
11855     * @return true if layout direction resolution can be done otherwise return false.
11856     *
11857     * @hide
11858     */
11859    public boolean canResolveLayoutDirection() {
11860        switch (getRawLayoutDirection()) {
11861            case LAYOUT_DIRECTION_INHERIT:
11862                return (mParent != null) && mParent.canResolveLayoutDirection();
11863            default:
11864                return true;
11865        }
11866    }
11867
11868    /**
11869     * Reset the resolved layout direction. Layout direction will be resolved during a call to
11870     * {@link #onMeasure(int, int)}.
11871     *
11872     * @hide
11873     */
11874    public void resetResolvedLayoutDirection() {
11875        // Reset the current resolved bits
11876        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
11877    }
11878
11879    /**
11880     * @return true if the layout direction is inherited.
11881     *
11882     * @hide
11883     */
11884    public boolean isLayoutDirectionInherited() {
11885        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
11886    }
11887
11888    /**
11889     * @return true if layout direction has been resolved.
11890     * @hide
11891     */
11892    public boolean isLayoutDirectionResolved() {
11893        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
11894    }
11895
11896    /**
11897     * Return if padding has been resolved
11898     *
11899     * @hide
11900     */
11901    boolean isPaddingResolved() {
11902        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
11903    }
11904
11905    /**
11906     * Resolve padding depending on layout direction.
11907     *
11908     * @hide
11909     */
11910    public void resolvePadding() {
11911        if (!isRtlCompatibilityMode()) {
11912            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
11913            // If start / end padding are defined, they will be resolved (hence overriding) to
11914            // left / right or right / left depending on the resolved layout direction.
11915            // If start / end padding are not defined, use the left / right ones.
11916            int resolvedLayoutDirection = getLayoutDirection();
11917            // Set user padding to initial values ...
11918            mUserPaddingLeft = mUserPaddingLeftInitial;
11919            mUserPaddingRight = mUserPaddingRightInitial;
11920            // ... then resolve it.
11921            switch (resolvedLayoutDirection) {
11922                case LAYOUT_DIRECTION_RTL:
11923                    if (mUserPaddingStart != UNDEFINED_PADDING) {
11924                        mUserPaddingRight = mUserPaddingStart;
11925                    }
11926                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
11927                        mUserPaddingLeft = mUserPaddingEnd;
11928                    }
11929                    break;
11930                case LAYOUT_DIRECTION_LTR:
11931                default:
11932                    if (mUserPaddingStart != UNDEFINED_PADDING) {
11933                        mUserPaddingLeft = mUserPaddingStart;
11934                    }
11935                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
11936                        mUserPaddingRight = mUserPaddingEnd;
11937                    }
11938            }
11939
11940            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11941
11942            internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11943                    mUserPaddingBottom);
11944            onRtlPropertiesChanged(resolvedLayoutDirection);
11945        }
11946
11947        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
11948    }
11949
11950    /**
11951     * Reset the resolved layout direction.
11952     *
11953     * @hide
11954     */
11955    public void resetResolvedPadding() {
11956        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
11957    }
11958
11959    /**
11960     * This is called when the view is detached from a window.  At this point it
11961     * no longer has a surface for drawing.
11962     *
11963     * @see #onAttachedToWindow()
11964     */
11965    protected void onDetachedFromWindow() {
11966        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
11967
11968        removeUnsetPressCallback();
11969        removeLongPressCallback();
11970        removePerformClickCallback();
11971        removeSendViewScrolledAccessibilityEventCallback();
11972
11973        destroyDrawingCache();
11974
11975        destroyLayer(false);
11976
11977        if (mAttachInfo != null) {
11978            if (mDisplayList != null) {
11979                mDisplayList.setDirty(true);
11980                mAttachInfo.mViewRootImpl.enqueueDisplayList(mDisplayList);
11981            }
11982            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
11983        } else {
11984            // Should never happen
11985            clearDisplayList();
11986        }
11987
11988        mCurrentAnimation = null;
11989
11990        resetAccessibilityStateChanged();
11991    }
11992
11993    /**
11994     * @return The number of times this view has been attached to a window
11995     */
11996    protected int getWindowAttachCount() {
11997        return mWindowAttachCount;
11998    }
11999
12000    /**
12001     * Retrieve a unique token identifying the window this view is attached to.
12002     * @return Return the window's token for use in
12003     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
12004     */
12005    public IBinder getWindowToken() {
12006        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
12007    }
12008
12009    /**
12010     * Retrieve a unique token identifying the top-level "real" window of
12011     * the window that this view is attached to.  That is, this is like
12012     * {@link #getWindowToken}, except if the window this view in is a panel
12013     * window (attached to another containing window), then the token of
12014     * the containing window is returned instead.
12015     *
12016     * @return Returns the associated window token, either
12017     * {@link #getWindowToken()} or the containing window's token.
12018     */
12019    public IBinder getApplicationWindowToken() {
12020        AttachInfo ai = mAttachInfo;
12021        if (ai != null) {
12022            IBinder appWindowToken = ai.mPanelParentWindowToken;
12023            if (appWindowToken == null) {
12024                appWindowToken = ai.mWindowToken;
12025            }
12026            return appWindowToken;
12027        }
12028        return null;
12029    }
12030
12031    /**
12032     * Gets the logical display to which the view's window has been attached.
12033     *
12034     * @return The logical display, or null if the view is not currently attached to a window.
12035     */
12036    public Display getDisplay() {
12037        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
12038    }
12039
12040    /**
12041     * Retrieve private session object this view hierarchy is using to
12042     * communicate with the window manager.
12043     * @return the session object to communicate with the window manager
12044     */
12045    /*package*/ IWindowSession getWindowSession() {
12046        return mAttachInfo != null ? mAttachInfo.mSession : null;
12047    }
12048
12049    /**
12050     * @param info the {@link android.view.View.AttachInfo} to associated with
12051     *        this view
12052     */
12053    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
12054        //System.out.println("Attached! " + this);
12055        mAttachInfo = info;
12056        mWindowAttachCount++;
12057        // We will need to evaluate the drawable state at least once.
12058        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
12059        if (mFloatingTreeObserver != null) {
12060            info.mTreeObserver.merge(mFloatingTreeObserver);
12061            mFloatingTreeObserver = null;
12062        }
12063        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
12064            mAttachInfo.mScrollContainers.add(this);
12065            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
12066        }
12067        performCollectViewAttributes(mAttachInfo, visibility);
12068        onAttachedToWindow();
12069
12070        ListenerInfo li = mListenerInfo;
12071        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
12072                li != null ? li.mOnAttachStateChangeListeners : null;
12073        if (listeners != null && listeners.size() > 0) {
12074            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
12075            // perform the dispatching. The iterator is a safe guard against listeners that
12076            // could mutate the list by calling the various add/remove methods. This prevents
12077            // the array from being modified while we iterate it.
12078            for (OnAttachStateChangeListener listener : listeners) {
12079                listener.onViewAttachedToWindow(this);
12080            }
12081        }
12082
12083        int vis = info.mWindowVisibility;
12084        if (vis != GONE) {
12085            onWindowVisibilityChanged(vis);
12086        }
12087        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
12088            // If nobody has evaluated the drawable state yet, then do it now.
12089            refreshDrawableState();
12090        }
12091        needGlobalAttributesUpdate(false);
12092    }
12093
12094    void dispatchDetachedFromWindow() {
12095        AttachInfo info = mAttachInfo;
12096        if (info != null) {
12097            int vis = info.mWindowVisibility;
12098            if (vis != GONE) {
12099                onWindowVisibilityChanged(GONE);
12100            }
12101        }
12102
12103        onDetachedFromWindow();
12104
12105        ListenerInfo li = mListenerInfo;
12106        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
12107                li != null ? li.mOnAttachStateChangeListeners : null;
12108        if (listeners != null && listeners.size() > 0) {
12109            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
12110            // perform the dispatching. The iterator is a safe guard against listeners that
12111            // could mutate the list by calling the various add/remove methods. This prevents
12112            // the array from being modified while we iterate it.
12113            for (OnAttachStateChangeListener listener : listeners) {
12114                listener.onViewDetachedFromWindow(this);
12115            }
12116        }
12117
12118        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
12119            mAttachInfo.mScrollContainers.remove(this);
12120            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
12121        }
12122
12123        mAttachInfo = null;
12124    }
12125
12126    /**
12127     * Store this view hierarchy's frozen state into the given container.
12128     *
12129     * @param container The SparseArray in which to save the view's state.
12130     *
12131     * @see #restoreHierarchyState(android.util.SparseArray)
12132     * @see #dispatchSaveInstanceState(android.util.SparseArray)
12133     * @see #onSaveInstanceState()
12134     */
12135    public void saveHierarchyState(SparseArray<Parcelable> container) {
12136        dispatchSaveInstanceState(container);
12137    }
12138
12139    /**
12140     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
12141     * this view and its children. May be overridden to modify how freezing happens to a
12142     * view's children; for example, some views may want to not store state for their children.
12143     *
12144     * @param container The SparseArray in which to save the view's state.
12145     *
12146     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
12147     * @see #saveHierarchyState(android.util.SparseArray)
12148     * @see #onSaveInstanceState()
12149     */
12150    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
12151        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
12152            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
12153            Parcelable state = onSaveInstanceState();
12154            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
12155                throw new IllegalStateException(
12156                        "Derived class did not call super.onSaveInstanceState()");
12157            }
12158            if (state != null) {
12159                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
12160                // + ": " + state);
12161                container.put(mID, state);
12162            }
12163        }
12164    }
12165
12166    /**
12167     * Hook allowing a view to generate a representation of its internal state
12168     * that can later be used to create a new instance with that same state.
12169     * This state should only contain information that is not persistent or can
12170     * not be reconstructed later. For example, you will never store your
12171     * current position on screen because that will be computed again when a
12172     * new instance of the view is placed in its view hierarchy.
12173     * <p>
12174     * Some examples of things you may store here: the current cursor position
12175     * in a text view (but usually not the text itself since that is stored in a
12176     * content provider or other persistent storage), the currently selected
12177     * item in a list view.
12178     *
12179     * @return Returns a Parcelable object containing the view's current dynamic
12180     *         state, or null if there is nothing interesting to save. The
12181     *         default implementation returns null.
12182     * @see #onRestoreInstanceState(android.os.Parcelable)
12183     * @see #saveHierarchyState(android.util.SparseArray)
12184     * @see #dispatchSaveInstanceState(android.util.SparseArray)
12185     * @see #setSaveEnabled(boolean)
12186     */
12187    protected Parcelable onSaveInstanceState() {
12188        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
12189        return BaseSavedState.EMPTY_STATE;
12190    }
12191
12192    /**
12193     * Restore this view hierarchy's frozen state from the given container.
12194     *
12195     * @param container The SparseArray which holds previously frozen states.
12196     *
12197     * @see #saveHierarchyState(android.util.SparseArray)
12198     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
12199     * @see #onRestoreInstanceState(android.os.Parcelable)
12200     */
12201    public void restoreHierarchyState(SparseArray<Parcelable> container) {
12202        dispatchRestoreInstanceState(container);
12203    }
12204
12205    /**
12206     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
12207     * state for this view and its children. May be overridden to modify how restoring
12208     * happens to a view's children; for example, some views may want to not store state
12209     * for their children.
12210     *
12211     * @param container The SparseArray which holds previously saved state.
12212     *
12213     * @see #dispatchSaveInstanceState(android.util.SparseArray)
12214     * @see #restoreHierarchyState(android.util.SparseArray)
12215     * @see #onRestoreInstanceState(android.os.Parcelable)
12216     */
12217    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
12218        if (mID != NO_ID) {
12219            Parcelable state = container.get(mID);
12220            if (state != null) {
12221                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
12222                // + ": " + state);
12223                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
12224                onRestoreInstanceState(state);
12225                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
12226                    throw new IllegalStateException(
12227                            "Derived class did not call super.onRestoreInstanceState()");
12228                }
12229            }
12230        }
12231    }
12232
12233    /**
12234     * Hook allowing a view to re-apply a representation of its internal state that had previously
12235     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
12236     * null state.
12237     *
12238     * @param state The frozen state that had previously been returned by
12239     *        {@link #onSaveInstanceState}.
12240     *
12241     * @see #onSaveInstanceState()
12242     * @see #restoreHierarchyState(android.util.SparseArray)
12243     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
12244     */
12245    protected void onRestoreInstanceState(Parcelable state) {
12246        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
12247        if (state != BaseSavedState.EMPTY_STATE && state != null) {
12248            throw new IllegalArgumentException("Wrong state class, expecting View State but "
12249                    + "received " + state.getClass().toString() + " instead. This usually happens "
12250                    + "when two views of different type have the same id in the same hierarchy. "
12251                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
12252                    + "other views do not use the same id.");
12253        }
12254    }
12255
12256    /**
12257     * <p>Return the time at which the drawing of the view hierarchy started.</p>
12258     *
12259     * @return the drawing start time in milliseconds
12260     */
12261    public long getDrawingTime() {
12262        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
12263    }
12264
12265    /**
12266     * <p>Enables or disables the duplication of the parent's state into this view. When
12267     * duplication is enabled, this view gets its drawable state from its parent rather
12268     * than from its own internal properties.</p>
12269     *
12270     * <p>Note: in the current implementation, setting this property to true after the
12271     * view was added to a ViewGroup might have no effect at all. This property should
12272     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
12273     *
12274     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
12275     * property is enabled, an exception will be thrown.</p>
12276     *
12277     * <p>Note: if the child view uses and updates additionnal states which are unknown to the
12278     * parent, these states should not be affected by this method.</p>
12279     *
12280     * @param enabled True to enable duplication of the parent's drawable state, false
12281     *                to disable it.
12282     *
12283     * @see #getDrawableState()
12284     * @see #isDuplicateParentStateEnabled()
12285     */
12286    public void setDuplicateParentStateEnabled(boolean enabled) {
12287        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
12288    }
12289
12290    /**
12291     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
12292     *
12293     * @return True if this view's drawable state is duplicated from the parent,
12294     *         false otherwise
12295     *
12296     * @see #getDrawableState()
12297     * @see #setDuplicateParentStateEnabled(boolean)
12298     */
12299    public boolean isDuplicateParentStateEnabled() {
12300        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
12301    }
12302
12303    /**
12304     * <p>Specifies the type of layer backing this view. The layer can be
12305     * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
12306     * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
12307     *
12308     * <p>A layer is associated with an optional {@link android.graphics.Paint}
12309     * instance that controls how the layer is composed on screen. The following
12310     * properties of the paint are taken into account when composing the layer:</p>
12311     * <ul>
12312     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
12313     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
12314     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
12315     * </ul>
12316     *
12317     * <p>If this view has an alpha value set to < 1.0 by calling
12318     * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
12319     * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
12320     * equivalent to setting a hardware layer on this view and providing a paint with
12321     * the desired alpha value.</p>
12322     *
12323     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
12324     * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
12325     * for more information on when and how to use layers.</p>
12326     *
12327     * @param layerType The type of layer to use with this view, must be one of
12328     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
12329     *        {@link #LAYER_TYPE_HARDWARE}
12330     * @param paint The paint used to compose the layer. This argument is optional
12331     *        and can be null. It is ignored when the layer type is
12332     *        {@link #LAYER_TYPE_NONE}
12333     *
12334     * @see #getLayerType()
12335     * @see #LAYER_TYPE_NONE
12336     * @see #LAYER_TYPE_SOFTWARE
12337     * @see #LAYER_TYPE_HARDWARE
12338     * @see #setAlpha(float)
12339     *
12340     * @attr ref android.R.styleable#View_layerType
12341     */
12342    public void setLayerType(int layerType, Paint paint) {
12343        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
12344            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
12345                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
12346        }
12347
12348        if (layerType == mLayerType) {
12349            if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
12350                mLayerPaint = paint == null ? new Paint() : paint;
12351                invalidateParentCaches();
12352                invalidate(true);
12353            }
12354            return;
12355        }
12356
12357        // Destroy any previous software drawing cache if needed
12358        switch (mLayerType) {
12359            case LAYER_TYPE_HARDWARE:
12360                destroyLayer(false);
12361                // fall through - non-accelerated views may use software layer mechanism instead
12362            case LAYER_TYPE_SOFTWARE:
12363                destroyDrawingCache();
12364                break;
12365            default:
12366                break;
12367        }
12368
12369        mLayerType = layerType;
12370        final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
12371        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
12372        mLocalDirtyRect = layerDisabled ? null : new Rect();
12373
12374        invalidateParentCaches();
12375        invalidate(true);
12376    }
12377
12378    /**
12379     * Updates the {@link Paint} object used with the current layer (used only if the current
12380     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
12381     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
12382     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
12383     * ensure that the view gets redrawn immediately.
12384     *
12385     * <p>A layer is associated with an optional {@link android.graphics.Paint}
12386     * instance that controls how the layer is composed on screen. The following
12387     * properties of the paint are taken into account when composing the layer:</p>
12388     * <ul>
12389     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
12390     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
12391     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
12392     * </ul>
12393     *
12394     * <p>If this view has an alpha value set to < 1.0 by calling
12395     * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
12396     * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
12397     * equivalent to setting a hardware layer on this view and providing a paint with
12398     * the desired alpha value.</p>
12399     *
12400     * @param paint The paint used to compose the layer. This argument is optional
12401     *        and can be null. It is ignored when the layer type is
12402     *        {@link #LAYER_TYPE_NONE}
12403     *
12404     * @see #setLayerType(int, android.graphics.Paint)
12405     */
12406    public void setLayerPaint(Paint paint) {
12407        int layerType = getLayerType();
12408        if (layerType != LAYER_TYPE_NONE) {
12409            mLayerPaint = paint == null ? new Paint() : paint;
12410            if (layerType == LAYER_TYPE_HARDWARE) {
12411                HardwareLayer layer = getHardwareLayer();
12412                if (layer != null) {
12413                    layer.setLayerPaint(paint);
12414                }
12415                invalidateViewProperty(false, false);
12416            } else {
12417                invalidate();
12418            }
12419        }
12420    }
12421
12422    /**
12423     * Indicates whether this view has a static layer. A view with layer type
12424     * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
12425     * dynamic.
12426     */
12427    boolean hasStaticLayer() {
12428        return true;
12429    }
12430
12431    /**
12432     * Indicates what type of layer is currently associated with this view. By default
12433     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
12434     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
12435     * for more information on the different types of layers.
12436     *
12437     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
12438     *         {@link #LAYER_TYPE_HARDWARE}
12439     *
12440     * @see #setLayerType(int, android.graphics.Paint)
12441     * @see #buildLayer()
12442     * @see #LAYER_TYPE_NONE
12443     * @see #LAYER_TYPE_SOFTWARE
12444     * @see #LAYER_TYPE_HARDWARE
12445     */
12446    public int getLayerType() {
12447        return mLayerType;
12448    }
12449
12450    /**
12451     * Forces this view's layer to be created and this view to be rendered
12452     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
12453     * invoking this method will have no effect.
12454     *
12455     * This method can for instance be used to render a view into its layer before
12456     * starting an animation. If this view is complex, rendering into the layer
12457     * before starting the animation will avoid skipping frames.
12458     *
12459     * @throws IllegalStateException If this view is not attached to a window
12460     *
12461     * @see #setLayerType(int, android.graphics.Paint)
12462     */
12463    public void buildLayer() {
12464        if (mLayerType == LAYER_TYPE_NONE) return;
12465
12466        if (mAttachInfo == null) {
12467            throw new IllegalStateException("This view must be attached to a window first");
12468        }
12469
12470        switch (mLayerType) {
12471            case LAYER_TYPE_HARDWARE:
12472                if (mAttachInfo.mHardwareRenderer != null &&
12473                        mAttachInfo.mHardwareRenderer.isEnabled() &&
12474                        mAttachInfo.mHardwareRenderer.validate()) {
12475                    getHardwareLayer();
12476                }
12477                break;
12478            case LAYER_TYPE_SOFTWARE:
12479                buildDrawingCache(true);
12480                break;
12481        }
12482    }
12483
12484    /**
12485     * <p>Returns a hardware layer that can be used to draw this view again
12486     * without executing its draw method.</p>
12487     *
12488     * @return A HardwareLayer ready to render, or null if an error occurred.
12489     */
12490    HardwareLayer getHardwareLayer() {
12491        if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
12492                !mAttachInfo.mHardwareRenderer.isEnabled()) {
12493            return null;
12494        }
12495
12496        if (!mAttachInfo.mHardwareRenderer.validate()) return null;
12497
12498        final int width = mRight - mLeft;
12499        final int height = mBottom - mTop;
12500
12501        if (width == 0 || height == 0) {
12502            return null;
12503        }
12504
12505        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
12506            if (mHardwareLayer == null) {
12507                mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
12508                        width, height, isOpaque());
12509                mLocalDirtyRect.set(0, 0, width, height);
12510            } else {
12511                if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
12512                    if (mHardwareLayer.resize(width, height)) {
12513                        mLocalDirtyRect.set(0, 0, width, height);
12514                    }
12515                }
12516
12517                // This should not be necessary but applications that change
12518                // the parameters of their background drawable without calling
12519                // this.setBackground(Drawable) can leave the view in a bad state
12520                // (for instance isOpaque() returns true, but the background is
12521                // not opaque.)
12522                computeOpaqueFlags();
12523
12524                final boolean opaque = isOpaque();
12525                if (mHardwareLayer.isValid() && mHardwareLayer.isOpaque() != opaque) {
12526                    mHardwareLayer.setOpaque(opaque);
12527                    mLocalDirtyRect.set(0, 0, width, height);
12528                }
12529            }
12530
12531            // The layer is not valid if the underlying GPU resources cannot be allocated
12532            if (!mHardwareLayer.isValid()) {
12533                return null;
12534            }
12535
12536            mHardwareLayer.setLayerPaint(mLayerPaint);
12537            mHardwareLayer.redrawLater(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
12538            ViewRootImpl viewRoot = getViewRootImpl();
12539            if (viewRoot != null) viewRoot.pushHardwareLayerUpdate(mHardwareLayer);
12540
12541            mLocalDirtyRect.setEmpty();
12542        }
12543
12544        return mHardwareLayer;
12545    }
12546
12547    /**
12548     * Destroys this View's hardware layer if possible.
12549     *
12550     * @return True if the layer was destroyed, false otherwise.
12551     *
12552     * @see #setLayerType(int, android.graphics.Paint)
12553     * @see #LAYER_TYPE_HARDWARE
12554     */
12555    boolean destroyLayer(boolean valid) {
12556        if (mHardwareLayer != null) {
12557            AttachInfo info = mAttachInfo;
12558            if (info != null && info.mHardwareRenderer != null &&
12559                    info.mHardwareRenderer.isEnabled() &&
12560                    (valid || info.mHardwareRenderer.validate())) {
12561                mHardwareLayer.destroy();
12562                mHardwareLayer = null;
12563
12564                if (mDisplayList != null) {
12565                    mDisplayList.reset();
12566                }
12567                invalidate(true);
12568                invalidateParentCaches();
12569            }
12570            return true;
12571        }
12572        return false;
12573    }
12574
12575    /**
12576     * Destroys all hardware rendering resources. This method is invoked
12577     * when the system needs to reclaim resources. Upon execution of this
12578     * method, you should free any OpenGL resources created by the view.
12579     *
12580     * Note: you <strong>must</strong> call
12581     * <code>super.destroyHardwareResources()</code> when overriding
12582     * this method.
12583     *
12584     * @hide
12585     */
12586    protected void destroyHardwareResources() {
12587        destroyLayer(true);
12588    }
12589
12590    /**
12591     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
12592     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
12593     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
12594     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
12595     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
12596     * null.</p>
12597     *
12598     * <p>Enabling the drawing cache is similar to
12599     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
12600     * acceleration is turned off. When hardware acceleration is turned on, enabling the
12601     * drawing cache has no effect on rendering because the system uses a different mechanism
12602     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
12603     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
12604     * for information on how to enable software and hardware layers.</p>
12605     *
12606     * <p>This API can be used to manually generate
12607     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
12608     * {@link #getDrawingCache()}.</p>
12609     *
12610     * @param enabled true to enable the drawing cache, false otherwise
12611     *
12612     * @see #isDrawingCacheEnabled()
12613     * @see #getDrawingCache()
12614     * @see #buildDrawingCache()
12615     * @see #setLayerType(int, android.graphics.Paint)
12616     */
12617    public void setDrawingCacheEnabled(boolean enabled) {
12618        mCachingFailed = false;
12619        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
12620    }
12621
12622    /**
12623     * <p>Indicates whether the drawing cache is enabled for this view.</p>
12624     *
12625     * @return true if the drawing cache is enabled
12626     *
12627     * @see #setDrawingCacheEnabled(boolean)
12628     * @see #getDrawingCache()
12629     */
12630    @ViewDebug.ExportedProperty(category = "drawing")
12631    public boolean isDrawingCacheEnabled() {
12632        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
12633    }
12634
12635    /**
12636     * Debugging utility which recursively outputs the dirty state of a view and its
12637     * descendants.
12638     *
12639     * @hide
12640     */
12641    @SuppressWarnings({"UnusedDeclaration"})
12642    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
12643        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
12644                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
12645                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
12646                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
12647        if (clear) {
12648            mPrivateFlags &= clearMask;
12649        }
12650        if (this instanceof ViewGroup) {
12651            ViewGroup parent = (ViewGroup) this;
12652            final int count = parent.getChildCount();
12653            for (int i = 0; i < count; i++) {
12654                final View child = parent.getChildAt(i);
12655                child.outputDirtyFlags(indent + "  ", clear, clearMask);
12656            }
12657        }
12658    }
12659
12660    /**
12661     * This method is used by ViewGroup to cause its children to restore or recreate their
12662     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
12663     * to recreate its own display list, which would happen if it went through the normal
12664     * draw/dispatchDraw mechanisms.
12665     *
12666     * @hide
12667     */
12668    protected void dispatchGetDisplayList() {}
12669
12670    /**
12671     * A view that is not attached or hardware accelerated cannot create a display list.
12672     * This method checks these conditions and returns the appropriate result.
12673     *
12674     * @return true if view has the ability to create a display list, false otherwise.
12675     *
12676     * @hide
12677     */
12678    public boolean canHaveDisplayList() {
12679        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
12680    }
12681
12682    /**
12683     * @return The HardwareRenderer associated with that view or null if hardware rendering
12684     * is not supported or this this has not been attached to a window.
12685     *
12686     * @hide
12687     */
12688    public HardwareRenderer getHardwareRenderer() {
12689        if (mAttachInfo != null) {
12690            return mAttachInfo.mHardwareRenderer;
12691        }
12692        return null;
12693    }
12694
12695    /**
12696     * Returns a DisplayList. If the incoming displayList is null, one will be created.
12697     * Otherwise, the same display list will be returned (after having been rendered into
12698     * along the way, depending on the invalidation state of the view).
12699     *
12700     * @param displayList The previous version of this displayList, could be null.
12701     * @param isLayer Whether the requester of the display list is a layer. If so,
12702     * the view will avoid creating a layer inside the resulting display list.
12703     * @return A new or reused DisplayList object.
12704     */
12705    private DisplayList getDisplayList(DisplayList displayList, boolean isLayer) {
12706        if (!canHaveDisplayList()) {
12707            return null;
12708        }
12709
12710        if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 ||
12711                displayList == null || !displayList.isValid() ||
12712                (!isLayer && mRecreateDisplayList))) {
12713            // Don't need to recreate the display list, just need to tell our
12714            // children to restore/recreate theirs
12715            if (displayList != null && displayList.isValid() &&
12716                    !isLayer && !mRecreateDisplayList) {
12717                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12718                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12719                dispatchGetDisplayList();
12720
12721                return displayList;
12722            }
12723
12724            if (!isLayer) {
12725                // If we got here, we're recreating it. Mark it as such to ensure that
12726                // we copy in child display lists into ours in drawChild()
12727                mRecreateDisplayList = true;
12728            }
12729            if (displayList == null) {
12730                final String name = getClass().getSimpleName();
12731                displayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
12732                // If we're creating a new display list, make sure our parent gets invalidated
12733                // since they will need to recreate their display list to account for this
12734                // new child display list.
12735                invalidateParentCaches();
12736            }
12737
12738            boolean caching = false;
12739            final HardwareCanvas canvas = displayList.start();
12740            int width = mRight - mLeft;
12741            int height = mBottom - mTop;
12742            int layerType = getLayerType();
12743
12744            try {
12745                canvas.setViewport(width, height);
12746                // The dirty rect should always be null for a display list
12747                canvas.onPreDraw(null);
12748                if (!isLayer && layerType != LAYER_TYPE_NONE) {
12749                    if (layerType == LAYER_TYPE_HARDWARE) {
12750                        final HardwareLayer layer = getHardwareLayer();
12751                        if (layer != null && layer.isValid()) {
12752                            canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
12753                        } else {
12754                            canvas.saveLayer(0, 0, mRight - mLeft, mBottom - mTop, mLayerPaint,
12755                                    Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
12756                                            Canvas.CLIP_TO_LAYER_SAVE_FLAG);
12757                        }
12758                        caching = true;
12759                    } else {
12760                        buildDrawingCache(true);
12761                        Bitmap cache = getDrawingCache(true);
12762                        if (cache != null) {
12763                            canvas.drawBitmap(cache, 0, 0, mLayerPaint);
12764                            caching = true;
12765                        }
12766                    }
12767                } else {
12768
12769                    computeScroll();
12770
12771                    canvas.translate(-mScrollX, -mScrollY);
12772                    if (!isLayer) {
12773                        mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12774                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12775                    }
12776
12777                    // Fast path for layouts with no backgrounds
12778                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
12779                        dispatchDraw(canvas);
12780                    } else {
12781                        draw(canvas);
12782                    }
12783                }
12784            } finally {
12785                canvas.onPostDraw();
12786
12787                displayList.end();
12788                displayList.setCaching(caching);
12789                if (isLayer) {
12790                    displayList.setLeftTopRightBottom(0, 0, width, height);
12791                } else {
12792                    setDisplayListProperties(displayList);
12793                }
12794            }
12795        } else if (!isLayer) {
12796            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12797            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12798        }
12799
12800        return displayList;
12801    }
12802
12803    /**
12804     * Get the DisplayList for the HardwareLayer
12805     *
12806     * @param layer The HardwareLayer whose DisplayList we want
12807     * @return A DisplayList fopr the specified HardwareLayer
12808     */
12809    private DisplayList getHardwareLayerDisplayList(HardwareLayer layer) {
12810        DisplayList displayList = getDisplayList(layer.getDisplayList(), true);
12811        layer.setDisplayList(displayList);
12812        return displayList;
12813    }
12814
12815
12816    /**
12817     * <p>Returns a display list that can be used to draw this view again
12818     * without executing its draw method.</p>
12819     *
12820     * @return A DisplayList ready to replay, or null if caching is not enabled.
12821     *
12822     * @hide
12823     */
12824    public DisplayList getDisplayList() {
12825        mDisplayList = getDisplayList(mDisplayList, false);
12826        return mDisplayList;
12827    }
12828
12829    private void clearDisplayList() {
12830        if (mDisplayList != null) {
12831            mDisplayList.invalidate();
12832            mDisplayList.clear();
12833        }
12834    }
12835
12836    /**
12837     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
12838     *
12839     * @return A non-scaled bitmap representing this view or null if cache is disabled.
12840     *
12841     * @see #getDrawingCache(boolean)
12842     */
12843    public Bitmap getDrawingCache() {
12844        return getDrawingCache(false);
12845    }
12846
12847    /**
12848     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
12849     * is null when caching is disabled. If caching is enabled and the cache is not ready,
12850     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
12851     * draw from the cache when the cache is enabled. To benefit from the cache, you must
12852     * request the drawing cache by calling this method and draw it on screen if the
12853     * returned bitmap is not null.</p>
12854     *
12855     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12856     * this method will create a bitmap of the same size as this view. Because this bitmap
12857     * will be drawn scaled by the parent ViewGroup, the result on screen might show
12858     * scaling artifacts. To avoid such artifacts, you should call this method by setting
12859     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12860     * size than the view. This implies that your application must be able to handle this
12861     * size.</p>
12862     *
12863     * @param autoScale Indicates whether the generated bitmap should be scaled based on
12864     *        the current density of the screen when the application is in compatibility
12865     *        mode.
12866     *
12867     * @return A bitmap representing this view or null if cache is disabled.
12868     *
12869     * @see #setDrawingCacheEnabled(boolean)
12870     * @see #isDrawingCacheEnabled()
12871     * @see #buildDrawingCache(boolean)
12872     * @see #destroyDrawingCache()
12873     */
12874    public Bitmap getDrawingCache(boolean autoScale) {
12875        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
12876            return null;
12877        }
12878        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
12879            buildDrawingCache(autoScale);
12880        }
12881        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
12882    }
12883
12884    /**
12885     * <p>Frees the resources used by the drawing cache. If you call
12886     * {@link #buildDrawingCache()} manually without calling
12887     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12888     * should cleanup the cache with this method afterwards.</p>
12889     *
12890     * @see #setDrawingCacheEnabled(boolean)
12891     * @see #buildDrawingCache()
12892     * @see #getDrawingCache()
12893     */
12894    public void destroyDrawingCache() {
12895        if (mDrawingCache != null) {
12896            mDrawingCache.recycle();
12897            mDrawingCache = null;
12898        }
12899        if (mUnscaledDrawingCache != null) {
12900            mUnscaledDrawingCache.recycle();
12901            mUnscaledDrawingCache = null;
12902        }
12903    }
12904
12905    /**
12906     * Setting a solid background color for the drawing cache's bitmaps will improve
12907     * performance and memory usage. Note, though that this should only be used if this
12908     * view will always be drawn on top of a solid color.
12909     *
12910     * @param color The background color to use for the drawing cache's bitmap
12911     *
12912     * @see #setDrawingCacheEnabled(boolean)
12913     * @see #buildDrawingCache()
12914     * @see #getDrawingCache()
12915     */
12916    public void setDrawingCacheBackgroundColor(int color) {
12917        if (color != mDrawingCacheBackgroundColor) {
12918            mDrawingCacheBackgroundColor = color;
12919            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12920        }
12921    }
12922
12923    /**
12924     * @see #setDrawingCacheBackgroundColor(int)
12925     *
12926     * @return The background color to used for the drawing cache's bitmap
12927     */
12928    public int getDrawingCacheBackgroundColor() {
12929        return mDrawingCacheBackgroundColor;
12930    }
12931
12932    /**
12933     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
12934     *
12935     * @see #buildDrawingCache(boolean)
12936     */
12937    public void buildDrawingCache() {
12938        buildDrawingCache(false);
12939    }
12940
12941    /**
12942     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
12943     *
12944     * <p>If you call {@link #buildDrawingCache()} manually without calling
12945     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12946     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
12947     *
12948     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12949     * this method will create a bitmap of the same size as this view. Because this bitmap
12950     * will be drawn scaled by the parent ViewGroup, the result on screen might show
12951     * scaling artifacts. To avoid such artifacts, you should call this method by setting
12952     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12953     * size than the view. This implies that your application must be able to handle this
12954     * size.</p>
12955     *
12956     * <p>You should avoid calling this method when hardware acceleration is enabled. If
12957     * you do not need the drawing cache bitmap, calling this method will increase memory
12958     * usage and cause the view to be rendered in software once, thus negatively impacting
12959     * performance.</p>
12960     *
12961     * @see #getDrawingCache()
12962     * @see #destroyDrawingCache()
12963     */
12964    public void buildDrawingCache(boolean autoScale) {
12965        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
12966                mDrawingCache == null : mUnscaledDrawingCache == null)) {
12967            mCachingFailed = false;
12968
12969            int width = mRight - mLeft;
12970            int height = mBottom - mTop;
12971
12972            final AttachInfo attachInfo = mAttachInfo;
12973            final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
12974
12975            if (autoScale && scalingRequired) {
12976                width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
12977                height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
12978            }
12979
12980            final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
12981            final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
12982            final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
12983
12984            final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
12985            final long drawingCacheSize =
12986                    ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
12987            if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
12988                if (width > 0 && height > 0) {
12989                    Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
12990                            + projectedBitmapSize + " bytes, only "
12991                            + drawingCacheSize + " available");
12992                }
12993                destroyDrawingCache();
12994                mCachingFailed = true;
12995                return;
12996            }
12997
12998            boolean clear = true;
12999            Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
13000
13001            if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
13002                Bitmap.Config quality;
13003                if (!opaque) {
13004                    // Never pick ARGB_4444 because it looks awful
13005                    // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
13006                    switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
13007                        case DRAWING_CACHE_QUALITY_AUTO:
13008                            quality = Bitmap.Config.ARGB_8888;
13009                            break;
13010                        case DRAWING_CACHE_QUALITY_LOW:
13011                            quality = Bitmap.Config.ARGB_8888;
13012                            break;
13013                        case DRAWING_CACHE_QUALITY_HIGH:
13014                            quality = Bitmap.Config.ARGB_8888;
13015                            break;
13016                        default:
13017                            quality = Bitmap.Config.ARGB_8888;
13018                            break;
13019                    }
13020                } else {
13021                    // Optimization for translucent windows
13022                    // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
13023                    quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
13024                }
13025
13026                // Try to cleanup memory
13027                if (bitmap != null) bitmap.recycle();
13028
13029                try {
13030                    bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
13031                            width, height, quality);
13032                    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
13033                    if (autoScale) {
13034                        mDrawingCache = bitmap;
13035                    } else {
13036                        mUnscaledDrawingCache = bitmap;
13037                    }
13038                    if (opaque && use32BitCache) bitmap.setHasAlpha(false);
13039                } catch (OutOfMemoryError e) {
13040                    // If there is not enough memory to create the bitmap cache, just
13041                    // ignore the issue as bitmap caches are not required to draw the
13042                    // view hierarchy
13043                    if (autoScale) {
13044                        mDrawingCache = null;
13045                    } else {
13046                        mUnscaledDrawingCache = null;
13047                    }
13048                    mCachingFailed = true;
13049                    return;
13050                }
13051
13052                clear = drawingCacheBackgroundColor != 0;
13053            }
13054
13055            Canvas canvas;
13056            if (attachInfo != null) {
13057                canvas = attachInfo.mCanvas;
13058                if (canvas == null) {
13059                    canvas = new Canvas();
13060                }
13061                canvas.setBitmap(bitmap);
13062                // Temporarily clobber the cached Canvas in case one of our children
13063                // is also using a drawing cache. Without this, the children would
13064                // steal the canvas by attaching their own bitmap to it and bad, bad
13065                // thing would happen (invisible views, corrupted drawings, etc.)
13066                attachInfo.mCanvas = null;
13067            } else {
13068                // This case should hopefully never or seldom happen
13069                canvas = new Canvas(bitmap);
13070            }
13071
13072            if (clear) {
13073                bitmap.eraseColor(drawingCacheBackgroundColor);
13074            }
13075
13076            computeScroll();
13077            final int restoreCount = canvas.save();
13078
13079            if (autoScale && scalingRequired) {
13080                final float scale = attachInfo.mApplicationScale;
13081                canvas.scale(scale, scale);
13082            }
13083
13084            canvas.translate(-mScrollX, -mScrollY);
13085
13086            mPrivateFlags |= PFLAG_DRAWN;
13087            if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
13088                    mLayerType != LAYER_TYPE_NONE) {
13089                mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
13090            }
13091
13092            // Fast path for layouts with no backgrounds
13093            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13094                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13095                dispatchDraw(canvas);
13096            } else {
13097                draw(canvas);
13098            }
13099
13100            canvas.restoreToCount(restoreCount);
13101            canvas.setBitmap(null);
13102
13103            if (attachInfo != null) {
13104                // Restore the cached Canvas for our siblings
13105                attachInfo.mCanvas = canvas;
13106            }
13107        }
13108    }
13109
13110    /**
13111     * Create a snapshot of the view into a bitmap.  We should probably make
13112     * some form of this public, but should think about the API.
13113     */
13114    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
13115        int width = mRight - mLeft;
13116        int height = mBottom - mTop;
13117
13118        final AttachInfo attachInfo = mAttachInfo;
13119        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
13120        width = (int) ((width * scale) + 0.5f);
13121        height = (int) ((height * scale) + 0.5f);
13122
13123        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
13124                width > 0 ? width : 1, height > 0 ? height : 1, quality);
13125        if (bitmap == null) {
13126            throw new OutOfMemoryError();
13127        }
13128
13129        Resources resources = getResources();
13130        if (resources != null) {
13131            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
13132        }
13133
13134        Canvas canvas;
13135        if (attachInfo != null) {
13136            canvas = attachInfo.mCanvas;
13137            if (canvas == null) {
13138                canvas = new Canvas();
13139            }
13140            canvas.setBitmap(bitmap);
13141            // Temporarily clobber the cached Canvas in case one of our children
13142            // is also using a drawing cache. Without this, the children would
13143            // steal the canvas by attaching their own bitmap to it and bad, bad
13144            // things would happen (invisible views, corrupted drawings, etc.)
13145            attachInfo.mCanvas = null;
13146        } else {
13147            // This case should hopefully never or seldom happen
13148            canvas = new Canvas(bitmap);
13149        }
13150
13151        if ((backgroundColor & 0xff000000) != 0) {
13152            bitmap.eraseColor(backgroundColor);
13153        }
13154
13155        computeScroll();
13156        final int restoreCount = canvas.save();
13157        canvas.scale(scale, scale);
13158        canvas.translate(-mScrollX, -mScrollY);
13159
13160        // Temporarily remove the dirty mask
13161        int flags = mPrivateFlags;
13162        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13163
13164        // Fast path for layouts with no backgrounds
13165        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13166            dispatchDraw(canvas);
13167        } else {
13168            draw(canvas);
13169        }
13170
13171        mPrivateFlags = flags;
13172
13173        canvas.restoreToCount(restoreCount);
13174        canvas.setBitmap(null);
13175
13176        if (attachInfo != null) {
13177            // Restore the cached Canvas for our siblings
13178            attachInfo.mCanvas = canvas;
13179        }
13180
13181        return bitmap;
13182    }
13183
13184    /**
13185     * Indicates whether this View is currently in edit mode. A View is usually
13186     * in edit mode when displayed within a developer tool. For instance, if
13187     * this View is being drawn by a visual user interface builder, this method
13188     * should return true.
13189     *
13190     * Subclasses should check the return value of this method to provide
13191     * different behaviors if their normal behavior might interfere with the
13192     * host environment. For instance: the class spawns a thread in its
13193     * constructor, the drawing code relies on device-specific features, etc.
13194     *
13195     * This method is usually checked in the drawing code of custom widgets.
13196     *
13197     * @return True if this View is in edit mode, false otherwise.
13198     */
13199    public boolean isInEditMode() {
13200        return false;
13201    }
13202
13203    /**
13204     * If the View draws content inside its padding and enables fading edges,
13205     * it needs to support padding offsets. Padding offsets are added to the
13206     * fading edges to extend the length of the fade so that it covers pixels
13207     * drawn inside the padding.
13208     *
13209     * Subclasses of this class should override this method if they need
13210     * to draw content inside the padding.
13211     *
13212     * @return True if padding offset must be applied, false otherwise.
13213     *
13214     * @see #getLeftPaddingOffset()
13215     * @see #getRightPaddingOffset()
13216     * @see #getTopPaddingOffset()
13217     * @see #getBottomPaddingOffset()
13218     *
13219     * @since CURRENT
13220     */
13221    protected boolean isPaddingOffsetRequired() {
13222        return false;
13223    }
13224
13225    /**
13226     * Amount by which to extend the left fading region. Called only when
13227     * {@link #isPaddingOffsetRequired()} returns true.
13228     *
13229     * @return The left padding offset in pixels.
13230     *
13231     * @see #isPaddingOffsetRequired()
13232     *
13233     * @since CURRENT
13234     */
13235    protected int getLeftPaddingOffset() {
13236        return 0;
13237    }
13238
13239    /**
13240     * Amount by which to extend the right fading region. Called only when
13241     * {@link #isPaddingOffsetRequired()} returns true.
13242     *
13243     * @return The right padding offset in pixels.
13244     *
13245     * @see #isPaddingOffsetRequired()
13246     *
13247     * @since CURRENT
13248     */
13249    protected int getRightPaddingOffset() {
13250        return 0;
13251    }
13252
13253    /**
13254     * Amount by which to extend the top fading region. Called only when
13255     * {@link #isPaddingOffsetRequired()} returns true.
13256     *
13257     * @return The top padding offset in pixels.
13258     *
13259     * @see #isPaddingOffsetRequired()
13260     *
13261     * @since CURRENT
13262     */
13263    protected int getTopPaddingOffset() {
13264        return 0;
13265    }
13266
13267    /**
13268     * Amount by which to extend the bottom fading region. Called only when
13269     * {@link #isPaddingOffsetRequired()} returns true.
13270     *
13271     * @return The bottom padding offset in pixels.
13272     *
13273     * @see #isPaddingOffsetRequired()
13274     *
13275     * @since CURRENT
13276     */
13277    protected int getBottomPaddingOffset() {
13278        return 0;
13279    }
13280
13281    /**
13282     * @hide
13283     * @param offsetRequired
13284     */
13285    protected int getFadeTop(boolean offsetRequired) {
13286        int top = mPaddingTop;
13287        if (offsetRequired) top += getTopPaddingOffset();
13288        return top;
13289    }
13290
13291    /**
13292     * @hide
13293     * @param offsetRequired
13294     */
13295    protected int getFadeHeight(boolean offsetRequired) {
13296        int padding = mPaddingTop;
13297        if (offsetRequired) padding += getTopPaddingOffset();
13298        return mBottom - mTop - mPaddingBottom - padding;
13299    }
13300
13301    /**
13302     * <p>Indicates whether this view is attached to a hardware accelerated
13303     * window or not.</p>
13304     *
13305     * <p>Even if this method returns true, it does not mean that every call
13306     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
13307     * accelerated {@link android.graphics.Canvas}. For instance, if this view
13308     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
13309     * window is hardware accelerated,
13310     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
13311     * return false, and this method will return true.</p>
13312     *
13313     * @return True if the view is attached to a window and the window is
13314     *         hardware accelerated; false in any other case.
13315     */
13316    public boolean isHardwareAccelerated() {
13317        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
13318    }
13319
13320    /**
13321     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
13322     * case of an active Animation being run on the view.
13323     */
13324    private boolean drawAnimation(ViewGroup parent, long drawingTime,
13325            Animation a, boolean scalingRequired) {
13326        Transformation invalidationTransform;
13327        final int flags = parent.mGroupFlags;
13328        final boolean initialized = a.isInitialized();
13329        if (!initialized) {
13330            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
13331            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
13332            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
13333            onAnimationStart();
13334        }
13335
13336        boolean more = a.getTransformation(drawingTime, parent.mChildTransformation, 1f);
13337        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
13338            if (parent.mInvalidationTransformation == null) {
13339                parent.mInvalidationTransformation = new Transformation();
13340            }
13341            invalidationTransform = parent.mInvalidationTransformation;
13342            a.getTransformation(drawingTime, invalidationTransform, 1f);
13343        } else {
13344            invalidationTransform = parent.mChildTransformation;
13345        }
13346
13347        if (more) {
13348            if (!a.willChangeBounds()) {
13349                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
13350                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
13351                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
13352                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
13353                    // The child need to draw an animation, potentially offscreen, so
13354                    // make sure we do not cancel invalidate requests
13355                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
13356                    parent.invalidate(mLeft, mTop, mRight, mBottom);
13357                }
13358            } else {
13359                if (parent.mInvalidateRegion == null) {
13360                    parent.mInvalidateRegion = new RectF();
13361                }
13362                final RectF region = parent.mInvalidateRegion;
13363                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
13364                        invalidationTransform);
13365
13366                // The child need to draw an animation, potentially offscreen, so
13367                // make sure we do not cancel invalidate requests
13368                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
13369
13370                final int left = mLeft + (int) region.left;
13371                final int top = mTop + (int) region.top;
13372                parent.invalidate(left, top, left + (int) (region.width() + .5f),
13373                        top + (int) (region.height() + .5f));
13374            }
13375        }
13376        return more;
13377    }
13378
13379    /**
13380     * This method is called by getDisplayList() when a display list is created or re-rendered.
13381     * It sets or resets the current value of all properties on that display list (resetting is
13382     * necessary when a display list is being re-created, because we need to make sure that
13383     * previously-set transform values
13384     */
13385    void setDisplayListProperties(DisplayList displayList) {
13386        if (displayList != null) {
13387            displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
13388            displayList.setHasOverlappingRendering(hasOverlappingRendering());
13389            if (mParent instanceof ViewGroup) {
13390                displayList.setClipChildren(
13391                        (((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
13392            }
13393            float alpha = 1;
13394            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
13395                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
13396                ViewGroup parentVG = (ViewGroup) mParent;
13397                final boolean hasTransform =
13398                        parentVG.getChildStaticTransformation(this, parentVG.mChildTransformation);
13399                if (hasTransform) {
13400                    Transformation transform = parentVG.mChildTransformation;
13401                    final int transformType = parentVG.mChildTransformation.getTransformationType();
13402                    if (transformType != Transformation.TYPE_IDENTITY) {
13403                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
13404                            alpha = transform.getAlpha();
13405                        }
13406                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
13407                            displayList.setStaticMatrix(transform.getMatrix());
13408                        }
13409                    }
13410                }
13411            }
13412            if (mTransformationInfo != null) {
13413                alpha *= mTransformationInfo.mAlpha;
13414                if (alpha < 1) {
13415                    final int multipliedAlpha = (int) (255 * alpha);
13416                    if (onSetAlpha(multipliedAlpha)) {
13417                        alpha = 1;
13418                    }
13419                }
13420                displayList.setTransformationInfo(alpha,
13421                        mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY,
13422                        mTransformationInfo.mRotation, mTransformationInfo.mRotationX,
13423                        mTransformationInfo.mRotationY, mTransformationInfo.mScaleX,
13424                        mTransformationInfo.mScaleY);
13425                if (mTransformationInfo.mCamera == null) {
13426                    mTransformationInfo.mCamera = new Camera();
13427                    mTransformationInfo.matrix3D = new Matrix();
13428                }
13429                displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ());
13430                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) {
13431                    displayList.setPivotX(getPivotX());
13432                    displayList.setPivotY(getPivotY());
13433                }
13434            } else if (alpha < 1) {
13435                displayList.setAlpha(alpha);
13436            }
13437        }
13438    }
13439
13440    /**
13441     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
13442     * This draw() method is an implementation detail and is not intended to be overridden or
13443     * to be called from anywhere else other than ViewGroup.drawChild().
13444     */
13445    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
13446        boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
13447        boolean more = false;
13448        final boolean childHasIdentityMatrix = hasIdentityMatrix();
13449        final int flags = parent.mGroupFlags;
13450
13451        if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
13452            parent.mChildTransformation.clear();
13453            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13454        }
13455
13456        Transformation transformToApply = null;
13457        boolean concatMatrix = false;
13458
13459        boolean scalingRequired = false;
13460        boolean caching;
13461        int layerType = getLayerType();
13462
13463        final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
13464        if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
13465                (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
13466            caching = true;
13467            // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
13468            if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
13469        } else {
13470            caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
13471        }
13472
13473        final Animation a = getAnimation();
13474        if (a != null) {
13475            more = drawAnimation(parent, drawingTime, a, scalingRequired);
13476            concatMatrix = a.willChangeTransformationMatrix();
13477            if (concatMatrix) {
13478                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
13479            }
13480            transformToApply = parent.mChildTransformation;
13481        } else {
13482            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) ==
13483                    PFLAG3_VIEW_IS_ANIMATING_TRANSFORM && mDisplayList != null) {
13484                // No longer animating: clear out old animation matrix
13485                mDisplayList.setAnimationMatrix(null);
13486                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
13487            }
13488            if (!useDisplayListProperties &&
13489                    (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
13490                final boolean hasTransform =
13491                        parent.getChildStaticTransformation(this, parent.mChildTransformation);
13492                if (hasTransform) {
13493                    final int transformType = parent.mChildTransformation.getTransformationType();
13494                    transformToApply = transformType != Transformation.TYPE_IDENTITY ?
13495                            parent.mChildTransformation : null;
13496                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
13497                }
13498            }
13499        }
13500
13501        concatMatrix |= !childHasIdentityMatrix;
13502
13503        // Sets the flag as early as possible to allow draw() implementations
13504        // to call invalidate() successfully when doing animations
13505        mPrivateFlags |= PFLAG_DRAWN;
13506
13507        if (!concatMatrix &&
13508                (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
13509                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
13510                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
13511                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
13512            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
13513            return more;
13514        }
13515        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
13516
13517        if (hardwareAccelerated) {
13518            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
13519            // retain the flag's value temporarily in the mRecreateDisplayList flag
13520            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
13521            mPrivateFlags &= ~PFLAG_INVALIDATED;
13522        }
13523
13524        DisplayList displayList = null;
13525        Bitmap cache = null;
13526        boolean hasDisplayList = false;
13527        if (caching) {
13528            if (!hardwareAccelerated) {
13529                if (layerType != LAYER_TYPE_NONE) {
13530                    layerType = LAYER_TYPE_SOFTWARE;
13531                    buildDrawingCache(true);
13532                }
13533                cache = getDrawingCache(true);
13534            } else {
13535                switch (layerType) {
13536                    case LAYER_TYPE_SOFTWARE:
13537                        if (useDisplayListProperties) {
13538                            hasDisplayList = canHaveDisplayList();
13539                        } else {
13540                            buildDrawingCache(true);
13541                            cache = getDrawingCache(true);
13542                        }
13543                        break;
13544                    case LAYER_TYPE_HARDWARE:
13545                        if (useDisplayListProperties) {
13546                            hasDisplayList = canHaveDisplayList();
13547                        }
13548                        break;
13549                    case LAYER_TYPE_NONE:
13550                        // Delay getting the display list until animation-driven alpha values are
13551                        // set up and possibly passed on to the view
13552                        hasDisplayList = canHaveDisplayList();
13553                        break;
13554                }
13555            }
13556        }
13557        useDisplayListProperties &= hasDisplayList;
13558        if (useDisplayListProperties) {
13559            displayList = getDisplayList();
13560            if (!displayList.isValid()) {
13561                // Uncommon, but possible. If a view is removed from the hierarchy during the call
13562                // to getDisplayList(), the display list will be marked invalid and we should not
13563                // try to use it again.
13564                displayList = null;
13565                hasDisplayList = false;
13566                useDisplayListProperties = false;
13567            }
13568        }
13569
13570        int sx = 0;
13571        int sy = 0;
13572        if (!hasDisplayList) {
13573            computeScroll();
13574            sx = mScrollX;
13575            sy = mScrollY;
13576        }
13577
13578        final boolean hasNoCache = cache == null || hasDisplayList;
13579        final boolean offsetForScroll = cache == null && !hasDisplayList &&
13580                layerType != LAYER_TYPE_HARDWARE;
13581
13582        int restoreTo = -1;
13583        if (!useDisplayListProperties || transformToApply != null) {
13584            restoreTo = canvas.save();
13585        }
13586        if (offsetForScroll) {
13587            canvas.translate(mLeft - sx, mTop - sy);
13588        } else {
13589            if (!useDisplayListProperties) {
13590                canvas.translate(mLeft, mTop);
13591            }
13592            if (scalingRequired) {
13593                if (useDisplayListProperties) {
13594                    // TODO: Might not need this if we put everything inside the DL
13595                    restoreTo = canvas.save();
13596                }
13597                // mAttachInfo cannot be null, otherwise scalingRequired == false
13598                final float scale = 1.0f / mAttachInfo.mApplicationScale;
13599                canvas.scale(scale, scale);
13600            }
13601        }
13602
13603        float alpha = useDisplayListProperties ? 1 : getAlpha();
13604        if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
13605                (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
13606            if (transformToApply != null || !childHasIdentityMatrix) {
13607                int transX = 0;
13608                int transY = 0;
13609
13610                if (offsetForScroll) {
13611                    transX = -sx;
13612                    transY = -sy;
13613                }
13614
13615                if (transformToApply != null) {
13616                    if (concatMatrix) {
13617                        if (useDisplayListProperties) {
13618                            displayList.setAnimationMatrix(transformToApply.getMatrix());
13619                        } else {
13620                            // Undo the scroll translation, apply the transformation matrix,
13621                            // then redo the scroll translate to get the correct result.
13622                            canvas.translate(-transX, -transY);
13623                            canvas.concat(transformToApply.getMatrix());
13624                            canvas.translate(transX, transY);
13625                        }
13626                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13627                    }
13628
13629                    float transformAlpha = transformToApply.getAlpha();
13630                    if (transformAlpha < 1) {
13631                        alpha *= transformAlpha;
13632                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13633                    }
13634                }
13635
13636                if (!childHasIdentityMatrix && !useDisplayListProperties) {
13637                    canvas.translate(-transX, -transY);
13638                    canvas.concat(getMatrix());
13639                    canvas.translate(transX, transY);
13640                }
13641            }
13642
13643            // Deal with alpha if it is or used to be <1
13644            if (alpha < 1 ||
13645                    (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
13646                if (alpha < 1) {
13647                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
13648                } else {
13649                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
13650                }
13651                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13652                if (hasNoCache) {
13653                    final int multipliedAlpha = (int) (255 * alpha);
13654                    if (!onSetAlpha(multipliedAlpha)) {
13655                        int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
13656                        if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
13657                                layerType != LAYER_TYPE_NONE) {
13658                            layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
13659                        }
13660                        if (useDisplayListProperties) {
13661                            displayList.setAlpha(alpha * getAlpha());
13662                        } else  if (layerType == LAYER_TYPE_NONE) {
13663                            final int scrollX = hasDisplayList ? 0 : sx;
13664                            final int scrollY = hasDisplayList ? 0 : sy;
13665                            canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
13666                                    scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
13667                        }
13668                    } else {
13669                        // Alpha is handled by the child directly, clobber the layer's alpha
13670                        mPrivateFlags |= PFLAG_ALPHA_SET;
13671                    }
13672                }
13673            }
13674        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
13675            onSetAlpha(255);
13676            mPrivateFlags &= ~PFLAG_ALPHA_SET;
13677        }
13678
13679        if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
13680                !useDisplayListProperties && layerType == LAYER_TYPE_NONE) {
13681            if (offsetForScroll) {
13682                canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
13683            } else {
13684                if (!scalingRequired || cache == null) {
13685                    canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
13686                } else {
13687                    canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
13688                }
13689            }
13690        }
13691
13692        if (!useDisplayListProperties && hasDisplayList) {
13693            displayList = getDisplayList();
13694            if (!displayList.isValid()) {
13695                // Uncommon, but possible. If a view is removed from the hierarchy during the call
13696                // to getDisplayList(), the display list will be marked invalid and we should not
13697                // try to use it again.
13698                displayList = null;
13699                hasDisplayList = false;
13700            }
13701        }
13702
13703        if (hasNoCache) {
13704            boolean layerRendered = false;
13705            if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) {
13706                final HardwareLayer layer = getHardwareLayer();
13707                if (layer != null && layer.isValid()) {
13708                    mLayerPaint.setAlpha((int) (alpha * 255));
13709                    ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
13710                    layerRendered = true;
13711                } else {
13712                    final int scrollX = hasDisplayList ? 0 : sx;
13713                    final int scrollY = hasDisplayList ? 0 : sy;
13714                    canvas.saveLayer(scrollX, scrollY,
13715                            scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
13716                            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
13717                }
13718            }
13719
13720            if (!layerRendered) {
13721                if (!hasDisplayList) {
13722                    // Fast path for layouts with no backgrounds
13723                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13724                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13725                        dispatchDraw(canvas);
13726                    } else {
13727                        draw(canvas);
13728                    }
13729                } else {
13730                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13731                    ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
13732                }
13733            }
13734        } else if (cache != null) {
13735            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13736            Paint cachePaint;
13737
13738            if (layerType == LAYER_TYPE_NONE) {
13739                cachePaint = parent.mCachePaint;
13740                if (cachePaint == null) {
13741                    cachePaint = new Paint();
13742                    cachePaint.setDither(false);
13743                    parent.mCachePaint = cachePaint;
13744                }
13745                if (alpha < 1) {
13746                    cachePaint.setAlpha((int) (alpha * 255));
13747                    parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
13748                } else if  ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) {
13749                    cachePaint.setAlpha(255);
13750                    parent.mGroupFlags &= ~ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
13751                }
13752            } else {
13753                cachePaint = mLayerPaint;
13754                cachePaint.setAlpha((int) (alpha * 255));
13755            }
13756            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
13757        }
13758
13759        if (restoreTo >= 0) {
13760            canvas.restoreToCount(restoreTo);
13761        }
13762
13763        if (a != null && !more) {
13764            if (!hardwareAccelerated && !a.getFillAfter()) {
13765                onSetAlpha(255);
13766            }
13767            parent.finishAnimatingView(this, a);
13768        }
13769
13770        if (more && hardwareAccelerated) {
13771            // invalidation is the trigger to recreate display lists, so if we're using
13772            // display lists to render, force an invalidate to allow the animation to
13773            // continue drawing another frame
13774            parent.invalidate(true);
13775            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
13776                // alpha animations should cause the child to recreate its display list
13777                invalidate(true);
13778            }
13779        }
13780
13781        mRecreateDisplayList = false;
13782
13783        return more;
13784    }
13785
13786    /**
13787     * Manually render this view (and all of its children) to the given Canvas.
13788     * The view must have already done a full layout before this function is
13789     * called.  When implementing a view, implement
13790     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
13791     * If you do need to override this method, call the superclass version.
13792     *
13793     * @param canvas The Canvas to which the View is rendered.
13794     */
13795    public void draw(Canvas canvas) {
13796        final int privateFlags = mPrivateFlags;
13797        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
13798                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
13799        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
13800
13801        /*
13802         * Draw traversal performs several drawing steps which must be executed
13803         * in the appropriate order:
13804         *
13805         *      1. Draw the background
13806         *      2. If necessary, save the canvas' layers to prepare for fading
13807         *      3. Draw view's content
13808         *      4. Draw children
13809         *      5. If necessary, draw the fading edges and restore layers
13810         *      6. Draw decorations (scrollbars for instance)
13811         */
13812
13813        // Step 1, draw the background, if needed
13814        int saveCount;
13815
13816        if (!dirtyOpaque) {
13817            final Drawable background = mBackground;
13818            if (background != null) {
13819                final int scrollX = mScrollX;
13820                final int scrollY = mScrollY;
13821
13822                if (mBackgroundSizeChanged) {
13823                    background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
13824                    mBackgroundSizeChanged = false;
13825                }
13826
13827                if ((scrollX | scrollY) == 0) {
13828                    background.draw(canvas);
13829                } else {
13830                    canvas.translate(scrollX, scrollY);
13831                    background.draw(canvas);
13832                    canvas.translate(-scrollX, -scrollY);
13833                }
13834            }
13835        }
13836
13837        // skip step 2 & 5 if possible (common case)
13838        final int viewFlags = mViewFlags;
13839        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
13840        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
13841        if (!verticalEdges && !horizontalEdges) {
13842            // Step 3, draw the content
13843            if (!dirtyOpaque) onDraw(canvas);
13844
13845            // Step 4, draw the children
13846            dispatchDraw(canvas);
13847
13848            // Step 6, draw decorations (scrollbars)
13849            onDrawScrollBars(canvas);
13850
13851            // we're done...
13852            return;
13853        }
13854
13855        /*
13856         * Here we do the full fledged routine...
13857         * (this is an uncommon case where speed matters less,
13858         * this is why we repeat some of the tests that have been
13859         * done above)
13860         */
13861
13862        boolean drawTop = false;
13863        boolean drawBottom = false;
13864        boolean drawLeft = false;
13865        boolean drawRight = false;
13866
13867        float topFadeStrength = 0.0f;
13868        float bottomFadeStrength = 0.0f;
13869        float leftFadeStrength = 0.0f;
13870        float rightFadeStrength = 0.0f;
13871
13872        // Step 2, save the canvas' layers
13873        int paddingLeft = mPaddingLeft;
13874
13875        final boolean offsetRequired = isPaddingOffsetRequired();
13876        if (offsetRequired) {
13877            paddingLeft += getLeftPaddingOffset();
13878        }
13879
13880        int left = mScrollX + paddingLeft;
13881        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
13882        int top = mScrollY + getFadeTop(offsetRequired);
13883        int bottom = top + getFadeHeight(offsetRequired);
13884
13885        if (offsetRequired) {
13886            right += getRightPaddingOffset();
13887            bottom += getBottomPaddingOffset();
13888        }
13889
13890        final ScrollabilityCache scrollabilityCache = mScrollCache;
13891        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
13892        int length = (int) fadeHeight;
13893
13894        // clip the fade length if top and bottom fades overlap
13895        // overlapping fades produce odd-looking artifacts
13896        if (verticalEdges && (top + length > bottom - length)) {
13897            length = (bottom - top) / 2;
13898        }
13899
13900        // also clip horizontal fades if necessary
13901        if (horizontalEdges && (left + length > right - length)) {
13902            length = (right - left) / 2;
13903        }
13904
13905        if (verticalEdges) {
13906            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
13907            drawTop = topFadeStrength * fadeHeight > 1.0f;
13908            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
13909            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
13910        }
13911
13912        if (horizontalEdges) {
13913            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
13914            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
13915            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
13916            drawRight = rightFadeStrength * fadeHeight > 1.0f;
13917        }
13918
13919        saveCount = canvas.getSaveCount();
13920
13921        int solidColor = getSolidColor();
13922        if (solidColor == 0) {
13923            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
13924
13925            if (drawTop) {
13926                canvas.saveLayer(left, top, right, top + length, null, flags);
13927            }
13928
13929            if (drawBottom) {
13930                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
13931            }
13932
13933            if (drawLeft) {
13934                canvas.saveLayer(left, top, left + length, bottom, null, flags);
13935            }
13936
13937            if (drawRight) {
13938                canvas.saveLayer(right - length, top, right, bottom, null, flags);
13939            }
13940        } else {
13941            scrollabilityCache.setFadeColor(solidColor);
13942        }
13943
13944        // Step 3, draw the content
13945        if (!dirtyOpaque) onDraw(canvas);
13946
13947        // Step 4, draw the children
13948        dispatchDraw(canvas);
13949
13950        // Step 5, draw the fade effect and restore layers
13951        final Paint p = scrollabilityCache.paint;
13952        final Matrix matrix = scrollabilityCache.matrix;
13953        final Shader fade = scrollabilityCache.shader;
13954
13955        if (drawTop) {
13956            matrix.setScale(1, fadeHeight * topFadeStrength);
13957            matrix.postTranslate(left, top);
13958            fade.setLocalMatrix(matrix);
13959            canvas.drawRect(left, top, right, top + length, p);
13960        }
13961
13962        if (drawBottom) {
13963            matrix.setScale(1, fadeHeight * bottomFadeStrength);
13964            matrix.postRotate(180);
13965            matrix.postTranslate(left, bottom);
13966            fade.setLocalMatrix(matrix);
13967            canvas.drawRect(left, bottom - length, right, bottom, p);
13968        }
13969
13970        if (drawLeft) {
13971            matrix.setScale(1, fadeHeight * leftFadeStrength);
13972            matrix.postRotate(-90);
13973            matrix.postTranslate(left, top);
13974            fade.setLocalMatrix(matrix);
13975            canvas.drawRect(left, top, left + length, bottom, p);
13976        }
13977
13978        if (drawRight) {
13979            matrix.setScale(1, fadeHeight * rightFadeStrength);
13980            matrix.postRotate(90);
13981            matrix.postTranslate(right, top);
13982            fade.setLocalMatrix(matrix);
13983            canvas.drawRect(right - length, top, right, bottom, p);
13984        }
13985
13986        canvas.restoreToCount(saveCount);
13987
13988        // Step 6, draw decorations (scrollbars)
13989        onDrawScrollBars(canvas);
13990    }
13991
13992    /**
13993     * Override this if your view is known to always be drawn on top of a solid color background,
13994     * and needs to draw fading edges. Returning a non-zero color enables the view system to
13995     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
13996     * should be set to 0xFF.
13997     *
13998     * @see #setVerticalFadingEdgeEnabled(boolean)
13999     * @see #setHorizontalFadingEdgeEnabled(boolean)
14000     *
14001     * @return The known solid color background for this view, or 0 if the color may vary
14002     */
14003    @ViewDebug.ExportedProperty(category = "drawing")
14004    public int getSolidColor() {
14005        return 0;
14006    }
14007
14008    /**
14009     * Build a human readable string representation of the specified view flags.
14010     *
14011     * @param flags the view flags to convert to a string
14012     * @return a String representing the supplied flags
14013     */
14014    private static String printFlags(int flags) {
14015        String output = "";
14016        int numFlags = 0;
14017        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
14018            output += "TAKES_FOCUS";
14019            numFlags++;
14020        }
14021
14022        switch (flags & VISIBILITY_MASK) {
14023        case INVISIBLE:
14024            if (numFlags > 0) {
14025                output += " ";
14026            }
14027            output += "INVISIBLE";
14028            // USELESS HERE numFlags++;
14029            break;
14030        case GONE:
14031            if (numFlags > 0) {
14032                output += " ";
14033            }
14034            output += "GONE";
14035            // USELESS HERE numFlags++;
14036            break;
14037        default:
14038            break;
14039        }
14040        return output;
14041    }
14042
14043    /**
14044     * Build a human readable string representation of the specified private
14045     * view flags.
14046     *
14047     * @param privateFlags the private view flags to convert to a string
14048     * @return a String representing the supplied flags
14049     */
14050    private static String printPrivateFlags(int privateFlags) {
14051        String output = "";
14052        int numFlags = 0;
14053
14054        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
14055            output += "WANTS_FOCUS";
14056            numFlags++;
14057        }
14058
14059        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
14060            if (numFlags > 0) {
14061                output += " ";
14062            }
14063            output += "FOCUSED";
14064            numFlags++;
14065        }
14066
14067        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
14068            if (numFlags > 0) {
14069                output += " ";
14070            }
14071            output += "SELECTED";
14072            numFlags++;
14073        }
14074
14075        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
14076            if (numFlags > 0) {
14077                output += " ";
14078            }
14079            output += "IS_ROOT_NAMESPACE";
14080            numFlags++;
14081        }
14082
14083        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
14084            if (numFlags > 0) {
14085                output += " ";
14086            }
14087            output += "HAS_BOUNDS";
14088            numFlags++;
14089        }
14090
14091        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
14092            if (numFlags > 0) {
14093                output += " ";
14094            }
14095            output += "DRAWN";
14096            // USELESS HERE numFlags++;
14097        }
14098        return output;
14099    }
14100
14101    /**
14102     * <p>Indicates whether or not this view's layout will be requested during
14103     * the next hierarchy layout pass.</p>
14104     *
14105     * @return true if the layout will be forced during next layout pass
14106     */
14107    public boolean isLayoutRequested() {
14108        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
14109    }
14110
14111    /**
14112     * Return true if o is a ViewGroup that is laying out using optical bounds.
14113     * @hide
14114     */
14115    public static boolean isLayoutModeOptical(Object o) {
14116        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
14117    }
14118
14119    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
14120        Insets parentInsets = mParent instanceof View ?
14121                ((View) mParent).getOpticalInsets() : Insets.NONE;
14122        Insets childInsets = getOpticalInsets();
14123        return setFrame(
14124                left   + parentInsets.left - childInsets.left,
14125                top    + parentInsets.top  - childInsets.top,
14126                right  + parentInsets.left + childInsets.right,
14127                bottom + parentInsets.top  + childInsets.bottom);
14128    }
14129
14130    /**
14131     * Assign a size and position to a view and all of its
14132     * descendants
14133     *
14134     * <p>This is the second phase of the layout mechanism.
14135     * (The first is measuring). In this phase, each parent calls
14136     * layout on all of its children to position them.
14137     * This is typically done using the child measurements
14138     * that were stored in the measure pass().</p>
14139     *
14140     * <p>Derived classes should not override this method.
14141     * Derived classes with children should override
14142     * onLayout. In that method, they should
14143     * call layout on each of their children.</p>
14144     *
14145     * @param l Left position, relative to parent
14146     * @param t Top position, relative to parent
14147     * @param r Right position, relative to parent
14148     * @param b Bottom position, relative to parent
14149     */
14150    @SuppressWarnings({"unchecked"})
14151    public void layout(int l, int t, int r, int b) {
14152        int oldL = mLeft;
14153        int oldT = mTop;
14154        int oldB = mBottom;
14155        int oldR = mRight;
14156        boolean changed = isLayoutModeOptical(mParent) ?
14157                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
14158        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
14159            onLayout(changed, l, t, r, b);
14160            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
14161
14162            ListenerInfo li = mListenerInfo;
14163            if (li != null && li.mOnLayoutChangeListeners != null) {
14164                ArrayList<OnLayoutChangeListener> listenersCopy =
14165                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
14166                int numListeners = listenersCopy.size();
14167                for (int i = 0; i < numListeners; ++i) {
14168                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
14169                }
14170            }
14171        }
14172        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
14173    }
14174
14175    /**
14176     * Called from layout when this view should
14177     * assign a size and position to each of its children.
14178     *
14179     * Derived classes with children should override
14180     * this method and call layout on each of
14181     * their children.
14182     * @param changed This is a new size or position for this view
14183     * @param left Left position, relative to parent
14184     * @param top Top position, relative to parent
14185     * @param right Right position, relative to parent
14186     * @param bottom Bottom position, relative to parent
14187     */
14188    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
14189    }
14190
14191    /**
14192     * Assign a size and position to this view.
14193     *
14194     * This is called from layout.
14195     *
14196     * @param left Left position, relative to parent
14197     * @param top Top position, relative to parent
14198     * @param right Right position, relative to parent
14199     * @param bottom Bottom position, relative to parent
14200     * @return true if the new size and position are different than the
14201     *         previous ones
14202     * {@hide}
14203     */
14204    protected boolean setFrame(int left, int top, int right, int bottom) {
14205        boolean changed = false;
14206
14207        if (DBG) {
14208            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
14209                    + right + "," + bottom + ")");
14210        }
14211
14212        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
14213            changed = true;
14214
14215            // Remember our drawn bit
14216            int drawn = mPrivateFlags & PFLAG_DRAWN;
14217
14218            int oldWidth = mRight - mLeft;
14219            int oldHeight = mBottom - mTop;
14220            int newWidth = right - left;
14221            int newHeight = bottom - top;
14222            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
14223
14224            // Invalidate our old position
14225            invalidate(sizeChanged);
14226
14227            mLeft = left;
14228            mTop = top;
14229            mRight = right;
14230            mBottom = bottom;
14231            if (mDisplayList != null) {
14232                mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
14233            }
14234
14235            mPrivateFlags |= PFLAG_HAS_BOUNDS;
14236
14237
14238            if (sizeChanged) {
14239                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
14240                    // A change in dimension means an auto-centered pivot point changes, too
14241                    if (mTransformationInfo != null) {
14242                        mTransformationInfo.mMatrixDirty = true;
14243                    }
14244                }
14245                onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
14246            }
14247
14248            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
14249                // If we are visible, force the DRAWN bit to on so that
14250                // this invalidate will go through (at least to our parent).
14251                // This is because someone may have invalidated this view
14252                // before this call to setFrame came in, thereby clearing
14253                // the DRAWN bit.
14254                mPrivateFlags |= PFLAG_DRAWN;
14255                invalidate(sizeChanged);
14256                // parent display list may need to be recreated based on a change in the bounds
14257                // of any child
14258                invalidateParentCaches();
14259            }
14260
14261            // Reset drawn bit to original value (invalidate turns it off)
14262            mPrivateFlags |= drawn;
14263
14264            mBackgroundSizeChanged = true;
14265        }
14266        return changed;
14267    }
14268
14269    /**
14270     * Finalize inflating a view from XML.  This is called as the last phase
14271     * of inflation, after all child views have been added.
14272     *
14273     * <p>Even if the subclass overrides onFinishInflate, they should always be
14274     * sure to call the super method, so that we get called.
14275     */
14276    protected void onFinishInflate() {
14277    }
14278
14279    /**
14280     * Returns the resources associated with this view.
14281     *
14282     * @return Resources object.
14283     */
14284    public Resources getResources() {
14285        return mResources;
14286    }
14287
14288    /**
14289     * Invalidates the specified Drawable.
14290     *
14291     * @param drawable the drawable to invalidate
14292     */
14293    public void invalidateDrawable(Drawable drawable) {
14294        if (verifyDrawable(drawable)) {
14295            final Rect dirty = drawable.getBounds();
14296            final int scrollX = mScrollX;
14297            final int scrollY = mScrollY;
14298
14299            invalidate(dirty.left + scrollX, dirty.top + scrollY,
14300                    dirty.right + scrollX, dirty.bottom + scrollY);
14301        }
14302    }
14303
14304    /**
14305     * Schedules an action on a drawable to occur at a specified time.
14306     *
14307     * @param who the recipient of the action
14308     * @param what the action to run on the drawable
14309     * @param when the time at which the action must occur. Uses the
14310     *        {@link SystemClock#uptimeMillis} timebase.
14311     */
14312    public void scheduleDrawable(Drawable who, Runnable what, long when) {
14313        if (verifyDrawable(who) && what != null) {
14314            final long delay = when - SystemClock.uptimeMillis();
14315            if (mAttachInfo != null) {
14316                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
14317                        Choreographer.CALLBACK_ANIMATION, what, who,
14318                        Choreographer.subtractFrameDelay(delay));
14319            } else {
14320                ViewRootImpl.getRunQueue().postDelayed(what, delay);
14321            }
14322        }
14323    }
14324
14325    /**
14326     * Cancels a scheduled action on a drawable.
14327     *
14328     * @param who the recipient of the action
14329     * @param what the action to cancel
14330     */
14331    public void unscheduleDrawable(Drawable who, Runnable what) {
14332        if (verifyDrawable(who) && what != null) {
14333            if (mAttachInfo != null) {
14334                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14335                        Choreographer.CALLBACK_ANIMATION, what, who);
14336            } else {
14337                ViewRootImpl.getRunQueue().removeCallbacks(what);
14338            }
14339        }
14340    }
14341
14342    /**
14343     * Unschedule any events associated with the given Drawable.  This can be
14344     * used when selecting a new Drawable into a view, so that the previous
14345     * one is completely unscheduled.
14346     *
14347     * @param who The Drawable to unschedule.
14348     *
14349     * @see #drawableStateChanged
14350     */
14351    public void unscheduleDrawable(Drawable who) {
14352        if (mAttachInfo != null && who != null) {
14353            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
14354                    Choreographer.CALLBACK_ANIMATION, null, who);
14355        }
14356    }
14357
14358    /**
14359     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
14360     * that the View directionality can and will be resolved before its Drawables.
14361     *
14362     * Will call {@link View#onResolveDrawables} when resolution is done.
14363     *
14364     * @hide
14365     */
14366    protected void resolveDrawables() {
14367        if (canResolveLayoutDirection()) {
14368            if (mBackground != null) {
14369                mBackground.setLayoutDirection(getLayoutDirection());
14370            }
14371            mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
14372            onResolveDrawables(getLayoutDirection());
14373        }
14374    }
14375
14376    /**
14377     * Called when layout direction has been resolved.
14378     *
14379     * The default implementation does nothing.
14380     *
14381     * @param layoutDirection The resolved layout direction.
14382     *
14383     * @see #LAYOUT_DIRECTION_LTR
14384     * @see #LAYOUT_DIRECTION_RTL
14385     *
14386     * @hide
14387     */
14388    public void onResolveDrawables(int layoutDirection) {
14389    }
14390
14391    /**
14392     * @hide
14393     */
14394    protected void resetResolvedDrawables() {
14395        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
14396    }
14397
14398    private boolean isDrawablesResolved() {
14399        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
14400    }
14401
14402    /**
14403     * If your view subclass is displaying its own Drawable objects, it should
14404     * override this function and return true for any Drawable it is
14405     * displaying.  This allows animations for those drawables to be
14406     * scheduled.
14407     *
14408     * <p>Be sure to call through to the super class when overriding this
14409     * function.
14410     *
14411     * @param who The Drawable to verify.  Return true if it is one you are
14412     *            displaying, else return the result of calling through to the
14413     *            super class.
14414     *
14415     * @return boolean If true than the Drawable is being displayed in the
14416     *         view; else false and it is not allowed to animate.
14417     *
14418     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
14419     * @see #drawableStateChanged()
14420     */
14421    protected boolean verifyDrawable(Drawable who) {
14422        return who == mBackground;
14423    }
14424
14425    /**
14426     * This function is called whenever the state of the view changes in such
14427     * a way that it impacts the state of drawables being shown.
14428     *
14429     * <p>Be sure to call through to the superclass when overriding this
14430     * function.
14431     *
14432     * @see Drawable#setState(int[])
14433     */
14434    protected void drawableStateChanged() {
14435        Drawable d = mBackground;
14436        if (d != null && d.isStateful()) {
14437            d.setState(getDrawableState());
14438        }
14439    }
14440
14441    /**
14442     * Call this to force a view to update its drawable state. This will cause
14443     * drawableStateChanged to be called on this view. Views that are interested
14444     * in the new state should call getDrawableState.
14445     *
14446     * @see #drawableStateChanged
14447     * @see #getDrawableState
14448     */
14449    public void refreshDrawableState() {
14450        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14451        drawableStateChanged();
14452
14453        ViewParent parent = mParent;
14454        if (parent != null) {
14455            parent.childDrawableStateChanged(this);
14456        }
14457    }
14458
14459    /**
14460     * Return an array of resource IDs of the drawable states representing the
14461     * current state of the view.
14462     *
14463     * @return The current drawable state
14464     *
14465     * @see Drawable#setState(int[])
14466     * @see #drawableStateChanged()
14467     * @see #onCreateDrawableState(int)
14468     */
14469    public final int[] getDrawableState() {
14470        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
14471            return mDrawableState;
14472        } else {
14473            mDrawableState = onCreateDrawableState(0);
14474            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
14475            return mDrawableState;
14476        }
14477    }
14478
14479    /**
14480     * Generate the new {@link android.graphics.drawable.Drawable} state for
14481     * this view. This is called by the view
14482     * system when the cached Drawable state is determined to be invalid.  To
14483     * retrieve the current state, you should use {@link #getDrawableState}.
14484     *
14485     * @param extraSpace if non-zero, this is the number of extra entries you
14486     * would like in the returned array in which you can place your own
14487     * states.
14488     *
14489     * @return Returns an array holding the current {@link Drawable} state of
14490     * the view.
14491     *
14492     * @see #mergeDrawableStates(int[], int[])
14493     */
14494    protected int[] onCreateDrawableState(int extraSpace) {
14495        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
14496                mParent instanceof View) {
14497            return ((View) mParent).onCreateDrawableState(extraSpace);
14498        }
14499
14500        int[] drawableState;
14501
14502        int privateFlags = mPrivateFlags;
14503
14504        int viewStateIndex = 0;
14505        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
14506        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
14507        if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
14508        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
14509        if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
14510        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
14511        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
14512                HardwareRenderer.isAvailable()) {
14513            // This is set if HW acceleration is requested, even if the current
14514            // process doesn't allow it.  This is just to allow app preview
14515            // windows to better match their app.
14516            viewStateIndex |= VIEW_STATE_ACCELERATED;
14517        }
14518        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
14519
14520        final int privateFlags2 = mPrivateFlags2;
14521        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
14522        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
14523
14524        drawableState = VIEW_STATE_SETS[viewStateIndex];
14525
14526        //noinspection ConstantIfStatement
14527        if (false) {
14528            Log.i("View", "drawableStateIndex=" + viewStateIndex);
14529            Log.i("View", toString()
14530                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
14531                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
14532                    + " fo=" + hasFocus()
14533                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
14534                    + " wf=" + hasWindowFocus()
14535                    + ": " + Arrays.toString(drawableState));
14536        }
14537
14538        if (extraSpace == 0) {
14539            return drawableState;
14540        }
14541
14542        final int[] fullState;
14543        if (drawableState != null) {
14544            fullState = new int[drawableState.length + extraSpace];
14545            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
14546        } else {
14547            fullState = new int[extraSpace];
14548        }
14549
14550        return fullState;
14551    }
14552
14553    /**
14554     * Merge your own state values in <var>additionalState</var> into the base
14555     * state values <var>baseState</var> that were returned by
14556     * {@link #onCreateDrawableState(int)}.
14557     *
14558     * @param baseState The base state values returned by
14559     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
14560     * own additional state values.
14561     *
14562     * @param additionalState The additional state values you would like
14563     * added to <var>baseState</var>; this array is not modified.
14564     *
14565     * @return As a convenience, the <var>baseState</var> array you originally
14566     * passed into the function is returned.
14567     *
14568     * @see #onCreateDrawableState(int)
14569     */
14570    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
14571        final int N = baseState.length;
14572        int i = N - 1;
14573        while (i >= 0 && baseState[i] == 0) {
14574            i--;
14575        }
14576        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
14577        return baseState;
14578    }
14579
14580    /**
14581     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
14582     * on all Drawable objects associated with this view.
14583     */
14584    public void jumpDrawablesToCurrentState() {
14585        if (mBackground != null) {
14586            mBackground.jumpToCurrentState();
14587        }
14588    }
14589
14590    /**
14591     * Sets the background color for this view.
14592     * @param color the color of the background
14593     */
14594    @RemotableViewMethod
14595    public void setBackgroundColor(int color) {
14596        if (mBackground instanceof ColorDrawable) {
14597            ((ColorDrawable) mBackground.mutate()).setColor(color);
14598            computeOpaqueFlags();
14599            mBackgroundResource = 0;
14600        } else {
14601            setBackground(new ColorDrawable(color));
14602        }
14603    }
14604
14605    /**
14606     * Set the background to a given resource. The resource should refer to
14607     * a Drawable object or 0 to remove the background.
14608     * @param resid The identifier of the resource.
14609     *
14610     * @attr ref android.R.styleable#View_background
14611     */
14612    @RemotableViewMethod
14613    public void setBackgroundResource(int resid) {
14614        if (resid != 0 && resid == mBackgroundResource) {
14615            return;
14616        }
14617
14618        Drawable d= null;
14619        if (resid != 0) {
14620            d = mResources.getDrawable(resid);
14621        }
14622        setBackground(d);
14623
14624        mBackgroundResource = resid;
14625    }
14626
14627    /**
14628     * Set the background to a given Drawable, or remove the background. If the
14629     * background has padding, this View's padding is set to the background's
14630     * padding. However, when a background is removed, this View's padding isn't
14631     * touched. If setting the padding is desired, please use
14632     * {@link #setPadding(int, int, int, int)}.
14633     *
14634     * @param background The Drawable to use as the background, or null to remove the
14635     *        background
14636     */
14637    public void setBackground(Drawable background) {
14638        //noinspection deprecation
14639        setBackgroundDrawable(background);
14640    }
14641
14642    /**
14643     * @deprecated use {@link #setBackground(Drawable)} instead
14644     */
14645    @Deprecated
14646    public void setBackgroundDrawable(Drawable background) {
14647        computeOpaqueFlags();
14648
14649        if (background == mBackground) {
14650            return;
14651        }
14652
14653        boolean requestLayout = false;
14654
14655        mBackgroundResource = 0;
14656
14657        /*
14658         * Regardless of whether we're setting a new background or not, we want
14659         * to clear the previous drawable.
14660         */
14661        if (mBackground != null) {
14662            mBackground.setCallback(null);
14663            unscheduleDrawable(mBackground);
14664        }
14665
14666        if (background != null) {
14667            Rect padding = sThreadLocal.get();
14668            if (padding == null) {
14669                padding = new Rect();
14670                sThreadLocal.set(padding);
14671            }
14672            resetResolvedDrawables();
14673            background.setLayoutDirection(getLayoutDirection());
14674            if (background.getPadding(padding)) {
14675                resetResolvedPadding();
14676                switch (background.getLayoutDirection()) {
14677                    case LAYOUT_DIRECTION_RTL:
14678                        mUserPaddingLeftInitial = padding.right;
14679                        mUserPaddingRightInitial = padding.left;
14680                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
14681                        break;
14682                    case LAYOUT_DIRECTION_LTR:
14683                    default:
14684                        mUserPaddingLeftInitial = padding.left;
14685                        mUserPaddingRightInitial = padding.right;
14686                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
14687                }
14688            }
14689
14690            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
14691            // if it has a different minimum size, we should layout again
14692            if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() ||
14693                    mBackground.getMinimumWidth() != background.getMinimumWidth()) {
14694                requestLayout = true;
14695            }
14696
14697            background.setCallback(this);
14698            if (background.isStateful()) {
14699                background.setState(getDrawableState());
14700            }
14701            background.setVisible(getVisibility() == VISIBLE, false);
14702            mBackground = background;
14703
14704            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
14705                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
14706                mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
14707                requestLayout = true;
14708            }
14709        } else {
14710            /* Remove the background */
14711            mBackground = null;
14712
14713            if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
14714                /*
14715                 * This view ONLY drew the background before and we're removing
14716                 * the background, so now it won't draw anything
14717                 * (hence we SKIP_DRAW)
14718                 */
14719                mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
14720                mPrivateFlags |= PFLAG_SKIP_DRAW;
14721            }
14722
14723            /*
14724             * When the background is set, we try to apply its padding to this
14725             * View. When the background is removed, we don't touch this View's
14726             * padding. This is noted in the Javadocs. Hence, we don't need to
14727             * requestLayout(), the invalidate() below is sufficient.
14728             */
14729
14730            // The old background's minimum size could have affected this
14731            // View's layout, so let's requestLayout
14732            requestLayout = true;
14733        }
14734
14735        computeOpaqueFlags();
14736
14737        if (requestLayout) {
14738            requestLayout();
14739        }
14740
14741        mBackgroundSizeChanged = true;
14742        invalidate(true);
14743    }
14744
14745    /**
14746     * Gets the background drawable
14747     *
14748     * @return The drawable used as the background for this view, if any.
14749     *
14750     * @see #setBackground(Drawable)
14751     *
14752     * @attr ref android.R.styleable#View_background
14753     */
14754    public Drawable getBackground() {
14755        return mBackground;
14756    }
14757
14758    /**
14759     * Sets the padding. The view may add on the space required to display
14760     * the scrollbars, depending on the style and visibility of the scrollbars.
14761     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
14762     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
14763     * from the values set in this call.
14764     *
14765     * @attr ref android.R.styleable#View_padding
14766     * @attr ref android.R.styleable#View_paddingBottom
14767     * @attr ref android.R.styleable#View_paddingLeft
14768     * @attr ref android.R.styleable#View_paddingRight
14769     * @attr ref android.R.styleable#View_paddingTop
14770     * @param left the left padding in pixels
14771     * @param top the top padding in pixels
14772     * @param right the right padding in pixels
14773     * @param bottom the bottom padding in pixels
14774     */
14775    public void setPadding(int left, int top, int right, int bottom) {
14776        resetResolvedPadding();
14777
14778        mUserPaddingStart = UNDEFINED_PADDING;
14779        mUserPaddingEnd = UNDEFINED_PADDING;
14780
14781        mUserPaddingLeftInitial = left;
14782        mUserPaddingRightInitial = right;
14783
14784        internalSetPadding(left, top, right, bottom);
14785    }
14786
14787    /**
14788     * @hide
14789     */
14790    protected void internalSetPadding(int left, int top, int right, int bottom) {
14791        mUserPaddingLeft = left;
14792        mUserPaddingRight = right;
14793        mUserPaddingBottom = bottom;
14794
14795        final int viewFlags = mViewFlags;
14796        boolean changed = false;
14797
14798        // Common case is there are no scroll bars.
14799        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
14800            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
14801                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
14802                        ? 0 : getVerticalScrollbarWidth();
14803                switch (mVerticalScrollbarPosition) {
14804                    case SCROLLBAR_POSITION_DEFAULT:
14805                        if (isLayoutRtl()) {
14806                            left += offset;
14807                        } else {
14808                            right += offset;
14809                        }
14810                        break;
14811                    case SCROLLBAR_POSITION_RIGHT:
14812                        right += offset;
14813                        break;
14814                    case SCROLLBAR_POSITION_LEFT:
14815                        left += offset;
14816                        break;
14817                }
14818            }
14819            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
14820                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
14821                        ? 0 : getHorizontalScrollbarHeight();
14822            }
14823        }
14824
14825        if (mPaddingLeft != left) {
14826            changed = true;
14827            mPaddingLeft = left;
14828        }
14829        if (mPaddingTop != top) {
14830            changed = true;
14831            mPaddingTop = top;
14832        }
14833        if (mPaddingRight != right) {
14834            changed = true;
14835            mPaddingRight = right;
14836        }
14837        if (mPaddingBottom != bottom) {
14838            changed = true;
14839            mPaddingBottom = bottom;
14840        }
14841
14842        if (changed) {
14843            requestLayout();
14844        }
14845    }
14846
14847    /**
14848     * Sets the relative padding. The view may add on the space required to display
14849     * the scrollbars, depending on the style and visibility of the scrollbars.
14850     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
14851     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
14852     * from the values set in this call.
14853     *
14854     * @attr ref android.R.styleable#View_padding
14855     * @attr ref android.R.styleable#View_paddingBottom
14856     * @attr ref android.R.styleable#View_paddingStart
14857     * @attr ref android.R.styleable#View_paddingEnd
14858     * @attr ref android.R.styleable#View_paddingTop
14859     * @param start the start padding in pixels
14860     * @param top the top padding in pixels
14861     * @param end the end padding in pixels
14862     * @param bottom the bottom padding in pixels
14863     */
14864    public void setPaddingRelative(int start, int top, int end, int bottom) {
14865        resetResolvedPadding();
14866
14867        mUserPaddingStart = start;
14868        mUserPaddingEnd = end;
14869
14870        switch(getLayoutDirection()) {
14871            case LAYOUT_DIRECTION_RTL:
14872                mUserPaddingLeftInitial = end;
14873                mUserPaddingRightInitial = start;
14874                internalSetPadding(end, top, start, bottom);
14875                break;
14876            case LAYOUT_DIRECTION_LTR:
14877            default:
14878                mUserPaddingLeftInitial = start;
14879                mUserPaddingRightInitial = end;
14880                internalSetPadding(start, top, end, bottom);
14881        }
14882    }
14883
14884    /**
14885     * Returns the top padding of this view.
14886     *
14887     * @return the top padding in pixels
14888     */
14889    public int getPaddingTop() {
14890        return mPaddingTop;
14891    }
14892
14893    /**
14894     * Returns the bottom padding of this view. If there are inset and enabled
14895     * scrollbars, this value may include the space required to display the
14896     * scrollbars as well.
14897     *
14898     * @return the bottom padding in pixels
14899     */
14900    public int getPaddingBottom() {
14901        return mPaddingBottom;
14902    }
14903
14904    /**
14905     * Returns the left padding of this view. If there are inset and enabled
14906     * scrollbars, this value may include the space required to display the
14907     * scrollbars as well.
14908     *
14909     * @return the left padding in pixels
14910     */
14911    public int getPaddingLeft() {
14912        if (!isPaddingResolved()) {
14913            resolvePadding();
14914        }
14915        return mPaddingLeft;
14916    }
14917
14918    /**
14919     * Returns the start padding of this view depending on its resolved layout direction.
14920     * If there are inset and enabled scrollbars, this value may include the space
14921     * required to display the scrollbars as well.
14922     *
14923     * @return the start padding in pixels
14924     */
14925    public int getPaddingStart() {
14926        if (!isPaddingResolved()) {
14927            resolvePadding();
14928        }
14929        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
14930                mPaddingRight : mPaddingLeft;
14931    }
14932
14933    /**
14934     * Returns the right padding of this view. If there are inset and enabled
14935     * scrollbars, this value may include the space required to display the
14936     * scrollbars as well.
14937     *
14938     * @return the right padding in pixels
14939     */
14940    public int getPaddingRight() {
14941        if (!isPaddingResolved()) {
14942            resolvePadding();
14943        }
14944        return mPaddingRight;
14945    }
14946
14947    /**
14948     * Returns the end padding of this view depending on its resolved layout direction.
14949     * If there are inset and enabled scrollbars, this value may include the space
14950     * required to display the scrollbars as well.
14951     *
14952     * @return the end padding in pixels
14953     */
14954    public int getPaddingEnd() {
14955        if (!isPaddingResolved()) {
14956            resolvePadding();
14957        }
14958        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
14959                mPaddingLeft : mPaddingRight;
14960    }
14961
14962    /**
14963     * Return if the padding as been set thru relative values
14964     * {@link #setPaddingRelative(int, int, int, int)} or thru
14965     * @attr ref android.R.styleable#View_paddingStart or
14966     * @attr ref android.R.styleable#View_paddingEnd
14967     *
14968     * @return true if the padding is relative or false if it is not.
14969     */
14970    public boolean isPaddingRelative() {
14971        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
14972    }
14973
14974    Insets computeOpticalInsets() {
14975        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
14976    }
14977
14978    /**
14979     * @hide
14980     */
14981    public void resetPaddingToInitialValues() {
14982        if (isRtlCompatibilityMode()) {
14983            mPaddingLeft = mUserPaddingLeftInitial;
14984            mPaddingRight = mUserPaddingRightInitial;
14985            return;
14986        }
14987        if (isLayoutRtl()) {
14988            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
14989            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
14990        } else {
14991            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
14992            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
14993        }
14994    }
14995
14996    /**
14997     * @hide
14998     */
14999    public Insets getOpticalInsets() {
15000        if (mLayoutInsets == null) {
15001            mLayoutInsets = computeOpticalInsets();
15002        }
15003        return mLayoutInsets;
15004    }
15005
15006    /**
15007     * Changes the selection state of this view. A view can be selected or not.
15008     * Note that selection is not the same as focus. Views are typically
15009     * selected in the context of an AdapterView like ListView or GridView;
15010     * the selected view is the view that is highlighted.
15011     *
15012     * @param selected true if the view must be selected, false otherwise
15013     */
15014    public void setSelected(boolean selected) {
15015        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
15016            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
15017            if (!selected) resetPressedState();
15018            invalidate(true);
15019            refreshDrawableState();
15020            dispatchSetSelected(selected);
15021            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
15022                notifyAccessibilityStateChanged();
15023            }
15024        }
15025    }
15026
15027    /**
15028     * Dispatch setSelected to all of this View's children.
15029     *
15030     * @see #setSelected(boolean)
15031     *
15032     * @param selected The new selected state
15033     */
15034    protected void dispatchSetSelected(boolean selected) {
15035    }
15036
15037    /**
15038     * Indicates the selection state of this view.
15039     *
15040     * @return true if the view is selected, false otherwise
15041     */
15042    @ViewDebug.ExportedProperty
15043    public boolean isSelected() {
15044        return (mPrivateFlags & PFLAG_SELECTED) != 0;
15045    }
15046
15047    /**
15048     * Changes the activated state of this view. A view can be activated or not.
15049     * Note that activation is not the same as selection.  Selection is
15050     * a transient property, representing the view (hierarchy) the user is
15051     * currently interacting with.  Activation is a longer-term state that the
15052     * user can move views in and out of.  For example, in a list view with
15053     * single or multiple selection enabled, the views in the current selection
15054     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
15055     * here.)  The activated state is propagated down to children of the view it
15056     * is set on.
15057     *
15058     * @param activated true if the view must be activated, false otherwise
15059     */
15060    public void setActivated(boolean activated) {
15061        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
15062            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
15063            invalidate(true);
15064            refreshDrawableState();
15065            dispatchSetActivated(activated);
15066        }
15067    }
15068
15069    /**
15070     * Dispatch setActivated to all of this View's children.
15071     *
15072     * @see #setActivated(boolean)
15073     *
15074     * @param activated The new activated state
15075     */
15076    protected void dispatchSetActivated(boolean activated) {
15077    }
15078
15079    /**
15080     * Indicates the activation state of this view.
15081     *
15082     * @return true if the view is activated, false otherwise
15083     */
15084    @ViewDebug.ExportedProperty
15085    public boolean isActivated() {
15086        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
15087    }
15088
15089    /**
15090     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
15091     * observer can be used to get notifications when global events, like
15092     * layout, happen.
15093     *
15094     * The returned ViewTreeObserver observer is not guaranteed to remain
15095     * valid for the lifetime of this View. If the caller of this method keeps
15096     * a long-lived reference to ViewTreeObserver, it should always check for
15097     * the return value of {@link ViewTreeObserver#isAlive()}.
15098     *
15099     * @return The ViewTreeObserver for this view's hierarchy.
15100     */
15101    public ViewTreeObserver getViewTreeObserver() {
15102        if (mAttachInfo != null) {
15103            return mAttachInfo.mTreeObserver;
15104        }
15105        if (mFloatingTreeObserver == null) {
15106            mFloatingTreeObserver = new ViewTreeObserver();
15107        }
15108        return mFloatingTreeObserver;
15109    }
15110
15111    /**
15112     * <p>Finds the topmost view in the current view hierarchy.</p>
15113     *
15114     * @return the topmost view containing this view
15115     */
15116    public View getRootView() {
15117        if (mAttachInfo != null) {
15118            final View v = mAttachInfo.mRootView;
15119            if (v != null) {
15120                return v;
15121            }
15122        }
15123
15124        View parent = this;
15125
15126        while (parent.mParent != null && parent.mParent instanceof View) {
15127            parent = (View) parent.mParent;
15128        }
15129
15130        return parent;
15131    }
15132
15133    /**
15134     * <p>Computes the coordinates of this view on the screen. The argument
15135     * must be an array of two integers. After the method returns, the array
15136     * contains the x and y location in that order.</p>
15137     *
15138     * @param location an array of two integers in which to hold the coordinates
15139     */
15140    public void getLocationOnScreen(int[] location) {
15141        getLocationInWindow(location);
15142
15143        final AttachInfo info = mAttachInfo;
15144        if (info != null) {
15145            location[0] += info.mWindowLeft;
15146            location[1] += info.mWindowTop;
15147        }
15148    }
15149
15150    /**
15151     * <p>Computes the coordinates of this view in its window. The argument
15152     * must be an array of two integers. After the method returns, the array
15153     * contains the x and y location in that order.</p>
15154     *
15155     * @param location an array of two integers in which to hold the coordinates
15156     */
15157    public void getLocationInWindow(int[] location) {
15158        if (location == null || location.length < 2) {
15159            throw new IllegalArgumentException("location must be an array of two integers");
15160        }
15161
15162        if (mAttachInfo == null) {
15163            // When the view is not attached to a window, this method does not make sense
15164            location[0] = location[1] = 0;
15165            return;
15166        }
15167
15168        float[] position = mAttachInfo.mTmpTransformLocation;
15169        position[0] = position[1] = 0.0f;
15170
15171        if (!hasIdentityMatrix()) {
15172            getMatrix().mapPoints(position);
15173        }
15174
15175        position[0] += mLeft;
15176        position[1] += mTop;
15177
15178        ViewParent viewParent = mParent;
15179        while (viewParent instanceof View) {
15180            final View view = (View) viewParent;
15181
15182            position[0] -= view.mScrollX;
15183            position[1] -= view.mScrollY;
15184
15185            if (!view.hasIdentityMatrix()) {
15186                view.getMatrix().mapPoints(position);
15187            }
15188
15189            position[0] += view.mLeft;
15190            position[1] += view.mTop;
15191
15192            viewParent = view.mParent;
15193         }
15194
15195        if (viewParent instanceof ViewRootImpl) {
15196            // *cough*
15197            final ViewRootImpl vr = (ViewRootImpl) viewParent;
15198            position[1] -= vr.mCurScrollY;
15199        }
15200
15201        location[0] = (int) (position[0] + 0.5f);
15202        location[1] = (int) (position[1] + 0.5f);
15203    }
15204
15205    /**
15206     * {@hide}
15207     * @param id the id of the view to be found
15208     * @return the view of the specified id, null if cannot be found
15209     */
15210    protected View findViewTraversal(int id) {
15211        if (id == mID) {
15212            return this;
15213        }
15214        return null;
15215    }
15216
15217    /**
15218     * {@hide}
15219     * @param tag the tag of the view to be found
15220     * @return the view of specified tag, null if cannot be found
15221     */
15222    protected View findViewWithTagTraversal(Object tag) {
15223        if (tag != null && tag.equals(mTag)) {
15224            return this;
15225        }
15226        return null;
15227    }
15228
15229    /**
15230     * {@hide}
15231     * @param predicate The predicate to evaluate.
15232     * @param childToSkip If not null, ignores this child during the recursive traversal.
15233     * @return The first view that matches the predicate or null.
15234     */
15235    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
15236        if (predicate.apply(this)) {
15237            return this;
15238        }
15239        return null;
15240    }
15241
15242    /**
15243     * Look for a child view with the given id.  If this view has the given
15244     * id, return this view.
15245     *
15246     * @param id The id to search for.
15247     * @return The view that has the given id in the hierarchy or null
15248     */
15249    public final View findViewById(int id) {
15250        if (id < 0) {
15251            return null;
15252        }
15253        return findViewTraversal(id);
15254    }
15255
15256    /**
15257     * Finds a view by its unuque and stable accessibility id.
15258     *
15259     * @param accessibilityId The searched accessibility id.
15260     * @return The found view.
15261     */
15262    final View findViewByAccessibilityId(int accessibilityId) {
15263        if (accessibilityId < 0) {
15264            return null;
15265        }
15266        return findViewByAccessibilityIdTraversal(accessibilityId);
15267    }
15268
15269    /**
15270     * Performs the traversal to find a view by its unuque and stable accessibility id.
15271     *
15272     * <strong>Note:</strong>This method does not stop at the root namespace
15273     * boundary since the user can touch the screen at an arbitrary location
15274     * potentially crossing the root namespace bounday which will send an
15275     * accessibility event to accessibility services and they should be able
15276     * to obtain the event source. Also accessibility ids are guaranteed to be
15277     * unique in the window.
15278     *
15279     * @param accessibilityId The accessibility id.
15280     * @return The found view.
15281     */
15282    View findViewByAccessibilityIdTraversal(int accessibilityId) {
15283        if (getAccessibilityViewId() == accessibilityId) {
15284            return this;
15285        }
15286        return null;
15287    }
15288
15289    /**
15290     * Look for a child view with the given tag.  If this view has the given
15291     * tag, return this view.
15292     *
15293     * @param tag The tag to search for, using "tag.equals(getTag())".
15294     * @return The View that has the given tag in the hierarchy or null
15295     */
15296    public final View findViewWithTag(Object tag) {
15297        if (tag == null) {
15298            return null;
15299        }
15300        return findViewWithTagTraversal(tag);
15301    }
15302
15303    /**
15304     * {@hide}
15305     * Look for a child view that matches the specified predicate.
15306     * If this view matches the predicate, return this view.
15307     *
15308     * @param predicate The predicate to evaluate.
15309     * @return The first view that matches the predicate or null.
15310     */
15311    public final View findViewByPredicate(Predicate<View> predicate) {
15312        return findViewByPredicateTraversal(predicate, null);
15313    }
15314
15315    /**
15316     * {@hide}
15317     * Look for a child view that matches the specified predicate,
15318     * starting with the specified view and its descendents and then
15319     * recusively searching the ancestors and siblings of that view
15320     * until this view is reached.
15321     *
15322     * This method is useful in cases where the predicate does not match
15323     * a single unique view (perhaps multiple views use the same id)
15324     * and we are trying to find the view that is "closest" in scope to the
15325     * starting view.
15326     *
15327     * @param start The view to start from.
15328     * @param predicate The predicate to evaluate.
15329     * @return The first view that matches the predicate or null.
15330     */
15331    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
15332        View childToSkip = null;
15333        for (;;) {
15334            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
15335            if (view != null || start == this) {
15336                return view;
15337            }
15338
15339            ViewParent parent = start.getParent();
15340            if (parent == null || !(parent instanceof View)) {
15341                return null;
15342            }
15343
15344            childToSkip = start;
15345            start = (View) parent;
15346        }
15347    }
15348
15349    /**
15350     * Sets the identifier for this view. The identifier does not have to be
15351     * unique in this view's hierarchy. The identifier should be a positive
15352     * number.
15353     *
15354     * @see #NO_ID
15355     * @see #getId()
15356     * @see #findViewById(int)
15357     *
15358     * @param id a number used to identify the view
15359     *
15360     * @attr ref android.R.styleable#View_id
15361     */
15362    public void setId(int id) {
15363        mID = id;
15364        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
15365            mID = generateViewId();
15366        }
15367    }
15368
15369    /**
15370     * {@hide}
15371     *
15372     * @param isRoot true if the view belongs to the root namespace, false
15373     *        otherwise
15374     */
15375    public void setIsRootNamespace(boolean isRoot) {
15376        if (isRoot) {
15377            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
15378        } else {
15379            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
15380        }
15381    }
15382
15383    /**
15384     * {@hide}
15385     *
15386     * @return true if the view belongs to the root namespace, false otherwise
15387     */
15388    public boolean isRootNamespace() {
15389        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
15390    }
15391
15392    /**
15393     * Returns this view's identifier.
15394     *
15395     * @return a positive integer used to identify the view or {@link #NO_ID}
15396     *         if the view has no ID
15397     *
15398     * @see #setId(int)
15399     * @see #findViewById(int)
15400     * @attr ref android.R.styleable#View_id
15401     */
15402    @ViewDebug.CapturedViewProperty
15403    public int getId() {
15404        return mID;
15405    }
15406
15407    /**
15408     * Returns this view's tag.
15409     *
15410     * @return the Object stored in this view as a tag
15411     *
15412     * @see #setTag(Object)
15413     * @see #getTag(int)
15414     */
15415    @ViewDebug.ExportedProperty
15416    public Object getTag() {
15417        return mTag;
15418    }
15419
15420    /**
15421     * Sets the tag associated with this view. A tag can be used to mark
15422     * a view in its hierarchy and does not have to be unique within the
15423     * hierarchy. Tags can also be used to store data within a view without
15424     * resorting to another data structure.
15425     *
15426     * @param tag an Object to tag the view with
15427     *
15428     * @see #getTag()
15429     * @see #setTag(int, Object)
15430     */
15431    public void setTag(final Object tag) {
15432        mTag = tag;
15433    }
15434
15435    /**
15436     * Returns the tag associated with this view and the specified key.
15437     *
15438     * @param key The key identifying the tag
15439     *
15440     * @return the Object stored in this view as a tag
15441     *
15442     * @see #setTag(int, Object)
15443     * @see #getTag()
15444     */
15445    public Object getTag(int key) {
15446        if (mKeyedTags != null) return mKeyedTags.get(key);
15447        return null;
15448    }
15449
15450    /**
15451     * Sets a tag associated with this view and a key. A tag can be used
15452     * to mark a view in its hierarchy and does not have to be unique within
15453     * the hierarchy. Tags can also be used to store data within a view
15454     * without resorting to another data structure.
15455     *
15456     * The specified key should be an id declared in the resources of the
15457     * application to ensure it is unique (see the <a
15458     * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
15459     * Keys identified as belonging to
15460     * the Android framework or not associated with any package will cause
15461     * an {@link IllegalArgumentException} to be thrown.
15462     *
15463     * @param key The key identifying the tag
15464     * @param tag An Object to tag the view with
15465     *
15466     * @throws IllegalArgumentException If they specified key is not valid
15467     *
15468     * @see #setTag(Object)
15469     * @see #getTag(int)
15470     */
15471    public void setTag(int key, final Object tag) {
15472        // If the package id is 0x00 or 0x01, it's either an undefined package
15473        // or a framework id
15474        if ((key >>> 24) < 2) {
15475            throw new IllegalArgumentException("The key must be an application-specific "
15476                    + "resource id.");
15477        }
15478
15479        setKeyedTag(key, tag);
15480    }
15481
15482    /**
15483     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
15484     * framework id.
15485     *
15486     * @hide
15487     */
15488    public void setTagInternal(int key, Object tag) {
15489        if ((key >>> 24) != 0x1) {
15490            throw new IllegalArgumentException("The key must be a framework-specific "
15491                    + "resource id.");
15492        }
15493
15494        setKeyedTag(key, tag);
15495    }
15496
15497    private void setKeyedTag(int key, Object tag) {
15498        if (mKeyedTags == null) {
15499            mKeyedTags = new SparseArray<Object>();
15500        }
15501
15502        mKeyedTags.put(key, tag);
15503    }
15504
15505    /**
15506     * Prints information about this view in the log output, with the tag
15507     * {@link #VIEW_LOG_TAG}.
15508     *
15509     * @hide
15510     */
15511    public void debug() {
15512        debug(0);
15513    }
15514
15515    /**
15516     * Prints information about this view in the log output, with the tag
15517     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
15518     * indentation defined by the <code>depth</code>.
15519     *
15520     * @param depth the indentation level
15521     *
15522     * @hide
15523     */
15524    protected void debug(int depth) {
15525        String output = debugIndent(depth - 1);
15526
15527        output += "+ " + this;
15528        int id = getId();
15529        if (id != -1) {
15530            output += " (id=" + id + ")";
15531        }
15532        Object tag = getTag();
15533        if (tag != null) {
15534            output += " (tag=" + tag + ")";
15535        }
15536        Log.d(VIEW_LOG_TAG, output);
15537
15538        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
15539            output = debugIndent(depth) + " FOCUSED";
15540            Log.d(VIEW_LOG_TAG, output);
15541        }
15542
15543        output = debugIndent(depth);
15544        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
15545                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
15546                + "} ";
15547        Log.d(VIEW_LOG_TAG, output);
15548
15549        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
15550                || mPaddingBottom != 0) {
15551            output = debugIndent(depth);
15552            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
15553                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
15554            Log.d(VIEW_LOG_TAG, output);
15555        }
15556
15557        output = debugIndent(depth);
15558        output += "mMeasureWidth=" + mMeasuredWidth +
15559                " mMeasureHeight=" + mMeasuredHeight;
15560        Log.d(VIEW_LOG_TAG, output);
15561
15562        output = debugIndent(depth);
15563        if (mLayoutParams == null) {
15564            output += "BAD! no layout params";
15565        } else {
15566            output = mLayoutParams.debug(output);
15567        }
15568        Log.d(VIEW_LOG_TAG, output);
15569
15570        output = debugIndent(depth);
15571        output += "flags={";
15572        output += View.printFlags(mViewFlags);
15573        output += "}";
15574        Log.d(VIEW_LOG_TAG, output);
15575
15576        output = debugIndent(depth);
15577        output += "privateFlags={";
15578        output += View.printPrivateFlags(mPrivateFlags);
15579        output += "}";
15580        Log.d(VIEW_LOG_TAG, output);
15581    }
15582
15583    /**
15584     * Creates a string of whitespaces used for indentation.
15585     *
15586     * @param depth the indentation level
15587     * @return a String containing (depth * 2 + 3) * 2 white spaces
15588     *
15589     * @hide
15590     */
15591    protected static String debugIndent(int depth) {
15592        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
15593        for (int i = 0; i < (depth * 2) + 3; i++) {
15594            spaces.append(' ').append(' ');
15595        }
15596        return spaces.toString();
15597    }
15598
15599    /**
15600     * <p>Return the offset of the widget's text baseline from the widget's top
15601     * boundary. If this widget does not support baseline alignment, this
15602     * method returns -1. </p>
15603     *
15604     * @return the offset of the baseline within the widget's bounds or -1
15605     *         if baseline alignment is not supported
15606     */
15607    @ViewDebug.ExportedProperty(category = "layout")
15608    public int getBaseline() {
15609        return -1;
15610    }
15611
15612    /**
15613     * Returns whether the view hierarchy is currently undergoing a layout pass. This
15614     * information is useful to avoid situations such as calling {@link #requestLayout()} during
15615     * a layout pass.
15616     *
15617     * @return whether the view hierarchy is currently undergoing a layout pass
15618     */
15619    public boolean isInLayout() {
15620        ViewRootImpl viewRoot = getViewRootImpl();
15621        return (viewRoot != null && viewRoot.isInLayout());
15622    }
15623
15624    /**
15625     * Call this when something has changed which has invalidated the
15626     * layout of this view. This will schedule a layout pass of the view
15627     * tree. This should not be called while the view hierarchy is currently in a layout
15628     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
15629     * end of the current layout pass (and then layout will run again) or after the current
15630     * frame is drawn and the next layout occurs.
15631     *
15632     * <p>Subclasses which override this method should call the superclass method to
15633     * handle possible request-during-layout errors correctly.</p>
15634     */
15635    public void requestLayout() {
15636        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
15637            // Only trigger request-during-layout logic if this is the view requesting it,
15638            // not the views in its parent hierarchy
15639            ViewRootImpl viewRoot = getViewRootImpl();
15640            if (viewRoot != null && viewRoot.isInLayout()) {
15641                if (!viewRoot.requestLayoutDuringLayout(this)) {
15642                    return;
15643                }
15644            }
15645            mAttachInfo.mViewRequestingLayout = this;
15646        }
15647
15648        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
15649        mPrivateFlags |= PFLAG_INVALIDATED;
15650
15651        if (mParent != null && !mParent.isLayoutRequested()) {
15652            mParent.requestLayout();
15653        }
15654        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
15655            mAttachInfo.mViewRequestingLayout = null;
15656        }
15657    }
15658
15659    /**
15660     * Forces this view to be laid out during the next layout pass.
15661     * This method does not call requestLayout() or forceLayout()
15662     * on the parent.
15663     */
15664    public void forceLayout() {
15665        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
15666        mPrivateFlags |= PFLAG_INVALIDATED;
15667    }
15668
15669    /**
15670     * <p>
15671     * This is called to find out how big a view should be. The parent
15672     * supplies constraint information in the width and height parameters.
15673     * </p>
15674     *
15675     * <p>
15676     * The actual measurement work of a view is performed in
15677     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
15678     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
15679     * </p>
15680     *
15681     *
15682     * @param widthMeasureSpec Horizontal space requirements as imposed by the
15683     *        parent
15684     * @param heightMeasureSpec Vertical space requirements as imposed by the
15685     *        parent
15686     *
15687     * @see #onMeasure(int, int)
15688     */
15689    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
15690        boolean optical = isLayoutModeOptical(this);
15691        if (optical != isLayoutModeOptical(mParent)) {
15692            Insets insets = getOpticalInsets();
15693            int oWidth  = insets.left + insets.right;
15694            int oHeight = insets.top  + insets.bottom;
15695            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
15696            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
15697        }
15698        if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
15699                widthMeasureSpec != mOldWidthMeasureSpec ||
15700                heightMeasureSpec != mOldHeightMeasureSpec) {
15701
15702            // first clears the measured dimension flag
15703            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
15704
15705            resolveRtlPropertiesIfNeeded();
15706
15707            // measure ourselves, this should set the measured dimension flag back
15708            onMeasure(widthMeasureSpec, heightMeasureSpec);
15709
15710            // flag not set, setMeasuredDimension() was not invoked, we raise
15711            // an exception to warn the developer
15712            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
15713                throw new IllegalStateException("onMeasure() did not set the"
15714                        + " measured dimension by calling"
15715                        + " setMeasuredDimension()");
15716            }
15717
15718            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
15719        }
15720
15721        mOldWidthMeasureSpec = widthMeasureSpec;
15722        mOldHeightMeasureSpec = heightMeasureSpec;
15723    }
15724
15725    /**
15726     * <p>
15727     * Measure the view and its content to determine the measured width and the
15728     * measured height. This method is invoked by {@link #measure(int, int)} and
15729     * should be overriden by subclasses to provide accurate and efficient
15730     * measurement of their contents.
15731     * </p>
15732     *
15733     * <p>
15734     * <strong>CONTRACT:</strong> When overriding this method, you
15735     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
15736     * measured width and height of this view. Failure to do so will trigger an
15737     * <code>IllegalStateException</code>, thrown by
15738     * {@link #measure(int, int)}. Calling the superclass'
15739     * {@link #onMeasure(int, int)} is a valid use.
15740     * </p>
15741     *
15742     * <p>
15743     * The base class implementation of measure defaults to the background size,
15744     * unless a larger size is allowed by the MeasureSpec. Subclasses should
15745     * override {@link #onMeasure(int, int)} to provide better measurements of
15746     * their content.
15747     * </p>
15748     *
15749     * <p>
15750     * If this method is overridden, it is the subclass's responsibility to make
15751     * sure the measured height and width are at least the view's minimum height
15752     * and width ({@link #getSuggestedMinimumHeight()} and
15753     * {@link #getSuggestedMinimumWidth()}).
15754     * </p>
15755     *
15756     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
15757     *                         The requirements are encoded with
15758     *                         {@link android.view.View.MeasureSpec}.
15759     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
15760     *                         The requirements are encoded with
15761     *                         {@link android.view.View.MeasureSpec}.
15762     *
15763     * @see #getMeasuredWidth()
15764     * @see #getMeasuredHeight()
15765     * @see #setMeasuredDimension(int, int)
15766     * @see #getSuggestedMinimumHeight()
15767     * @see #getSuggestedMinimumWidth()
15768     * @see android.view.View.MeasureSpec#getMode(int)
15769     * @see android.view.View.MeasureSpec#getSize(int)
15770     */
15771    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
15772        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
15773                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
15774    }
15775
15776    /**
15777     * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
15778     * measured width and measured height. Failing to do so will trigger an
15779     * exception at measurement time.</p>
15780     *
15781     * @param measuredWidth The measured width of this view.  May be a complex
15782     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15783     * {@link #MEASURED_STATE_TOO_SMALL}.
15784     * @param measuredHeight The measured height of this view.  May be a complex
15785     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15786     * {@link #MEASURED_STATE_TOO_SMALL}.
15787     */
15788    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
15789        boolean optical = isLayoutModeOptical(this);
15790        if (optical != isLayoutModeOptical(mParent)) {
15791            Insets insets = getOpticalInsets();
15792            int opticalWidth  = insets.left + insets.right;
15793            int opticalHeight = insets.top  + insets.bottom;
15794
15795            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
15796            measuredHeight += optical ? opticalHeight : -opticalHeight;
15797        }
15798        mMeasuredWidth = measuredWidth;
15799        mMeasuredHeight = measuredHeight;
15800
15801        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
15802    }
15803
15804    /**
15805     * Merge two states as returned by {@link #getMeasuredState()}.
15806     * @param curState The current state as returned from a view or the result
15807     * of combining multiple views.
15808     * @param newState The new view state to combine.
15809     * @return Returns a new integer reflecting the combination of the two
15810     * states.
15811     */
15812    public static int combineMeasuredStates(int curState, int newState) {
15813        return curState | newState;
15814    }
15815
15816    /**
15817     * Version of {@link #resolveSizeAndState(int, int, int)}
15818     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
15819     */
15820    public static int resolveSize(int size, int measureSpec) {
15821        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
15822    }
15823
15824    /**
15825     * Utility to reconcile a desired size and state, with constraints imposed
15826     * by a MeasureSpec.  Will take the desired size, unless a different size
15827     * is imposed by the constraints.  The returned value is a compound integer,
15828     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
15829     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
15830     * size is smaller than the size the view wants to be.
15831     *
15832     * @param size How big the view wants to be
15833     * @param measureSpec Constraints imposed by the parent
15834     * @return Size information bit mask as defined by
15835     * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
15836     */
15837    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
15838        int result = size;
15839        int specMode = MeasureSpec.getMode(measureSpec);
15840        int specSize =  MeasureSpec.getSize(measureSpec);
15841        switch (specMode) {
15842        case MeasureSpec.UNSPECIFIED:
15843            result = size;
15844            break;
15845        case MeasureSpec.AT_MOST:
15846            if (specSize < size) {
15847                result = specSize | MEASURED_STATE_TOO_SMALL;
15848            } else {
15849                result = size;
15850            }
15851            break;
15852        case MeasureSpec.EXACTLY:
15853            result = specSize;
15854            break;
15855        }
15856        return result | (childMeasuredState&MEASURED_STATE_MASK);
15857    }
15858
15859    /**
15860     * Utility to return a default size. Uses the supplied size if the
15861     * MeasureSpec imposed no constraints. Will get larger if allowed
15862     * by the MeasureSpec.
15863     *
15864     * @param size Default size for this view
15865     * @param measureSpec Constraints imposed by the parent
15866     * @return The size this view should be.
15867     */
15868    public static int getDefaultSize(int size, int measureSpec) {
15869        int result = size;
15870        int specMode = MeasureSpec.getMode(measureSpec);
15871        int specSize = MeasureSpec.getSize(measureSpec);
15872
15873        switch (specMode) {
15874        case MeasureSpec.UNSPECIFIED:
15875            result = size;
15876            break;
15877        case MeasureSpec.AT_MOST:
15878        case MeasureSpec.EXACTLY:
15879            result = specSize;
15880            break;
15881        }
15882        return result;
15883    }
15884
15885    /**
15886     * Returns the suggested minimum height that the view should use. This
15887     * returns the maximum of the view's minimum height
15888     * and the background's minimum height
15889     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
15890     * <p>
15891     * When being used in {@link #onMeasure(int, int)}, the caller should still
15892     * ensure the returned height is within the requirements of the parent.
15893     *
15894     * @return The suggested minimum height of the view.
15895     */
15896    protected int getSuggestedMinimumHeight() {
15897        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
15898
15899    }
15900
15901    /**
15902     * Returns the suggested minimum width that the view should use. This
15903     * returns the maximum of the view's minimum width)
15904     * and the background's minimum width
15905     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
15906     * <p>
15907     * When being used in {@link #onMeasure(int, int)}, the caller should still
15908     * ensure the returned width is within the requirements of the parent.
15909     *
15910     * @return The suggested minimum width of the view.
15911     */
15912    protected int getSuggestedMinimumWidth() {
15913        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
15914    }
15915
15916    /**
15917     * Returns the minimum height of the view.
15918     *
15919     * @return the minimum height the view will try to be.
15920     *
15921     * @see #setMinimumHeight(int)
15922     *
15923     * @attr ref android.R.styleable#View_minHeight
15924     */
15925    public int getMinimumHeight() {
15926        return mMinHeight;
15927    }
15928
15929    /**
15930     * Sets the minimum height of the view. It is not guaranteed the view will
15931     * be able to achieve this minimum height (for example, if its parent layout
15932     * constrains it with less available height).
15933     *
15934     * @param minHeight The minimum height the view will try to be.
15935     *
15936     * @see #getMinimumHeight()
15937     *
15938     * @attr ref android.R.styleable#View_minHeight
15939     */
15940    public void setMinimumHeight(int minHeight) {
15941        mMinHeight = minHeight;
15942        requestLayout();
15943    }
15944
15945    /**
15946     * Returns the minimum width of the view.
15947     *
15948     * @return the minimum width the view will try to be.
15949     *
15950     * @see #setMinimumWidth(int)
15951     *
15952     * @attr ref android.R.styleable#View_minWidth
15953     */
15954    public int getMinimumWidth() {
15955        return mMinWidth;
15956    }
15957
15958    /**
15959     * Sets the minimum width of the view. It is not guaranteed the view will
15960     * be able to achieve this minimum width (for example, if its parent layout
15961     * constrains it with less available width).
15962     *
15963     * @param minWidth The minimum width the view will try to be.
15964     *
15965     * @see #getMinimumWidth()
15966     *
15967     * @attr ref android.R.styleable#View_minWidth
15968     */
15969    public void setMinimumWidth(int minWidth) {
15970        mMinWidth = minWidth;
15971        requestLayout();
15972
15973    }
15974
15975    /**
15976     * Get the animation currently associated with this view.
15977     *
15978     * @return The animation that is currently playing or
15979     *         scheduled to play for this view.
15980     */
15981    public Animation getAnimation() {
15982        return mCurrentAnimation;
15983    }
15984
15985    /**
15986     * Start the specified animation now.
15987     *
15988     * @param animation the animation to start now
15989     */
15990    public void startAnimation(Animation animation) {
15991        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
15992        setAnimation(animation);
15993        invalidateParentCaches();
15994        invalidate(true);
15995    }
15996
15997    /**
15998     * Cancels any animations for this view.
15999     */
16000    public void clearAnimation() {
16001        if (mCurrentAnimation != null) {
16002            mCurrentAnimation.detach();
16003        }
16004        mCurrentAnimation = null;
16005        invalidateParentIfNeeded();
16006    }
16007
16008    /**
16009     * Sets the next animation to play for this view.
16010     * If you want the animation to play immediately, use
16011     * {@link #startAnimation(android.view.animation.Animation)} instead.
16012     * This method provides allows fine-grained
16013     * control over the start time and invalidation, but you
16014     * must make sure that 1) the animation has a start time set, and
16015     * 2) the view's parent (which controls animations on its children)
16016     * will be invalidated when the animation is supposed to
16017     * start.
16018     *
16019     * @param animation The next animation, or null.
16020     */
16021    public void setAnimation(Animation animation) {
16022        mCurrentAnimation = animation;
16023
16024        if (animation != null) {
16025            // If the screen is off assume the animation start time is now instead of
16026            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
16027            // would cause the animation to start when the screen turns back on
16028            if (mAttachInfo != null && !mAttachInfo.mScreenOn &&
16029                    animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
16030                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
16031            }
16032            animation.reset();
16033        }
16034    }
16035
16036    /**
16037     * Invoked by a parent ViewGroup to notify the start of the animation
16038     * currently associated with this view. If you override this method,
16039     * always call super.onAnimationStart();
16040     *
16041     * @see #setAnimation(android.view.animation.Animation)
16042     * @see #getAnimation()
16043     */
16044    protected void onAnimationStart() {
16045        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
16046    }
16047
16048    /**
16049     * Invoked by a parent ViewGroup to notify the end of the animation
16050     * currently associated with this view. If you override this method,
16051     * always call super.onAnimationEnd();
16052     *
16053     * @see #setAnimation(android.view.animation.Animation)
16054     * @see #getAnimation()
16055     */
16056    protected void onAnimationEnd() {
16057        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
16058    }
16059
16060    /**
16061     * Invoked if there is a Transform that involves alpha. Subclass that can
16062     * draw themselves with the specified alpha should return true, and then
16063     * respect that alpha when their onDraw() is called. If this returns false
16064     * then the view may be redirected to draw into an offscreen buffer to
16065     * fulfill the request, which will look fine, but may be slower than if the
16066     * subclass handles it internally. The default implementation returns false.
16067     *
16068     * @param alpha The alpha (0..255) to apply to the view's drawing
16069     * @return true if the view can draw with the specified alpha.
16070     */
16071    protected boolean onSetAlpha(int alpha) {
16072        return false;
16073    }
16074
16075    /**
16076     * This is used by the RootView to perform an optimization when
16077     * the view hierarchy contains one or several SurfaceView.
16078     * SurfaceView is always considered transparent, but its children are not,
16079     * therefore all View objects remove themselves from the global transparent
16080     * region (passed as a parameter to this function).
16081     *
16082     * @param region The transparent region for this ViewAncestor (window).
16083     *
16084     * @return Returns true if the effective visibility of the view at this
16085     * point is opaque, regardless of the transparent region; returns false
16086     * if it is possible for underlying windows to be seen behind the view.
16087     *
16088     * {@hide}
16089     */
16090    public boolean gatherTransparentRegion(Region region) {
16091        final AttachInfo attachInfo = mAttachInfo;
16092        if (region != null && attachInfo != null) {
16093            final int pflags = mPrivateFlags;
16094            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
16095                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
16096                // remove it from the transparent region.
16097                final int[] location = attachInfo.mTransparentLocation;
16098                getLocationInWindow(location);
16099                region.op(location[0], location[1], location[0] + mRight - mLeft,
16100                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
16101            } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
16102                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
16103                // exists, so we remove the background drawable's non-transparent
16104                // parts from this transparent region.
16105                applyDrawableToTransparentRegion(mBackground, region);
16106            }
16107        }
16108        return true;
16109    }
16110
16111    /**
16112     * Play a sound effect for this view.
16113     *
16114     * <p>The framework will play sound effects for some built in actions, such as
16115     * clicking, but you may wish to play these effects in your widget,
16116     * for instance, for internal navigation.
16117     *
16118     * <p>The sound effect will only be played if sound effects are enabled by the user, and
16119     * {@link #isSoundEffectsEnabled()} is true.
16120     *
16121     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
16122     */
16123    public void playSoundEffect(int soundConstant) {
16124        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
16125            return;
16126        }
16127        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
16128    }
16129
16130    /**
16131     * BZZZTT!!1!
16132     *
16133     * <p>Provide haptic feedback to the user for this view.
16134     *
16135     * <p>The framework will provide haptic feedback for some built in actions,
16136     * such as long presses, but you may wish to provide feedback for your
16137     * own widget.
16138     *
16139     * <p>The feedback will only be performed if
16140     * {@link #isHapticFeedbackEnabled()} is true.
16141     *
16142     * @param feedbackConstant One of the constants defined in
16143     * {@link HapticFeedbackConstants}
16144     */
16145    public boolean performHapticFeedback(int feedbackConstant) {
16146        return performHapticFeedback(feedbackConstant, 0);
16147    }
16148
16149    /**
16150     * BZZZTT!!1!
16151     *
16152     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
16153     *
16154     * @param feedbackConstant One of the constants defined in
16155     * {@link HapticFeedbackConstants}
16156     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
16157     */
16158    public boolean performHapticFeedback(int feedbackConstant, int flags) {
16159        if (mAttachInfo == null) {
16160            return false;
16161        }
16162        //noinspection SimplifiableIfStatement
16163        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
16164                && !isHapticFeedbackEnabled()) {
16165            return false;
16166        }
16167        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
16168                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
16169    }
16170
16171    /**
16172     * Request that the visibility of the status bar or other screen/window
16173     * decorations be changed.
16174     *
16175     * <p>This method is used to put the over device UI into temporary modes
16176     * where the user's attention is focused more on the application content,
16177     * by dimming or hiding surrounding system affordances.  This is typically
16178     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
16179     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
16180     * to be placed behind the action bar (and with these flags other system
16181     * affordances) so that smooth transitions between hiding and showing them
16182     * can be done.
16183     *
16184     * <p>Two representative examples of the use of system UI visibility is
16185     * implementing a content browsing application (like a magazine reader)
16186     * and a video playing application.
16187     *
16188     * <p>The first code shows a typical implementation of a View in a content
16189     * browsing application.  In this implementation, the application goes
16190     * into a content-oriented mode by hiding the status bar and action bar,
16191     * and putting the navigation elements into lights out mode.  The user can
16192     * then interact with content while in this mode.  Such an application should
16193     * provide an easy way for the user to toggle out of the mode (such as to
16194     * check information in the status bar or access notifications).  In the
16195     * implementation here, this is done simply by tapping on the content.
16196     *
16197     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
16198     *      content}
16199     *
16200     * <p>This second code sample shows a typical implementation of a View
16201     * in a video playing application.  In this situation, while the video is
16202     * playing the application would like to go into a complete full-screen mode,
16203     * to use as much of the display as possible for the video.  When in this state
16204     * the user can not interact with the application; the system intercepts
16205     * touching on the screen to pop the UI out of full screen mode.  See
16206     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
16207     *
16208     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
16209     *      content}
16210     *
16211     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
16212     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
16213     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
16214     * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
16215     */
16216    public void setSystemUiVisibility(int visibility) {
16217        if (visibility != mSystemUiVisibility) {
16218            mSystemUiVisibility = visibility;
16219            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
16220                mParent.recomputeViewAttributes(this);
16221            }
16222        }
16223    }
16224
16225    /**
16226     * Returns the last {@link #setSystemUiVisibility(int) that this view has requested.
16227     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
16228     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
16229     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
16230     * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
16231     */
16232    public int getSystemUiVisibility() {
16233        return mSystemUiVisibility;
16234    }
16235
16236    /**
16237     * Returns the current system UI visibility that is currently set for
16238     * the entire window.  This is the combination of the
16239     * {@link #setSystemUiVisibility(int)} values supplied by all of the
16240     * views in the window.
16241     */
16242    public int getWindowSystemUiVisibility() {
16243        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
16244    }
16245
16246    /**
16247     * Override to find out when the window's requested system UI visibility
16248     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
16249     * This is different from the callbacks recieved through
16250     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
16251     * in that this is only telling you about the local request of the window,
16252     * not the actual values applied by the system.
16253     */
16254    public void onWindowSystemUiVisibilityChanged(int visible) {
16255    }
16256
16257    /**
16258     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
16259     * the view hierarchy.
16260     */
16261    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
16262        onWindowSystemUiVisibilityChanged(visible);
16263    }
16264
16265    /**
16266     * Set a listener to receive callbacks when the visibility of the system bar changes.
16267     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
16268     */
16269    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
16270        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
16271        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
16272            mParent.recomputeViewAttributes(this);
16273        }
16274    }
16275
16276    /**
16277     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
16278     * the view hierarchy.
16279     */
16280    public void dispatchSystemUiVisibilityChanged(int visibility) {
16281        ListenerInfo li = mListenerInfo;
16282        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
16283            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
16284                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
16285        }
16286    }
16287
16288    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
16289        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
16290        if (val != mSystemUiVisibility) {
16291            setSystemUiVisibility(val);
16292            return true;
16293        }
16294        return false;
16295    }
16296
16297    /** @hide */
16298    public void setDisabledSystemUiVisibility(int flags) {
16299        if (mAttachInfo != null) {
16300            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
16301                mAttachInfo.mDisabledSystemUiVisibility = flags;
16302                if (mParent != null) {
16303                    mParent.recomputeViewAttributes(this);
16304                }
16305            }
16306        }
16307    }
16308
16309    /**
16310     * Creates an image that the system displays during the drag and drop
16311     * operation. This is called a &quot;drag shadow&quot;. The default implementation
16312     * for a DragShadowBuilder based on a View returns an image that has exactly the same
16313     * appearance as the given View. The default also positions the center of the drag shadow
16314     * directly under the touch point. If no View is provided (the constructor with no parameters
16315     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
16316     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
16317     * default is an invisible drag shadow.
16318     * <p>
16319     * You are not required to use the View you provide to the constructor as the basis of the
16320     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
16321     * anything you want as the drag shadow.
16322     * </p>
16323     * <p>
16324     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
16325     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
16326     *  size and position of the drag shadow. It uses this data to construct a
16327     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
16328     *  so that your application can draw the shadow image in the Canvas.
16329     * </p>
16330     *
16331     * <div class="special reference">
16332     * <h3>Developer Guides</h3>
16333     * <p>For a guide to implementing drag and drop features, read the
16334     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
16335     * </div>
16336     */
16337    public static class DragShadowBuilder {
16338        private final WeakReference<View> mView;
16339
16340        /**
16341         * Constructs a shadow image builder based on a View. By default, the resulting drag
16342         * shadow will have the same appearance and dimensions as the View, with the touch point
16343         * over the center of the View.
16344         * @param view A View. Any View in scope can be used.
16345         */
16346        public DragShadowBuilder(View view) {
16347            mView = new WeakReference<View>(view);
16348        }
16349
16350        /**
16351         * Construct a shadow builder object with no associated View.  This
16352         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
16353         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
16354         * to supply the drag shadow's dimensions and appearance without
16355         * reference to any View object. If they are not overridden, then the result is an
16356         * invisible drag shadow.
16357         */
16358        public DragShadowBuilder() {
16359            mView = new WeakReference<View>(null);
16360        }
16361
16362        /**
16363         * Returns the View object that had been passed to the
16364         * {@link #View.DragShadowBuilder(View)}
16365         * constructor.  If that View parameter was {@code null} or if the
16366         * {@link #View.DragShadowBuilder()}
16367         * constructor was used to instantiate the builder object, this method will return
16368         * null.
16369         *
16370         * @return The View object associate with this builder object.
16371         */
16372        @SuppressWarnings({"JavadocReference"})
16373        final public View getView() {
16374            return mView.get();
16375        }
16376
16377        /**
16378         * Provides the metrics for the shadow image. These include the dimensions of
16379         * the shadow image, and the point within that shadow that should
16380         * be centered under the touch location while dragging.
16381         * <p>
16382         * The default implementation sets the dimensions of the shadow to be the
16383         * same as the dimensions of the View itself and centers the shadow under
16384         * the touch point.
16385         * </p>
16386         *
16387         * @param shadowSize A {@link android.graphics.Point} containing the width and height
16388         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
16389         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
16390         * image.
16391         *
16392         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
16393         * shadow image that should be underneath the touch point during the drag and drop
16394         * operation. Your application must set {@link android.graphics.Point#x} to the
16395         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
16396         */
16397        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
16398            final View view = mView.get();
16399            if (view != null) {
16400                shadowSize.set(view.getWidth(), view.getHeight());
16401                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
16402            } else {
16403                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
16404            }
16405        }
16406
16407        /**
16408         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
16409         * based on the dimensions it received from the
16410         * {@link #onProvideShadowMetrics(Point, Point)} callback.
16411         *
16412         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
16413         */
16414        public void onDrawShadow(Canvas canvas) {
16415            final View view = mView.get();
16416            if (view != null) {
16417                view.draw(canvas);
16418            } else {
16419                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
16420            }
16421        }
16422    }
16423
16424    /**
16425     * Starts a drag and drop operation. When your application calls this method, it passes a
16426     * {@link android.view.View.DragShadowBuilder} object to the system. The
16427     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
16428     * to get metrics for the drag shadow, and then calls the object's
16429     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
16430     * <p>
16431     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
16432     *  drag events to all the View objects in your application that are currently visible. It does
16433     *  this either by calling the View object's drag listener (an implementation of
16434     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
16435     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
16436     *  Both are passed a {@link android.view.DragEvent} object that has a
16437     *  {@link android.view.DragEvent#getAction()} value of
16438     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
16439     * </p>
16440     * <p>
16441     * Your application can invoke startDrag() on any attached View object. The View object does not
16442     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
16443     * be related to the View the user selected for dragging.
16444     * </p>
16445     * @param data A {@link android.content.ClipData} object pointing to the data to be
16446     * transferred by the drag and drop operation.
16447     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
16448     * drag shadow.
16449     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
16450     * drop operation. This Object is put into every DragEvent object sent by the system during the
16451     * current drag.
16452     * <p>
16453     * myLocalState is a lightweight mechanism for the sending information from the dragged View
16454     * to the target Views. For example, it can contain flags that differentiate between a
16455     * a copy operation and a move operation.
16456     * </p>
16457     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
16458     * so the parameter should be set to 0.
16459     * @return {@code true} if the method completes successfully, or
16460     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
16461     * do a drag, and so no drag operation is in progress.
16462     */
16463    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
16464            Object myLocalState, int flags) {
16465        if (ViewDebug.DEBUG_DRAG) {
16466            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
16467        }
16468        boolean okay = false;
16469
16470        Point shadowSize = new Point();
16471        Point shadowTouchPoint = new Point();
16472        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
16473
16474        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
16475                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
16476            throw new IllegalStateException("Drag shadow dimensions must not be negative");
16477        }
16478
16479        if (ViewDebug.DEBUG_DRAG) {
16480            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
16481                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
16482        }
16483        Surface surface = new Surface();
16484        try {
16485            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
16486                    flags, shadowSize.x, shadowSize.y, surface);
16487            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
16488                    + " surface=" + surface);
16489            if (token != null) {
16490                Canvas canvas = surface.lockCanvas(null);
16491                try {
16492                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
16493                    shadowBuilder.onDrawShadow(canvas);
16494                } finally {
16495                    surface.unlockCanvasAndPost(canvas);
16496                }
16497
16498                final ViewRootImpl root = getViewRootImpl();
16499
16500                // Cache the local state object for delivery with DragEvents
16501                root.setLocalDragState(myLocalState);
16502
16503                // repurpose 'shadowSize' for the last touch point
16504                root.getLastTouchPoint(shadowSize);
16505
16506                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
16507                        shadowSize.x, shadowSize.y,
16508                        shadowTouchPoint.x, shadowTouchPoint.y, data);
16509                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
16510
16511                // Off and running!  Release our local surface instance; the drag
16512                // shadow surface is now managed by the system process.
16513                surface.release();
16514            }
16515        } catch (Exception e) {
16516            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
16517            surface.destroy();
16518        }
16519
16520        return okay;
16521    }
16522
16523    /**
16524     * Handles drag events sent by the system following a call to
16525     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
16526     *<p>
16527     * When the system calls this method, it passes a
16528     * {@link android.view.DragEvent} object. A call to
16529     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
16530     * in DragEvent. The method uses these to determine what is happening in the drag and drop
16531     * operation.
16532     * @param event The {@link android.view.DragEvent} sent by the system.
16533     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
16534     * in DragEvent, indicating the type of drag event represented by this object.
16535     * @return {@code true} if the method was successful, otherwise {@code false}.
16536     * <p>
16537     *  The method should return {@code true} in response to an action type of
16538     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
16539     *  operation.
16540     * </p>
16541     * <p>
16542     *  The method should also return {@code true} in response to an action type of
16543     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
16544     *  {@code false} if it didn't.
16545     * </p>
16546     */
16547    public boolean onDragEvent(DragEvent event) {
16548        return false;
16549    }
16550
16551    /**
16552     * Detects if this View is enabled and has a drag event listener.
16553     * If both are true, then it calls the drag event listener with the
16554     * {@link android.view.DragEvent} it received. If the drag event listener returns
16555     * {@code true}, then dispatchDragEvent() returns {@code true}.
16556     * <p>
16557     * For all other cases, the method calls the
16558     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
16559     * method and returns its result.
16560     * </p>
16561     * <p>
16562     * This ensures that a drag event is always consumed, even if the View does not have a drag
16563     * event listener. However, if the View has a listener and the listener returns true, then
16564     * onDragEvent() is not called.
16565     * </p>
16566     */
16567    public boolean dispatchDragEvent(DragEvent event) {
16568        //noinspection SimplifiableIfStatement
16569        ListenerInfo li = mListenerInfo;
16570        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
16571                && li.mOnDragListener.onDrag(this, event)) {
16572            return true;
16573        }
16574        return onDragEvent(event);
16575    }
16576
16577    boolean canAcceptDrag() {
16578        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
16579    }
16580
16581    /**
16582     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
16583     * it is ever exposed at all.
16584     * @hide
16585     */
16586    public void onCloseSystemDialogs(String reason) {
16587    }
16588
16589    /**
16590     * Given a Drawable whose bounds have been set to draw into this view,
16591     * update a Region being computed for
16592     * {@link #gatherTransparentRegion(android.graphics.Region)} so
16593     * that any non-transparent parts of the Drawable are removed from the
16594     * given transparent region.
16595     *
16596     * @param dr The Drawable whose transparency is to be applied to the region.
16597     * @param region A Region holding the current transparency information,
16598     * where any parts of the region that are set are considered to be
16599     * transparent.  On return, this region will be modified to have the
16600     * transparency information reduced by the corresponding parts of the
16601     * Drawable that are not transparent.
16602     * {@hide}
16603     */
16604    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
16605        if (DBG) {
16606            Log.i("View", "Getting transparent region for: " + this);
16607        }
16608        final Region r = dr.getTransparentRegion();
16609        final Rect db = dr.getBounds();
16610        final AttachInfo attachInfo = mAttachInfo;
16611        if (r != null && attachInfo != null) {
16612            final int w = getRight()-getLeft();
16613            final int h = getBottom()-getTop();
16614            if (db.left > 0) {
16615                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
16616                r.op(0, 0, db.left, h, Region.Op.UNION);
16617            }
16618            if (db.right < w) {
16619                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
16620                r.op(db.right, 0, w, h, Region.Op.UNION);
16621            }
16622            if (db.top > 0) {
16623                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
16624                r.op(0, 0, w, db.top, Region.Op.UNION);
16625            }
16626            if (db.bottom < h) {
16627                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
16628                r.op(0, db.bottom, w, h, Region.Op.UNION);
16629            }
16630            final int[] location = attachInfo.mTransparentLocation;
16631            getLocationInWindow(location);
16632            r.translate(location[0], location[1]);
16633            region.op(r, Region.Op.INTERSECT);
16634        } else {
16635            region.op(db, Region.Op.DIFFERENCE);
16636        }
16637    }
16638
16639    private void checkForLongClick(int delayOffset) {
16640        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
16641            mHasPerformedLongPress = false;
16642
16643            if (mPendingCheckForLongPress == null) {
16644                mPendingCheckForLongPress = new CheckForLongPress();
16645            }
16646            mPendingCheckForLongPress.rememberWindowAttachCount();
16647            postDelayed(mPendingCheckForLongPress,
16648                    ViewConfiguration.getLongPressTimeout() - delayOffset);
16649        }
16650    }
16651
16652    /**
16653     * Inflate a view from an XML resource.  This convenience method wraps the {@link
16654     * LayoutInflater} class, which provides a full range of options for view inflation.
16655     *
16656     * @param context The Context object for your activity or application.
16657     * @param resource The resource ID to inflate
16658     * @param root A view group that will be the parent.  Used to properly inflate the
16659     * layout_* parameters.
16660     * @see LayoutInflater
16661     */
16662    public static View inflate(Context context, int resource, ViewGroup root) {
16663        LayoutInflater factory = LayoutInflater.from(context);
16664        return factory.inflate(resource, root);
16665    }
16666
16667    /**
16668     * Scroll the view with standard behavior for scrolling beyond the normal
16669     * content boundaries. Views that call this method should override
16670     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
16671     * results of an over-scroll operation.
16672     *
16673     * Views can use this method to handle any touch or fling-based scrolling.
16674     *
16675     * @param deltaX Change in X in pixels
16676     * @param deltaY Change in Y in pixels
16677     * @param scrollX Current X scroll value in pixels before applying deltaX
16678     * @param scrollY Current Y scroll value in pixels before applying deltaY
16679     * @param scrollRangeX Maximum content scroll range along the X axis
16680     * @param scrollRangeY Maximum content scroll range along the Y axis
16681     * @param maxOverScrollX Number of pixels to overscroll by in either direction
16682     *          along the X axis.
16683     * @param maxOverScrollY Number of pixels to overscroll by in either direction
16684     *          along the Y axis.
16685     * @param isTouchEvent true if this scroll operation is the result of a touch event.
16686     * @return true if scrolling was clamped to an over-scroll boundary along either
16687     *          axis, false otherwise.
16688     */
16689    @SuppressWarnings({"UnusedParameters"})
16690    protected boolean overScrollBy(int deltaX, int deltaY,
16691            int scrollX, int scrollY,
16692            int scrollRangeX, int scrollRangeY,
16693            int maxOverScrollX, int maxOverScrollY,
16694            boolean isTouchEvent) {
16695        final int overScrollMode = mOverScrollMode;
16696        final boolean canScrollHorizontal =
16697                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
16698        final boolean canScrollVertical =
16699                computeVerticalScrollRange() > computeVerticalScrollExtent();
16700        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
16701                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
16702        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
16703                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
16704
16705        int newScrollX = scrollX + deltaX;
16706        if (!overScrollHorizontal) {
16707            maxOverScrollX = 0;
16708        }
16709
16710        int newScrollY = scrollY + deltaY;
16711        if (!overScrollVertical) {
16712            maxOverScrollY = 0;
16713        }
16714
16715        // Clamp values if at the limits and record
16716        final int left = -maxOverScrollX;
16717        final int right = maxOverScrollX + scrollRangeX;
16718        final int top = -maxOverScrollY;
16719        final int bottom = maxOverScrollY + scrollRangeY;
16720
16721        boolean clampedX = false;
16722        if (newScrollX > right) {
16723            newScrollX = right;
16724            clampedX = true;
16725        } else if (newScrollX < left) {
16726            newScrollX = left;
16727            clampedX = true;
16728        }
16729
16730        boolean clampedY = false;
16731        if (newScrollY > bottom) {
16732            newScrollY = bottom;
16733            clampedY = true;
16734        } else if (newScrollY < top) {
16735            newScrollY = top;
16736            clampedY = true;
16737        }
16738
16739        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
16740
16741        return clampedX || clampedY;
16742    }
16743
16744    /**
16745     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
16746     * respond to the results of an over-scroll operation.
16747     *
16748     * @param scrollX New X scroll value in pixels
16749     * @param scrollY New Y scroll value in pixels
16750     * @param clampedX True if scrollX was clamped to an over-scroll boundary
16751     * @param clampedY True if scrollY was clamped to an over-scroll boundary
16752     */
16753    protected void onOverScrolled(int scrollX, int scrollY,
16754            boolean clampedX, boolean clampedY) {
16755        // Intentionally empty.
16756    }
16757
16758    /**
16759     * Returns the over-scroll mode for this view. The result will be
16760     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16761     * (allow over-scrolling only if the view content is larger than the container),
16762     * or {@link #OVER_SCROLL_NEVER}.
16763     *
16764     * @return This view's over-scroll mode.
16765     */
16766    public int getOverScrollMode() {
16767        return mOverScrollMode;
16768    }
16769
16770    /**
16771     * Set the over-scroll mode for this view. Valid over-scroll modes are
16772     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16773     * (allow over-scrolling only if the view content is larger than the container),
16774     * or {@link #OVER_SCROLL_NEVER}.
16775     *
16776     * Setting the over-scroll mode of a view will have an effect only if the
16777     * view is capable of scrolling.
16778     *
16779     * @param overScrollMode The new over-scroll mode for this view.
16780     */
16781    public void setOverScrollMode(int overScrollMode) {
16782        if (overScrollMode != OVER_SCROLL_ALWAYS &&
16783                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
16784                overScrollMode != OVER_SCROLL_NEVER) {
16785            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
16786        }
16787        mOverScrollMode = overScrollMode;
16788    }
16789
16790    /**
16791     * Gets a scale factor that determines the distance the view should scroll
16792     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
16793     * @return The vertical scroll scale factor.
16794     * @hide
16795     */
16796    protected float getVerticalScrollFactor() {
16797        if (mVerticalScrollFactor == 0) {
16798            TypedValue outValue = new TypedValue();
16799            if (!mContext.getTheme().resolveAttribute(
16800                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
16801                throw new IllegalStateException(
16802                        "Expected theme to define listPreferredItemHeight.");
16803            }
16804            mVerticalScrollFactor = outValue.getDimension(
16805                    mContext.getResources().getDisplayMetrics());
16806        }
16807        return mVerticalScrollFactor;
16808    }
16809
16810    /**
16811     * Gets a scale factor that determines the distance the view should scroll
16812     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
16813     * @return The horizontal scroll scale factor.
16814     * @hide
16815     */
16816    protected float getHorizontalScrollFactor() {
16817        // TODO: Should use something else.
16818        return getVerticalScrollFactor();
16819    }
16820
16821    /**
16822     * Return the value specifying the text direction or policy that was set with
16823     * {@link #setTextDirection(int)}.
16824     *
16825     * @return the defined text direction. It can be one of:
16826     *
16827     * {@link #TEXT_DIRECTION_INHERIT},
16828     * {@link #TEXT_DIRECTION_FIRST_STRONG}
16829     * {@link #TEXT_DIRECTION_ANY_RTL},
16830     * {@link #TEXT_DIRECTION_LTR},
16831     * {@link #TEXT_DIRECTION_RTL},
16832     * {@link #TEXT_DIRECTION_LOCALE}
16833     *
16834     * @attr ref android.R.styleable#View_textDirection
16835     *
16836     * @hide
16837     */
16838    @ViewDebug.ExportedProperty(category = "text", mapping = {
16839            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
16840            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
16841            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
16842            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
16843            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
16844            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
16845    })
16846    public int getRawTextDirection() {
16847        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
16848    }
16849
16850    /**
16851     * Set the text direction.
16852     *
16853     * @param textDirection the direction to set. Should be one of:
16854     *
16855     * {@link #TEXT_DIRECTION_INHERIT},
16856     * {@link #TEXT_DIRECTION_FIRST_STRONG}
16857     * {@link #TEXT_DIRECTION_ANY_RTL},
16858     * {@link #TEXT_DIRECTION_LTR},
16859     * {@link #TEXT_DIRECTION_RTL},
16860     * {@link #TEXT_DIRECTION_LOCALE}
16861     *
16862     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
16863     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
16864     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
16865     *
16866     * @attr ref android.R.styleable#View_textDirection
16867     */
16868    public void setTextDirection(int textDirection) {
16869        if (getRawTextDirection() != textDirection) {
16870            // Reset the current text direction and the resolved one
16871            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
16872            resetResolvedTextDirection();
16873            // Set the new text direction
16874            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
16875            // Do resolution
16876            resolveTextDirection();
16877            // Notify change
16878            onRtlPropertiesChanged(getLayoutDirection());
16879            // Refresh
16880            requestLayout();
16881            invalidate(true);
16882        }
16883    }
16884
16885    /**
16886     * Return the resolved text direction.
16887     *
16888     * @return the resolved text direction. Returns one of:
16889     *
16890     * {@link #TEXT_DIRECTION_FIRST_STRONG}
16891     * {@link #TEXT_DIRECTION_ANY_RTL},
16892     * {@link #TEXT_DIRECTION_LTR},
16893     * {@link #TEXT_DIRECTION_RTL},
16894     * {@link #TEXT_DIRECTION_LOCALE}
16895     *
16896     * @attr ref android.R.styleable#View_textDirection
16897     */
16898    public int getTextDirection() {
16899        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
16900    }
16901
16902    /**
16903     * Resolve the text direction.
16904     *
16905     * @return true if resolution has been done, false otherwise.
16906     *
16907     * @hide
16908     */
16909    public boolean resolveTextDirection() {
16910        // Reset any previous text direction resolution
16911        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
16912
16913        if (hasRtlSupport()) {
16914            // Set resolved text direction flag depending on text direction flag
16915            final int textDirection = getRawTextDirection();
16916            switch(textDirection) {
16917                case TEXT_DIRECTION_INHERIT:
16918                    if (!canResolveTextDirection()) {
16919                        // We cannot do the resolution if there is no parent, so use the default one
16920                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16921                        // Resolution will need to happen again later
16922                        return false;
16923                    }
16924
16925                    // Parent has not yet resolved, so we still return the default
16926                    if (!mParent.isTextDirectionResolved()) {
16927                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16928                        // Resolution will need to happen again later
16929                        return false;
16930                    }
16931
16932                    // Set current resolved direction to the same value as the parent's one
16933                    final int parentResolvedDirection = mParent.getTextDirection();
16934                    switch (parentResolvedDirection) {
16935                        case TEXT_DIRECTION_FIRST_STRONG:
16936                        case TEXT_DIRECTION_ANY_RTL:
16937                        case TEXT_DIRECTION_LTR:
16938                        case TEXT_DIRECTION_RTL:
16939                        case TEXT_DIRECTION_LOCALE:
16940                            mPrivateFlags2 |=
16941                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
16942                            break;
16943                        default:
16944                            // Default resolved direction is "first strong" heuristic
16945                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16946                    }
16947                    break;
16948                case TEXT_DIRECTION_FIRST_STRONG:
16949                case TEXT_DIRECTION_ANY_RTL:
16950                case TEXT_DIRECTION_LTR:
16951                case TEXT_DIRECTION_RTL:
16952                case TEXT_DIRECTION_LOCALE:
16953                    // Resolved direction is the same as text direction
16954                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
16955                    break;
16956                default:
16957                    // Default resolved direction is "first strong" heuristic
16958                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16959            }
16960        } else {
16961            // Default resolved direction is "first strong" heuristic
16962            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16963        }
16964
16965        // Set to resolved
16966        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
16967        return true;
16968    }
16969
16970    /**
16971     * Check if text direction resolution can be done.
16972     *
16973     * @return true if text direction resolution can be done otherwise return false.
16974     *
16975     * @hide
16976     */
16977    public boolean canResolveTextDirection() {
16978        switch (getRawTextDirection()) {
16979            case TEXT_DIRECTION_INHERIT:
16980                return (mParent != null) && mParent.canResolveTextDirection();
16981            default:
16982                return true;
16983        }
16984    }
16985
16986    /**
16987     * Reset resolved text direction. Text direction will be resolved during a call to
16988     * {@link #onMeasure(int, int)}.
16989     *
16990     * @hide
16991     */
16992    public void resetResolvedTextDirection() {
16993        // Reset any previous text direction resolution
16994        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
16995        // Set to default value
16996        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16997    }
16998
16999    /**
17000     * @return true if text direction is inherited.
17001     *
17002     * @hide
17003     */
17004    public boolean isTextDirectionInherited() {
17005        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
17006    }
17007
17008    /**
17009     * @return true if text direction is resolved.
17010     *
17011     * @hide
17012     */
17013    public boolean isTextDirectionResolved() {
17014        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
17015    }
17016
17017    /**
17018     * Return the value specifying the text alignment or policy that was set with
17019     * {@link #setTextAlignment(int)}.
17020     *
17021     * @return the defined text alignment. It can be one of:
17022     *
17023     * {@link #TEXT_ALIGNMENT_INHERIT},
17024     * {@link #TEXT_ALIGNMENT_GRAVITY},
17025     * {@link #TEXT_ALIGNMENT_CENTER},
17026     * {@link #TEXT_ALIGNMENT_TEXT_START},
17027     * {@link #TEXT_ALIGNMENT_TEXT_END},
17028     * {@link #TEXT_ALIGNMENT_VIEW_START},
17029     * {@link #TEXT_ALIGNMENT_VIEW_END}
17030     *
17031     * @attr ref android.R.styleable#View_textAlignment
17032     *
17033     * @hide
17034     */
17035    @ViewDebug.ExportedProperty(category = "text", mapping = {
17036            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
17037            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
17038            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
17039            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
17040            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
17041            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
17042            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
17043    })
17044    public int getRawTextAlignment() {
17045        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
17046    }
17047
17048    /**
17049     * Set the text alignment.
17050     *
17051     * @param textAlignment The text alignment to set. Should be one of
17052     *
17053     * {@link #TEXT_ALIGNMENT_INHERIT},
17054     * {@link #TEXT_ALIGNMENT_GRAVITY},
17055     * {@link #TEXT_ALIGNMENT_CENTER},
17056     * {@link #TEXT_ALIGNMENT_TEXT_START},
17057     * {@link #TEXT_ALIGNMENT_TEXT_END},
17058     * {@link #TEXT_ALIGNMENT_VIEW_START},
17059     * {@link #TEXT_ALIGNMENT_VIEW_END}
17060     *
17061     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
17062     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
17063     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
17064     *
17065     * @attr ref android.R.styleable#View_textAlignment
17066     */
17067    public void setTextAlignment(int textAlignment) {
17068        if (textAlignment != getRawTextAlignment()) {
17069            // Reset the current and resolved text alignment
17070            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
17071            resetResolvedTextAlignment();
17072            // Set the new text alignment
17073            mPrivateFlags2 |=
17074                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
17075            // Do resolution
17076            resolveTextAlignment();
17077            // Notify change
17078            onRtlPropertiesChanged(getLayoutDirection());
17079            // Refresh
17080            requestLayout();
17081            invalidate(true);
17082        }
17083    }
17084
17085    /**
17086     * Return the resolved text alignment.
17087     *
17088     * @return the resolved text alignment. Returns one of:
17089     *
17090     * {@link #TEXT_ALIGNMENT_GRAVITY},
17091     * {@link #TEXT_ALIGNMENT_CENTER},
17092     * {@link #TEXT_ALIGNMENT_TEXT_START},
17093     * {@link #TEXT_ALIGNMENT_TEXT_END},
17094     * {@link #TEXT_ALIGNMENT_VIEW_START},
17095     * {@link #TEXT_ALIGNMENT_VIEW_END}
17096     *
17097     * @attr ref android.R.styleable#View_textAlignment
17098     */
17099    @ViewDebug.ExportedProperty(category = "text", mapping = {
17100            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
17101            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
17102            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
17103            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
17104            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
17105            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
17106            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
17107    })
17108    public int getTextAlignment() {
17109        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
17110                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
17111    }
17112
17113    /**
17114     * Resolve the text alignment.
17115     *
17116     * @return true if resolution has been done, false otherwise.
17117     *
17118     * @hide
17119     */
17120    public boolean resolveTextAlignment() {
17121        // Reset any previous text alignment resolution
17122        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
17123
17124        if (hasRtlSupport()) {
17125            // Set resolved text alignment flag depending on text alignment flag
17126            final int textAlignment = getRawTextAlignment();
17127            switch (textAlignment) {
17128                case TEXT_ALIGNMENT_INHERIT:
17129                    // Check if we can resolve the text alignment
17130                    if (!canResolveTextAlignment()) {
17131                        // We cannot do the resolution if there is no parent so use the default
17132                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17133                        // Resolution will need to happen again later
17134                        return false;
17135                    }
17136
17137                    // Parent has not yet resolved, so we still return the default
17138                    if (!mParent.isTextAlignmentResolved()) {
17139                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17140                        // Resolution will need to happen again later
17141                        return false;
17142                    }
17143
17144                    final int parentResolvedTextAlignment = mParent.getTextAlignment();
17145                    switch (parentResolvedTextAlignment) {
17146                        case TEXT_ALIGNMENT_GRAVITY:
17147                        case TEXT_ALIGNMENT_TEXT_START:
17148                        case TEXT_ALIGNMENT_TEXT_END:
17149                        case TEXT_ALIGNMENT_CENTER:
17150                        case TEXT_ALIGNMENT_VIEW_START:
17151                        case TEXT_ALIGNMENT_VIEW_END:
17152                            // Resolved text alignment is the same as the parent resolved
17153                            // text alignment
17154                            mPrivateFlags2 |=
17155                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
17156                            break;
17157                        default:
17158                            // Use default resolved text alignment
17159                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17160                    }
17161                    break;
17162                case TEXT_ALIGNMENT_GRAVITY:
17163                case TEXT_ALIGNMENT_TEXT_START:
17164                case TEXT_ALIGNMENT_TEXT_END:
17165                case TEXT_ALIGNMENT_CENTER:
17166                case TEXT_ALIGNMENT_VIEW_START:
17167                case TEXT_ALIGNMENT_VIEW_END:
17168                    // Resolved text alignment is the same as text alignment
17169                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
17170                    break;
17171                default:
17172                    // Use default resolved text alignment
17173                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17174            }
17175        } else {
17176            // Use default resolved text alignment
17177            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17178        }
17179
17180        // Set the resolved
17181        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
17182        return true;
17183    }
17184
17185    /**
17186     * Check if text alignment resolution can be done.
17187     *
17188     * @return true if text alignment resolution can be done otherwise return false.
17189     *
17190     * @hide
17191     */
17192    public boolean canResolveTextAlignment() {
17193        switch (getRawTextAlignment()) {
17194            case TEXT_DIRECTION_INHERIT:
17195                return (mParent != null) && mParent.canResolveTextAlignment();
17196            default:
17197                return true;
17198        }
17199    }
17200
17201    /**
17202     * Reset resolved text alignment. Text alignment will be resolved during a call to
17203     * {@link #onMeasure(int, int)}.
17204     *
17205     * @hide
17206     */
17207    public void resetResolvedTextAlignment() {
17208        // Reset any previous text alignment resolution
17209        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
17210        // Set to default
17211        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
17212    }
17213
17214    /**
17215     * @return true if text alignment is inherited.
17216     *
17217     * @hide
17218     */
17219    public boolean isTextAlignmentInherited() {
17220        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
17221    }
17222
17223    /**
17224     * @return true if text alignment is resolved.
17225     *
17226     * @hide
17227     */
17228    public boolean isTextAlignmentResolved() {
17229        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
17230    }
17231
17232    /**
17233     * Generate a value suitable for use in {@link #setId(int)}.
17234     * This value will not collide with ID values generated at build time by aapt for R.id.
17235     *
17236     * @return a generated ID value
17237     */
17238    public static int generateViewId() {
17239        for (;;) {
17240            final int result = sNextGeneratedId.get();
17241            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
17242            int newValue = result + 1;
17243            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
17244            if (sNextGeneratedId.compareAndSet(result, newValue)) {
17245                return result;
17246            }
17247        }
17248    }
17249
17250    //
17251    // Properties
17252    //
17253    /**
17254     * A Property wrapper around the <code>alpha</code> functionality handled by the
17255     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
17256     */
17257    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
17258        @Override
17259        public void setValue(View object, float value) {
17260            object.setAlpha(value);
17261        }
17262
17263        @Override
17264        public Float get(View object) {
17265            return object.getAlpha();
17266        }
17267    };
17268
17269    /**
17270     * A Property wrapper around the <code>translationX</code> functionality handled by the
17271     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
17272     */
17273    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
17274        @Override
17275        public void setValue(View object, float value) {
17276            object.setTranslationX(value);
17277        }
17278
17279                @Override
17280        public Float get(View object) {
17281            return object.getTranslationX();
17282        }
17283    };
17284
17285    /**
17286     * A Property wrapper around the <code>translationY</code> functionality handled by the
17287     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
17288     */
17289    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
17290        @Override
17291        public void setValue(View object, float value) {
17292            object.setTranslationY(value);
17293        }
17294
17295        @Override
17296        public Float get(View object) {
17297            return object.getTranslationY();
17298        }
17299    };
17300
17301    /**
17302     * A Property wrapper around the <code>x</code> functionality handled by the
17303     * {@link View#setX(float)} and {@link View#getX()} methods.
17304     */
17305    public static final Property<View, Float> X = new FloatProperty<View>("x") {
17306        @Override
17307        public void setValue(View object, float value) {
17308            object.setX(value);
17309        }
17310
17311        @Override
17312        public Float get(View object) {
17313            return object.getX();
17314        }
17315    };
17316
17317    /**
17318     * A Property wrapper around the <code>y</code> functionality handled by the
17319     * {@link View#setY(float)} and {@link View#getY()} methods.
17320     */
17321    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
17322        @Override
17323        public void setValue(View object, float value) {
17324            object.setY(value);
17325        }
17326
17327        @Override
17328        public Float get(View object) {
17329            return object.getY();
17330        }
17331    };
17332
17333    /**
17334     * A Property wrapper around the <code>rotation</code> functionality handled by the
17335     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
17336     */
17337    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
17338        @Override
17339        public void setValue(View object, float value) {
17340            object.setRotation(value);
17341        }
17342
17343        @Override
17344        public Float get(View object) {
17345            return object.getRotation();
17346        }
17347    };
17348
17349    /**
17350     * A Property wrapper around the <code>rotationX</code> functionality handled by the
17351     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
17352     */
17353    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
17354        @Override
17355        public void setValue(View object, float value) {
17356            object.setRotationX(value);
17357        }
17358
17359        @Override
17360        public Float get(View object) {
17361            return object.getRotationX();
17362        }
17363    };
17364
17365    /**
17366     * A Property wrapper around the <code>rotationY</code> functionality handled by the
17367     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
17368     */
17369    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
17370        @Override
17371        public void setValue(View object, float value) {
17372            object.setRotationY(value);
17373        }
17374
17375        @Override
17376        public Float get(View object) {
17377            return object.getRotationY();
17378        }
17379    };
17380
17381    /**
17382     * A Property wrapper around the <code>scaleX</code> functionality handled by the
17383     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
17384     */
17385    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
17386        @Override
17387        public void setValue(View object, float value) {
17388            object.setScaleX(value);
17389        }
17390
17391        @Override
17392        public Float get(View object) {
17393            return object.getScaleX();
17394        }
17395    };
17396
17397    /**
17398     * A Property wrapper around the <code>scaleY</code> functionality handled by the
17399     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
17400     */
17401    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
17402        @Override
17403        public void setValue(View object, float value) {
17404            object.setScaleY(value);
17405        }
17406
17407        @Override
17408        public Float get(View object) {
17409            return object.getScaleY();
17410        }
17411    };
17412
17413    /**
17414     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
17415     * Each MeasureSpec represents a requirement for either the width or the height.
17416     * A MeasureSpec is comprised of a size and a mode. There are three possible
17417     * modes:
17418     * <dl>
17419     * <dt>UNSPECIFIED</dt>
17420     * <dd>
17421     * The parent has not imposed any constraint on the child. It can be whatever size
17422     * it wants.
17423     * </dd>
17424     *
17425     * <dt>EXACTLY</dt>
17426     * <dd>
17427     * The parent has determined an exact size for the child. The child is going to be
17428     * given those bounds regardless of how big it wants to be.
17429     * </dd>
17430     *
17431     * <dt>AT_MOST</dt>
17432     * <dd>
17433     * The child can be as large as it wants up to the specified size.
17434     * </dd>
17435     * </dl>
17436     *
17437     * MeasureSpecs are implemented as ints to reduce object allocation. This class
17438     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
17439     */
17440    public static class MeasureSpec {
17441        private static final int MODE_SHIFT = 30;
17442        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
17443
17444        /**
17445         * Measure specification mode: The parent has not imposed any constraint
17446         * on the child. It can be whatever size it wants.
17447         */
17448        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
17449
17450        /**
17451         * Measure specification mode: The parent has determined an exact size
17452         * for the child. The child is going to be given those bounds regardless
17453         * of how big it wants to be.
17454         */
17455        public static final int EXACTLY     = 1 << MODE_SHIFT;
17456
17457        /**
17458         * Measure specification mode: The child can be as large as it wants up
17459         * to the specified size.
17460         */
17461        public static final int AT_MOST     = 2 << MODE_SHIFT;
17462
17463        /**
17464         * Creates a measure specification based on the supplied size and mode.
17465         *
17466         * The mode must always be one of the following:
17467         * <ul>
17468         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
17469         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
17470         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
17471         * </ul>
17472         *
17473         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
17474         * implementation was such that the order of arguments did not matter
17475         * and overflow in either value could impact the resulting MeasureSpec.
17476         * {@link android.widget.RelativeLayout} was affected by this bug.
17477         * Apps targeting API levels greater than 17 will get the fixed, more strict
17478         * behavior.</p>
17479         *
17480         * @param size the size of the measure specification
17481         * @param mode the mode of the measure specification
17482         * @return the measure specification based on size and mode
17483         */
17484        public static int makeMeasureSpec(int size, int mode) {
17485            if (sUseBrokenMakeMeasureSpec) {
17486                return size + mode;
17487            } else {
17488                return (size & ~MODE_MASK) | (mode & MODE_MASK);
17489            }
17490        }
17491
17492        /**
17493         * Extracts the mode from the supplied measure specification.
17494         *
17495         * @param measureSpec the measure specification to extract the mode from
17496         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
17497         *         {@link android.view.View.MeasureSpec#AT_MOST} or
17498         *         {@link android.view.View.MeasureSpec#EXACTLY}
17499         */
17500        public static int getMode(int measureSpec) {
17501            return (measureSpec & MODE_MASK);
17502        }
17503
17504        /**
17505         * Extracts the size from the supplied measure specification.
17506         *
17507         * @param measureSpec the measure specification to extract the size from
17508         * @return the size in pixels defined in the supplied measure specification
17509         */
17510        public static int getSize(int measureSpec) {
17511            return (measureSpec & ~MODE_MASK);
17512        }
17513
17514        static int adjust(int measureSpec, int delta) {
17515            return makeMeasureSpec(getSize(measureSpec + delta), getMode(measureSpec));
17516        }
17517
17518        /**
17519         * Returns a String representation of the specified measure
17520         * specification.
17521         *
17522         * @param measureSpec the measure specification to convert to a String
17523         * @return a String with the following format: "MeasureSpec: MODE SIZE"
17524         */
17525        public static String toString(int measureSpec) {
17526            int mode = getMode(measureSpec);
17527            int size = getSize(measureSpec);
17528
17529            StringBuilder sb = new StringBuilder("MeasureSpec: ");
17530
17531            if (mode == UNSPECIFIED)
17532                sb.append("UNSPECIFIED ");
17533            else if (mode == EXACTLY)
17534                sb.append("EXACTLY ");
17535            else if (mode == AT_MOST)
17536                sb.append("AT_MOST ");
17537            else
17538                sb.append(mode).append(" ");
17539
17540            sb.append(size);
17541            return sb.toString();
17542        }
17543    }
17544
17545    class CheckForLongPress implements Runnable {
17546
17547        private int mOriginalWindowAttachCount;
17548
17549        public void run() {
17550            if (isPressed() && (mParent != null)
17551                    && mOriginalWindowAttachCount == mWindowAttachCount) {
17552                if (performLongClick()) {
17553                    mHasPerformedLongPress = true;
17554                }
17555            }
17556        }
17557
17558        public void rememberWindowAttachCount() {
17559            mOriginalWindowAttachCount = mWindowAttachCount;
17560        }
17561    }
17562
17563    private final class CheckForTap implements Runnable {
17564        public void run() {
17565            mPrivateFlags &= ~PFLAG_PREPRESSED;
17566            setPressed(true);
17567            checkForLongClick(ViewConfiguration.getTapTimeout());
17568        }
17569    }
17570
17571    private final class PerformClick implements Runnable {
17572        public void run() {
17573            performClick();
17574        }
17575    }
17576
17577    /** @hide */
17578    public void hackTurnOffWindowResizeAnim(boolean off) {
17579        mAttachInfo.mTurnOffWindowResizeAnim = off;
17580    }
17581
17582    /**
17583     * This method returns a ViewPropertyAnimator object, which can be used to animate
17584     * specific properties on this View.
17585     *
17586     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
17587     */
17588    public ViewPropertyAnimator animate() {
17589        if (mAnimator == null) {
17590            mAnimator = new ViewPropertyAnimator(this);
17591        }
17592        return mAnimator;
17593    }
17594
17595    /**
17596     * Interface definition for a callback to be invoked when a hardware key event is
17597     * dispatched to this view. The callback will be invoked before the key event is
17598     * given to the view. This is only useful for hardware keyboards; a software input
17599     * method has no obligation to trigger this listener.
17600     */
17601    public interface OnKeyListener {
17602        /**
17603         * Called when a hardware key is dispatched to a view. This allows listeners to
17604         * get a chance to respond before the target view.
17605         * <p>Key presses in software keyboards will generally NOT trigger this method,
17606         * although some may elect to do so in some situations. Do not assume a
17607         * software input method has to be key-based; even if it is, it may use key presses
17608         * in a different way than you expect, so there is no way to reliably catch soft
17609         * input key presses.
17610         *
17611         * @param v The view the key has been dispatched to.
17612         * @param keyCode The code for the physical key that was pressed
17613         * @param event The KeyEvent object containing full information about
17614         *        the event.
17615         * @return True if the listener has consumed the event, false otherwise.
17616         */
17617        boolean onKey(View v, int keyCode, KeyEvent event);
17618    }
17619
17620    /**
17621     * Interface definition for a callback to be invoked when a touch event is
17622     * dispatched to this view. The callback will be invoked before the touch
17623     * event is given to the view.
17624     */
17625    public interface OnTouchListener {
17626        /**
17627         * Called when a touch event is dispatched to a view. This allows listeners to
17628         * get a chance to respond before the target view.
17629         *
17630         * @param v The view the touch event has been dispatched to.
17631         * @param event The MotionEvent object containing full information about
17632         *        the event.
17633         * @return True if the listener has consumed the event, false otherwise.
17634         */
17635        boolean onTouch(View v, MotionEvent event);
17636    }
17637
17638    /**
17639     * Interface definition for a callback to be invoked when a hover event is
17640     * dispatched to this view. The callback will be invoked before the hover
17641     * event is given to the view.
17642     */
17643    public interface OnHoverListener {
17644        /**
17645         * Called when a hover event is dispatched to a view. This allows listeners to
17646         * get a chance to respond before the target view.
17647         *
17648         * @param v The view the hover event has been dispatched to.
17649         * @param event The MotionEvent object containing full information about
17650         *        the event.
17651         * @return True if the listener has consumed the event, false otherwise.
17652         */
17653        boolean onHover(View v, MotionEvent event);
17654    }
17655
17656    /**
17657     * Interface definition for a callback to be invoked when a generic motion event is
17658     * dispatched to this view. The callback will be invoked before the generic motion
17659     * event is given to the view.
17660     */
17661    public interface OnGenericMotionListener {
17662        /**
17663         * Called when a generic motion event is dispatched to a view. This allows listeners to
17664         * get a chance to respond before the target view.
17665         *
17666         * @param v The view the generic motion event has been dispatched to.
17667         * @param event The MotionEvent object containing full information about
17668         *        the event.
17669         * @return True if the listener has consumed the event, false otherwise.
17670         */
17671        boolean onGenericMotion(View v, MotionEvent event);
17672    }
17673
17674    /**
17675     * Interface definition for a callback to be invoked when a view has been clicked and held.
17676     */
17677    public interface OnLongClickListener {
17678        /**
17679         * Called when a view has been clicked and held.
17680         *
17681         * @param v The view that was clicked and held.
17682         *
17683         * @return true if the callback consumed the long click, false otherwise.
17684         */
17685        boolean onLongClick(View v);
17686    }
17687
17688    /**
17689     * Interface definition for a callback to be invoked when a drag is being dispatched
17690     * to this view.  The callback will be invoked before the hosting view's own
17691     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
17692     * onDrag(event) behavior, it should return 'false' from this callback.
17693     *
17694     * <div class="special reference">
17695     * <h3>Developer Guides</h3>
17696     * <p>For a guide to implementing drag and drop features, read the
17697     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
17698     * </div>
17699     */
17700    public interface OnDragListener {
17701        /**
17702         * Called when a drag event is dispatched to a view. This allows listeners
17703         * to get a chance to override base View behavior.
17704         *
17705         * @param v The View that received the drag event.
17706         * @param event The {@link android.view.DragEvent} object for the drag event.
17707         * @return {@code true} if the drag event was handled successfully, or {@code false}
17708         * if the drag event was not handled. Note that {@code false} will trigger the View
17709         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
17710         */
17711        boolean onDrag(View v, DragEvent event);
17712    }
17713
17714    /**
17715     * Interface definition for a callback to be invoked when the focus state of
17716     * a view changed.
17717     */
17718    public interface OnFocusChangeListener {
17719        /**
17720         * Called when the focus state of a view has changed.
17721         *
17722         * @param v The view whose state has changed.
17723         * @param hasFocus The new focus state of v.
17724         */
17725        void onFocusChange(View v, boolean hasFocus);
17726    }
17727
17728    /**
17729     * Interface definition for a callback to be invoked when a view is clicked.
17730     */
17731    public interface OnClickListener {
17732        /**
17733         * Called when a view has been clicked.
17734         *
17735         * @param v The view that was clicked.
17736         */
17737        void onClick(View v);
17738    }
17739
17740    /**
17741     * Interface definition for a callback to be invoked when the context menu
17742     * for this view is being built.
17743     */
17744    public interface OnCreateContextMenuListener {
17745        /**
17746         * Called when the context menu for this view is being built. It is not
17747         * safe to hold onto the menu after this method returns.
17748         *
17749         * @param menu The context menu that is being built
17750         * @param v The view for which the context menu is being built
17751         * @param menuInfo Extra information about the item for which the
17752         *            context menu should be shown. This information will vary
17753         *            depending on the class of v.
17754         */
17755        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
17756    }
17757
17758    /**
17759     * Interface definition for a callback to be invoked when the status bar changes
17760     * visibility.  This reports <strong>global</strong> changes to the system UI
17761     * state, not what the application is requesting.
17762     *
17763     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
17764     */
17765    public interface OnSystemUiVisibilityChangeListener {
17766        /**
17767         * Called when the status bar changes visibility because of a call to
17768         * {@link View#setSystemUiVisibility(int)}.
17769         *
17770         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17771         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
17772         * This tells you the <strong>global</strong> state of these UI visibility
17773         * flags, not what your app is currently applying.
17774         */
17775        public void onSystemUiVisibilityChange(int visibility);
17776    }
17777
17778    /**
17779     * Interface definition for a callback to be invoked when this view is attached
17780     * or detached from its window.
17781     */
17782    public interface OnAttachStateChangeListener {
17783        /**
17784         * Called when the view is attached to a window.
17785         * @param v The view that was attached
17786         */
17787        public void onViewAttachedToWindow(View v);
17788        /**
17789         * Called when the view is detached from a window.
17790         * @param v The view that was detached
17791         */
17792        public void onViewDetachedFromWindow(View v);
17793    }
17794
17795    private final class UnsetPressedState implements Runnable {
17796        public void run() {
17797            setPressed(false);
17798        }
17799    }
17800
17801    /**
17802     * Base class for derived classes that want to save and restore their own
17803     * state in {@link android.view.View#onSaveInstanceState()}.
17804     */
17805    public static class BaseSavedState extends AbsSavedState {
17806        /**
17807         * Constructor used when reading from a parcel. Reads the state of the superclass.
17808         *
17809         * @param source
17810         */
17811        public BaseSavedState(Parcel source) {
17812            super(source);
17813        }
17814
17815        /**
17816         * Constructor called by derived classes when creating their SavedState objects
17817         *
17818         * @param superState The state of the superclass of this view
17819         */
17820        public BaseSavedState(Parcelable superState) {
17821            super(superState);
17822        }
17823
17824        public static final Parcelable.Creator<BaseSavedState> CREATOR =
17825                new Parcelable.Creator<BaseSavedState>() {
17826            public BaseSavedState createFromParcel(Parcel in) {
17827                return new BaseSavedState(in);
17828            }
17829
17830            public BaseSavedState[] newArray(int size) {
17831                return new BaseSavedState[size];
17832            }
17833        };
17834    }
17835
17836    /**
17837     * A set of information given to a view when it is attached to its parent
17838     * window.
17839     */
17840    static class AttachInfo {
17841        interface Callbacks {
17842            void playSoundEffect(int effectId);
17843            boolean performHapticFeedback(int effectId, boolean always);
17844        }
17845
17846        /**
17847         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
17848         * to a Handler. This class contains the target (View) to invalidate and
17849         * the coordinates of the dirty rectangle.
17850         *
17851         * For performance purposes, this class also implements a pool of up to
17852         * POOL_LIMIT objects that get reused. This reduces memory allocations
17853         * whenever possible.
17854         */
17855        static class InvalidateInfo {
17856            private static final int POOL_LIMIT = 10;
17857
17858            private static final SynchronizedPool<InvalidateInfo> sPool =
17859                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
17860
17861            View target;
17862
17863            int left;
17864            int top;
17865            int right;
17866            int bottom;
17867
17868            public static InvalidateInfo obtain() {
17869                InvalidateInfo instance = sPool.acquire();
17870                return (instance != null) ? instance : new InvalidateInfo();
17871            }
17872
17873            public void recycle() {
17874                target = null;
17875                sPool.release(this);
17876            }
17877        }
17878
17879        final IWindowSession mSession;
17880
17881        final IWindow mWindow;
17882
17883        final IBinder mWindowToken;
17884
17885        final Display mDisplay;
17886
17887        final Callbacks mRootCallbacks;
17888
17889        HardwareCanvas mHardwareCanvas;
17890
17891        /**
17892         * The top view of the hierarchy.
17893         */
17894        View mRootView;
17895
17896        IBinder mPanelParentWindowToken;
17897        Surface mSurface;
17898
17899        boolean mHardwareAccelerated;
17900        boolean mHardwareAccelerationRequested;
17901        HardwareRenderer mHardwareRenderer;
17902
17903        boolean mScreenOn;
17904
17905        /**
17906         * Scale factor used by the compatibility mode
17907         */
17908        float mApplicationScale;
17909
17910        /**
17911         * Indicates whether the application is in compatibility mode
17912         */
17913        boolean mScalingRequired;
17914
17915        /**
17916         * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
17917         */
17918        boolean mTurnOffWindowResizeAnim;
17919
17920        /**
17921         * Left position of this view's window
17922         */
17923        int mWindowLeft;
17924
17925        /**
17926         * Top position of this view's window
17927         */
17928        int mWindowTop;
17929
17930        /**
17931         * Indicates whether views need to use 32-bit drawing caches
17932         */
17933        boolean mUse32BitDrawingCache;
17934
17935        /**
17936         * For windows that are full-screen but using insets to layout inside
17937         * of the screen decorations, these are the current insets for the
17938         * content of the window.
17939         */
17940        final Rect mContentInsets = new Rect();
17941
17942        /**
17943         * For windows that are full-screen but using insets to layout inside
17944         * of the screen decorations, these are the current insets for the
17945         * actual visible parts of the window.
17946         */
17947        final Rect mVisibleInsets = new Rect();
17948
17949        /**
17950         * The internal insets given by this window.  This value is
17951         * supplied by the client (through
17952         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
17953         * be given to the window manager when changed to be used in laying
17954         * out windows behind it.
17955         */
17956        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
17957                = new ViewTreeObserver.InternalInsetsInfo();
17958
17959        /**
17960         * All views in the window's hierarchy that serve as scroll containers,
17961         * used to determine if the window can be resized or must be panned
17962         * to adjust for a soft input area.
17963         */
17964        final ArrayList<View> mScrollContainers = new ArrayList<View>();
17965
17966        final KeyEvent.DispatcherState mKeyDispatchState
17967                = new KeyEvent.DispatcherState();
17968
17969        /**
17970         * Indicates whether the view's window currently has the focus.
17971         */
17972        boolean mHasWindowFocus;
17973
17974        /**
17975         * The current visibility of the window.
17976         */
17977        int mWindowVisibility;
17978
17979        /**
17980         * Indicates the time at which drawing started to occur.
17981         */
17982        long mDrawingTime;
17983
17984        /**
17985         * Indicates whether or not ignoring the DIRTY_MASK flags.
17986         */
17987        boolean mIgnoreDirtyState;
17988
17989        /**
17990         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
17991         * to avoid clearing that flag prematurely.
17992         */
17993        boolean mSetIgnoreDirtyState = false;
17994
17995        /**
17996         * Indicates whether the view's window is currently in touch mode.
17997         */
17998        boolean mInTouchMode;
17999
18000        /**
18001         * Indicates that ViewAncestor should trigger a global layout change
18002         * the next time it performs a traversal
18003         */
18004        boolean mRecomputeGlobalAttributes;
18005
18006        /**
18007         * Always report new attributes at next traversal.
18008         */
18009        boolean mForceReportNewAttributes;
18010
18011        /**
18012         * Set during a traveral if any views want to keep the screen on.
18013         */
18014        boolean mKeepScreenOn;
18015
18016        /**
18017         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
18018         */
18019        int mSystemUiVisibility;
18020
18021        /**
18022         * Hack to force certain system UI visibility flags to be cleared.
18023         */
18024        int mDisabledSystemUiVisibility;
18025
18026        /**
18027         * Last global system UI visibility reported by the window manager.
18028         */
18029        int mGlobalSystemUiVisibility;
18030
18031        /**
18032         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
18033         * attached.
18034         */
18035        boolean mHasSystemUiListeners;
18036
18037        /**
18038         * Set if the visibility of any views has changed.
18039         */
18040        boolean mViewVisibilityChanged;
18041
18042        /**
18043         * Set to true if a view has been scrolled.
18044         */
18045        boolean mViewScrollChanged;
18046
18047        /**
18048         * Global to the view hierarchy used as a temporary for dealing with
18049         * x/y points in the transparent region computations.
18050         */
18051        final int[] mTransparentLocation = new int[2];
18052
18053        /**
18054         * Global to the view hierarchy used as a temporary for dealing with
18055         * x/y points in the ViewGroup.invalidateChild implementation.
18056         */
18057        final int[] mInvalidateChildLocation = new int[2];
18058
18059
18060        /**
18061         * Global to the view hierarchy used as a temporary for dealing with
18062         * x/y location when view is transformed.
18063         */
18064        final float[] mTmpTransformLocation = new float[2];
18065
18066        /**
18067         * The view tree observer used to dispatch global events like
18068         * layout, pre-draw, touch mode change, etc.
18069         */
18070        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
18071
18072        /**
18073         * A Canvas used by the view hierarchy to perform bitmap caching.
18074         */
18075        Canvas mCanvas;
18076
18077        /**
18078         * The view root impl.
18079         */
18080        final ViewRootImpl mViewRootImpl;
18081
18082        /**
18083         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
18084         * handler can be used to pump events in the UI events queue.
18085         */
18086        final Handler mHandler;
18087
18088        /**
18089         * Temporary for use in computing invalidate rectangles while
18090         * calling up the hierarchy.
18091         */
18092        final Rect mTmpInvalRect = new Rect();
18093
18094        /**
18095         * Temporary for use in computing hit areas with transformed views
18096         */
18097        final RectF mTmpTransformRect = new RectF();
18098
18099        /**
18100         * Temporary for use in transforming invalidation rect
18101         */
18102        final Matrix mTmpMatrix = new Matrix();
18103
18104        /**
18105         * Temporary for use in transforming invalidation rect
18106         */
18107        final Transformation mTmpTransformation = new Transformation();
18108
18109        /**
18110         * Temporary list for use in collecting focusable descendents of a view.
18111         */
18112        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
18113
18114        /**
18115         * The id of the window for accessibility purposes.
18116         */
18117        int mAccessibilityWindowId = View.NO_ID;
18118
18119        /**
18120         * Flags related to accessibility processing.
18121         *
18122         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
18123         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
18124         */
18125        int mAccessibilityFetchFlags;
18126
18127        /**
18128         * The drawable for highlighting accessibility focus.
18129         */
18130        Drawable mAccessibilityFocusDrawable;
18131
18132        /**
18133         * Show where the margins, bounds and layout bounds are for each view.
18134         */
18135        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
18136
18137        /**
18138         * Point used to compute visible regions.
18139         */
18140        final Point mPoint = new Point();
18141
18142        /**
18143         * Used to track which View originated a requestLayout() call, used when
18144         * requestLayout() is called during layout.
18145         */
18146        View mViewRequestingLayout;
18147
18148        /**
18149         * Creates a new set of attachment information with the specified
18150         * events handler and thread.
18151         *
18152         * @param handler the events handler the view must use
18153         */
18154        AttachInfo(IWindowSession session, IWindow window, Display display,
18155                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
18156            mSession = session;
18157            mWindow = window;
18158            mWindowToken = window.asBinder();
18159            mDisplay = display;
18160            mViewRootImpl = viewRootImpl;
18161            mHandler = handler;
18162            mRootCallbacks = effectPlayer;
18163        }
18164    }
18165
18166    /**
18167     * <p>ScrollabilityCache holds various fields used by a View when scrolling
18168     * is supported. This avoids keeping too many unused fields in most
18169     * instances of View.</p>
18170     */
18171    private static class ScrollabilityCache implements Runnable {
18172
18173        /**
18174         * Scrollbars are not visible
18175         */
18176        public static final int OFF = 0;
18177
18178        /**
18179         * Scrollbars are visible
18180         */
18181        public static final int ON = 1;
18182
18183        /**
18184         * Scrollbars are fading away
18185         */
18186        public static final int FADING = 2;
18187
18188        public boolean fadeScrollBars;
18189
18190        public int fadingEdgeLength;
18191        public int scrollBarDefaultDelayBeforeFade;
18192        public int scrollBarFadeDuration;
18193
18194        public int scrollBarSize;
18195        public ScrollBarDrawable scrollBar;
18196        public float[] interpolatorValues;
18197        public View host;
18198
18199        public final Paint paint;
18200        public final Matrix matrix;
18201        public Shader shader;
18202
18203        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
18204
18205        private static final float[] OPAQUE = { 255 };
18206        private static final float[] TRANSPARENT = { 0.0f };
18207
18208        /**
18209         * When fading should start. This time moves into the future every time
18210         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
18211         */
18212        public long fadeStartTime;
18213
18214
18215        /**
18216         * The current state of the scrollbars: ON, OFF, or FADING
18217         */
18218        public int state = OFF;
18219
18220        private int mLastColor;
18221
18222        public ScrollabilityCache(ViewConfiguration configuration, View host) {
18223            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
18224            scrollBarSize = configuration.getScaledScrollBarSize();
18225            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
18226            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
18227
18228            paint = new Paint();
18229            matrix = new Matrix();
18230            // use use a height of 1, and then wack the matrix each time we
18231            // actually use it.
18232            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
18233            paint.setShader(shader);
18234            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
18235
18236            this.host = host;
18237        }
18238
18239        public void setFadeColor(int color) {
18240            if (color != mLastColor) {
18241                mLastColor = color;
18242
18243                if (color != 0) {
18244                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
18245                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
18246                    paint.setShader(shader);
18247                    // Restore the default transfer mode (src_over)
18248                    paint.setXfermode(null);
18249                } else {
18250                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
18251                    paint.setShader(shader);
18252                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
18253                }
18254            }
18255        }
18256
18257        public void run() {
18258            long now = AnimationUtils.currentAnimationTimeMillis();
18259            if (now >= fadeStartTime) {
18260
18261                // the animation fades the scrollbars out by changing
18262                // the opacity (alpha) from fully opaque to fully
18263                // transparent
18264                int nextFrame = (int) now;
18265                int framesCount = 0;
18266
18267                Interpolator interpolator = scrollBarInterpolator;
18268
18269                // Start opaque
18270                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
18271
18272                // End transparent
18273                nextFrame += scrollBarFadeDuration;
18274                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
18275
18276                state = FADING;
18277
18278                // Kick off the fade animation
18279                host.invalidate(true);
18280            }
18281        }
18282    }
18283
18284    /**
18285     * Resuable callback for sending
18286     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
18287     */
18288    private class SendViewScrolledAccessibilityEvent implements Runnable {
18289        public volatile boolean mIsPending;
18290
18291        public void run() {
18292            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
18293            mIsPending = false;
18294        }
18295    }
18296
18297    /**
18298     * <p>
18299     * This class represents a delegate that can be registered in a {@link View}
18300     * to enhance accessibility support via composition rather via inheritance.
18301     * It is specifically targeted to widget developers that extend basic View
18302     * classes i.e. classes in package android.view, that would like their
18303     * applications to be backwards compatible.
18304     * </p>
18305     * <div class="special reference">
18306     * <h3>Developer Guides</h3>
18307     * <p>For more information about making applications accessible, read the
18308     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
18309     * developer guide.</p>
18310     * </div>
18311     * <p>
18312     * A scenario in which a developer would like to use an accessibility delegate
18313     * is overriding a method introduced in a later API version then the minimal API
18314     * version supported by the application. For example, the method
18315     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
18316     * in API version 4 when the accessibility APIs were first introduced. If a
18317     * developer would like his application to run on API version 4 devices (assuming
18318     * all other APIs used by the application are version 4 or lower) and take advantage
18319     * of this method, instead of overriding the method which would break the application's
18320     * backwards compatibility, he can override the corresponding method in this
18321     * delegate and register the delegate in the target View if the API version of
18322     * the system is high enough i.e. the API version is same or higher to the API
18323     * version that introduced
18324     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
18325     * </p>
18326     * <p>
18327     * Here is an example implementation:
18328     * </p>
18329     * <code><pre><p>
18330     * if (Build.VERSION.SDK_INT >= 14) {
18331     *     // If the API version is equal of higher than the version in
18332     *     // which onInitializeAccessibilityNodeInfo was introduced we
18333     *     // register a delegate with a customized implementation.
18334     *     View view = findViewById(R.id.view_id);
18335     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
18336     *         public void onInitializeAccessibilityNodeInfo(View host,
18337     *                 AccessibilityNodeInfo info) {
18338     *             // Let the default implementation populate the info.
18339     *             super.onInitializeAccessibilityNodeInfo(host, info);
18340     *             // Set some other information.
18341     *             info.setEnabled(host.isEnabled());
18342     *         }
18343     *     });
18344     * }
18345     * </code></pre></p>
18346     * <p>
18347     * This delegate contains methods that correspond to the accessibility methods
18348     * in View. If a delegate has been specified the implementation in View hands
18349     * off handling to the corresponding method in this delegate. The default
18350     * implementation the delegate methods behaves exactly as the corresponding
18351     * method in View for the case of no accessibility delegate been set. Hence,
18352     * to customize the behavior of a View method, clients can override only the
18353     * corresponding delegate method without altering the behavior of the rest
18354     * accessibility related methods of the host view.
18355     * </p>
18356     */
18357    public static class AccessibilityDelegate {
18358
18359        /**
18360         * Sends an accessibility event of the given type. If accessibility is not
18361         * enabled this method has no effect.
18362         * <p>
18363         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
18364         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
18365         * been set.
18366         * </p>
18367         *
18368         * @param host The View hosting the delegate.
18369         * @param eventType The type of the event to send.
18370         *
18371         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
18372         */
18373        public void sendAccessibilityEvent(View host, int eventType) {
18374            host.sendAccessibilityEventInternal(eventType);
18375        }
18376
18377        /**
18378         * Performs the specified accessibility action on the view. For
18379         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
18380         * <p>
18381         * The default implementation behaves as
18382         * {@link View#performAccessibilityAction(int, Bundle)
18383         *  View#performAccessibilityAction(int, Bundle)} for the case of
18384         *  no accessibility delegate been set.
18385         * </p>
18386         *
18387         * @param action The action to perform.
18388         * @return Whether the action was performed.
18389         *
18390         * @see View#performAccessibilityAction(int, Bundle)
18391         *      View#performAccessibilityAction(int, Bundle)
18392         */
18393        public boolean performAccessibilityAction(View host, int action, Bundle args) {
18394            return host.performAccessibilityActionInternal(action, args);
18395        }
18396
18397        /**
18398         * Sends an accessibility event. This method behaves exactly as
18399         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
18400         * empty {@link AccessibilityEvent} and does not perform a check whether
18401         * accessibility is enabled.
18402         * <p>
18403         * The default implementation behaves as
18404         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
18405         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
18406         * the case of no accessibility delegate been set.
18407         * </p>
18408         *
18409         * @param host The View hosting the delegate.
18410         * @param event The event to send.
18411         *
18412         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
18413         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
18414         */
18415        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
18416            host.sendAccessibilityEventUncheckedInternal(event);
18417        }
18418
18419        /**
18420         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
18421         * to its children for adding their text content to the event.
18422         * <p>
18423         * The default implementation behaves as
18424         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
18425         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
18426         * the case of no accessibility delegate been set.
18427         * </p>
18428         *
18429         * @param host The View hosting the delegate.
18430         * @param event The event.
18431         * @return True if the event population was completed.
18432         *
18433         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
18434         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
18435         */
18436        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
18437            return host.dispatchPopulateAccessibilityEventInternal(event);
18438        }
18439
18440        /**
18441         * Gives a chance to the host View to populate the accessibility event with its
18442         * text content.
18443         * <p>
18444         * The default implementation behaves as
18445         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
18446         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
18447         * the case of no accessibility delegate been set.
18448         * </p>
18449         *
18450         * @param host The View hosting the delegate.
18451         * @param event The accessibility event which to populate.
18452         *
18453         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
18454         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
18455         */
18456        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
18457            host.onPopulateAccessibilityEventInternal(event);
18458        }
18459
18460        /**
18461         * Initializes an {@link AccessibilityEvent} with information about the
18462         * the host View which is the event source.
18463         * <p>
18464         * The default implementation behaves as
18465         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
18466         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
18467         * the case of no accessibility delegate been set.
18468         * </p>
18469         *
18470         * @param host The View hosting the delegate.
18471         * @param event The event to initialize.
18472         *
18473         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
18474         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
18475         */
18476        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
18477            host.onInitializeAccessibilityEventInternal(event);
18478        }
18479
18480        /**
18481         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
18482         * <p>
18483         * The default implementation behaves as
18484         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
18485         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
18486         * the case of no accessibility delegate been set.
18487         * </p>
18488         *
18489         * @param host The View hosting the delegate.
18490         * @param info The instance to initialize.
18491         *
18492         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
18493         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
18494         */
18495        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
18496            host.onInitializeAccessibilityNodeInfoInternal(info);
18497        }
18498
18499        /**
18500         * Called when a child of the host View has requested sending an
18501         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
18502         * to augment the event.
18503         * <p>
18504         * The default implementation behaves as
18505         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
18506         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
18507         * the case of no accessibility delegate been set.
18508         * </p>
18509         *
18510         * @param host The View hosting the delegate.
18511         * @param child The child which requests sending the event.
18512         * @param event The event to be sent.
18513         * @return True if the event should be sent
18514         *
18515         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
18516         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
18517         */
18518        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
18519                AccessibilityEvent event) {
18520            return host.onRequestSendAccessibilityEventInternal(child, event);
18521        }
18522
18523        /**
18524         * Gets the provider for managing a virtual view hierarchy rooted at this View
18525         * and reported to {@link android.accessibilityservice.AccessibilityService}s
18526         * that explore the window content.
18527         * <p>
18528         * The default implementation behaves as
18529         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
18530         * the case of no accessibility delegate been set.
18531         * </p>
18532         *
18533         * @return The provider.
18534         *
18535         * @see AccessibilityNodeProvider
18536         */
18537        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
18538            return null;
18539        }
18540    }
18541
18542    private class MatchIdPredicate implements Predicate<View> {
18543        public int mId;
18544
18545        @Override
18546        public boolean apply(View view) {
18547            return (view.mID == mId);
18548        }
18549    }
18550
18551    private class MatchLabelForPredicate implements Predicate<View> {
18552        private int mLabeledId;
18553
18554        @Override
18555        public boolean apply(View view) {
18556            return (view.mLabelForId == mLabeledId);
18557        }
18558    }
18559
18560    /**
18561     * Dump all private flags in readable format, useful for documentation and
18562     * sanity checking.
18563     */
18564    private static void dumpFlags() {
18565        final HashMap<String, String> found = Maps.newHashMap();
18566        try {
18567            for (Field field : View.class.getDeclaredFields()) {
18568                final int modifiers = field.getModifiers();
18569                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
18570                    if (field.getType().equals(int.class)) {
18571                        final int value = field.getInt(null);
18572                        dumpFlag(found, field.getName(), value);
18573                    } else if (field.getType().equals(int[].class)) {
18574                        final int[] values = (int[]) field.get(null);
18575                        for (int i = 0; i < values.length; i++) {
18576                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
18577                        }
18578                    }
18579                }
18580            }
18581        } catch (IllegalAccessException e) {
18582            throw new RuntimeException(e);
18583        }
18584
18585        final ArrayList<String> keys = Lists.newArrayList();
18586        keys.addAll(found.keySet());
18587        Collections.sort(keys);
18588        for (String key : keys) {
18589            Log.d(VIEW_LOG_TAG, found.get(key));
18590        }
18591    }
18592
18593    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
18594        // Sort flags by prefix, then by bits, always keeping unique keys
18595        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
18596        final int prefix = name.indexOf('_');
18597        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
18598        final String output = bits + " " + name;
18599        found.put(key, output);
18600    }
18601}
18602