View.java revision 7eac0f557cd87486d0f10b7c72e25aeb195a4351
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.content.ClipData;
20import android.content.Context;
21import android.content.res.Configuration;
22import android.content.res.Resources;
23import android.content.res.TypedArray;
24import android.graphics.Bitmap;
25import android.graphics.Camera;
26import android.graphics.Canvas;
27import android.graphics.Insets;
28import android.graphics.Interpolator;
29import android.graphics.LinearGradient;
30import android.graphics.Matrix;
31import android.graphics.Paint;
32import android.graphics.PixelFormat;
33import android.graphics.Point;
34import android.graphics.PorterDuff;
35import android.graphics.PorterDuffXfermode;
36import android.graphics.Rect;
37import android.graphics.RectF;
38import android.graphics.Region;
39import android.graphics.Shader;
40import android.graphics.drawable.ColorDrawable;
41import android.graphics.drawable.Drawable;
42import android.hardware.display.DisplayManagerGlobal;
43import android.os.Bundle;
44import android.os.Handler;
45import android.os.IBinder;
46import android.os.Parcel;
47import android.os.Parcelable;
48import android.os.RemoteException;
49import android.os.SystemClock;
50import android.os.SystemProperties;
51import android.util.AttributeSet;
52import android.util.FloatProperty;
53import android.util.LocaleUtil;
54import android.util.Log;
55import android.util.Pool;
56import android.util.Poolable;
57import android.util.PoolableManager;
58import android.util.Pools;
59import android.util.Property;
60import android.util.SparseArray;
61import android.util.TypedValue;
62import android.view.ContextMenu.ContextMenuInfo;
63import android.view.AccessibilityIterators.TextSegmentIterator;
64import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
65import android.view.AccessibilityIterators.WordTextSegmentIterator;
66import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
67import android.view.accessibility.AccessibilityEvent;
68import android.view.accessibility.AccessibilityEventSource;
69import android.view.accessibility.AccessibilityManager;
70import android.view.accessibility.AccessibilityNodeInfo;
71import android.view.accessibility.AccessibilityNodeProvider;
72import android.view.animation.Animation;
73import android.view.animation.AnimationUtils;
74import android.view.animation.Transformation;
75import android.view.inputmethod.EditorInfo;
76import android.view.inputmethod.InputConnection;
77import android.view.inputmethod.InputMethodManager;
78import android.widget.ScrollBarDrawable;
79
80import static android.os.Build.VERSION_CODES.*;
81import static java.lang.Math.max;
82
83import com.android.internal.R;
84import com.android.internal.util.Predicate;
85import com.android.internal.view.menu.MenuBuilder;
86
87import java.lang.ref.WeakReference;
88import java.lang.reflect.InvocationTargetException;
89import java.lang.reflect.Method;
90import java.util.ArrayList;
91import java.util.Arrays;
92import java.util.Locale;
93import java.util.concurrent.CopyOnWriteArrayList;
94import java.util.concurrent.atomic.AtomicInteger;
95
96/**
97 * <p>
98 * This class represents the basic building block for user interface components. A View
99 * occupies a rectangular area on the screen and is responsible for drawing and
100 * event handling. View is the base class for <em>widgets</em>, which are
101 * used to create interactive UI components (buttons, text fields, etc.). The
102 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
103 * are invisible containers that hold other Views (or other ViewGroups) and define
104 * their layout properties.
105 * </p>
106 *
107 * <div class="special reference">
108 * <h3>Developer Guides</h3>
109 * <p>For information about using this class to develop your application's user interface,
110 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
111 * </div>
112 *
113 * <a name="Using"></a>
114 * <h3>Using Views</h3>
115 * <p>
116 * All of the views in a window are arranged in a single tree. You can add views
117 * either from code or by specifying a tree of views in one or more XML layout
118 * files. There are many specialized subclasses of views that act as controls or
119 * are capable of displaying text, images, or other content.
120 * </p>
121 * <p>
122 * Once you have created a tree of views, there are typically a few types of
123 * common operations you may wish to perform:
124 * <ul>
125 * <li><strong>Set properties:</strong> for example setting the text of a
126 * {@link android.widget.TextView}. The available properties and the methods
127 * that set them will vary among the different subclasses of views. Note that
128 * properties that are known at build time can be set in the XML layout
129 * files.</li>
130 * <li><strong>Set focus:</strong> The framework will handled moving focus in
131 * response to user input. To force focus to a specific view, call
132 * {@link #requestFocus}.</li>
133 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
134 * that will be notified when something interesting happens to the view. For
135 * example, all views will let you set a listener to be notified when the view
136 * gains or loses focus. You can register such a listener using
137 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
138 * Other view subclasses offer more specialized listeners. For example, a Button
139 * exposes a listener to notify clients when the button is clicked.</li>
140 * <li><strong>Set visibility:</strong> You can hide or show views using
141 * {@link #setVisibility(int)}.</li>
142 * </ul>
143 * </p>
144 * <p><em>
145 * Note: The Android framework is responsible for measuring, laying out and
146 * drawing views. You should not call methods that perform these actions on
147 * views yourself unless you are actually implementing a
148 * {@link android.view.ViewGroup}.
149 * </em></p>
150 *
151 * <a name="Lifecycle"></a>
152 * <h3>Implementing a Custom View</h3>
153 *
154 * <p>
155 * To implement a custom view, you will usually begin by providing overrides for
156 * some of the standard methods that the framework calls on all views. You do
157 * not need to override all of these methods. In fact, you can start by just
158 * overriding {@link #onDraw(android.graphics.Canvas)}.
159 * <table border="2" width="85%" align="center" cellpadding="5">
160 *     <thead>
161 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
162 *     </thead>
163 *
164 *     <tbody>
165 *     <tr>
166 *         <td rowspan="2">Creation</td>
167 *         <td>Constructors</td>
168 *         <td>There is a form of the constructor that are called when the view
169 *         is created from code and a form that is called when the view is
170 *         inflated from a layout file. The second form should parse and apply
171 *         any attributes defined in the layout file.
172 *         </td>
173 *     </tr>
174 *     <tr>
175 *         <td><code>{@link #onFinishInflate()}</code></td>
176 *         <td>Called after a view and all of its children has been inflated
177 *         from XML.</td>
178 *     </tr>
179 *
180 *     <tr>
181 *         <td rowspan="3">Layout</td>
182 *         <td><code>{@link #onMeasure(int, int)}</code></td>
183 *         <td>Called to determine the size requirements for this view and all
184 *         of its children.
185 *         </td>
186 *     </tr>
187 *     <tr>
188 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
189 *         <td>Called when this view should assign a size and position to all
190 *         of its children.
191 *         </td>
192 *     </tr>
193 *     <tr>
194 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
195 *         <td>Called when the size of this view has changed.
196 *         </td>
197 *     </tr>
198 *
199 *     <tr>
200 *         <td>Drawing</td>
201 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
202 *         <td>Called when the view should render its content.
203 *         </td>
204 *     </tr>
205 *
206 *     <tr>
207 *         <td rowspan="4">Event processing</td>
208 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
209 *         <td>Called when a new hardware key event occurs.
210 *         </td>
211 *     </tr>
212 *     <tr>
213 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
214 *         <td>Called when a hardware key up event occurs.
215 *         </td>
216 *     </tr>
217 *     <tr>
218 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
219 *         <td>Called when a trackball motion event occurs.
220 *         </td>
221 *     </tr>
222 *     <tr>
223 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
224 *         <td>Called when a touch screen motion event occurs.
225 *         </td>
226 *     </tr>
227 *
228 *     <tr>
229 *         <td rowspan="2">Focus</td>
230 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
231 *         <td>Called when the view gains or loses focus.
232 *         </td>
233 *     </tr>
234 *
235 *     <tr>
236 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
237 *         <td>Called when the window containing the view gains or loses focus.
238 *         </td>
239 *     </tr>
240 *
241 *     <tr>
242 *         <td rowspan="3">Attaching</td>
243 *         <td><code>{@link #onAttachedToWindow()}</code></td>
244 *         <td>Called when the view is attached to a window.
245 *         </td>
246 *     </tr>
247 *
248 *     <tr>
249 *         <td><code>{@link #onDetachedFromWindow}</code></td>
250 *         <td>Called when the view is detached from its window.
251 *         </td>
252 *     </tr>
253 *
254 *     <tr>
255 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
256 *         <td>Called when the visibility of the window containing the view
257 *         has changed.
258 *         </td>
259 *     </tr>
260 *     </tbody>
261 *
262 * </table>
263 * </p>
264 *
265 * <a name="IDs"></a>
266 * <h3>IDs</h3>
267 * Views may have an integer id associated with them. These ids are typically
268 * assigned in the layout XML files, and are used to find specific views within
269 * the view tree. A common pattern is to:
270 * <ul>
271 * <li>Define a Button in the layout file and assign it a unique ID.
272 * <pre>
273 * &lt;Button
274 *     android:id="@+id/my_button"
275 *     android:layout_width="wrap_content"
276 *     android:layout_height="wrap_content"
277 *     android:text="@string/my_button_text"/&gt;
278 * </pre></li>
279 * <li>From the onCreate method of an Activity, find the Button
280 * <pre class="prettyprint">
281 *      Button myButton = (Button) findViewById(R.id.my_button);
282 * </pre></li>
283 * </ul>
284 * <p>
285 * View IDs need not be unique throughout the tree, but it is good practice to
286 * ensure that they are at least unique within the part of the tree you are
287 * searching.
288 * </p>
289 *
290 * <a name="Position"></a>
291 * <h3>Position</h3>
292 * <p>
293 * The geometry of a view is that of a rectangle. A view has a location,
294 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
295 * two dimensions, expressed as a width and a height. The unit for location
296 * and dimensions is the pixel.
297 * </p>
298 *
299 * <p>
300 * It is possible to retrieve the location of a view by invoking the methods
301 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
302 * coordinate of the rectangle representing the view. The latter returns the
303 * top, or Y, coordinate of the rectangle representing the view. These methods
304 * both return the location of the view relative to its parent. For instance,
305 * when getLeft() returns 20, that means the view is located 20 pixels to the
306 * right of the left edge of its direct parent.
307 * </p>
308 *
309 * <p>
310 * In addition, several convenience methods are offered to avoid unnecessary
311 * computations, namely {@link #getRight()} and {@link #getBottom()}.
312 * These methods return the coordinates of the right and bottom edges of the
313 * rectangle representing the view. For instance, calling {@link #getRight()}
314 * is similar to the following computation: <code>getLeft() + getWidth()</code>
315 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
316 * </p>
317 *
318 * <a name="SizePaddingMargins"></a>
319 * <h3>Size, padding and margins</h3>
320 * <p>
321 * The size of a view is expressed with a width and a height. A view actually
322 * possess two pairs of width and height values.
323 * </p>
324 *
325 * <p>
326 * The first pair is known as <em>measured width</em> and
327 * <em>measured height</em>. These dimensions define how big a view wants to be
328 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
329 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
330 * and {@link #getMeasuredHeight()}.
331 * </p>
332 *
333 * <p>
334 * The second pair is simply known as <em>width</em> and <em>height</em>, or
335 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
336 * dimensions define the actual size of the view on screen, at drawing time and
337 * after layout. These values may, but do not have to, be different from the
338 * measured width and height. The width and height can be obtained by calling
339 * {@link #getWidth()} and {@link #getHeight()}.
340 * </p>
341 *
342 * <p>
343 * To measure its dimensions, a view takes into account its padding. The padding
344 * is expressed in pixels for the left, top, right and bottom parts of the view.
345 * Padding can be used to offset the content of the view by a specific amount of
346 * pixels. For instance, a left padding of 2 will push the view's content by
347 * 2 pixels to the right of the left edge. Padding can be set using the
348 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
349 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
350 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
351 * {@link #getPaddingEnd()}.
352 * </p>
353 *
354 * <p>
355 * Even though a view can define a padding, it does not provide any support for
356 * margins. However, view groups provide such a support. Refer to
357 * {@link android.view.ViewGroup} and
358 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
359 * </p>
360 *
361 * <a name="Layout"></a>
362 * <h3>Layout</h3>
363 * <p>
364 * Layout is a two pass process: a measure pass and a layout pass. The measuring
365 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
366 * of the view tree. Each view pushes dimension specifications down the tree
367 * during the recursion. At the end of the measure pass, every view has stored
368 * its measurements. The second pass happens in
369 * {@link #layout(int,int,int,int)} and is also top-down. During
370 * this pass each parent is responsible for positioning all of its children
371 * using the sizes computed in the measure pass.
372 * </p>
373 *
374 * <p>
375 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
376 * {@link #getMeasuredHeight()} values must be set, along with those for all of
377 * that view's descendants. A view's measured width and measured height values
378 * must respect the constraints imposed by the view's parents. This guarantees
379 * that at the end of the measure pass, all parents accept all of their
380 * children's measurements. A parent view may call measure() more than once on
381 * its children. For example, the parent may measure each child once with
382 * unspecified dimensions to find out how big they want to be, then call
383 * measure() on them again with actual numbers if the sum of all the children's
384 * unconstrained sizes is too big or too small.
385 * </p>
386 *
387 * <p>
388 * The measure pass uses two classes to communicate dimensions. The
389 * {@link MeasureSpec} class is used by views to tell their parents how they
390 * want to be measured and positioned. The base LayoutParams class just
391 * describes how big the view wants to be for both width and height. For each
392 * dimension, it can specify one of:
393 * <ul>
394 * <li> an exact number
395 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
396 * (minus padding)
397 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
398 * enclose its content (plus padding).
399 * </ul>
400 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
401 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
402 * an X and Y value.
403 * </p>
404 *
405 * <p>
406 * MeasureSpecs are used to push requirements down the tree from parent to
407 * child. A MeasureSpec can be in one of three modes:
408 * <ul>
409 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
410 * of a child view. For example, a LinearLayout may call measure() on its child
411 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
412 * tall the child view wants to be given a width of 240 pixels.
413 * <li>EXACTLY: This is used by the parent to impose an exact size on the
414 * child. The child must use this size, and guarantee that all of its
415 * descendants will fit within this size.
416 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
417 * child. The child must gurantee that it and all of its descendants will fit
418 * within this size.
419 * </ul>
420 * </p>
421 *
422 * <p>
423 * To intiate a layout, call {@link #requestLayout}. This method is typically
424 * called by a view on itself when it believes that is can no longer fit within
425 * its current bounds.
426 * </p>
427 *
428 * <a name="Drawing"></a>
429 * <h3>Drawing</h3>
430 * <p>
431 * Drawing is handled by walking the tree and rendering each view that
432 * intersects the invalid region. Because the tree is traversed in-order,
433 * this means that parents will draw before (i.e., behind) their children, with
434 * siblings drawn in the order they appear in the tree.
435 * If you set a background drawable for a View, then the View will draw it for you
436 * before calling back to its <code>onDraw()</code> method.
437 * </p>
438 *
439 * <p>
440 * Note that the framework will not draw views that are not in the invalid region.
441 * </p>
442 *
443 * <p>
444 * To force a view to draw, call {@link #invalidate()}.
445 * </p>
446 *
447 * <a name="EventHandlingThreading"></a>
448 * <h3>Event Handling and Threading</h3>
449 * <p>
450 * The basic cycle of a view is as follows:
451 * <ol>
452 * <li>An event comes in and is dispatched to the appropriate view. The view
453 * handles the event and notifies any listeners.</li>
454 * <li>If in the course of processing the event, the view's bounds may need
455 * to be changed, the view will call {@link #requestLayout()}.</li>
456 * <li>Similarly, if in the course of processing the event the view's appearance
457 * may need to be changed, the view will call {@link #invalidate()}.</li>
458 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
459 * the framework will take care of measuring, laying out, and drawing the tree
460 * as appropriate.</li>
461 * </ol>
462 * </p>
463 *
464 * <p><em>Note: The entire view tree is single threaded. You must always be on
465 * the UI thread when calling any method on any view.</em>
466 * If you are doing work on other threads and want to update the state of a view
467 * from that thread, you should use a {@link Handler}.
468 * </p>
469 *
470 * <a name="FocusHandling"></a>
471 * <h3>Focus Handling</h3>
472 * <p>
473 * The framework will handle routine focus movement in response to user input.
474 * This includes changing the focus as views are removed or hidden, or as new
475 * views become available. Views indicate their willingness to take focus
476 * through the {@link #isFocusable} method. To change whether a view can take
477 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
478 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
479 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
480 * </p>
481 * <p>
482 * Focus movement is based on an algorithm which finds the nearest neighbor in a
483 * given direction. In rare cases, the default algorithm may not match the
484 * intended behavior of the developer. In these situations, you can provide
485 * explicit overrides by using these XML attributes in the layout file:
486 * <pre>
487 * nextFocusDown
488 * nextFocusLeft
489 * nextFocusRight
490 * nextFocusUp
491 * </pre>
492 * </p>
493 *
494 *
495 * <p>
496 * To get a particular view to take focus, call {@link #requestFocus()}.
497 * </p>
498 *
499 * <a name="TouchMode"></a>
500 * <h3>Touch Mode</h3>
501 * <p>
502 * When a user is navigating a user interface via directional keys such as a D-pad, it is
503 * necessary to give focus to actionable items such as buttons so the user can see
504 * what will take input.  If the device has touch capabilities, however, and the user
505 * begins interacting with the interface by touching it, it is no longer necessary to
506 * always highlight, or give focus to, a particular view.  This motivates a mode
507 * for interaction named 'touch mode'.
508 * </p>
509 * <p>
510 * For a touch capable device, once the user touches the screen, the device
511 * will enter touch mode.  From this point onward, only views for which
512 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
513 * Other views that are touchable, like buttons, will not take focus when touched; they will
514 * only fire the on click listeners.
515 * </p>
516 * <p>
517 * Any time a user hits a directional key, such as a D-pad direction, the view device will
518 * exit touch mode, and find a view to take focus, so that the user may resume interacting
519 * with the user interface without touching the screen again.
520 * </p>
521 * <p>
522 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
523 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
524 * </p>
525 *
526 * <a name="Scrolling"></a>
527 * <h3>Scrolling</h3>
528 * <p>
529 * The framework provides basic support for views that wish to internally
530 * scroll their content. This includes keeping track of the X and Y scroll
531 * offset as well as mechanisms for drawing scrollbars. See
532 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
533 * {@link #awakenScrollBars()} for more details.
534 * </p>
535 *
536 * <a name="Tags"></a>
537 * <h3>Tags</h3>
538 * <p>
539 * Unlike IDs, tags are not used to identify views. Tags are essentially an
540 * extra piece of information that can be associated with a view. They are most
541 * often used as a convenience to store data related to views in the views
542 * themselves rather than by putting them in a separate structure.
543 * </p>
544 *
545 * <a name="Properties"></a>
546 * <h3>Properties</h3>
547 * <p>
548 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
549 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
550 * available both in the {@link Property} form as well as in similarly-named setter/getter
551 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
552 * be used to set persistent state associated with these rendering-related properties on the view.
553 * The properties and methods can also be used in conjunction with
554 * {@link android.animation.Animator Animator}-based animations, described more in the
555 * <a href="#Animation">Animation</a> section.
556 * </p>
557 *
558 * <a name="Animation"></a>
559 * <h3>Animation</h3>
560 * <p>
561 * Starting with Android 3.0, the preferred way of animating views is to use the
562 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
563 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
564 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
565 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
566 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
567 * makes animating these View properties particularly easy and efficient.
568 * </p>
569 * <p>
570 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
571 * You can attach an {@link Animation} object to a view using
572 * {@link #setAnimation(Animation)} or
573 * {@link #startAnimation(Animation)}. The animation can alter the scale,
574 * rotation, translation and alpha of a view over time. If the animation is
575 * attached to a view that has children, the animation will affect the entire
576 * subtree rooted by that node. When an animation is started, the framework will
577 * take care of redrawing the appropriate views until the animation completes.
578 * </p>
579 *
580 * <a name="Security"></a>
581 * <h3>Security</h3>
582 * <p>
583 * Sometimes it is essential that an application be able to verify that an action
584 * is being performed with the full knowledge and consent of the user, such as
585 * granting a permission request, making a purchase or clicking on an advertisement.
586 * Unfortunately, a malicious application could try to spoof the user into
587 * performing these actions, unaware, by concealing the intended purpose of the view.
588 * As a remedy, the framework offers a touch filtering mechanism that can be used to
589 * improve the security of views that provide access to sensitive functionality.
590 * </p><p>
591 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
592 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
593 * will discard touches that are received whenever the view's window is obscured by
594 * another visible window.  As a result, the view will not receive touches whenever a
595 * toast, dialog or other window appears above the view's window.
596 * </p><p>
597 * For more fine-grained control over security, consider overriding the
598 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
599 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
600 * </p>
601 *
602 * @attr ref android.R.styleable#View_alpha
603 * @attr ref android.R.styleable#View_background
604 * @attr ref android.R.styleable#View_clickable
605 * @attr ref android.R.styleable#View_contentDescription
606 * @attr ref android.R.styleable#View_drawingCacheQuality
607 * @attr ref android.R.styleable#View_duplicateParentState
608 * @attr ref android.R.styleable#View_id
609 * @attr ref android.R.styleable#View_requiresFadingEdge
610 * @attr ref android.R.styleable#View_fadeScrollbars
611 * @attr ref android.R.styleable#View_fadingEdgeLength
612 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
613 * @attr ref android.R.styleable#View_fitsSystemWindows
614 * @attr ref android.R.styleable#View_isScrollContainer
615 * @attr ref android.R.styleable#View_focusable
616 * @attr ref android.R.styleable#View_focusableInTouchMode
617 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
618 * @attr ref android.R.styleable#View_keepScreenOn
619 * @attr ref android.R.styleable#View_layerType
620 * @attr ref android.R.styleable#View_longClickable
621 * @attr ref android.R.styleable#View_minHeight
622 * @attr ref android.R.styleable#View_minWidth
623 * @attr ref android.R.styleable#View_nextFocusDown
624 * @attr ref android.R.styleable#View_nextFocusLeft
625 * @attr ref android.R.styleable#View_nextFocusRight
626 * @attr ref android.R.styleable#View_nextFocusUp
627 * @attr ref android.R.styleable#View_onClick
628 * @attr ref android.R.styleable#View_padding
629 * @attr ref android.R.styleable#View_paddingBottom
630 * @attr ref android.R.styleable#View_paddingLeft
631 * @attr ref android.R.styleable#View_paddingRight
632 * @attr ref android.R.styleable#View_paddingTop
633 * @attr ref android.R.styleable#View_paddingStart
634 * @attr ref android.R.styleable#View_paddingEnd
635 * @attr ref android.R.styleable#View_saveEnabled
636 * @attr ref android.R.styleable#View_rotation
637 * @attr ref android.R.styleable#View_rotationX
638 * @attr ref android.R.styleable#View_rotationY
639 * @attr ref android.R.styleable#View_scaleX
640 * @attr ref android.R.styleable#View_scaleY
641 * @attr ref android.R.styleable#View_scrollX
642 * @attr ref android.R.styleable#View_scrollY
643 * @attr ref android.R.styleable#View_scrollbarSize
644 * @attr ref android.R.styleable#View_scrollbarStyle
645 * @attr ref android.R.styleable#View_scrollbars
646 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
647 * @attr ref android.R.styleable#View_scrollbarFadeDuration
648 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
649 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
650 * @attr ref android.R.styleable#View_scrollbarThumbVertical
651 * @attr ref android.R.styleable#View_scrollbarTrackVertical
652 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
653 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
654 * @attr ref android.R.styleable#View_soundEffectsEnabled
655 * @attr ref android.R.styleable#View_tag
656 * @attr ref android.R.styleable#View_textAlignment
657 * @attr ref android.R.styleable#View_transformPivotX
658 * @attr ref android.R.styleable#View_transformPivotY
659 * @attr ref android.R.styleable#View_translationX
660 * @attr ref android.R.styleable#View_translationY
661 * @attr ref android.R.styleable#View_visibility
662 *
663 * @see android.view.ViewGroup
664 */
665public class View implements Drawable.Callback, KeyEvent.Callback,
666        AccessibilityEventSource {
667    private static final boolean DBG = false;
668
669    /**
670     * The logging tag used by this class with android.util.Log.
671     */
672    protected static final String VIEW_LOG_TAG = "View";
673
674    /**
675     * When set to true, apps will draw debugging information about their layouts.
676     *
677     * @hide
678     */
679    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
680
681    /**
682     * Used to mark a View that has no ID.
683     */
684    public static final int NO_ID = -1;
685
686    /**
687     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
688     * calling setFlags.
689     */
690    private static final int NOT_FOCUSABLE = 0x00000000;
691
692    /**
693     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
694     * setFlags.
695     */
696    private static final int FOCUSABLE = 0x00000001;
697
698    /**
699     * Mask for use with setFlags indicating bits used for focus.
700     */
701    private static final int FOCUSABLE_MASK = 0x00000001;
702
703    /**
704     * This view will adjust its padding to fit sytem windows (e.g. status bar)
705     */
706    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
707
708    /**
709     * This view is visible.
710     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
711     * android:visibility}.
712     */
713    public static final int VISIBLE = 0x00000000;
714
715    /**
716     * This view is invisible, but it still takes up space for layout purposes.
717     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
718     * android:visibility}.
719     */
720    public static final int INVISIBLE = 0x00000004;
721
722    /**
723     * This view is invisible, and it doesn't take any space for layout
724     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
725     * android:visibility}.
726     */
727    public static final int GONE = 0x00000008;
728
729    /**
730     * Mask for use with setFlags indicating bits used for visibility.
731     * {@hide}
732     */
733    static final int VISIBILITY_MASK = 0x0000000C;
734
735    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
736
737    /**
738     * This view is enabled. Interpretation varies by subclass.
739     * Use with ENABLED_MASK when calling setFlags.
740     * {@hide}
741     */
742    static final int ENABLED = 0x00000000;
743
744    /**
745     * This view is disabled. Interpretation varies by subclass.
746     * Use with ENABLED_MASK when calling setFlags.
747     * {@hide}
748     */
749    static final int DISABLED = 0x00000020;
750
751   /**
752    * Mask for use with setFlags indicating bits used for indicating whether
753    * this view is enabled
754    * {@hide}
755    */
756    static final int ENABLED_MASK = 0x00000020;
757
758    /**
759     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
760     * called and further optimizations will be performed. It is okay to have
761     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
762     * {@hide}
763     */
764    static final int WILL_NOT_DRAW = 0x00000080;
765
766    /**
767     * Mask for use with setFlags indicating bits used for indicating whether
768     * this view is will draw
769     * {@hide}
770     */
771    static final int DRAW_MASK = 0x00000080;
772
773    /**
774     * <p>This view doesn't show scrollbars.</p>
775     * {@hide}
776     */
777    static final int SCROLLBARS_NONE = 0x00000000;
778
779    /**
780     * <p>This view shows horizontal scrollbars.</p>
781     * {@hide}
782     */
783    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
784
785    /**
786     * <p>This view shows vertical scrollbars.</p>
787     * {@hide}
788     */
789    static final int SCROLLBARS_VERTICAL = 0x00000200;
790
791    /**
792     * <p>Mask for use with setFlags indicating bits used for indicating which
793     * scrollbars are enabled.</p>
794     * {@hide}
795     */
796    static final int SCROLLBARS_MASK = 0x00000300;
797
798    /**
799     * Indicates that the view should filter touches when its window is obscured.
800     * Refer to the class comments for more information about this security feature.
801     * {@hide}
802     */
803    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
804
805    /**
806     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
807     * that they are optional and should be skipped if the window has
808     * requested system UI flags that ignore those insets for layout.
809     */
810    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
811
812    /**
813     * <p>This view doesn't show fading edges.</p>
814     * {@hide}
815     */
816    static final int FADING_EDGE_NONE = 0x00000000;
817
818    /**
819     * <p>This view shows horizontal fading edges.</p>
820     * {@hide}
821     */
822    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
823
824    /**
825     * <p>This view shows vertical fading edges.</p>
826     * {@hide}
827     */
828    static final int FADING_EDGE_VERTICAL = 0x00002000;
829
830    /**
831     * <p>Mask for use with setFlags indicating bits used for indicating which
832     * fading edges are enabled.</p>
833     * {@hide}
834     */
835    static final int FADING_EDGE_MASK = 0x00003000;
836
837    /**
838     * <p>Indicates this view can be clicked. When clickable, a View reacts
839     * to clicks by notifying the OnClickListener.<p>
840     * {@hide}
841     */
842    static final int CLICKABLE = 0x00004000;
843
844    /**
845     * <p>Indicates this view is caching its drawing into a bitmap.</p>
846     * {@hide}
847     */
848    static final int DRAWING_CACHE_ENABLED = 0x00008000;
849
850    /**
851     * <p>Indicates that no icicle should be saved for this view.<p>
852     * {@hide}
853     */
854    static final int SAVE_DISABLED = 0x000010000;
855
856    /**
857     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
858     * property.</p>
859     * {@hide}
860     */
861    static final int SAVE_DISABLED_MASK = 0x000010000;
862
863    /**
864     * <p>Indicates that no drawing cache should ever be created for this view.<p>
865     * {@hide}
866     */
867    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
868
869    /**
870     * <p>Indicates this view can take / keep focus when int touch mode.</p>
871     * {@hide}
872     */
873    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
874
875    /**
876     * <p>Enables low quality mode for the drawing cache.</p>
877     */
878    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
879
880    /**
881     * <p>Enables high quality mode for the drawing cache.</p>
882     */
883    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
884
885    /**
886     * <p>Enables automatic quality mode for the drawing cache.</p>
887     */
888    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
889
890    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
891            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
892    };
893
894    /**
895     * <p>Mask for use with setFlags indicating bits used for the cache
896     * quality property.</p>
897     * {@hide}
898     */
899    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
900
901    /**
902     * <p>
903     * Indicates this view can be long clicked. When long clickable, a View
904     * reacts to long clicks by notifying the OnLongClickListener or showing a
905     * context menu.
906     * </p>
907     * {@hide}
908     */
909    static final int LONG_CLICKABLE = 0x00200000;
910
911    /**
912     * <p>Indicates that this view gets its drawable states from its direct parent
913     * and ignores its original internal states.</p>
914     *
915     * @hide
916     */
917    static final int DUPLICATE_PARENT_STATE = 0x00400000;
918
919    /**
920     * The scrollbar style to display the scrollbars inside the content area,
921     * without increasing the padding. The scrollbars will be overlaid with
922     * translucency on the view's content.
923     */
924    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
925
926    /**
927     * The scrollbar style to display the scrollbars inside the padded area,
928     * increasing the padding of the view. The scrollbars will not overlap the
929     * content area of the view.
930     */
931    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
932
933    /**
934     * The scrollbar style to display the scrollbars at the edge of the view,
935     * without increasing the padding. The scrollbars will be overlaid with
936     * translucency.
937     */
938    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
939
940    /**
941     * The scrollbar style to display the scrollbars at the edge of the view,
942     * increasing the padding of the view. The scrollbars will only overlap the
943     * background, if any.
944     */
945    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
946
947    /**
948     * Mask to check if the scrollbar style is overlay or inset.
949     * {@hide}
950     */
951    static final int SCROLLBARS_INSET_MASK = 0x01000000;
952
953    /**
954     * Mask to check if the scrollbar style is inside or outside.
955     * {@hide}
956     */
957    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
958
959    /**
960     * Mask for scrollbar style.
961     * {@hide}
962     */
963    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
964
965    /**
966     * View flag indicating that the screen should remain on while the
967     * window containing this view is visible to the user.  This effectively
968     * takes care of automatically setting the WindowManager's
969     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
970     */
971    public static final int KEEP_SCREEN_ON = 0x04000000;
972
973    /**
974     * View flag indicating whether this view should have sound effects enabled
975     * for events such as clicking and touching.
976     */
977    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
978
979    /**
980     * View flag indicating whether this view should have haptic feedback
981     * enabled for events such as long presses.
982     */
983    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
984
985    /**
986     * <p>Indicates that the view hierarchy should stop saving state when
987     * it reaches this view.  If state saving is initiated immediately at
988     * the view, it will be allowed.
989     * {@hide}
990     */
991    static final int PARENT_SAVE_DISABLED = 0x20000000;
992
993    /**
994     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
995     * {@hide}
996     */
997    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
998
999    /**
1000     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1001     * should add all focusable Views regardless if they are focusable in touch mode.
1002     */
1003    public static final int FOCUSABLES_ALL = 0x00000000;
1004
1005    /**
1006     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1007     * should add only Views focusable in touch mode.
1008     */
1009    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1010
1011    /**
1012     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1013     * item.
1014     */
1015    public static final int FOCUS_BACKWARD = 0x00000001;
1016
1017    /**
1018     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1019     * item.
1020     */
1021    public static final int FOCUS_FORWARD = 0x00000002;
1022
1023    /**
1024     * Use with {@link #focusSearch(int)}. Move focus to the left.
1025     */
1026    public static final int FOCUS_LEFT = 0x00000011;
1027
1028    /**
1029     * Use with {@link #focusSearch(int)}. Move focus up.
1030     */
1031    public static final int FOCUS_UP = 0x00000021;
1032
1033    /**
1034     * Use with {@link #focusSearch(int)}. Move focus to the right.
1035     */
1036    public static final int FOCUS_RIGHT = 0x00000042;
1037
1038    /**
1039     * Use with {@link #focusSearch(int)}. Move focus down.
1040     */
1041    public static final int FOCUS_DOWN = 0x00000082;
1042
1043    /**
1044     * Bits of {@link #getMeasuredWidthAndState()} and
1045     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1046     */
1047    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1048
1049    /**
1050     * Bits of {@link #getMeasuredWidthAndState()} and
1051     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1052     */
1053    public static final int MEASURED_STATE_MASK = 0xff000000;
1054
1055    /**
1056     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1057     * for functions that combine both width and height into a single int,
1058     * such as {@link #getMeasuredState()} and the childState argument of
1059     * {@link #resolveSizeAndState(int, int, int)}.
1060     */
1061    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1062
1063    /**
1064     * Bit of {@link #getMeasuredWidthAndState()} and
1065     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1066     * is smaller that the space the view would like to have.
1067     */
1068    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1069
1070    /**
1071     * Base View state sets
1072     */
1073    // Singles
1074    /**
1075     * Indicates the view has no states set. States are used with
1076     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1077     * view depending on its state.
1078     *
1079     * @see android.graphics.drawable.Drawable
1080     * @see #getDrawableState()
1081     */
1082    protected static final int[] EMPTY_STATE_SET;
1083    /**
1084     * Indicates the view is enabled. 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[] ENABLED_STATE_SET;
1092    /**
1093     * Indicates the view is focused. 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[] FOCUSED_STATE_SET;
1101    /**
1102     * Indicates the view is selected. 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[] SELECTED_STATE_SET;
1110    /**
1111     * Indicates the view is pressed. 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     * @hide
1118     */
1119    protected static final int[] PRESSED_STATE_SET;
1120    /**
1121     * Indicates the view's window has focus. States are used with
1122     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1123     * view depending on its state.
1124     *
1125     * @see android.graphics.drawable.Drawable
1126     * @see #getDrawableState()
1127     */
1128    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1129    // Doubles
1130    /**
1131     * Indicates the view is enabled and has the focus.
1132     *
1133     * @see #ENABLED_STATE_SET
1134     * @see #FOCUSED_STATE_SET
1135     */
1136    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1137    /**
1138     * Indicates the view is enabled and selected.
1139     *
1140     * @see #ENABLED_STATE_SET
1141     * @see #SELECTED_STATE_SET
1142     */
1143    protected static final int[] ENABLED_SELECTED_STATE_SET;
1144    /**
1145     * Indicates the view is enabled and that its window has focus.
1146     *
1147     * @see #ENABLED_STATE_SET
1148     * @see #WINDOW_FOCUSED_STATE_SET
1149     */
1150    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1151    /**
1152     * Indicates the view is focused and selected.
1153     *
1154     * @see #FOCUSED_STATE_SET
1155     * @see #SELECTED_STATE_SET
1156     */
1157    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1158    /**
1159     * Indicates the view has the focus and that its window has the focus.
1160     *
1161     * @see #FOCUSED_STATE_SET
1162     * @see #WINDOW_FOCUSED_STATE_SET
1163     */
1164    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1165    /**
1166     * Indicates the view is selected and that its window has the focus.
1167     *
1168     * @see #SELECTED_STATE_SET
1169     * @see #WINDOW_FOCUSED_STATE_SET
1170     */
1171    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1172    // Triples
1173    /**
1174     * Indicates the view is enabled, focused and selected.
1175     *
1176     * @see #ENABLED_STATE_SET
1177     * @see #FOCUSED_STATE_SET
1178     * @see #SELECTED_STATE_SET
1179     */
1180    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1181    /**
1182     * Indicates the view is enabled, focused and its window has the focus.
1183     *
1184     * @see #ENABLED_STATE_SET
1185     * @see #FOCUSED_STATE_SET
1186     * @see #WINDOW_FOCUSED_STATE_SET
1187     */
1188    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1189    /**
1190     * Indicates the view is enabled, selected and its window has the focus.
1191     *
1192     * @see #ENABLED_STATE_SET
1193     * @see #SELECTED_STATE_SET
1194     * @see #WINDOW_FOCUSED_STATE_SET
1195     */
1196    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1197    /**
1198     * Indicates the view is focused, selected and its window has the focus.
1199     *
1200     * @see #FOCUSED_STATE_SET
1201     * @see #SELECTED_STATE_SET
1202     * @see #WINDOW_FOCUSED_STATE_SET
1203     */
1204    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1205    /**
1206     * Indicates the view is enabled, focused, selected and its window
1207     * has the focus.
1208     *
1209     * @see #ENABLED_STATE_SET
1210     * @see #FOCUSED_STATE_SET
1211     * @see #SELECTED_STATE_SET
1212     * @see #WINDOW_FOCUSED_STATE_SET
1213     */
1214    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1215    /**
1216     * Indicates the view is pressed and its window has the focus.
1217     *
1218     * @see #PRESSED_STATE_SET
1219     * @see #WINDOW_FOCUSED_STATE_SET
1220     */
1221    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1222    /**
1223     * Indicates the view is pressed and selected.
1224     *
1225     * @see #PRESSED_STATE_SET
1226     * @see #SELECTED_STATE_SET
1227     */
1228    protected static final int[] PRESSED_SELECTED_STATE_SET;
1229    /**
1230     * Indicates the view is pressed, selected and its window has the focus.
1231     *
1232     * @see #PRESSED_STATE_SET
1233     * @see #SELECTED_STATE_SET
1234     * @see #WINDOW_FOCUSED_STATE_SET
1235     */
1236    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1237    /**
1238     * Indicates the view is pressed and focused.
1239     *
1240     * @see #PRESSED_STATE_SET
1241     * @see #FOCUSED_STATE_SET
1242     */
1243    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1244    /**
1245     * Indicates the view is pressed, focused and its window has the focus.
1246     *
1247     * @see #PRESSED_STATE_SET
1248     * @see #FOCUSED_STATE_SET
1249     * @see #WINDOW_FOCUSED_STATE_SET
1250     */
1251    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1252    /**
1253     * Indicates the view is pressed, focused and selected.
1254     *
1255     * @see #PRESSED_STATE_SET
1256     * @see #SELECTED_STATE_SET
1257     * @see #FOCUSED_STATE_SET
1258     */
1259    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1260    /**
1261     * Indicates the view is pressed, focused, selected and its window has the focus.
1262     *
1263     * @see #PRESSED_STATE_SET
1264     * @see #FOCUSED_STATE_SET
1265     * @see #SELECTED_STATE_SET
1266     * @see #WINDOW_FOCUSED_STATE_SET
1267     */
1268    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1269    /**
1270     * Indicates the view is pressed and enabled.
1271     *
1272     * @see #PRESSED_STATE_SET
1273     * @see #ENABLED_STATE_SET
1274     */
1275    protected static final int[] PRESSED_ENABLED_STATE_SET;
1276    /**
1277     * Indicates the view is pressed, enabled and its window has the focus.
1278     *
1279     * @see #PRESSED_STATE_SET
1280     * @see #ENABLED_STATE_SET
1281     * @see #WINDOW_FOCUSED_STATE_SET
1282     */
1283    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1284    /**
1285     * Indicates the view is pressed, enabled and selected.
1286     *
1287     * @see #PRESSED_STATE_SET
1288     * @see #ENABLED_STATE_SET
1289     * @see #SELECTED_STATE_SET
1290     */
1291    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1292    /**
1293     * Indicates the view is pressed, enabled, selected and its window has the
1294     * focus.
1295     *
1296     * @see #PRESSED_STATE_SET
1297     * @see #ENABLED_STATE_SET
1298     * @see #SELECTED_STATE_SET
1299     * @see #WINDOW_FOCUSED_STATE_SET
1300     */
1301    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1302    /**
1303     * Indicates the view is pressed, enabled and focused.
1304     *
1305     * @see #PRESSED_STATE_SET
1306     * @see #ENABLED_STATE_SET
1307     * @see #FOCUSED_STATE_SET
1308     */
1309    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1310    /**
1311     * Indicates the view is pressed, enabled, focused and its window has the
1312     * focus.
1313     *
1314     * @see #PRESSED_STATE_SET
1315     * @see #ENABLED_STATE_SET
1316     * @see #FOCUSED_STATE_SET
1317     * @see #WINDOW_FOCUSED_STATE_SET
1318     */
1319    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1320    /**
1321     * Indicates the view is pressed, enabled, focused and selected.
1322     *
1323     * @see #PRESSED_STATE_SET
1324     * @see #ENABLED_STATE_SET
1325     * @see #SELECTED_STATE_SET
1326     * @see #FOCUSED_STATE_SET
1327     */
1328    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1329    /**
1330     * Indicates the view is pressed, enabled, focused, selected and its window
1331     * has the focus.
1332     *
1333     * @see #PRESSED_STATE_SET
1334     * @see #ENABLED_STATE_SET
1335     * @see #SELECTED_STATE_SET
1336     * @see #FOCUSED_STATE_SET
1337     * @see #WINDOW_FOCUSED_STATE_SET
1338     */
1339    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1340
1341    /**
1342     * The order here is very important to {@link #getDrawableState()}
1343     */
1344    private static final int[][] VIEW_STATE_SETS;
1345
1346    static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1347    static final int VIEW_STATE_SELECTED = 1 << 1;
1348    static final int VIEW_STATE_FOCUSED = 1 << 2;
1349    static final int VIEW_STATE_ENABLED = 1 << 3;
1350    static final int VIEW_STATE_PRESSED = 1 << 4;
1351    static final int VIEW_STATE_ACTIVATED = 1 << 5;
1352    static final int VIEW_STATE_ACCELERATED = 1 << 6;
1353    static final int VIEW_STATE_HOVERED = 1 << 7;
1354    static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1355    static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
1356
1357    static final int[] VIEW_STATE_IDS = new int[] {
1358        R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
1359        R.attr.state_selected,          VIEW_STATE_SELECTED,
1360        R.attr.state_focused,           VIEW_STATE_FOCUSED,
1361        R.attr.state_enabled,           VIEW_STATE_ENABLED,
1362        R.attr.state_pressed,           VIEW_STATE_PRESSED,
1363        R.attr.state_activated,         VIEW_STATE_ACTIVATED,
1364        R.attr.state_accelerated,       VIEW_STATE_ACCELERATED,
1365        R.attr.state_hovered,           VIEW_STATE_HOVERED,
1366        R.attr.state_drag_can_accept,   VIEW_STATE_DRAG_CAN_ACCEPT,
1367        R.attr.state_drag_hovered,      VIEW_STATE_DRAG_HOVERED
1368    };
1369
1370    static {
1371        if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1372            throw new IllegalStateException(
1373                    "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1374        }
1375        int[] orderedIds = new int[VIEW_STATE_IDS.length];
1376        for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
1377            int viewState = R.styleable.ViewDrawableStates[i];
1378            for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
1379                if (VIEW_STATE_IDS[j] == viewState) {
1380                    orderedIds[i * 2] = viewState;
1381                    orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
1382                }
1383            }
1384        }
1385        final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1386        VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1387        for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
1388            int numBits = Integer.bitCount(i);
1389            int[] set = new int[numBits];
1390            int pos = 0;
1391            for (int j = 0; j < orderedIds.length; j += 2) {
1392                if ((i & orderedIds[j+1]) != 0) {
1393                    set[pos++] = orderedIds[j];
1394                }
1395            }
1396            VIEW_STATE_SETS[i] = set;
1397        }
1398
1399        EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1400        WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1401        SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1402        SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1403                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1404        FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1405        FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1406                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1407        FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1408                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1409        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1410                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1411                | VIEW_STATE_FOCUSED];
1412        ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1413        ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1414                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1415        ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1416                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1417        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1418                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1419                | VIEW_STATE_ENABLED];
1420        ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1421                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1422        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1423                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1424                | VIEW_STATE_ENABLED];
1425        ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1426                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1427                | VIEW_STATE_ENABLED];
1428        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1429                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1430                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1431
1432        PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1433        PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1434                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1435        PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1436                VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1437        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1438                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1439                | VIEW_STATE_PRESSED];
1440        PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1441                VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1442        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1443                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1444                | VIEW_STATE_PRESSED];
1445        PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1446                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1447                | VIEW_STATE_PRESSED];
1448        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1449                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1450                | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1451        PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1452                VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1453        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1454                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1455                | VIEW_STATE_PRESSED];
1456        PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1457                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1458                | VIEW_STATE_PRESSED];
1459        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1460                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1461                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1462        PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1463                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1464                | VIEW_STATE_PRESSED];
1465        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1466                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1467                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1468        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1469                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1470                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1471        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1472                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1473                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1474                | VIEW_STATE_PRESSED];
1475    }
1476
1477    /**
1478     * Accessibility event types that are dispatched for text population.
1479     */
1480    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1481            AccessibilityEvent.TYPE_VIEW_CLICKED
1482            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1483            | AccessibilityEvent.TYPE_VIEW_SELECTED
1484            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1485            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1486            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1487            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1488            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1489            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1490            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1491            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1492
1493    /**
1494     * Temporary Rect currently for use in setBackground().  This will probably
1495     * be extended in the future to hold our own class with more than just
1496     * a Rect. :)
1497     */
1498    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1499
1500    /**
1501     * Map used to store views' tags.
1502     */
1503    private SparseArray<Object> mKeyedTags;
1504
1505    /**
1506     * The next available accessiiblity id.
1507     */
1508    private static int sNextAccessibilityViewId;
1509
1510    /**
1511     * The animation currently associated with this view.
1512     * @hide
1513     */
1514    protected Animation mCurrentAnimation = null;
1515
1516    /**
1517     * Width as measured during measure pass.
1518     * {@hide}
1519     */
1520    @ViewDebug.ExportedProperty(category = "measurement")
1521    int mMeasuredWidth;
1522
1523    /**
1524     * Height as measured during measure pass.
1525     * {@hide}
1526     */
1527    @ViewDebug.ExportedProperty(category = "measurement")
1528    int mMeasuredHeight;
1529
1530    /**
1531     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1532     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1533     * its display list. This flag, used only when hw accelerated, allows us to clear the
1534     * flag while retaining this information until it's needed (at getDisplayList() time and
1535     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1536     *
1537     * {@hide}
1538     */
1539    boolean mRecreateDisplayList = false;
1540
1541    /**
1542     * The view's identifier.
1543     * {@hide}
1544     *
1545     * @see #setId(int)
1546     * @see #getId()
1547     */
1548    @ViewDebug.ExportedProperty(resolveId = true)
1549    int mID = NO_ID;
1550
1551    /**
1552     * The stable ID of this view for accessibility purposes.
1553     */
1554    int mAccessibilityViewId = NO_ID;
1555
1556    /**
1557     * @hide
1558     */
1559    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1560
1561    /**
1562     * The view's tag.
1563     * {@hide}
1564     *
1565     * @see #setTag(Object)
1566     * @see #getTag()
1567     */
1568    protected Object mTag;
1569
1570    // for mPrivateFlags:
1571    /** {@hide} */
1572    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1573    /** {@hide} */
1574    static final int PFLAG_FOCUSED                     = 0x00000002;
1575    /** {@hide} */
1576    static final int PFLAG_SELECTED                    = 0x00000004;
1577    /** {@hide} */
1578    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1579    /** {@hide} */
1580    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1581    /** {@hide} */
1582    static final int PFLAG_DRAWN                       = 0x00000020;
1583    /**
1584     * When this flag is set, this view is running an animation on behalf of its
1585     * children and should therefore not cancel invalidate requests, even if they
1586     * lie outside of this view's bounds.
1587     *
1588     * {@hide}
1589     */
1590    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1591    /** {@hide} */
1592    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1593    /** {@hide} */
1594    static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
1595    /** {@hide} */
1596    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1597    /** {@hide} */
1598    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1599    /** {@hide} */
1600    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1601    /** {@hide} */
1602    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1603    /** {@hide} */
1604    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1605
1606    private static final int PFLAG_PRESSED             = 0x00004000;
1607
1608    /** {@hide} */
1609    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1610    /**
1611     * Flag used to indicate that this view should be drawn once more (and only once
1612     * more) after its animation has completed.
1613     * {@hide}
1614     */
1615    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1616
1617    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1618
1619    /**
1620     * Indicates that the View returned true when onSetAlpha() was called and that
1621     * the alpha must be restored.
1622     * {@hide}
1623     */
1624    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1625
1626    /**
1627     * Set by {@link #setScrollContainer(boolean)}.
1628     */
1629    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1630
1631    /**
1632     * Set by {@link #setScrollContainer(boolean)}.
1633     */
1634    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1635
1636    /**
1637     * View flag indicating whether this view was invalidated (fully or partially.)
1638     *
1639     * @hide
1640     */
1641    static final int PFLAG_DIRTY                       = 0x00200000;
1642
1643    /**
1644     * View flag indicating whether this view was invalidated by an opaque
1645     * invalidate request.
1646     *
1647     * @hide
1648     */
1649    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1650
1651    /**
1652     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1653     *
1654     * @hide
1655     */
1656    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1657
1658    /**
1659     * Indicates whether the background is opaque.
1660     *
1661     * @hide
1662     */
1663    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1664
1665    /**
1666     * Indicates whether the scrollbars are opaque.
1667     *
1668     * @hide
1669     */
1670    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1671
1672    /**
1673     * Indicates whether the view is opaque.
1674     *
1675     * @hide
1676     */
1677    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1678
1679    /**
1680     * Indicates a prepressed state;
1681     * the short time between ACTION_DOWN and recognizing
1682     * a 'real' press. Prepressed is used to recognize quick taps
1683     * even when they are shorter than ViewConfiguration.getTapTimeout().
1684     *
1685     * @hide
1686     */
1687    private static final int PFLAG_PREPRESSED          = 0x02000000;
1688
1689    /**
1690     * Indicates whether the view is temporarily detached.
1691     *
1692     * @hide
1693     */
1694    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1695
1696    /**
1697     * Indicates that we should awaken scroll bars once attached
1698     *
1699     * @hide
1700     */
1701    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1702
1703    /**
1704     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1705     * @hide
1706     */
1707    private static final int PFLAG_HOVERED             = 0x10000000;
1708
1709    /**
1710     * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
1711     * for transform operations
1712     *
1713     * @hide
1714     */
1715    private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000;
1716
1717    /** {@hide} */
1718    static final int PFLAG_ACTIVATED                   = 0x40000000;
1719
1720    /**
1721     * Indicates that this view was specifically invalidated, not just dirtied because some
1722     * child view was invalidated. The flag is used to determine when we need to recreate
1723     * a view's display list (as opposed to just returning a reference to its existing
1724     * display list).
1725     *
1726     * @hide
1727     */
1728    static final int PFLAG_INVALIDATED                 = 0x80000000;
1729
1730    /* Masks for mPrivateFlags2 */
1731
1732    /**
1733     * Indicates that this view has reported that it can accept the current drag's content.
1734     * Cleared when the drag operation concludes.
1735     * @hide
1736     */
1737    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1738
1739    /**
1740     * Indicates that this view is currently directly under the drag location in a
1741     * drag-and-drop operation involving content that it can accept.  Cleared when
1742     * the drag exits the view, or when the drag operation concludes.
1743     * @hide
1744     */
1745    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1746
1747    /**
1748     * Horizontal layout direction of this view is from Left to Right.
1749     * Use with {@link #setLayoutDirection}.
1750     */
1751    public static final int LAYOUT_DIRECTION_LTR = 0;
1752
1753    /**
1754     * Horizontal layout direction of this view is from Right to Left.
1755     * Use with {@link #setLayoutDirection}.
1756     */
1757    public static final int LAYOUT_DIRECTION_RTL = 1;
1758
1759    /**
1760     * Horizontal layout direction of this view is inherited from its parent.
1761     * Use with {@link #setLayoutDirection}.
1762     */
1763    public static final int LAYOUT_DIRECTION_INHERIT = 2;
1764
1765    /**
1766     * Horizontal layout direction of this view is from deduced from the default language
1767     * script for the locale. Use with {@link #setLayoutDirection}.
1768     */
1769    public static final int LAYOUT_DIRECTION_LOCALE = 3;
1770
1771    /**
1772     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1773     * @hide
1774     */
1775    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1776
1777    /**
1778     * Mask for use with private flags indicating bits used for horizontal layout direction.
1779     * @hide
1780     */
1781    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1782
1783    /**
1784     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1785     * right-to-left direction.
1786     * @hide
1787     */
1788    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1789
1790    /**
1791     * Indicates whether the view horizontal layout direction has been resolved.
1792     * @hide
1793     */
1794    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1795
1796    /**
1797     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1798     * @hide
1799     */
1800    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1801            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1802
1803    /*
1804     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1805     * flag value.
1806     * @hide
1807     */
1808    private static final int[] LAYOUT_DIRECTION_FLAGS = {
1809            LAYOUT_DIRECTION_LTR,
1810            LAYOUT_DIRECTION_RTL,
1811            LAYOUT_DIRECTION_INHERIT,
1812            LAYOUT_DIRECTION_LOCALE
1813    };
1814
1815    /**
1816     * Default horizontal layout direction.
1817     * @hide
1818     */
1819    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1820
1821    /**
1822     * Indicates that the view is tracking some sort of transient state
1823     * that the app should not need to be aware of, but that the framework
1824     * should take special care to preserve.
1825     *
1826     * @hide
1827     */
1828    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x00000100;
1829
1830
1831    /**
1832     * Text direction is inherited thru {@link ViewGroup}
1833     */
1834    public static final int TEXT_DIRECTION_INHERIT = 0;
1835
1836    /**
1837     * Text direction is using "first strong algorithm". The first strong directional character
1838     * determines the paragraph direction. If there is no strong directional character, the
1839     * paragraph direction is the view's resolved layout direction.
1840     */
1841    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1842
1843    /**
1844     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1845     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1846     * If there are neither, the paragraph direction is the view's resolved layout direction.
1847     */
1848    public static final int TEXT_DIRECTION_ANY_RTL = 2;
1849
1850    /**
1851     * Text direction is forced to LTR.
1852     */
1853    public static final int TEXT_DIRECTION_LTR = 3;
1854
1855    /**
1856     * Text direction is forced to RTL.
1857     */
1858    public static final int TEXT_DIRECTION_RTL = 4;
1859
1860    /**
1861     * Text direction is coming from the system Locale.
1862     */
1863    public static final int TEXT_DIRECTION_LOCALE = 5;
1864
1865    /**
1866     * Default text direction is inherited
1867     */
1868    public static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
1869
1870    /**
1871     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
1872     * @hide
1873     */
1874    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
1875
1876    /**
1877     * Mask for use with private flags indicating bits used for text direction.
1878     * @hide
1879     */
1880    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
1881            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
1882
1883    /**
1884     * Array of text direction flags for mapping attribute "textDirection" to correct
1885     * flag value.
1886     * @hide
1887     */
1888    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
1889            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1890            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1891            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1892            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1893            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1894            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
1895    };
1896
1897    /**
1898     * Indicates whether the view text direction has been resolved.
1899     * @hide
1900     */
1901    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
1902            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
1903
1904    /**
1905     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1906     * @hide
1907     */
1908    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
1909
1910    /**
1911     * Mask for use with private flags indicating bits used for resolved text direction.
1912     * @hide
1913     */
1914    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
1915            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
1916
1917    /**
1918     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
1919     * @hide
1920     */
1921    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
1922            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
1923
1924    /*
1925     * Default text alignment. The text alignment of this View is inherited from its parent.
1926     * Use with {@link #setTextAlignment(int)}
1927     */
1928    public static final int TEXT_ALIGNMENT_INHERIT = 0;
1929
1930    /**
1931     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
1932     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
1933     *
1934     * Use with {@link #setTextAlignment(int)}
1935     */
1936    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
1937
1938    /**
1939     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
1940     *
1941     * Use with {@link #setTextAlignment(int)}
1942     */
1943    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
1944
1945    /**
1946     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
1947     *
1948     * Use with {@link #setTextAlignment(int)}
1949     */
1950    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
1951
1952    /**
1953     * Center the paragraph, e.g. ALIGN_CENTER.
1954     *
1955     * Use with {@link #setTextAlignment(int)}
1956     */
1957    public static final int TEXT_ALIGNMENT_CENTER = 4;
1958
1959    /**
1960     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
1961     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
1962     *
1963     * Use with {@link #setTextAlignment(int)}
1964     */
1965    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
1966
1967    /**
1968     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
1969     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
1970     *
1971     * Use with {@link #setTextAlignment(int)}
1972     */
1973    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
1974
1975    /**
1976     * Default text alignment is inherited
1977     */
1978    public static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
1979
1980    /**
1981      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1982      * @hide
1983      */
1984    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
1985
1986    /**
1987      * Mask for use with private flags indicating bits used for text alignment.
1988      * @hide
1989      */
1990    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
1991
1992    /**
1993     * Array of text direction flags for mapping attribute "textAlignment" to correct
1994     * flag value.
1995     * @hide
1996     */
1997    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
1998            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
1999            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2000            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2001            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2002            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2003            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2004            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2005    };
2006
2007    /**
2008     * Indicates whether the view text alignment has been resolved.
2009     * @hide
2010     */
2011    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2012
2013    /**
2014     * Bit shift to get the resolved text alignment.
2015     * @hide
2016     */
2017    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2018
2019    /**
2020     * Mask for use with private flags indicating bits used for text alignment.
2021     * @hide
2022     */
2023    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2024            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2025
2026    /**
2027     * Indicates whether if the view text alignment has been resolved to gravity
2028     */
2029    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2030            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2031
2032    // Accessiblity constants for mPrivateFlags2
2033
2034    /**
2035     * Shift for the bits in {@link #mPrivateFlags2} related to the
2036     * "importantForAccessibility" attribute.
2037     */
2038    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2039
2040    /**
2041     * Automatically determine whether a view is important for accessibility.
2042     */
2043    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2044
2045    /**
2046     * The view is important for accessibility.
2047     */
2048    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2049
2050    /**
2051     * The view is not important for accessibility.
2052     */
2053    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2054
2055    /**
2056     * The default whether the view is important for accessiblity.
2057     */
2058    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2059
2060    /**
2061     * Mask for obtainig the bits which specify how to determine
2062     * whether a view is important for accessibility.
2063     */
2064    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2065        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO)
2066        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2067
2068    /**
2069     * Flag indicating whether a view has accessibility focus.
2070     */
2071    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x00000040 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2072
2073    /**
2074     * Flag indicating whether a view state for accessibility has changed.
2075     */
2076    static final int PFLAG2_ACCESSIBILITY_STATE_CHANGED = 0x00000080
2077            << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2078
2079    /**
2080     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2081     * is used to check whether later changes to the view's transform should invalidate the
2082     * view to force the quickReject test to run again.
2083     */
2084    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2085
2086    /**
2087     * Flag indicating that start/end padding has been resolved into left/right padding
2088     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2089     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2090     * during measurement. In some special cases this is required such as when an adapter-based
2091     * view measures prospective children without attaching them to a window.
2092     */
2093    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2094
2095    // There are a couple of flags left in mPrivateFlags2
2096
2097    /* End of masks for mPrivateFlags2 */
2098
2099    /* Masks for mPrivateFlags3 */
2100
2101    /**
2102     * Flag indicating that view has a transform animation set on it. This is used to track whether
2103     * an animation is cleared between successive frames, in order to tell the associated
2104     * DisplayList to clear its animation matrix.
2105     */
2106    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2107
2108    /**
2109     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2110     * animation is cleared between successive frames, in order to tell the associated
2111     * DisplayList to restore its alpha value.
2112     */
2113    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2114
2115
2116    /* End of masks for mPrivateFlags3 */
2117
2118    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2119
2120    /**
2121     * Always allow a user to over-scroll this view, provided it is a
2122     * view that can scroll.
2123     *
2124     * @see #getOverScrollMode()
2125     * @see #setOverScrollMode(int)
2126     */
2127    public static final int OVER_SCROLL_ALWAYS = 0;
2128
2129    /**
2130     * Allow a user to over-scroll this view only if the content is large
2131     * enough to meaningfully scroll, provided it is a view that can scroll.
2132     *
2133     * @see #getOverScrollMode()
2134     * @see #setOverScrollMode(int)
2135     */
2136    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2137
2138    /**
2139     * Never allow a user to over-scroll this view.
2140     *
2141     * @see #getOverScrollMode()
2142     * @see #setOverScrollMode(int)
2143     */
2144    public static final int OVER_SCROLL_NEVER = 2;
2145
2146    /**
2147     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2148     * requested the system UI (status bar) to be visible (the default).
2149     *
2150     * @see #setSystemUiVisibility(int)
2151     */
2152    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2153
2154    /**
2155     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2156     * system UI to enter an unobtrusive "low profile" mode.
2157     *
2158     * <p>This is for use in games, book readers, video players, or any other
2159     * "immersive" application where the usual system chrome is deemed too distracting.
2160     *
2161     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2162     *
2163     * @see #setSystemUiVisibility(int)
2164     */
2165    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2166
2167    /**
2168     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2169     * system navigation be temporarily hidden.
2170     *
2171     * <p>This is an even less obtrusive state than that called for by
2172     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2173     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2174     * those to disappear. This is useful (in conjunction with the
2175     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2176     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2177     * window flags) for displaying content using every last pixel on the display.
2178     *
2179     * <p>There is a limitation: because navigation controls are so important, the least user
2180     * interaction will cause them to reappear immediately.  When this happens, both
2181     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2182     * so that both elements reappear at the same time.
2183     *
2184     * @see #setSystemUiVisibility(int)
2185     */
2186    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2187
2188    /**
2189     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2190     * into the normal fullscreen mode so that its content can take over the screen
2191     * while still allowing the user to interact with the application.
2192     *
2193     * <p>This has the same visual effect as
2194     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2195     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2196     * meaning that non-critical screen decorations (such as the status bar) will be
2197     * hidden while the user is in the View's window, focusing the experience on
2198     * that content.  Unlike the window flag, if you are using ActionBar in
2199     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2200     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2201     * hide the action bar.
2202     *
2203     * <p>This approach to going fullscreen is best used over the window flag when
2204     * it is a transient state -- that is, the application does this at certain
2205     * points in its user interaction where it wants to allow the user to focus
2206     * on content, but not as a continuous state.  For situations where the application
2207     * would like to simply stay full screen the entire time (such as a game that
2208     * wants to take over the screen), the
2209     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2210     * is usually a better approach.  The state set here will be removed by the system
2211     * in various situations (such as the user moving to another application) like
2212     * the other system UI states.
2213     *
2214     * <p>When using this flag, the application should provide some easy facility
2215     * for the user to go out of it.  A common example would be in an e-book
2216     * reader, where tapping on the screen brings back whatever screen and UI
2217     * decorations that had been hidden while the user was immersed in reading
2218     * the book.
2219     *
2220     * @see #setSystemUiVisibility(int)
2221     */
2222    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2223
2224    /**
2225     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2226     * flags, we would like a stable view of the content insets given to
2227     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2228     * will always represent the worst case that the application can expect
2229     * as a continuous state.  In the stock Android UI this is the space for
2230     * the system bar, nav bar, and status bar, but not more transient elements
2231     * such as an input method.
2232     *
2233     * The stable layout your UI sees is based on the system UI modes you can
2234     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2235     * then you will get a stable layout for changes of the
2236     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2237     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2238     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2239     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2240     * with a stable layout.  (Note that you should avoid using
2241     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2242     *
2243     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2244     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2245     * then a hidden status bar will be considered a "stable" state for purposes
2246     * here.  This allows your UI to continually hide the status bar, while still
2247     * using the system UI flags to hide the action bar while still retaining
2248     * a stable layout.  Note that changing the window fullscreen flag will never
2249     * provide a stable layout for a clean transition.
2250     *
2251     * <p>If you are using ActionBar in
2252     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2253     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2254     * insets it adds to those given to the application.
2255     */
2256    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2257
2258    /**
2259     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2260     * to be layed out as if it has requested
2261     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2262     * allows it to avoid artifacts when switching in and out of that mode, at
2263     * the expense that some of its user interface may be covered by screen
2264     * decorations when they are shown.  You can perform layout of your inner
2265     * UI elements to account for the navagation system UI through the
2266     * {@link #fitSystemWindows(Rect)} method.
2267     */
2268    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2269
2270    /**
2271     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2272     * to be layed out as if it has requested
2273     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2274     * allows it to avoid artifacts when switching in and out of that mode, at
2275     * the expense that some of its user interface may be covered by screen
2276     * decorations when they are shown.  You can perform layout of your inner
2277     * UI elements to account for non-fullscreen system UI through the
2278     * {@link #fitSystemWindows(Rect)} method.
2279     */
2280    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2281
2282    /**
2283     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2284     */
2285    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2286
2287    /**
2288     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2289     */
2290    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2291
2292    /**
2293     * @hide
2294     *
2295     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2296     * out of the public fields to keep the undefined bits out of the developer's way.
2297     *
2298     * Flag to make the status bar not expandable.  Unless you also
2299     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2300     */
2301    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2302
2303    /**
2304     * @hide
2305     *
2306     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2307     * out of the public fields to keep the undefined bits out of the developer's way.
2308     *
2309     * Flag to hide notification icons and scrolling ticker text.
2310     */
2311    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2312
2313    /**
2314     * @hide
2315     *
2316     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2317     * out of the public fields to keep the undefined bits out of the developer's way.
2318     *
2319     * Flag to disable incoming notification alerts.  This will not block
2320     * icons, but it will block sound, vibrating and other visual or aural notifications.
2321     */
2322    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2323
2324    /**
2325     * @hide
2326     *
2327     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2328     * out of the public fields to keep the undefined bits out of the developer's way.
2329     *
2330     * Flag to hide only the scrolling ticker.  Note that
2331     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2332     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2333     */
2334    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2335
2336    /**
2337     * @hide
2338     *
2339     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2340     * out of the public fields to keep the undefined bits out of the developer's way.
2341     *
2342     * Flag to hide the center system info area.
2343     */
2344    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2345
2346    /**
2347     * @hide
2348     *
2349     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2350     * out of the public fields to keep the undefined bits out of the developer's way.
2351     *
2352     * Flag to hide only the home button.  Don't use this
2353     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2354     */
2355    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2356
2357    /**
2358     * @hide
2359     *
2360     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2361     * out of the public fields to keep the undefined bits out of the developer's way.
2362     *
2363     * Flag to hide only the back button. Don't use this
2364     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2365     */
2366    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2367
2368    /**
2369     * @hide
2370     *
2371     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2372     * out of the public fields to keep the undefined bits out of the developer's way.
2373     *
2374     * Flag to hide only the clock.  You might use this if your activity has
2375     * its own clock making the status bar's clock redundant.
2376     */
2377    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2378
2379    /**
2380     * @hide
2381     *
2382     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2383     * out of the public fields to keep the undefined bits out of the developer's way.
2384     *
2385     * Flag to hide only the recent apps button. Don't use this
2386     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2387     */
2388    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2389
2390    /**
2391     * @hide
2392     */
2393    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
2394
2395    /**
2396     * These are the system UI flags that can be cleared by events outside
2397     * of an application.  Currently this is just the ability to tap on the
2398     * screen while hiding the navigation bar to have it return.
2399     * @hide
2400     */
2401    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2402            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2403            | SYSTEM_UI_FLAG_FULLSCREEN;
2404
2405    /**
2406     * Flags that can impact the layout in relation to system UI.
2407     */
2408    public static final int SYSTEM_UI_LAYOUT_FLAGS =
2409            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2410            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2411
2412    /**
2413     * Find views that render the specified text.
2414     *
2415     * @see #findViewsWithText(ArrayList, CharSequence, int)
2416     */
2417    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2418
2419    /**
2420     * Find find views that contain the specified content description.
2421     *
2422     * @see #findViewsWithText(ArrayList, CharSequence, int)
2423     */
2424    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2425
2426    /**
2427     * Find views that contain {@link AccessibilityNodeProvider}. Such
2428     * a View is a root of virtual view hierarchy and may contain the searched
2429     * text. If this flag is set Views with providers are automatically
2430     * added and it is a responsibility of the client to call the APIs of
2431     * the provider to determine whether the virtual tree rooted at this View
2432     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2433     * represeting the virtual views with this text.
2434     *
2435     * @see #findViewsWithText(ArrayList, CharSequence, int)
2436     *
2437     * @hide
2438     */
2439    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2440
2441    /**
2442     * The undefined cursor position.
2443     */
2444    private static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2445
2446    /**
2447     * Indicates that the screen has changed state and is now off.
2448     *
2449     * @see #onScreenStateChanged(int)
2450     */
2451    public static final int SCREEN_STATE_OFF = 0x0;
2452
2453    /**
2454     * Indicates that the screen has changed state and is now on.
2455     *
2456     * @see #onScreenStateChanged(int)
2457     */
2458    public static final int SCREEN_STATE_ON = 0x1;
2459
2460    /**
2461     * Controls the over-scroll mode for this view.
2462     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2463     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2464     * and {@link #OVER_SCROLL_NEVER}.
2465     */
2466    private int mOverScrollMode;
2467
2468    /**
2469     * The parent this view is attached to.
2470     * {@hide}
2471     *
2472     * @see #getParent()
2473     */
2474    protected ViewParent mParent;
2475
2476    /**
2477     * {@hide}
2478     */
2479    AttachInfo mAttachInfo;
2480
2481    /**
2482     * {@hide}
2483     */
2484    @ViewDebug.ExportedProperty(flagMapping = {
2485        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2486                name = "FORCE_LAYOUT"),
2487        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2488                name = "LAYOUT_REQUIRED"),
2489        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2490            name = "DRAWING_CACHE_INVALID", outputIf = false),
2491        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2492        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2493        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2494        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2495    })
2496    int mPrivateFlags;
2497    int mPrivateFlags2;
2498    int mPrivateFlags3;
2499
2500    /**
2501     * This view's request for the visibility of the status bar.
2502     * @hide
2503     */
2504    @ViewDebug.ExportedProperty(flagMapping = {
2505        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2506                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2507                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2508        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2509                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2510                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2511        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2512                                equals = SYSTEM_UI_FLAG_VISIBLE,
2513                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2514    })
2515    int mSystemUiVisibility;
2516
2517    /**
2518     * Reference count for transient state.
2519     * @see #setHasTransientState(boolean)
2520     */
2521    int mTransientStateCount = 0;
2522
2523    /**
2524     * Count of how many windows this view has been attached to.
2525     */
2526    int mWindowAttachCount;
2527
2528    /**
2529     * The layout parameters associated with this view and used by the parent
2530     * {@link android.view.ViewGroup} to determine how this view should be
2531     * laid out.
2532     * {@hide}
2533     */
2534    protected ViewGroup.LayoutParams mLayoutParams;
2535
2536    /**
2537     * The view flags hold various views states.
2538     * {@hide}
2539     */
2540    @ViewDebug.ExportedProperty
2541    int mViewFlags;
2542
2543    static class TransformationInfo {
2544        /**
2545         * The transform matrix for the View. This transform is calculated internally
2546         * based on the rotation, scaleX, and scaleY properties. The identity matrix
2547         * is used by default. Do *not* use this variable directly; instead call
2548         * getMatrix(), which will automatically recalculate the matrix if necessary
2549         * to get the correct matrix based on the latest rotation and scale properties.
2550         */
2551        private final Matrix mMatrix = new Matrix();
2552
2553        /**
2554         * The transform matrix for the View. This transform is calculated internally
2555         * based on the rotation, scaleX, and scaleY properties. The identity matrix
2556         * is used by default. Do *not* use this variable directly; instead call
2557         * getInverseMatrix(), which will automatically recalculate the matrix if necessary
2558         * to get the correct matrix based on the latest rotation and scale properties.
2559         */
2560        private Matrix mInverseMatrix;
2561
2562        /**
2563         * An internal variable that tracks whether we need to recalculate the
2564         * transform matrix, based on whether the rotation or scaleX/Y properties
2565         * have changed since the matrix was last calculated.
2566         */
2567        boolean mMatrixDirty = false;
2568
2569        /**
2570         * An internal variable that tracks whether we need to recalculate the
2571         * transform matrix, based on whether the rotation or scaleX/Y properties
2572         * have changed since the matrix was last calculated.
2573         */
2574        private boolean mInverseMatrixDirty = true;
2575
2576        /**
2577         * A variable that tracks whether we need to recalculate the
2578         * transform matrix, based on whether the rotation or scaleX/Y properties
2579         * have changed since the matrix was last calculated. This variable
2580         * is only valid after a call to updateMatrix() or to a function that
2581         * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
2582         */
2583        private boolean mMatrixIsIdentity = true;
2584
2585        /**
2586         * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
2587         */
2588        private Camera mCamera = null;
2589
2590        /**
2591         * This matrix is used when computing the matrix for 3D rotations.
2592         */
2593        private Matrix matrix3D = null;
2594
2595        /**
2596         * These prev values are used to recalculate a centered pivot point when necessary. The
2597         * pivot point is only used in matrix operations (when rotation, scale, or translation are
2598         * set), so thes values are only used then as well.
2599         */
2600        private int mPrevWidth = -1;
2601        private int mPrevHeight = -1;
2602
2603        /**
2604         * The degrees rotation around the vertical axis through the pivot point.
2605         */
2606        @ViewDebug.ExportedProperty
2607        float mRotationY = 0f;
2608
2609        /**
2610         * The degrees rotation around the horizontal axis through the pivot point.
2611         */
2612        @ViewDebug.ExportedProperty
2613        float mRotationX = 0f;
2614
2615        /**
2616         * The degrees rotation around the pivot point.
2617         */
2618        @ViewDebug.ExportedProperty
2619        float mRotation = 0f;
2620
2621        /**
2622         * The amount of translation of the object away from its left property (post-layout).
2623         */
2624        @ViewDebug.ExportedProperty
2625        float mTranslationX = 0f;
2626
2627        /**
2628         * The amount of translation of the object away from its top property (post-layout).
2629         */
2630        @ViewDebug.ExportedProperty
2631        float mTranslationY = 0f;
2632
2633        /**
2634         * The amount of scale in the x direction around the pivot point. A
2635         * value of 1 means no scaling is applied.
2636         */
2637        @ViewDebug.ExportedProperty
2638        float mScaleX = 1f;
2639
2640        /**
2641         * The amount of scale in the y direction around the pivot point. A
2642         * value of 1 means no scaling is applied.
2643         */
2644        @ViewDebug.ExportedProperty
2645        float mScaleY = 1f;
2646
2647        /**
2648         * The x location of the point around which the view is rotated and scaled.
2649         */
2650        @ViewDebug.ExportedProperty
2651        float mPivotX = 0f;
2652
2653        /**
2654         * The y location of the point around which the view is rotated and scaled.
2655         */
2656        @ViewDebug.ExportedProperty
2657        float mPivotY = 0f;
2658
2659        /**
2660         * The opacity of the View. This is a value from 0 to 1, where 0 means
2661         * completely transparent and 1 means completely opaque.
2662         */
2663        @ViewDebug.ExportedProperty
2664        float mAlpha = 1f;
2665    }
2666
2667    TransformationInfo mTransformationInfo;
2668
2669    private boolean mLastIsOpaque;
2670
2671    /**
2672     * Convenience value to check for float values that are close enough to zero to be considered
2673     * zero.
2674     */
2675    private static final float NONZERO_EPSILON = .001f;
2676
2677    /**
2678     * The distance in pixels from the left edge of this view's parent
2679     * to the left edge of this view.
2680     * {@hide}
2681     */
2682    @ViewDebug.ExportedProperty(category = "layout")
2683    protected int mLeft;
2684    /**
2685     * The distance in pixels from the left edge of this view's parent
2686     * to the right edge of this view.
2687     * {@hide}
2688     */
2689    @ViewDebug.ExportedProperty(category = "layout")
2690    protected int mRight;
2691    /**
2692     * The distance in pixels from the top edge of this view's parent
2693     * to the top edge of this view.
2694     * {@hide}
2695     */
2696    @ViewDebug.ExportedProperty(category = "layout")
2697    protected int mTop;
2698    /**
2699     * The distance in pixels from the top edge of this view's parent
2700     * to the bottom edge of this view.
2701     * {@hide}
2702     */
2703    @ViewDebug.ExportedProperty(category = "layout")
2704    protected int mBottom;
2705
2706    /**
2707     * The offset, in pixels, by which the content of this view is scrolled
2708     * horizontally.
2709     * {@hide}
2710     */
2711    @ViewDebug.ExportedProperty(category = "scrolling")
2712    protected int mScrollX;
2713    /**
2714     * The offset, in pixels, by which the content of this view is scrolled
2715     * vertically.
2716     * {@hide}
2717     */
2718    @ViewDebug.ExportedProperty(category = "scrolling")
2719    protected int mScrollY;
2720
2721    /**
2722     * The left padding in pixels, that is the distance in pixels between the
2723     * left edge of this view and the left edge of its content.
2724     * {@hide}
2725     */
2726    @ViewDebug.ExportedProperty(category = "padding")
2727    protected int mPaddingLeft;
2728    /**
2729     * The right padding in pixels, that is the distance in pixels between the
2730     * right edge of this view and the right edge of its content.
2731     * {@hide}
2732     */
2733    @ViewDebug.ExportedProperty(category = "padding")
2734    protected int mPaddingRight;
2735    /**
2736     * The top padding in pixels, that is the distance in pixels between the
2737     * top edge of this view and the top edge of its content.
2738     * {@hide}
2739     */
2740    @ViewDebug.ExportedProperty(category = "padding")
2741    protected int mPaddingTop;
2742    /**
2743     * The bottom padding in pixels, that is the distance in pixels between the
2744     * bottom edge of this view and the bottom edge of its content.
2745     * {@hide}
2746     */
2747    @ViewDebug.ExportedProperty(category = "padding")
2748    protected int mPaddingBottom;
2749
2750    /**
2751     * The layout insets in pixels, that is the distance in pixels between the
2752     * visible edges of this view its bounds.
2753     */
2754    private Insets mLayoutInsets;
2755
2756    /**
2757     * Briefly describes the view and is primarily used for accessibility support.
2758     */
2759    private CharSequence mContentDescription;
2760
2761    /**
2762     * Cache the paddingRight set by the user to append to the scrollbar's size.
2763     *
2764     * @hide
2765     */
2766    @ViewDebug.ExportedProperty(category = "padding")
2767    protected int mUserPaddingRight;
2768
2769    /**
2770     * Cache the paddingBottom set by the user to append to the scrollbar's size.
2771     *
2772     * @hide
2773     */
2774    @ViewDebug.ExportedProperty(category = "padding")
2775    protected int mUserPaddingBottom;
2776
2777    /**
2778     * Cache the paddingLeft set by the user to append to the scrollbar's size.
2779     *
2780     * @hide
2781     */
2782    @ViewDebug.ExportedProperty(category = "padding")
2783    protected int mUserPaddingLeft;
2784
2785    /**
2786     * Cache the paddingStart set by the user to append to the scrollbar's size.
2787     *
2788     */
2789    @ViewDebug.ExportedProperty(category = "padding")
2790    int mUserPaddingStart;
2791
2792    /**
2793     * Cache the paddingEnd set by the user to append to the scrollbar's size.
2794     *
2795     */
2796    @ViewDebug.ExportedProperty(category = "padding")
2797    int mUserPaddingEnd;
2798
2799    /**
2800     * Whether a left padding has been defined during layout inflation.
2801     *
2802     * @hide
2803     */
2804    boolean mUserPaddingLeftDefined = false;
2805
2806    /**
2807     * Whether a right padding has been defined during layout inflation.
2808     *
2809     * @hide
2810     */
2811    boolean mUserPaddingRightDefined = false;
2812
2813    /**
2814     * Default undefined padding
2815     */
2816    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
2817
2818    /**
2819     * @hide
2820     */
2821    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
2822    /**
2823     * @hide
2824     */
2825    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
2826
2827    private Drawable mBackground;
2828
2829    private int mBackgroundResource;
2830    private boolean mBackgroundSizeChanged;
2831
2832    static class ListenerInfo {
2833        /**
2834         * Listener used to dispatch focus change events.
2835         * This field should be made private, so it is hidden from the SDK.
2836         * {@hide}
2837         */
2838        protected OnFocusChangeListener mOnFocusChangeListener;
2839
2840        /**
2841         * Listeners for layout change events.
2842         */
2843        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
2844
2845        /**
2846         * Listeners for attach events.
2847         */
2848        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
2849
2850        /**
2851         * Listener used to dispatch click events.
2852         * This field should be made private, so it is hidden from the SDK.
2853         * {@hide}
2854         */
2855        public OnClickListener mOnClickListener;
2856
2857        /**
2858         * Listener used to dispatch long click events.
2859         * This field should be made private, so it is hidden from the SDK.
2860         * {@hide}
2861         */
2862        protected OnLongClickListener mOnLongClickListener;
2863
2864        /**
2865         * Listener used to build the context menu.
2866         * This field should be made private, so it is hidden from the SDK.
2867         * {@hide}
2868         */
2869        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
2870
2871        private OnKeyListener mOnKeyListener;
2872
2873        private OnTouchListener mOnTouchListener;
2874
2875        private OnHoverListener mOnHoverListener;
2876
2877        private OnGenericMotionListener mOnGenericMotionListener;
2878
2879        private OnDragListener mOnDragListener;
2880
2881        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
2882    }
2883
2884    ListenerInfo mListenerInfo;
2885
2886    /**
2887     * The application environment this view lives in.
2888     * This field should be made private, so it is hidden from the SDK.
2889     * {@hide}
2890     */
2891    protected Context mContext;
2892
2893    private final Resources mResources;
2894
2895    private ScrollabilityCache mScrollCache;
2896
2897    private int[] mDrawableState = null;
2898
2899    /**
2900     * Set to true when drawing cache is enabled and cannot be created.
2901     *
2902     * @hide
2903     */
2904    public boolean mCachingFailed;
2905
2906    private Bitmap mDrawingCache;
2907    private Bitmap mUnscaledDrawingCache;
2908    private HardwareLayer mHardwareLayer;
2909    DisplayList mDisplayList;
2910
2911    /**
2912     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
2913     * the user may specify which view to go to next.
2914     */
2915    private int mNextFocusLeftId = View.NO_ID;
2916
2917    /**
2918     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
2919     * the user may specify which view to go to next.
2920     */
2921    private int mNextFocusRightId = View.NO_ID;
2922
2923    /**
2924     * When this view has focus and the next focus is {@link #FOCUS_UP},
2925     * the user may specify which view to go to next.
2926     */
2927    private int mNextFocusUpId = View.NO_ID;
2928
2929    /**
2930     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
2931     * the user may specify which view to go to next.
2932     */
2933    private int mNextFocusDownId = View.NO_ID;
2934
2935    /**
2936     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
2937     * the user may specify which view to go to next.
2938     */
2939    int mNextFocusForwardId = View.NO_ID;
2940
2941    private CheckForLongPress mPendingCheckForLongPress;
2942    private CheckForTap mPendingCheckForTap = null;
2943    private PerformClick mPerformClick;
2944    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
2945
2946    private UnsetPressedState mUnsetPressedState;
2947
2948    /**
2949     * Whether the long press's action has been invoked.  The tap's action is invoked on the
2950     * up event while a long press is invoked as soon as the long press duration is reached, so
2951     * a long press could be performed before the tap is checked, in which case the tap's action
2952     * should not be invoked.
2953     */
2954    private boolean mHasPerformedLongPress;
2955
2956    /**
2957     * The minimum height of the view. We'll try our best to have the height
2958     * of this view to at least this amount.
2959     */
2960    @ViewDebug.ExportedProperty(category = "measurement")
2961    private int mMinHeight;
2962
2963    /**
2964     * The minimum width of the view. We'll try our best to have the width
2965     * of this view to at least this amount.
2966     */
2967    @ViewDebug.ExportedProperty(category = "measurement")
2968    private int mMinWidth;
2969
2970    /**
2971     * The delegate to handle touch events that are physically in this view
2972     * but should be handled by another view.
2973     */
2974    private TouchDelegate mTouchDelegate = null;
2975
2976    /**
2977     * Solid color to use as a background when creating the drawing cache. Enables
2978     * the cache to use 16 bit bitmaps instead of 32 bit.
2979     */
2980    private int mDrawingCacheBackgroundColor = 0;
2981
2982    /**
2983     * Special tree observer used when mAttachInfo is null.
2984     */
2985    private ViewTreeObserver mFloatingTreeObserver;
2986
2987    /**
2988     * Cache the touch slop from the context that created the view.
2989     */
2990    private int mTouchSlop;
2991
2992    /**
2993     * Object that handles automatic animation of view properties.
2994     */
2995    private ViewPropertyAnimator mAnimator = null;
2996
2997    /**
2998     * Flag indicating that a drag can cross window boundaries.  When
2999     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3000     * with this flag set, all visible applications will be able to participate
3001     * in the drag operation and receive the dragged content.
3002     *
3003     * @hide
3004     */
3005    public static final int DRAG_FLAG_GLOBAL = 1;
3006
3007    /**
3008     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3009     */
3010    private float mVerticalScrollFactor;
3011
3012    /**
3013     * Position of the vertical scroll bar.
3014     */
3015    private int mVerticalScrollbarPosition;
3016
3017    /**
3018     * Position the scroll bar at the default position as determined by the system.
3019     */
3020    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3021
3022    /**
3023     * Position the scroll bar along the left edge.
3024     */
3025    public static final int SCROLLBAR_POSITION_LEFT = 1;
3026
3027    /**
3028     * Position the scroll bar along the right edge.
3029     */
3030    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3031
3032    /**
3033     * Indicates that the view does not have a layer.
3034     *
3035     * @see #getLayerType()
3036     * @see #setLayerType(int, android.graphics.Paint)
3037     * @see #LAYER_TYPE_SOFTWARE
3038     * @see #LAYER_TYPE_HARDWARE
3039     */
3040    public static final int LAYER_TYPE_NONE = 0;
3041
3042    /**
3043     * <p>Indicates that the view has a software layer. A software layer is backed
3044     * by a bitmap and causes the view to be rendered using Android's software
3045     * rendering pipeline, even if hardware acceleration is enabled.</p>
3046     *
3047     * <p>Software layers have various usages:</p>
3048     * <p>When the application is not using hardware acceleration, a software layer
3049     * is useful to apply a specific color filter and/or blending mode and/or
3050     * translucency to a view and all its children.</p>
3051     * <p>When the application is using hardware acceleration, a software layer
3052     * is useful to render drawing primitives not supported by the hardware
3053     * accelerated pipeline. It can also be used to cache a complex view tree
3054     * into a texture and reduce the complexity of drawing operations. For instance,
3055     * when animating a complex view tree with a translation, a software layer can
3056     * be used to render the view tree only once.</p>
3057     * <p>Software layers should be avoided when the affected view tree updates
3058     * often. Every update will require to re-render the software layer, which can
3059     * potentially be slow (particularly when hardware acceleration is turned on
3060     * since the layer will have to be uploaded into a hardware texture after every
3061     * update.)</p>
3062     *
3063     * @see #getLayerType()
3064     * @see #setLayerType(int, android.graphics.Paint)
3065     * @see #LAYER_TYPE_NONE
3066     * @see #LAYER_TYPE_HARDWARE
3067     */
3068    public static final int LAYER_TYPE_SOFTWARE = 1;
3069
3070    /**
3071     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3072     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3073     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3074     * rendering pipeline, but only if hardware acceleration is turned on for the
3075     * view hierarchy. When hardware acceleration is turned off, hardware layers
3076     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3077     *
3078     * <p>A hardware layer is useful to apply a specific color filter and/or
3079     * blending mode and/or translucency to a view and all its children.</p>
3080     * <p>A hardware layer can be used to cache a complex view tree into a
3081     * texture and reduce the complexity of drawing operations. For instance,
3082     * when animating a complex view tree with a translation, a hardware layer can
3083     * be used to render the view tree only once.</p>
3084     * <p>A hardware layer can also be used to increase the rendering quality when
3085     * rotation transformations are applied on a view. It can also be used to
3086     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3087     *
3088     * @see #getLayerType()
3089     * @see #setLayerType(int, android.graphics.Paint)
3090     * @see #LAYER_TYPE_NONE
3091     * @see #LAYER_TYPE_SOFTWARE
3092     */
3093    public static final int LAYER_TYPE_HARDWARE = 2;
3094
3095    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3096            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3097            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3098            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3099    })
3100    int mLayerType = LAYER_TYPE_NONE;
3101    Paint mLayerPaint;
3102    Rect mLocalDirtyRect;
3103
3104    /**
3105     * Set to true when the view is sending hover accessibility events because it
3106     * is the innermost hovered view.
3107     */
3108    private boolean mSendingHoverAccessibilityEvents;
3109
3110    /**
3111     * Delegate for injecting accessiblity functionality.
3112     */
3113    AccessibilityDelegate mAccessibilityDelegate;
3114
3115    /**
3116     * Consistency verifier for debugging purposes.
3117     * @hide
3118     */
3119    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3120            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3121                    new InputEventConsistencyVerifier(this, 0) : null;
3122
3123    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3124
3125    /**
3126     * Simple constructor to use when creating a view from code.
3127     *
3128     * @param context The Context the view is running in, through which it can
3129     *        access the current theme, resources, etc.
3130     */
3131    public View(Context context) {
3132        mContext = context;
3133        mResources = context != null ? context.getResources() : null;
3134        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3135        // Set layout and text direction defaults
3136        mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3137                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3138                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3139                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3140        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3141        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3142        mUserPaddingStart = UNDEFINED_PADDING;
3143        mUserPaddingEnd = UNDEFINED_PADDING;
3144    }
3145
3146    /**
3147     * Constructor that is called when inflating a view from XML. This is called
3148     * when a view is being constructed from an XML file, supplying attributes
3149     * that were specified in the XML file. This version uses a default style of
3150     * 0, so the only attribute values applied are those in the Context's Theme
3151     * and the given AttributeSet.
3152     *
3153     * <p>
3154     * The method onFinishInflate() will be called after all children have been
3155     * added.
3156     *
3157     * @param context The Context the view is running in, through which it can
3158     *        access the current theme, resources, etc.
3159     * @param attrs The attributes of the XML tag that is inflating the view.
3160     * @see #View(Context, AttributeSet, int)
3161     */
3162    public View(Context context, AttributeSet attrs) {
3163        this(context, attrs, 0);
3164    }
3165
3166    /**
3167     * Perform inflation from XML and apply a class-specific base style. This
3168     * constructor of View allows subclasses to use their own base style when
3169     * they are inflating. For example, a Button class's constructor would call
3170     * this version of the super class constructor and supply
3171     * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
3172     * the theme's button style to modify all of the base view attributes (in
3173     * particular its background) as well as the Button class's attributes.
3174     *
3175     * @param context The Context the view is running in, through which it can
3176     *        access the current theme, resources, etc.
3177     * @param attrs The attributes of the XML tag that is inflating the view.
3178     * @param defStyle The default style to apply to this view. If 0, no style
3179     *        will be applied (beyond what is included in the theme). This may
3180     *        either be an attribute resource, whose value will be retrieved
3181     *        from the current theme, or an explicit style resource.
3182     * @see #View(Context, AttributeSet)
3183     */
3184    public View(Context context, AttributeSet attrs, int defStyle) {
3185        this(context);
3186
3187        TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
3188                defStyle, 0);
3189
3190        Drawable background = null;
3191
3192        int leftPadding = -1;
3193        int topPadding = -1;
3194        int rightPadding = -1;
3195        int bottomPadding = -1;
3196        int startPadding = UNDEFINED_PADDING;
3197        int endPadding = UNDEFINED_PADDING;
3198
3199        int padding = -1;
3200
3201        int viewFlagValues = 0;
3202        int viewFlagMasks = 0;
3203
3204        boolean setScrollContainer = false;
3205
3206        int x = 0;
3207        int y = 0;
3208
3209        float tx = 0;
3210        float ty = 0;
3211        float rotation = 0;
3212        float rotationX = 0;
3213        float rotationY = 0;
3214        float sx = 1f;
3215        float sy = 1f;
3216        boolean transformSet = false;
3217
3218        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3219        int overScrollMode = mOverScrollMode;
3220        boolean initializeScrollbars = false;
3221
3222        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3223
3224        final int N = a.getIndexCount();
3225        for (int i = 0; i < N; i++) {
3226            int attr = a.getIndex(i);
3227            switch (attr) {
3228                case com.android.internal.R.styleable.View_background:
3229                    background = a.getDrawable(attr);
3230                    break;
3231                case com.android.internal.R.styleable.View_padding:
3232                    padding = a.getDimensionPixelSize(attr, -1);
3233                    mUserPaddingLeftDefined = true;
3234                    mUserPaddingRightDefined = true;
3235                    break;
3236                 case com.android.internal.R.styleable.View_paddingLeft:
3237                    leftPadding = a.getDimensionPixelSize(attr, -1);
3238                    mUserPaddingLeftDefined = true;
3239                    break;
3240                case com.android.internal.R.styleable.View_paddingTop:
3241                    topPadding = a.getDimensionPixelSize(attr, -1);
3242                    break;
3243                case com.android.internal.R.styleable.View_paddingRight:
3244                    rightPadding = a.getDimensionPixelSize(attr, -1);
3245                    mUserPaddingRightDefined = true;
3246                    break;
3247                case com.android.internal.R.styleable.View_paddingBottom:
3248                    bottomPadding = a.getDimensionPixelSize(attr, -1);
3249                    break;
3250                case com.android.internal.R.styleable.View_paddingStart:
3251                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3252                    break;
3253                case com.android.internal.R.styleable.View_paddingEnd:
3254                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3255                    break;
3256                case com.android.internal.R.styleable.View_scrollX:
3257                    x = a.getDimensionPixelOffset(attr, 0);
3258                    break;
3259                case com.android.internal.R.styleable.View_scrollY:
3260                    y = a.getDimensionPixelOffset(attr, 0);
3261                    break;
3262                case com.android.internal.R.styleable.View_alpha:
3263                    setAlpha(a.getFloat(attr, 1f));
3264                    break;
3265                case com.android.internal.R.styleable.View_transformPivotX:
3266                    setPivotX(a.getDimensionPixelOffset(attr, 0));
3267                    break;
3268                case com.android.internal.R.styleable.View_transformPivotY:
3269                    setPivotY(a.getDimensionPixelOffset(attr, 0));
3270                    break;
3271                case com.android.internal.R.styleable.View_translationX:
3272                    tx = a.getDimensionPixelOffset(attr, 0);
3273                    transformSet = true;
3274                    break;
3275                case com.android.internal.R.styleable.View_translationY:
3276                    ty = a.getDimensionPixelOffset(attr, 0);
3277                    transformSet = true;
3278                    break;
3279                case com.android.internal.R.styleable.View_rotation:
3280                    rotation = a.getFloat(attr, 0);
3281                    transformSet = true;
3282                    break;
3283                case com.android.internal.R.styleable.View_rotationX:
3284                    rotationX = a.getFloat(attr, 0);
3285                    transformSet = true;
3286                    break;
3287                case com.android.internal.R.styleable.View_rotationY:
3288                    rotationY = a.getFloat(attr, 0);
3289                    transformSet = true;
3290                    break;
3291                case com.android.internal.R.styleable.View_scaleX:
3292                    sx = a.getFloat(attr, 1f);
3293                    transformSet = true;
3294                    break;
3295                case com.android.internal.R.styleable.View_scaleY:
3296                    sy = a.getFloat(attr, 1f);
3297                    transformSet = true;
3298                    break;
3299                case com.android.internal.R.styleable.View_id:
3300                    mID = a.getResourceId(attr, NO_ID);
3301                    break;
3302                case com.android.internal.R.styleable.View_tag:
3303                    mTag = a.getText(attr);
3304                    break;
3305                case com.android.internal.R.styleable.View_fitsSystemWindows:
3306                    if (a.getBoolean(attr, false)) {
3307                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
3308                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3309                    }
3310                    break;
3311                case com.android.internal.R.styleable.View_focusable:
3312                    if (a.getBoolean(attr, false)) {
3313                        viewFlagValues |= FOCUSABLE;
3314                        viewFlagMasks |= FOCUSABLE_MASK;
3315                    }
3316                    break;
3317                case com.android.internal.R.styleable.View_focusableInTouchMode:
3318                    if (a.getBoolean(attr, false)) {
3319                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3320                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3321                    }
3322                    break;
3323                case com.android.internal.R.styleable.View_clickable:
3324                    if (a.getBoolean(attr, false)) {
3325                        viewFlagValues |= CLICKABLE;
3326                        viewFlagMasks |= CLICKABLE;
3327                    }
3328                    break;
3329                case com.android.internal.R.styleable.View_longClickable:
3330                    if (a.getBoolean(attr, false)) {
3331                        viewFlagValues |= LONG_CLICKABLE;
3332                        viewFlagMasks |= LONG_CLICKABLE;
3333                    }
3334                    break;
3335                case com.android.internal.R.styleable.View_saveEnabled:
3336                    if (!a.getBoolean(attr, true)) {
3337                        viewFlagValues |= SAVE_DISABLED;
3338                        viewFlagMasks |= SAVE_DISABLED_MASK;
3339                    }
3340                    break;
3341                case com.android.internal.R.styleable.View_duplicateParentState:
3342                    if (a.getBoolean(attr, false)) {
3343                        viewFlagValues |= DUPLICATE_PARENT_STATE;
3344                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
3345                    }
3346                    break;
3347                case com.android.internal.R.styleable.View_visibility:
3348                    final int visibility = a.getInt(attr, 0);
3349                    if (visibility != 0) {
3350                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
3351                        viewFlagMasks |= VISIBILITY_MASK;
3352                    }
3353                    break;
3354                case com.android.internal.R.styleable.View_layoutDirection:
3355                    // Clear any layout direction flags (included resolved bits) already set
3356                    mPrivateFlags2 &= ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3357                    // Set the layout direction flags depending on the value of the attribute
3358                    final int layoutDirection = a.getInt(attr, -1);
3359                    final int value = (layoutDirection != -1) ?
3360                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3361                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3362                    break;
3363                case com.android.internal.R.styleable.View_drawingCacheQuality:
3364                    final int cacheQuality = a.getInt(attr, 0);
3365                    if (cacheQuality != 0) {
3366                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3367                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3368                    }
3369                    break;
3370                case com.android.internal.R.styleable.View_contentDescription:
3371                    setContentDescription(a.getString(attr));
3372                    break;
3373                case com.android.internal.R.styleable.View_soundEffectsEnabled:
3374                    if (!a.getBoolean(attr, true)) {
3375                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3376                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3377                    }
3378                    break;
3379                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3380                    if (!a.getBoolean(attr, true)) {
3381                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3382                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3383                    }
3384                    break;
3385                case R.styleable.View_scrollbars:
3386                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3387                    if (scrollbars != SCROLLBARS_NONE) {
3388                        viewFlagValues |= scrollbars;
3389                        viewFlagMasks |= SCROLLBARS_MASK;
3390                        initializeScrollbars = true;
3391                    }
3392                    break;
3393                //noinspection deprecation
3394                case R.styleable.View_fadingEdge:
3395                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3396                        // Ignore the attribute starting with ICS
3397                        break;
3398                    }
3399                    // With builds < ICS, fall through and apply fading edges
3400                case R.styleable.View_requiresFadingEdge:
3401                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3402                    if (fadingEdge != FADING_EDGE_NONE) {
3403                        viewFlagValues |= fadingEdge;
3404                        viewFlagMasks |= FADING_EDGE_MASK;
3405                        initializeFadingEdge(a);
3406                    }
3407                    break;
3408                case R.styleable.View_scrollbarStyle:
3409                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3410                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3411                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3412                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3413                    }
3414                    break;
3415                case R.styleable.View_isScrollContainer:
3416                    setScrollContainer = true;
3417                    if (a.getBoolean(attr, false)) {
3418                        setScrollContainer(true);
3419                    }
3420                    break;
3421                case com.android.internal.R.styleable.View_keepScreenOn:
3422                    if (a.getBoolean(attr, false)) {
3423                        viewFlagValues |= KEEP_SCREEN_ON;
3424                        viewFlagMasks |= KEEP_SCREEN_ON;
3425                    }
3426                    break;
3427                case R.styleable.View_filterTouchesWhenObscured:
3428                    if (a.getBoolean(attr, false)) {
3429                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3430                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3431                    }
3432                    break;
3433                case R.styleable.View_nextFocusLeft:
3434                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3435                    break;
3436                case R.styleable.View_nextFocusRight:
3437                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3438                    break;
3439                case R.styleable.View_nextFocusUp:
3440                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3441                    break;
3442                case R.styleable.View_nextFocusDown:
3443                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3444                    break;
3445                case R.styleable.View_nextFocusForward:
3446                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3447                    break;
3448                case R.styleable.View_minWidth:
3449                    mMinWidth = a.getDimensionPixelSize(attr, 0);
3450                    break;
3451                case R.styleable.View_minHeight:
3452                    mMinHeight = a.getDimensionPixelSize(attr, 0);
3453                    break;
3454                case R.styleable.View_onClick:
3455                    if (context.isRestricted()) {
3456                        throw new IllegalStateException("The android:onClick attribute cannot "
3457                                + "be used within a restricted context");
3458                    }
3459
3460                    final String handlerName = a.getString(attr);
3461                    if (handlerName != null) {
3462                        setOnClickListener(new OnClickListener() {
3463                            private Method mHandler;
3464
3465                            public void onClick(View v) {
3466                                if (mHandler == null) {
3467                                    try {
3468                                        mHandler = getContext().getClass().getMethod(handlerName,
3469                                                View.class);
3470                                    } catch (NoSuchMethodException e) {
3471                                        int id = getId();
3472                                        String idText = id == NO_ID ? "" : " with id '"
3473                                                + getContext().getResources().getResourceEntryName(
3474                                                    id) + "'";
3475                                        throw new IllegalStateException("Could not find a method " +
3476                                                handlerName + "(View) in the activity "
3477                                                + getContext().getClass() + " for onClick handler"
3478                                                + " on view " + View.this.getClass() + idText, e);
3479                                    }
3480                                }
3481
3482                                try {
3483                                    mHandler.invoke(getContext(), View.this);
3484                                } catch (IllegalAccessException e) {
3485                                    throw new IllegalStateException("Could not execute non "
3486                                            + "public method of the activity", e);
3487                                } catch (InvocationTargetException e) {
3488                                    throw new IllegalStateException("Could not execute "
3489                                            + "method of the activity", e);
3490                                }
3491                            }
3492                        });
3493                    }
3494                    break;
3495                case R.styleable.View_overScrollMode:
3496                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3497                    break;
3498                case R.styleable.View_verticalScrollbarPosition:
3499                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3500                    break;
3501                case R.styleable.View_layerType:
3502                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3503                    break;
3504                case R.styleable.View_textDirection:
3505                    // Clear any text direction flag already set
3506                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
3507                    // Set the text direction flags depending on the value of the attribute
3508                    final int textDirection = a.getInt(attr, -1);
3509                    if (textDirection != -1) {
3510                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
3511                    }
3512                    break;
3513                case R.styleable.View_textAlignment:
3514                    // Clear any text alignment flag already set
3515                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
3516                    // Set the text alignment flag depending on the value of the attribute
3517                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
3518                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
3519                    break;
3520                case R.styleable.View_importantForAccessibility:
3521                    setImportantForAccessibility(a.getInt(attr,
3522                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
3523                    break;
3524            }
3525        }
3526
3527        setOverScrollMode(overScrollMode);
3528
3529        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
3530        // the resolved layout direction). Those cached values will be used later during padding
3531        // resolution.
3532        mUserPaddingStart = startPadding;
3533        mUserPaddingEnd = endPadding;
3534
3535        if (background != null) {
3536            setBackground(background);
3537        }
3538
3539        if (padding >= 0) {
3540            leftPadding = padding;
3541            topPadding = padding;
3542            rightPadding = padding;
3543            bottomPadding = padding;
3544        }
3545
3546        // If the user specified the padding (either with android:padding or
3547        // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
3548        // use the default padding or the padding from the background drawable
3549        // (stored at this point in mPadding*)
3550        internalSetPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
3551                topPadding >= 0 ? topPadding : mPaddingTop,
3552                rightPadding >= 0 ? rightPadding : mPaddingRight,
3553                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
3554
3555        if (viewFlagMasks != 0) {
3556            setFlags(viewFlagValues, viewFlagMasks);
3557        }
3558
3559        if (initializeScrollbars) {
3560            initializeScrollbars(a);
3561        }
3562
3563        a.recycle();
3564
3565        // Needs to be called after mViewFlags is set
3566        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3567            recomputePadding();
3568        }
3569
3570        if (x != 0 || y != 0) {
3571            scrollTo(x, y);
3572        }
3573
3574        if (transformSet) {
3575            setTranslationX(tx);
3576            setTranslationY(ty);
3577            setRotation(rotation);
3578            setRotationX(rotationX);
3579            setRotationY(rotationY);
3580            setScaleX(sx);
3581            setScaleY(sy);
3582        }
3583
3584        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
3585            setScrollContainer(true);
3586        }
3587
3588        computeOpaqueFlags();
3589    }
3590
3591    /**
3592     * Non-public constructor for use in testing
3593     */
3594    View() {
3595        mResources = null;
3596    }
3597
3598    public String toString() {
3599        StringBuilder out = new StringBuilder(128);
3600        out.append(getClass().getName());
3601        out.append('{');
3602        out.append(Integer.toHexString(System.identityHashCode(this)));
3603        out.append(' ');
3604        switch (mViewFlags&VISIBILITY_MASK) {
3605            case VISIBLE: out.append('V'); break;
3606            case INVISIBLE: out.append('I'); break;
3607            case GONE: out.append('G'); break;
3608            default: out.append('.'); break;
3609        }
3610        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
3611        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
3612        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
3613        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
3614        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
3615        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
3616        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
3617        out.append(' ');
3618        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
3619        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
3620        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
3621        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
3622            out.append('p');
3623        } else {
3624            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
3625        }
3626        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
3627        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
3628        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
3629        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
3630        out.append(' ');
3631        out.append(mLeft);
3632        out.append(',');
3633        out.append(mTop);
3634        out.append('-');
3635        out.append(mRight);
3636        out.append(',');
3637        out.append(mBottom);
3638        final int id = getId();
3639        if (id != NO_ID) {
3640            out.append(" #");
3641            out.append(Integer.toHexString(id));
3642            final Resources r = mResources;
3643            if (id != 0 && r != null) {
3644                try {
3645                    String pkgname;
3646                    switch (id&0xff000000) {
3647                        case 0x7f000000:
3648                            pkgname="app";
3649                            break;
3650                        case 0x01000000:
3651                            pkgname="android";
3652                            break;
3653                        default:
3654                            pkgname = r.getResourcePackageName(id);
3655                            break;
3656                    }
3657                    String typename = r.getResourceTypeName(id);
3658                    String entryname = r.getResourceEntryName(id);
3659                    out.append(" ");
3660                    out.append(pkgname);
3661                    out.append(":");
3662                    out.append(typename);
3663                    out.append("/");
3664                    out.append(entryname);
3665                } catch (Resources.NotFoundException e) {
3666                }
3667            }
3668        }
3669        out.append("}");
3670        return out.toString();
3671    }
3672
3673    /**
3674     * <p>
3675     * Initializes the fading edges from a given set of styled attributes. This
3676     * method should be called by subclasses that need fading edges and when an
3677     * instance of these subclasses is created programmatically rather than
3678     * being inflated from XML. This method is automatically called when the XML
3679     * is inflated.
3680     * </p>
3681     *
3682     * @param a the styled attributes set to initialize the fading edges from
3683     */
3684    protected void initializeFadingEdge(TypedArray a) {
3685        initScrollCache();
3686
3687        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
3688                R.styleable.View_fadingEdgeLength,
3689                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
3690    }
3691
3692    /**
3693     * Returns the size of the vertical faded edges used to indicate that more
3694     * content in this view is visible.
3695     *
3696     * @return The size in pixels of the vertical faded edge or 0 if vertical
3697     *         faded edges are not enabled for this view.
3698     * @attr ref android.R.styleable#View_fadingEdgeLength
3699     */
3700    public int getVerticalFadingEdgeLength() {
3701        if (isVerticalFadingEdgeEnabled()) {
3702            ScrollabilityCache cache = mScrollCache;
3703            if (cache != null) {
3704                return cache.fadingEdgeLength;
3705            }
3706        }
3707        return 0;
3708    }
3709
3710    /**
3711     * Set the size of the faded edge used to indicate that more content in this
3712     * view is available.  Will not change whether the fading edge is enabled; use
3713     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
3714     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
3715     * for the vertical or horizontal fading edges.
3716     *
3717     * @param length The size in pixels of the faded edge used to indicate that more
3718     *        content in this view is visible.
3719     */
3720    public void setFadingEdgeLength(int length) {
3721        initScrollCache();
3722        mScrollCache.fadingEdgeLength = length;
3723    }
3724
3725    /**
3726     * Returns the size of the horizontal faded edges used to indicate that more
3727     * content in this view is visible.
3728     *
3729     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
3730     *         faded edges are not enabled for this view.
3731     * @attr ref android.R.styleable#View_fadingEdgeLength
3732     */
3733    public int getHorizontalFadingEdgeLength() {
3734        if (isHorizontalFadingEdgeEnabled()) {
3735            ScrollabilityCache cache = mScrollCache;
3736            if (cache != null) {
3737                return cache.fadingEdgeLength;
3738            }
3739        }
3740        return 0;
3741    }
3742
3743    /**
3744     * Returns the width of the vertical scrollbar.
3745     *
3746     * @return The width in pixels of the vertical scrollbar or 0 if there
3747     *         is no vertical scrollbar.
3748     */
3749    public int getVerticalScrollbarWidth() {
3750        ScrollabilityCache cache = mScrollCache;
3751        if (cache != null) {
3752            ScrollBarDrawable scrollBar = cache.scrollBar;
3753            if (scrollBar != null) {
3754                int size = scrollBar.getSize(true);
3755                if (size <= 0) {
3756                    size = cache.scrollBarSize;
3757                }
3758                return size;
3759            }
3760            return 0;
3761        }
3762        return 0;
3763    }
3764
3765    /**
3766     * Returns the height of the horizontal scrollbar.
3767     *
3768     * @return The height in pixels of the horizontal scrollbar or 0 if
3769     *         there is no horizontal scrollbar.
3770     */
3771    protected int getHorizontalScrollbarHeight() {
3772        ScrollabilityCache cache = mScrollCache;
3773        if (cache != null) {
3774            ScrollBarDrawable scrollBar = cache.scrollBar;
3775            if (scrollBar != null) {
3776                int size = scrollBar.getSize(false);
3777                if (size <= 0) {
3778                    size = cache.scrollBarSize;
3779                }
3780                return size;
3781            }
3782            return 0;
3783        }
3784        return 0;
3785    }
3786
3787    /**
3788     * <p>
3789     * Initializes the scrollbars from a given set of styled attributes. This
3790     * method should be called by subclasses that need scrollbars and when an
3791     * instance of these subclasses is created programmatically rather than
3792     * being inflated from XML. This method is automatically called when the XML
3793     * is inflated.
3794     * </p>
3795     *
3796     * @param a the styled attributes set to initialize the scrollbars from
3797     */
3798    protected void initializeScrollbars(TypedArray a) {
3799        initScrollCache();
3800
3801        final ScrollabilityCache scrollabilityCache = mScrollCache;
3802
3803        if (scrollabilityCache.scrollBar == null) {
3804            scrollabilityCache.scrollBar = new ScrollBarDrawable();
3805        }
3806
3807        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
3808
3809        if (!fadeScrollbars) {
3810            scrollabilityCache.state = ScrollabilityCache.ON;
3811        }
3812        scrollabilityCache.fadeScrollBars = fadeScrollbars;
3813
3814
3815        scrollabilityCache.scrollBarFadeDuration = a.getInt(
3816                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
3817                        .getScrollBarFadeDuration());
3818        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
3819                R.styleable.View_scrollbarDefaultDelayBeforeFade,
3820                ViewConfiguration.getScrollDefaultDelay());
3821
3822
3823        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
3824                com.android.internal.R.styleable.View_scrollbarSize,
3825                ViewConfiguration.get(mContext).getScaledScrollBarSize());
3826
3827        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
3828        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
3829
3830        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
3831        if (thumb != null) {
3832            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
3833        }
3834
3835        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
3836                false);
3837        if (alwaysDraw) {
3838            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
3839        }
3840
3841        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
3842        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
3843
3844        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
3845        if (thumb != null) {
3846            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
3847        }
3848
3849        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
3850                false);
3851        if (alwaysDraw) {
3852            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
3853        }
3854
3855        // Apply layout direction to the new Drawables if needed
3856        final int layoutDirection = getResolvedLayoutDirection();
3857        if (track != null) {
3858            track.setLayoutDirection(layoutDirection);
3859        }
3860        if (thumb != null) {
3861            thumb.setLayoutDirection(layoutDirection);
3862        }
3863
3864        // Re-apply user/background padding so that scrollbar(s) get added
3865        resolvePadding();
3866    }
3867
3868    /**
3869     * <p>
3870     * Initalizes the scrollability cache if necessary.
3871     * </p>
3872     */
3873    private void initScrollCache() {
3874        if (mScrollCache == null) {
3875            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
3876        }
3877    }
3878
3879    private ScrollabilityCache getScrollCache() {
3880        initScrollCache();
3881        return mScrollCache;
3882    }
3883
3884    /**
3885     * Set the position of the vertical scroll bar. Should be one of
3886     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
3887     * {@link #SCROLLBAR_POSITION_RIGHT}.
3888     *
3889     * @param position Where the vertical scroll bar should be positioned.
3890     */
3891    public void setVerticalScrollbarPosition(int position) {
3892        if (mVerticalScrollbarPosition != position) {
3893            mVerticalScrollbarPosition = position;
3894            computeOpaqueFlags();
3895            resolvePadding();
3896        }
3897    }
3898
3899    /**
3900     * @return The position where the vertical scroll bar will show, if applicable.
3901     * @see #setVerticalScrollbarPosition(int)
3902     */
3903    public int getVerticalScrollbarPosition() {
3904        return mVerticalScrollbarPosition;
3905    }
3906
3907    ListenerInfo getListenerInfo() {
3908        if (mListenerInfo != null) {
3909            return mListenerInfo;
3910        }
3911        mListenerInfo = new ListenerInfo();
3912        return mListenerInfo;
3913    }
3914
3915    /**
3916     * Register a callback to be invoked when focus of this view changed.
3917     *
3918     * @param l The callback that will run.
3919     */
3920    public void setOnFocusChangeListener(OnFocusChangeListener l) {
3921        getListenerInfo().mOnFocusChangeListener = l;
3922    }
3923
3924    /**
3925     * Add a listener that will be called when the bounds of the view change due to
3926     * layout processing.
3927     *
3928     * @param listener The listener that will be called when layout bounds change.
3929     */
3930    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
3931        ListenerInfo li = getListenerInfo();
3932        if (li.mOnLayoutChangeListeners == null) {
3933            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
3934        }
3935        if (!li.mOnLayoutChangeListeners.contains(listener)) {
3936            li.mOnLayoutChangeListeners.add(listener);
3937        }
3938    }
3939
3940    /**
3941     * Remove a listener for layout changes.
3942     *
3943     * @param listener The listener for layout bounds change.
3944     */
3945    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
3946        ListenerInfo li = mListenerInfo;
3947        if (li == null || li.mOnLayoutChangeListeners == null) {
3948            return;
3949        }
3950        li.mOnLayoutChangeListeners.remove(listener);
3951    }
3952
3953    /**
3954     * Add a listener for attach state changes.
3955     *
3956     * This listener will be called whenever this view is attached or detached
3957     * from a window. Remove the listener using
3958     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
3959     *
3960     * @param listener Listener to attach
3961     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
3962     */
3963    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
3964        ListenerInfo li = getListenerInfo();
3965        if (li.mOnAttachStateChangeListeners == null) {
3966            li.mOnAttachStateChangeListeners
3967                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
3968        }
3969        li.mOnAttachStateChangeListeners.add(listener);
3970    }
3971
3972    /**
3973     * Remove a listener for attach state changes. The listener will receive no further
3974     * notification of window attach/detach events.
3975     *
3976     * @param listener Listener to remove
3977     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
3978     */
3979    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
3980        ListenerInfo li = mListenerInfo;
3981        if (li == null || li.mOnAttachStateChangeListeners == null) {
3982            return;
3983        }
3984        li.mOnAttachStateChangeListeners.remove(listener);
3985    }
3986
3987    /**
3988     * Returns the focus-change callback registered for this view.
3989     *
3990     * @return The callback, or null if one is not registered.
3991     */
3992    public OnFocusChangeListener getOnFocusChangeListener() {
3993        ListenerInfo li = mListenerInfo;
3994        return li != null ? li.mOnFocusChangeListener : null;
3995    }
3996
3997    /**
3998     * Register a callback to be invoked when this view is clicked. If this view is not
3999     * clickable, it becomes clickable.
4000     *
4001     * @param l The callback that will run
4002     *
4003     * @see #setClickable(boolean)
4004     */
4005    public void setOnClickListener(OnClickListener l) {
4006        if (!isClickable()) {
4007            setClickable(true);
4008        }
4009        getListenerInfo().mOnClickListener = l;
4010    }
4011
4012    /**
4013     * Return whether this view has an attached OnClickListener.  Returns
4014     * true if there is a listener, false if there is none.
4015     */
4016    public boolean hasOnClickListeners() {
4017        ListenerInfo li = mListenerInfo;
4018        return (li != null && li.mOnClickListener != null);
4019    }
4020
4021    /**
4022     * Register a callback to be invoked when this view is clicked and held. If this view is not
4023     * long clickable, it becomes long clickable.
4024     *
4025     * @param l The callback that will run
4026     *
4027     * @see #setLongClickable(boolean)
4028     */
4029    public void setOnLongClickListener(OnLongClickListener l) {
4030        if (!isLongClickable()) {
4031            setLongClickable(true);
4032        }
4033        getListenerInfo().mOnLongClickListener = l;
4034    }
4035
4036    /**
4037     * Register a callback to be invoked when the context menu for this view is
4038     * being built. If this view is not long clickable, it becomes long clickable.
4039     *
4040     * @param l The callback that will run
4041     *
4042     */
4043    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4044        if (!isLongClickable()) {
4045            setLongClickable(true);
4046        }
4047        getListenerInfo().mOnCreateContextMenuListener = l;
4048    }
4049
4050    /**
4051     * Call this view's OnClickListener, if it is defined.  Performs all normal
4052     * actions associated with clicking: reporting accessibility event, playing
4053     * a sound, etc.
4054     *
4055     * @return True there was an assigned OnClickListener that was called, false
4056     *         otherwise is returned.
4057     */
4058    public boolean performClick() {
4059        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4060
4061        ListenerInfo li = mListenerInfo;
4062        if (li != null && li.mOnClickListener != null) {
4063            playSoundEffect(SoundEffectConstants.CLICK);
4064            li.mOnClickListener.onClick(this);
4065            return true;
4066        }
4067
4068        return false;
4069    }
4070
4071    /**
4072     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
4073     * this only calls the listener, and does not do any associated clicking
4074     * actions like reporting an accessibility event.
4075     *
4076     * @return True there was an assigned OnClickListener that was called, false
4077     *         otherwise is returned.
4078     */
4079    public boolean callOnClick() {
4080        ListenerInfo li = mListenerInfo;
4081        if (li != null && li.mOnClickListener != null) {
4082            li.mOnClickListener.onClick(this);
4083            return true;
4084        }
4085        return false;
4086    }
4087
4088    /**
4089     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4090     * OnLongClickListener did not consume the event.
4091     *
4092     * @return True if one of the above receivers consumed the event, false otherwise.
4093     */
4094    public boolean performLongClick() {
4095        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4096
4097        boolean handled = false;
4098        ListenerInfo li = mListenerInfo;
4099        if (li != null && li.mOnLongClickListener != null) {
4100            handled = li.mOnLongClickListener.onLongClick(View.this);
4101        }
4102        if (!handled) {
4103            handled = showContextMenu();
4104        }
4105        if (handled) {
4106            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4107        }
4108        return handled;
4109    }
4110
4111    /**
4112     * Performs button-related actions during a touch down event.
4113     *
4114     * @param event The event.
4115     * @return True if the down was consumed.
4116     *
4117     * @hide
4118     */
4119    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4120        if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4121            if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4122                return true;
4123            }
4124        }
4125        return false;
4126    }
4127
4128    /**
4129     * Bring up the context menu for this view.
4130     *
4131     * @return Whether a context menu was displayed.
4132     */
4133    public boolean showContextMenu() {
4134        return getParent().showContextMenuForChild(this);
4135    }
4136
4137    /**
4138     * Bring up the context menu for this view, referring to the item under the specified point.
4139     *
4140     * @param x The referenced x coordinate.
4141     * @param y The referenced y coordinate.
4142     * @param metaState The keyboard modifiers that were pressed.
4143     * @return Whether a context menu was displayed.
4144     *
4145     * @hide
4146     */
4147    public boolean showContextMenu(float x, float y, int metaState) {
4148        return showContextMenu();
4149    }
4150
4151    /**
4152     * Start an action mode.
4153     *
4154     * @param callback Callback that will control the lifecycle of the action mode
4155     * @return The new action mode if it is started, null otherwise
4156     *
4157     * @see ActionMode
4158     */
4159    public ActionMode startActionMode(ActionMode.Callback callback) {
4160        ViewParent parent = getParent();
4161        if (parent == null) return null;
4162        return parent.startActionModeForChild(this, callback);
4163    }
4164
4165    /**
4166     * Register a callback to be invoked when a hardware key is pressed in this view.
4167     * Key presses in software input methods will generally not trigger the methods of
4168     * this listener.
4169     * @param l the key listener to attach to this view
4170     */
4171    public void setOnKeyListener(OnKeyListener l) {
4172        getListenerInfo().mOnKeyListener = l;
4173    }
4174
4175    /**
4176     * Register a callback to be invoked when a touch event is sent to this view.
4177     * @param l the touch listener to attach to this view
4178     */
4179    public void setOnTouchListener(OnTouchListener l) {
4180        getListenerInfo().mOnTouchListener = l;
4181    }
4182
4183    /**
4184     * Register a callback to be invoked when a generic motion event is sent to this view.
4185     * @param l the generic motion listener to attach to this view
4186     */
4187    public void setOnGenericMotionListener(OnGenericMotionListener l) {
4188        getListenerInfo().mOnGenericMotionListener = l;
4189    }
4190
4191    /**
4192     * Register a callback to be invoked when a hover event is sent to this view.
4193     * @param l the hover listener to attach to this view
4194     */
4195    public void setOnHoverListener(OnHoverListener l) {
4196        getListenerInfo().mOnHoverListener = l;
4197    }
4198
4199    /**
4200     * Register a drag event listener callback object for this View. The parameter is
4201     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4202     * View, the system calls the
4203     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4204     * @param l An implementation of {@link android.view.View.OnDragListener}.
4205     */
4206    public void setOnDragListener(OnDragListener l) {
4207        getListenerInfo().mOnDragListener = l;
4208    }
4209
4210    /**
4211     * Give this view focus. This will cause
4212     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
4213     *
4214     * Note: this does not check whether this {@link View} should get focus, it just
4215     * gives it focus no matter what.  It should only be called internally by framework
4216     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4217     *
4218     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4219     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
4220     *        focus moved when requestFocus() is called. It may not always
4221     *        apply, in which case use the default View.FOCUS_DOWN.
4222     * @param previouslyFocusedRect The rectangle of the view that had focus
4223     *        prior in this View's coordinate system.
4224     */
4225    void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
4226        if (DBG) {
4227            System.out.println(this + " requestFocus()");
4228        }
4229
4230        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4231            mPrivateFlags |= PFLAG_FOCUSED;
4232
4233            if (mParent != null) {
4234                mParent.requestChildFocus(this, this);
4235            }
4236
4237            onFocusChanged(true, direction, previouslyFocusedRect);
4238            refreshDrawableState();
4239
4240            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4241                notifyAccessibilityStateChanged();
4242            }
4243        }
4244    }
4245
4246    /**
4247     * Request that a rectangle of this view be visible on the screen,
4248     * scrolling if necessary just enough.
4249     *
4250     * <p>A View should call this if it maintains some notion of which part
4251     * of its content is interesting.  For example, a text editing view
4252     * should call this when its cursor moves.
4253     *
4254     * @param rectangle The rectangle.
4255     * @return Whether any parent scrolled.
4256     */
4257    public boolean requestRectangleOnScreen(Rect rectangle) {
4258        return requestRectangleOnScreen(rectangle, false);
4259    }
4260
4261    /**
4262     * Request that a rectangle of this view be visible on the screen,
4263     * scrolling if necessary just enough.
4264     *
4265     * <p>A View should call this if it maintains some notion of which part
4266     * of its content is interesting.  For example, a text editing view
4267     * should call this when its cursor moves.
4268     *
4269     * <p>When <code>immediate</code> is set to true, scrolling will not be
4270     * animated.
4271     *
4272     * @param rectangle The rectangle.
4273     * @param immediate True to forbid animated scrolling, false otherwise
4274     * @return Whether any parent scrolled.
4275     */
4276    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
4277        if (mAttachInfo == null) {
4278            return false;
4279        }
4280
4281        View child = this;
4282
4283        RectF position = mAttachInfo.mTmpTransformRect;
4284        position.set(rectangle);
4285
4286        ViewParent parent = mParent;
4287        boolean scrolled = false;
4288        while (parent != null) {
4289            rectangle.set((int) position.left, (int) position.top,
4290                    (int) position.right, (int) position.bottom);
4291
4292            scrolled |= parent.requestChildRectangleOnScreen(child,
4293                    rectangle, immediate);
4294
4295            if (!child.hasIdentityMatrix()) {
4296                child.getMatrix().mapRect(position);
4297            }
4298
4299            position.offset(child.mLeft, child.mTop);
4300
4301            if (!(parent instanceof View)) {
4302                break;
4303            }
4304
4305            View parentView = (View) parent;
4306
4307            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
4308
4309            child = parentView;
4310            parent = child.getParent();
4311        }
4312
4313        return scrolled;
4314    }
4315
4316    /**
4317     * Called when this view wants to give up focus. If focus is cleared
4318     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
4319     * <p>
4320     * <strong>Note:</strong> When a View clears focus the framework is trying
4321     * to give focus to the first focusable View from the top. Hence, if this
4322     * View is the first from the top that can take focus, then all callbacks
4323     * related to clearing focus will be invoked after wich the framework will
4324     * give focus to this view.
4325     * </p>
4326     */
4327    public void clearFocus() {
4328        if (DBG) {
4329            System.out.println(this + " clearFocus()");
4330        }
4331
4332        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4333            mPrivateFlags &= ~PFLAG_FOCUSED;
4334
4335            if (mParent != null) {
4336                mParent.clearChildFocus(this);
4337            }
4338
4339            onFocusChanged(false, 0, null);
4340
4341            refreshDrawableState();
4342
4343            ensureInputFocusOnFirstFocusable();
4344
4345            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4346                notifyAccessibilityStateChanged();
4347            }
4348        }
4349    }
4350
4351    void ensureInputFocusOnFirstFocusable() {
4352        View root = getRootView();
4353        if (root != null) {
4354            root.requestFocus();
4355        }
4356    }
4357
4358    /**
4359     * Called internally by the view system when a new view is getting focus.
4360     * This is what clears the old focus.
4361     */
4362    void unFocus() {
4363        if (DBG) {
4364            System.out.println(this + " unFocus()");
4365        }
4366
4367        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4368            mPrivateFlags &= ~PFLAG_FOCUSED;
4369
4370            onFocusChanged(false, 0, null);
4371            refreshDrawableState();
4372
4373            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4374                notifyAccessibilityStateChanged();
4375            }
4376        }
4377    }
4378
4379    /**
4380     * Returns true if this view has focus iteself, or is the ancestor of the
4381     * view that has focus.
4382     *
4383     * @return True if this view has or contains focus, false otherwise.
4384     */
4385    @ViewDebug.ExportedProperty(category = "focus")
4386    public boolean hasFocus() {
4387        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
4388    }
4389
4390    /**
4391     * Returns true if this view is focusable or if it contains a reachable View
4392     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
4393     * is a View whose parents do not block descendants focus.
4394     *
4395     * Only {@link #VISIBLE} views are considered focusable.
4396     *
4397     * @return True if the view is focusable or if the view contains a focusable
4398     *         View, false otherwise.
4399     *
4400     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
4401     */
4402    public boolean hasFocusable() {
4403        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
4404    }
4405
4406    /**
4407     * Called by the view system when the focus state of this view changes.
4408     * When the focus change event is caused by directional navigation, direction
4409     * and previouslyFocusedRect provide insight into where the focus is coming from.
4410     * When overriding, be sure to call up through to the super class so that
4411     * the standard focus handling will occur.
4412     *
4413     * @param gainFocus True if the View has focus; false otherwise.
4414     * @param direction The direction focus has moved when requestFocus()
4415     *                  is called to give this view focus. Values are
4416     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
4417     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
4418     *                  It may not always apply, in which case use the default.
4419     * @param previouslyFocusedRect The rectangle, in this view's coordinate
4420     *        system, of the previously focused view.  If applicable, this will be
4421     *        passed in as finer grained information about where the focus is coming
4422     *        from (in addition to direction).  Will be <code>null</code> otherwise.
4423     */
4424    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
4425        if (gainFocus) {
4426            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4427                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
4428            }
4429        }
4430
4431        InputMethodManager imm = InputMethodManager.peekInstance();
4432        if (!gainFocus) {
4433            if (isPressed()) {
4434                setPressed(false);
4435            }
4436            if (imm != null && mAttachInfo != null
4437                    && mAttachInfo.mHasWindowFocus) {
4438                imm.focusOut(this);
4439            }
4440            onFocusLost();
4441        } else if (imm != null && mAttachInfo != null
4442                && mAttachInfo.mHasWindowFocus) {
4443            imm.focusIn(this);
4444        }
4445
4446        invalidate(true);
4447        ListenerInfo li = mListenerInfo;
4448        if (li != null && li.mOnFocusChangeListener != null) {
4449            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
4450        }
4451
4452        if (mAttachInfo != null) {
4453            mAttachInfo.mKeyDispatchState.reset(this);
4454        }
4455    }
4456
4457    /**
4458     * Sends an accessibility event of the given type. If accessiiblity is
4459     * not enabled this method has no effect. The default implementation calls
4460     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
4461     * to populate information about the event source (this View), then calls
4462     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
4463     * populate the text content of the event source including its descendants,
4464     * and last calls
4465     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
4466     * on its parent to resuest sending of the event to interested parties.
4467     * <p>
4468     * If an {@link AccessibilityDelegate} has been specified via calling
4469     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4470     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
4471     * responsible for handling this call.
4472     * </p>
4473     *
4474     * @param eventType The type of the event to send, as defined by several types from
4475     * {@link android.view.accessibility.AccessibilityEvent}, such as
4476     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
4477     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
4478     *
4479     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4480     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4481     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
4482     * @see AccessibilityDelegate
4483     */
4484    public void sendAccessibilityEvent(int eventType) {
4485        if (mAccessibilityDelegate != null) {
4486            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
4487        } else {
4488            sendAccessibilityEventInternal(eventType);
4489        }
4490    }
4491
4492    /**
4493     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
4494     * {@link AccessibilityEvent} to make an announcement which is related to some
4495     * sort of a context change for which none of the events representing UI transitions
4496     * is a good fit. For example, announcing a new page in a book. If accessibility
4497     * is not enabled this method does nothing.
4498     *
4499     * @param text The announcement text.
4500     */
4501    public void announceForAccessibility(CharSequence text) {
4502        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
4503            AccessibilityEvent event = AccessibilityEvent.obtain(
4504                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
4505            onInitializeAccessibilityEvent(event);
4506            event.getText().add(text);
4507            event.setContentDescription(null);
4508            mParent.requestSendAccessibilityEvent(this, event);
4509        }
4510    }
4511
4512    /**
4513     * @see #sendAccessibilityEvent(int)
4514     *
4515     * Note: Called from the default {@link AccessibilityDelegate}.
4516     */
4517    void sendAccessibilityEventInternal(int eventType) {
4518        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4519            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
4520        }
4521    }
4522
4523    /**
4524     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
4525     * takes as an argument an empty {@link AccessibilityEvent} and does not
4526     * perform a check whether accessibility is enabled.
4527     * <p>
4528     * If an {@link AccessibilityDelegate} has been specified via calling
4529     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4530     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
4531     * is responsible for handling this call.
4532     * </p>
4533     *
4534     * @param event The event to send.
4535     *
4536     * @see #sendAccessibilityEvent(int)
4537     */
4538    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
4539        if (mAccessibilityDelegate != null) {
4540            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
4541        } else {
4542            sendAccessibilityEventUncheckedInternal(event);
4543        }
4544    }
4545
4546    /**
4547     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
4548     *
4549     * Note: Called from the default {@link AccessibilityDelegate}.
4550     */
4551    void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
4552        if (!isShown()) {
4553            return;
4554        }
4555        onInitializeAccessibilityEvent(event);
4556        // Only a subset of accessibility events populates text content.
4557        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
4558            dispatchPopulateAccessibilityEvent(event);
4559        }
4560        // In the beginning we called #isShown(), so we know that getParent() is not null.
4561        getParent().requestSendAccessibilityEvent(this, event);
4562    }
4563
4564    /**
4565     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
4566     * to its children for adding their text content to the event. Note that the
4567     * event text is populated in a separate dispatch path since we add to the
4568     * event not only the text of the source but also the text of all its descendants.
4569     * A typical implementation will call
4570     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
4571     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4572     * on each child. Override this method if custom population of the event text
4573     * content is required.
4574     * <p>
4575     * If an {@link AccessibilityDelegate} has been specified via calling
4576     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4577     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
4578     * is responsible for handling this call.
4579     * </p>
4580     * <p>
4581     * <em>Note:</em> Accessibility events of certain types are not dispatched for
4582     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
4583     * </p>
4584     *
4585     * @param event The event.
4586     *
4587     * @return True if the event population was completed.
4588     */
4589    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
4590        if (mAccessibilityDelegate != null) {
4591            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
4592        } else {
4593            return dispatchPopulateAccessibilityEventInternal(event);
4594        }
4595    }
4596
4597    /**
4598     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4599     *
4600     * Note: Called from the default {@link AccessibilityDelegate}.
4601     */
4602    boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4603        onPopulateAccessibilityEvent(event);
4604        return false;
4605    }
4606
4607    /**
4608     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4609     * giving a chance to this View to populate the accessibility event with its
4610     * text content. While this method is free to modify event
4611     * attributes other than text content, doing so should normally be performed in
4612     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
4613     * <p>
4614     * Example: Adding formatted date string to an accessibility event in addition
4615     *          to the text added by the super implementation:
4616     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
4617     *     super.onPopulateAccessibilityEvent(event);
4618     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
4619     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
4620     *         mCurrentDate.getTimeInMillis(), flags);
4621     *     event.getText().add(selectedDateUtterance);
4622     * }</pre>
4623     * <p>
4624     * If an {@link AccessibilityDelegate} has been specified via calling
4625     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4626     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
4627     * is responsible for handling this call.
4628     * </p>
4629     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4630     * information to the event, in case the default implementation has basic information to add.
4631     * </p>
4632     *
4633     * @param event The accessibility event which to populate.
4634     *
4635     * @see #sendAccessibilityEvent(int)
4636     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4637     */
4638    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
4639        if (mAccessibilityDelegate != null) {
4640            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
4641        } else {
4642            onPopulateAccessibilityEventInternal(event);
4643        }
4644    }
4645
4646    /**
4647     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
4648     *
4649     * Note: Called from the default {@link AccessibilityDelegate}.
4650     */
4651    void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4652
4653    }
4654
4655    /**
4656     * Initializes an {@link AccessibilityEvent} with information about
4657     * this View which is the event source. In other words, the source of
4658     * an accessibility event is the view whose state change triggered firing
4659     * the event.
4660     * <p>
4661     * Example: Setting the password property of an event in addition
4662     *          to properties set by the super implementation:
4663     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4664     *     super.onInitializeAccessibilityEvent(event);
4665     *     event.setPassword(true);
4666     * }</pre>
4667     * <p>
4668     * If an {@link AccessibilityDelegate} has been specified via calling
4669     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4670     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
4671     * is responsible for handling this call.
4672     * </p>
4673     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4674     * information to the event, in case the default implementation has basic information to add.
4675     * </p>
4676     * @param event The event to initialize.
4677     *
4678     * @see #sendAccessibilityEvent(int)
4679     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4680     */
4681    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4682        if (mAccessibilityDelegate != null) {
4683            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
4684        } else {
4685            onInitializeAccessibilityEventInternal(event);
4686        }
4687    }
4688
4689    /**
4690     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4691     *
4692     * Note: Called from the default {@link AccessibilityDelegate}.
4693     */
4694    void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
4695        event.setSource(this);
4696        event.setClassName(View.class.getName());
4697        event.setPackageName(getContext().getPackageName());
4698        event.setEnabled(isEnabled());
4699        event.setContentDescription(mContentDescription);
4700
4701        if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
4702            ArrayList<View> focusablesTempList = mAttachInfo.mTempArrayList;
4703            getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
4704                    FOCUSABLES_ALL);
4705            event.setItemCount(focusablesTempList.size());
4706            event.setCurrentItemIndex(focusablesTempList.indexOf(this));
4707            focusablesTempList.clear();
4708        }
4709    }
4710
4711    /**
4712     * Returns an {@link AccessibilityNodeInfo} representing this view from the
4713     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
4714     * This method is responsible for obtaining an accessibility node info from a
4715     * pool of reusable instances and calling
4716     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
4717     * initialize the former.
4718     * <p>
4719     * Note: The client is responsible for recycling the obtained instance by calling
4720     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
4721     * </p>
4722     *
4723     * @return A populated {@link AccessibilityNodeInfo}.
4724     *
4725     * @see AccessibilityNodeInfo
4726     */
4727    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
4728        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
4729        if (provider != null) {
4730            return provider.createAccessibilityNodeInfo(View.NO_ID);
4731        } else {
4732            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
4733            onInitializeAccessibilityNodeInfo(info);
4734            return info;
4735        }
4736    }
4737
4738    /**
4739     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
4740     * The base implementation sets:
4741     * <ul>
4742     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
4743     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
4744     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
4745     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
4746     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
4747     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
4748     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
4749     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
4750     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
4751     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
4752     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
4753     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
4754     * </ul>
4755     * <p>
4756     * Subclasses should override this method, call the super implementation,
4757     * and set additional attributes.
4758     * </p>
4759     * <p>
4760     * If an {@link AccessibilityDelegate} has been specified via calling
4761     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4762     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
4763     * is responsible for handling this call.
4764     * </p>
4765     *
4766     * @param info The instance to initialize.
4767     */
4768    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
4769        if (mAccessibilityDelegate != null) {
4770            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
4771        } else {
4772            onInitializeAccessibilityNodeInfoInternal(info);
4773        }
4774    }
4775
4776    /**
4777     * Gets the location of this view in screen coordintates.
4778     *
4779     * @param outRect The output location
4780     */
4781    private void getBoundsOnScreen(Rect outRect) {
4782        if (mAttachInfo == null) {
4783            return;
4784        }
4785
4786        RectF position = mAttachInfo.mTmpTransformRect;
4787        position.set(0, 0, mRight - mLeft, mBottom - mTop);
4788
4789        if (!hasIdentityMatrix()) {
4790            getMatrix().mapRect(position);
4791        }
4792
4793        position.offset(mLeft, mTop);
4794
4795        ViewParent parent = mParent;
4796        while (parent instanceof View) {
4797            View parentView = (View) parent;
4798
4799            position.offset(-parentView.mScrollX, -parentView.mScrollY);
4800
4801            if (!parentView.hasIdentityMatrix()) {
4802                parentView.getMatrix().mapRect(position);
4803            }
4804
4805            position.offset(parentView.mLeft, parentView.mTop);
4806
4807            parent = parentView.mParent;
4808        }
4809
4810        if (parent instanceof ViewRootImpl) {
4811            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
4812            position.offset(0, -viewRootImpl.mCurScrollY);
4813        }
4814
4815        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
4816
4817        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
4818                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
4819    }
4820
4821    /**
4822     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
4823     *
4824     * Note: Called from the default {@link AccessibilityDelegate}.
4825     */
4826    void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
4827        Rect bounds = mAttachInfo.mTmpInvalRect;
4828
4829        getDrawingRect(bounds);
4830        info.setBoundsInParent(bounds);
4831
4832        getBoundsOnScreen(bounds);
4833        info.setBoundsInScreen(bounds);
4834
4835        ViewParent parent = getParentForAccessibility();
4836        if (parent instanceof View) {
4837            info.setParent((View) parent);
4838        }
4839
4840        info.setVisibleToUser(isVisibleToUser());
4841
4842        info.setPackageName(mContext.getPackageName());
4843        info.setClassName(View.class.getName());
4844        info.setContentDescription(getContentDescription());
4845
4846        info.setEnabled(isEnabled());
4847        info.setClickable(isClickable());
4848        info.setFocusable(isFocusable());
4849        info.setFocused(isFocused());
4850        info.setAccessibilityFocused(isAccessibilityFocused());
4851        info.setSelected(isSelected());
4852        info.setLongClickable(isLongClickable());
4853
4854        // TODO: These make sense only if we are in an AdapterView but all
4855        // views can be selected. Maybe from accessiiblity perspective
4856        // we should report as selectable view in an AdapterView.
4857        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
4858        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
4859
4860        if (isFocusable()) {
4861            if (isFocused()) {
4862                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
4863            } else {
4864                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
4865            }
4866        }
4867
4868        if (!isAccessibilityFocused()) {
4869            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
4870        } else {
4871            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
4872        }
4873
4874        if (isClickable() && isEnabled()) {
4875            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
4876        }
4877
4878        if (isLongClickable() && isEnabled()) {
4879            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
4880        }
4881
4882        if (mContentDescription != null && mContentDescription.length() > 0) {
4883            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
4884            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
4885            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
4886                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
4887                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
4888        }
4889    }
4890
4891    /**
4892     * Computes whether this view is visible to the user. Such a view is
4893     * attached, visible, all its predecessors are visible, it is not clipped
4894     * entirely by its predecessors, and has an alpha greater than zero.
4895     *
4896     * @return Whether the view is visible on the screen.
4897     *
4898     * @hide
4899     */
4900    protected boolean isVisibleToUser() {
4901        return isVisibleToUser(null);
4902    }
4903
4904    /**
4905     * Computes whether the given portion of this view is visible to the user.
4906     * Such a view is attached, visible, all its predecessors are visible,
4907     * has an alpha greater than zero, and the specified portion is not
4908     * clipped entirely by its predecessors.
4909     *
4910     * @param boundInView the portion of the view to test; coordinates should be relative; may be
4911     *                    <code>null</code>, and the entire view will be tested in this case.
4912     *                    When <code>true</code> is returned by the function, the actual visible
4913     *                    region will be stored in this parameter; that is, if boundInView is fully
4914     *                    contained within the view, no modification will be made, otherwise regions
4915     *                    outside of the visible area of the view will be clipped.
4916     *
4917     * @return Whether the specified portion of the view is visible on the screen.
4918     *
4919     * @hide
4920     */
4921    protected boolean isVisibleToUser(Rect boundInView) {
4922        if (mAttachInfo != null) {
4923            Rect visibleRect = mAttachInfo.mTmpInvalRect;
4924            Point offset = mAttachInfo.mPoint;
4925            // The first two checks are made also made by isShown() which
4926            // however traverses the tree up to the parent to catch that.
4927            // Therefore, we do some fail fast check to minimize the up
4928            // tree traversal.
4929            boolean isVisible = mAttachInfo.mWindowVisibility == View.VISIBLE
4930                && getAlpha() > 0
4931                && isShown()
4932                && getGlobalVisibleRect(visibleRect, offset);
4933            if (isVisible && boundInView != null) {
4934                visibleRect.offset(-offset.x, -offset.y);
4935                // isVisible is always true here, use a simple assignment
4936                isVisible = boundInView.intersect(visibleRect);
4937            }
4938            return isVisible;
4939        }
4940
4941        return false;
4942    }
4943
4944    /**
4945     * Returns the delegate for implementing accessibility support via
4946     * composition. For more details see {@link AccessibilityDelegate}.
4947     *
4948     * @return The delegate, or null if none set.
4949     *
4950     * @hide
4951     */
4952    public AccessibilityDelegate getAccessibilityDelegate() {
4953        return mAccessibilityDelegate;
4954    }
4955
4956    /**
4957     * Sets a delegate for implementing accessibility support via compositon as
4958     * opposed to inheritance. The delegate's primary use is for implementing
4959     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
4960     *
4961     * @param delegate The delegate instance.
4962     *
4963     * @see AccessibilityDelegate
4964     */
4965    public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
4966        mAccessibilityDelegate = delegate;
4967    }
4968
4969    /**
4970     * Gets the provider for managing a virtual view hierarchy rooted at this View
4971     * and reported to {@link android.accessibilityservice.AccessibilityService}s
4972     * that explore the window content.
4973     * <p>
4974     * If this method returns an instance, this instance is responsible for managing
4975     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
4976     * View including the one representing the View itself. Similarly the returned
4977     * instance is responsible for performing accessibility actions on any virtual
4978     * view or the root view itself.
4979     * </p>
4980     * <p>
4981     * If an {@link AccessibilityDelegate} has been specified via calling
4982     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4983     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
4984     * is responsible for handling this call.
4985     * </p>
4986     *
4987     * @return The provider.
4988     *
4989     * @see AccessibilityNodeProvider
4990     */
4991    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
4992        if (mAccessibilityDelegate != null) {
4993            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
4994        } else {
4995            return null;
4996        }
4997    }
4998
4999    /**
5000     * Gets the unique identifier of this view on the screen for accessibility purposes.
5001     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
5002     *
5003     * @return The view accessibility id.
5004     *
5005     * @hide
5006     */
5007    public int getAccessibilityViewId() {
5008        if (mAccessibilityViewId == NO_ID) {
5009            mAccessibilityViewId = sNextAccessibilityViewId++;
5010        }
5011        return mAccessibilityViewId;
5012    }
5013
5014    /**
5015     * Gets the unique identifier of the window in which this View reseides.
5016     *
5017     * @return The window accessibility id.
5018     *
5019     * @hide
5020     */
5021    public int getAccessibilityWindowId() {
5022        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
5023    }
5024
5025    /**
5026     * Gets the {@link View} description. It briefly describes the view and is
5027     * primarily used for accessibility support. Set this property to enable
5028     * better accessibility support for your application. This is especially
5029     * true for views that do not have textual representation (For example,
5030     * ImageButton).
5031     *
5032     * @return The content description.
5033     *
5034     * @attr ref android.R.styleable#View_contentDescription
5035     */
5036    @ViewDebug.ExportedProperty(category = "accessibility")
5037    public CharSequence getContentDescription() {
5038        return mContentDescription;
5039    }
5040
5041    /**
5042     * Sets the {@link View} description. It briefly describes the view and is
5043     * primarily used for accessibility support. Set this property to enable
5044     * better accessibility support for your application. This is especially
5045     * true for views that do not have textual representation (For example,
5046     * ImageButton).
5047     *
5048     * @param contentDescription The content description.
5049     *
5050     * @attr ref android.R.styleable#View_contentDescription
5051     */
5052    @RemotableViewMethod
5053    public void setContentDescription(CharSequence contentDescription) {
5054        mContentDescription = contentDescription;
5055        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
5056        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
5057             setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
5058        }
5059    }
5060
5061    /**
5062     * Invoked whenever this view loses focus, either by losing window focus or by losing
5063     * focus within its window. This method can be used to clear any state tied to the
5064     * focus. For instance, if a button is held pressed with the trackball and the window
5065     * loses focus, this method can be used to cancel the press.
5066     *
5067     * Subclasses of View overriding this method should always call super.onFocusLost().
5068     *
5069     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
5070     * @see #onWindowFocusChanged(boolean)
5071     *
5072     * @hide pending API council approval
5073     */
5074    protected void onFocusLost() {
5075        resetPressedState();
5076    }
5077
5078    private void resetPressedState() {
5079        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
5080            return;
5081        }
5082
5083        if (isPressed()) {
5084            setPressed(false);
5085
5086            if (!mHasPerformedLongPress) {
5087                removeLongPressCallback();
5088            }
5089        }
5090    }
5091
5092    /**
5093     * Returns true if this view has focus
5094     *
5095     * @return True if this view has focus, false otherwise.
5096     */
5097    @ViewDebug.ExportedProperty(category = "focus")
5098    public boolean isFocused() {
5099        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5100    }
5101
5102    /**
5103     * Find the view in the hierarchy rooted at this view that currently has
5104     * focus.
5105     *
5106     * @return The view that currently has focus, or null if no focused view can
5107     *         be found.
5108     */
5109    public View findFocus() {
5110        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
5111    }
5112
5113    /**
5114     * Indicates whether this view is one of the set of scrollable containers in
5115     * its window.
5116     *
5117     * @return whether this view is one of the set of scrollable containers in
5118     * its window
5119     *
5120     * @attr ref android.R.styleable#View_isScrollContainer
5121     */
5122    public boolean isScrollContainer() {
5123        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
5124    }
5125
5126    /**
5127     * Change whether this view is one of the set of scrollable containers in
5128     * its window.  This will be used to determine whether the window can
5129     * resize or must pan when a soft input area is open -- scrollable
5130     * containers allow the window to use resize mode since the container
5131     * will appropriately shrink.
5132     *
5133     * @attr ref android.R.styleable#View_isScrollContainer
5134     */
5135    public void setScrollContainer(boolean isScrollContainer) {
5136        if (isScrollContainer) {
5137            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
5138                mAttachInfo.mScrollContainers.add(this);
5139                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
5140            }
5141            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
5142        } else {
5143            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
5144                mAttachInfo.mScrollContainers.remove(this);
5145            }
5146            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
5147        }
5148    }
5149
5150    /**
5151     * Returns the quality of the drawing cache.
5152     *
5153     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5154     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5155     *
5156     * @see #setDrawingCacheQuality(int)
5157     * @see #setDrawingCacheEnabled(boolean)
5158     * @see #isDrawingCacheEnabled()
5159     *
5160     * @attr ref android.R.styleable#View_drawingCacheQuality
5161     */
5162    public int getDrawingCacheQuality() {
5163        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
5164    }
5165
5166    /**
5167     * Set the drawing cache quality of this view. This value is used only when the
5168     * drawing cache is enabled
5169     *
5170     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5171     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5172     *
5173     * @see #getDrawingCacheQuality()
5174     * @see #setDrawingCacheEnabled(boolean)
5175     * @see #isDrawingCacheEnabled()
5176     *
5177     * @attr ref android.R.styleable#View_drawingCacheQuality
5178     */
5179    public void setDrawingCacheQuality(int quality) {
5180        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
5181    }
5182
5183    /**
5184     * Returns whether the screen should remain on, corresponding to the current
5185     * value of {@link #KEEP_SCREEN_ON}.
5186     *
5187     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
5188     *
5189     * @see #setKeepScreenOn(boolean)
5190     *
5191     * @attr ref android.R.styleable#View_keepScreenOn
5192     */
5193    public boolean getKeepScreenOn() {
5194        return (mViewFlags & KEEP_SCREEN_ON) != 0;
5195    }
5196
5197    /**
5198     * Controls whether the screen should remain on, modifying the
5199     * value of {@link #KEEP_SCREEN_ON}.
5200     *
5201     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
5202     *
5203     * @see #getKeepScreenOn()
5204     *
5205     * @attr ref android.R.styleable#View_keepScreenOn
5206     */
5207    public void setKeepScreenOn(boolean keepScreenOn) {
5208        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
5209    }
5210
5211    /**
5212     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5213     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5214     *
5215     * @attr ref android.R.styleable#View_nextFocusLeft
5216     */
5217    public int getNextFocusLeftId() {
5218        return mNextFocusLeftId;
5219    }
5220
5221    /**
5222     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5223     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
5224     * decide automatically.
5225     *
5226     * @attr ref android.R.styleable#View_nextFocusLeft
5227     */
5228    public void setNextFocusLeftId(int nextFocusLeftId) {
5229        mNextFocusLeftId = nextFocusLeftId;
5230    }
5231
5232    /**
5233     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5234     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5235     *
5236     * @attr ref android.R.styleable#View_nextFocusRight
5237     */
5238    public int getNextFocusRightId() {
5239        return mNextFocusRightId;
5240    }
5241
5242    /**
5243     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5244     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
5245     * decide automatically.
5246     *
5247     * @attr ref android.R.styleable#View_nextFocusRight
5248     */
5249    public void setNextFocusRightId(int nextFocusRightId) {
5250        mNextFocusRightId = nextFocusRightId;
5251    }
5252
5253    /**
5254     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5255     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5256     *
5257     * @attr ref android.R.styleable#View_nextFocusUp
5258     */
5259    public int getNextFocusUpId() {
5260        return mNextFocusUpId;
5261    }
5262
5263    /**
5264     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5265     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
5266     * decide automatically.
5267     *
5268     * @attr ref android.R.styleable#View_nextFocusUp
5269     */
5270    public void setNextFocusUpId(int nextFocusUpId) {
5271        mNextFocusUpId = nextFocusUpId;
5272    }
5273
5274    /**
5275     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5276     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5277     *
5278     * @attr ref android.R.styleable#View_nextFocusDown
5279     */
5280    public int getNextFocusDownId() {
5281        return mNextFocusDownId;
5282    }
5283
5284    /**
5285     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5286     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
5287     * decide automatically.
5288     *
5289     * @attr ref android.R.styleable#View_nextFocusDown
5290     */
5291    public void setNextFocusDownId(int nextFocusDownId) {
5292        mNextFocusDownId = nextFocusDownId;
5293    }
5294
5295    /**
5296     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5297     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5298     *
5299     * @attr ref android.R.styleable#View_nextFocusForward
5300     */
5301    public int getNextFocusForwardId() {
5302        return mNextFocusForwardId;
5303    }
5304
5305    /**
5306     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5307     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
5308     * decide automatically.
5309     *
5310     * @attr ref android.R.styleable#View_nextFocusForward
5311     */
5312    public void setNextFocusForwardId(int nextFocusForwardId) {
5313        mNextFocusForwardId = nextFocusForwardId;
5314    }
5315
5316    /**
5317     * Returns the visibility of this view and all of its ancestors
5318     *
5319     * @return True if this view and all of its ancestors are {@link #VISIBLE}
5320     */
5321    public boolean isShown() {
5322        View current = this;
5323        //noinspection ConstantConditions
5324        do {
5325            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
5326                return false;
5327            }
5328            ViewParent parent = current.mParent;
5329            if (parent == null) {
5330                return false; // We are not attached to the view root
5331            }
5332            if (!(parent instanceof View)) {
5333                return true;
5334            }
5335            current = (View) parent;
5336        } while (current != null);
5337
5338        return false;
5339    }
5340
5341    /**
5342     * Called by the view hierarchy when the content insets for a window have
5343     * changed, to allow it to adjust its content to fit within those windows.
5344     * The content insets tell you the space that the status bar, input method,
5345     * and other system windows infringe on the application's window.
5346     *
5347     * <p>You do not normally need to deal with this function, since the default
5348     * window decoration given to applications takes care of applying it to the
5349     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
5350     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
5351     * and your content can be placed under those system elements.  You can then
5352     * use this method within your view hierarchy if you have parts of your UI
5353     * which you would like to ensure are not being covered.
5354     *
5355     * <p>The default implementation of this method simply applies the content
5356     * inset's to the view's padding, consuming that content (modifying the
5357     * insets to be 0), and returning true.  This behavior is off by default, but can
5358     * be enabled through {@link #setFitsSystemWindows(boolean)}.
5359     *
5360     * <p>This function's traversal down the hierarchy is depth-first.  The same content
5361     * insets object is propagated down the hierarchy, so any changes made to it will
5362     * be seen by all following views (including potentially ones above in
5363     * the hierarchy since this is a depth-first traversal).  The first view
5364     * that returns true will abort the entire traversal.
5365     *
5366     * <p>The default implementation works well for a situation where it is
5367     * used with a container that covers the entire window, allowing it to
5368     * apply the appropriate insets to its content on all edges.  If you need
5369     * a more complicated layout (such as two different views fitting system
5370     * windows, one on the top of the window, and one on the bottom),
5371     * you can override the method and handle the insets however you would like.
5372     * Note that the insets provided by the framework are always relative to the
5373     * far edges of the window, not accounting for the location of the called view
5374     * within that window.  (In fact when this method is called you do not yet know
5375     * where the layout will place the view, as it is done before layout happens.)
5376     *
5377     * <p>Note: unlike many View methods, there is no dispatch phase to this
5378     * call.  If you are overriding it in a ViewGroup and want to allow the
5379     * call to continue to your children, you must be sure to call the super
5380     * implementation.
5381     *
5382     * <p>Here is a sample layout that makes use of fitting system windows
5383     * to have controls for a video view placed inside of the window decorations
5384     * that it hides and shows.  This can be used with code like the second
5385     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
5386     *
5387     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
5388     *
5389     * @param insets Current content insets of the window.  Prior to
5390     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
5391     * the insets or else you and Android will be unhappy.
5392     *
5393     * @return Return true if this view applied the insets and it should not
5394     * continue propagating further down the hierarchy, false otherwise.
5395     * @see #getFitsSystemWindows()
5396     * @see #setFitsSystemWindows(boolean)
5397     * @see #setSystemUiVisibility(int)
5398     */
5399    protected boolean fitSystemWindows(Rect insets) {
5400        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
5401            mUserPaddingStart = UNDEFINED_PADDING;
5402            mUserPaddingEnd = UNDEFINED_PADDING;
5403            if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
5404                    || mAttachInfo == null
5405                    || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
5406                internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
5407                return true;
5408            } else {
5409                internalSetPadding(0, 0, 0, 0);
5410                return false;
5411            }
5412        }
5413        return false;
5414    }
5415
5416    /**
5417     * Sets whether or not this view should account for system screen decorations
5418     * such as the status bar and inset its content; that is, controlling whether
5419     * the default implementation of {@link #fitSystemWindows(Rect)} will be
5420     * executed.  See that method for more details.
5421     *
5422     * <p>Note that if you are providing your own implementation of
5423     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
5424     * flag to true -- your implementation will be overriding the default
5425     * implementation that checks this flag.
5426     *
5427     * @param fitSystemWindows If true, then the default implementation of
5428     * {@link #fitSystemWindows(Rect)} will be executed.
5429     *
5430     * @attr ref android.R.styleable#View_fitsSystemWindows
5431     * @see #getFitsSystemWindows()
5432     * @see #fitSystemWindows(Rect)
5433     * @see #setSystemUiVisibility(int)
5434     */
5435    public void setFitsSystemWindows(boolean fitSystemWindows) {
5436        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
5437    }
5438
5439    /**
5440     * Check for state of {@link #setFitsSystemWindows(boolean). If this method
5441     * returns true, the default implementation of {@link #fitSystemWindows(Rect)}
5442     * will be executed.
5443     *
5444     * @return Returns true if the default implementation of
5445     * {@link #fitSystemWindows(Rect)} will be executed.
5446     *
5447     * @attr ref android.R.styleable#View_fitsSystemWindows
5448     * @see #setFitsSystemWindows()
5449     * @see #fitSystemWindows(Rect)
5450     * @see #setSystemUiVisibility(int)
5451     */
5452    public boolean getFitsSystemWindows() {
5453        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
5454    }
5455
5456    /** @hide */
5457    public boolean fitsSystemWindows() {
5458        return getFitsSystemWindows();
5459    }
5460
5461    /**
5462     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
5463     */
5464    public void requestFitSystemWindows() {
5465        if (mParent != null) {
5466            mParent.requestFitSystemWindows();
5467        }
5468    }
5469
5470    /**
5471     * For use by PhoneWindow to make its own system window fitting optional.
5472     * @hide
5473     */
5474    public void makeOptionalFitsSystemWindows() {
5475        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
5476    }
5477
5478    /**
5479     * Returns the visibility status for this view.
5480     *
5481     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5482     * @attr ref android.R.styleable#View_visibility
5483     */
5484    @ViewDebug.ExportedProperty(mapping = {
5485        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
5486        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
5487        @ViewDebug.IntToString(from = GONE,      to = "GONE")
5488    })
5489    public int getVisibility() {
5490        return mViewFlags & VISIBILITY_MASK;
5491    }
5492
5493    /**
5494     * Set the enabled state of this view.
5495     *
5496     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5497     * @attr ref android.R.styleable#View_visibility
5498     */
5499    @RemotableViewMethod
5500    public void setVisibility(int visibility) {
5501        setFlags(visibility, VISIBILITY_MASK);
5502        if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
5503    }
5504
5505    /**
5506     * Returns the enabled status for this view. The interpretation of the
5507     * enabled state varies by subclass.
5508     *
5509     * @return True if this view is enabled, false otherwise.
5510     */
5511    @ViewDebug.ExportedProperty
5512    public boolean isEnabled() {
5513        return (mViewFlags & ENABLED_MASK) == ENABLED;
5514    }
5515
5516    /**
5517     * Set the enabled state of this view. The interpretation of the enabled
5518     * state varies by subclass.
5519     *
5520     * @param enabled True if this view is enabled, false otherwise.
5521     */
5522    @RemotableViewMethod
5523    public void setEnabled(boolean enabled) {
5524        if (enabled == isEnabled()) return;
5525
5526        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
5527
5528        /*
5529         * The View most likely has to change its appearance, so refresh
5530         * the drawable state.
5531         */
5532        refreshDrawableState();
5533
5534        // Invalidate too, since the default behavior for views is to be
5535        // be drawn at 50% alpha rather than to change the drawable.
5536        invalidate(true);
5537    }
5538
5539    /**
5540     * Set whether this view can receive the focus.
5541     *
5542     * Setting this to false will also ensure that this view is not focusable
5543     * in touch mode.
5544     *
5545     * @param focusable If true, this view can receive the focus.
5546     *
5547     * @see #setFocusableInTouchMode(boolean)
5548     * @attr ref android.R.styleable#View_focusable
5549     */
5550    public void setFocusable(boolean focusable) {
5551        if (!focusable) {
5552            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
5553        }
5554        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
5555    }
5556
5557    /**
5558     * Set whether this view can receive focus while in touch mode.
5559     *
5560     * Setting this to true will also ensure that this view is focusable.
5561     *
5562     * @param focusableInTouchMode If true, this view can receive the focus while
5563     *   in touch mode.
5564     *
5565     * @see #setFocusable(boolean)
5566     * @attr ref android.R.styleable#View_focusableInTouchMode
5567     */
5568    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
5569        // Focusable in touch mode should always be set before the focusable flag
5570        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
5571        // which, in touch mode, will not successfully request focus on this view
5572        // because the focusable in touch mode flag is not set
5573        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
5574        if (focusableInTouchMode) {
5575            setFlags(FOCUSABLE, FOCUSABLE_MASK);
5576        }
5577    }
5578
5579    /**
5580     * Set whether this view should have sound effects enabled for events such as
5581     * clicking and touching.
5582     *
5583     * <p>You may wish to disable sound effects for a view if you already play sounds,
5584     * for instance, a dial key that plays dtmf tones.
5585     *
5586     * @param soundEffectsEnabled whether sound effects are enabled for this view.
5587     * @see #isSoundEffectsEnabled()
5588     * @see #playSoundEffect(int)
5589     * @attr ref android.R.styleable#View_soundEffectsEnabled
5590     */
5591    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
5592        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
5593    }
5594
5595    /**
5596     * @return whether this view should have sound effects enabled for events such as
5597     *     clicking and touching.
5598     *
5599     * @see #setSoundEffectsEnabled(boolean)
5600     * @see #playSoundEffect(int)
5601     * @attr ref android.R.styleable#View_soundEffectsEnabled
5602     */
5603    @ViewDebug.ExportedProperty
5604    public boolean isSoundEffectsEnabled() {
5605        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
5606    }
5607
5608    /**
5609     * Set whether this view should have haptic feedback for events such as
5610     * long presses.
5611     *
5612     * <p>You may wish to disable haptic feedback if your view already controls
5613     * its own haptic feedback.
5614     *
5615     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
5616     * @see #isHapticFeedbackEnabled()
5617     * @see #performHapticFeedback(int)
5618     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5619     */
5620    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
5621        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
5622    }
5623
5624    /**
5625     * @return whether this view should have haptic feedback enabled for events
5626     * long presses.
5627     *
5628     * @see #setHapticFeedbackEnabled(boolean)
5629     * @see #performHapticFeedback(int)
5630     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5631     */
5632    @ViewDebug.ExportedProperty
5633    public boolean isHapticFeedbackEnabled() {
5634        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
5635    }
5636
5637    /**
5638     * Returns the layout direction for this view.
5639     *
5640     * @return One of {@link #LAYOUT_DIRECTION_LTR},
5641     *   {@link #LAYOUT_DIRECTION_RTL},
5642     *   {@link #LAYOUT_DIRECTION_INHERIT} or
5643     *   {@link #LAYOUT_DIRECTION_LOCALE}.
5644     * @attr ref android.R.styleable#View_layoutDirection
5645     */
5646    @ViewDebug.ExportedProperty(category = "layout", mapping = {
5647        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
5648        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
5649        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
5650        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
5651    })
5652    public int getLayoutDirection() {
5653        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
5654    }
5655
5656    /**
5657     * Set the layout direction for this view. This will propagate a reset of layout direction
5658     * resolution to the view's children and resolve layout direction for this view.
5659     *
5660     * @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR},
5661     *   {@link #LAYOUT_DIRECTION_RTL},
5662     *   {@link #LAYOUT_DIRECTION_INHERIT} or
5663     *   {@link #LAYOUT_DIRECTION_LOCALE}.
5664     *
5665     * @attr ref android.R.styleable#View_layoutDirection
5666     */
5667    @RemotableViewMethod
5668    public void setLayoutDirection(int layoutDirection) {
5669        if (getLayoutDirection() != layoutDirection) {
5670            // Reset the current layout direction and the resolved one
5671            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
5672            resetResolvedLayoutDirection();
5673            // Reset padding resolution
5674            mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
5675            // Set the new layout direction (filtered)
5676            mPrivateFlags2 |=
5677                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
5678            resolveRtlProperties();
5679            // ... and ask for a layout pass
5680            requestLayout();
5681        }
5682    }
5683
5684    /**
5685     * Returns the resolved layout direction for this view.
5686     *
5687     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
5688     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
5689     */
5690    @ViewDebug.ExportedProperty(category = "layout", mapping = {
5691        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
5692        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
5693    })
5694    public int getResolvedLayoutDirection() {
5695        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
5696        if (targetSdkVersion < JELLY_BEAN_MR1) {
5697            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
5698            return LAYOUT_DIRECTION_LTR;
5699        }
5700        // The layout direction will be resolved only if needed
5701        if ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) != PFLAG2_LAYOUT_DIRECTION_RESOLVED) {
5702            resolveLayoutDirection();
5703        }
5704        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) == PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ?
5705                LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
5706    }
5707
5708    /**
5709     * Indicates whether or not this view's layout is right-to-left. This is resolved from
5710     * layout attribute and/or the inherited value from the parent
5711     *
5712     * @return true if the layout is right-to-left.
5713     */
5714    @ViewDebug.ExportedProperty(category = "layout")
5715    public boolean isLayoutRtl() {
5716        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
5717    }
5718
5719    /**
5720     * Indicates whether the view is currently tracking transient state that the
5721     * app should not need to concern itself with saving and restoring, but that
5722     * the framework should take special note to preserve when possible.
5723     *
5724     * <p>A view with transient state cannot be trivially rebound from an external
5725     * data source, such as an adapter binding item views in a list. This may be
5726     * because the view is performing an animation, tracking user selection
5727     * of content, or similar.</p>
5728     *
5729     * @return true if the view has transient state
5730     */
5731    @ViewDebug.ExportedProperty(category = "layout")
5732    public boolean hasTransientState() {
5733        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
5734    }
5735
5736    /**
5737     * Set whether this view is currently tracking transient state that the
5738     * framework should attempt to preserve when possible. This flag is reference counted,
5739     * so every call to setHasTransientState(true) should be paired with a later call
5740     * to setHasTransientState(false).
5741     *
5742     * <p>A view with transient state cannot be trivially rebound from an external
5743     * data source, such as an adapter binding item views in a list. This may be
5744     * because the view is performing an animation, tracking user selection
5745     * of content, or similar.</p>
5746     *
5747     * @param hasTransientState true if this view has transient state
5748     */
5749    public void setHasTransientState(boolean hasTransientState) {
5750        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
5751                mTransientStateCount - 1;
5752        if (mTransientStateCount < 0) {
5753            mTransientStateCount = 0;
5754            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
5755                    "unmatched pair of setHasTransientState calls");
5756        }
5757        if ((hasTransientState && mTransientStateCount == 1) ||
5758                (!hasTransientState && mTransientStateCount == 0)) {
5759            // update flag if we've just incremented up from 0 or decremented down to 0
5760            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
5761                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
5762            if (mParent != null) {
5763                try {
5764                    mParent.childHasTransientStateChanged(this, hasTransientState);
5765                } catch (AbstractMethodError e) {
5766                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
5767                            " does not fully implement ViewParent", e);
5768                }
5769            }
5770        }
5771    }
5772
5773    /**
5774     * If this view doesn't do any drawing on its own, set this flag to
5775     * allow further optimizations. By default, this flag is not set on
5776     * View, but could be set on some View subclasses such as ViewGroup.
5777     *
5778     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
5779     * you should clear this flag.
5780     *
5781     * @param willNotDraw whether or not this View draw on its own
5782     */
5783    public void setWillNotDraw(boolean willNotDraw) {
5784        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
5785    }
5786
5787    /**
5788     * Returns whether or not this View draws on its own.
5789     *
5790     * @return true if this view has nothing to draw, false otherwise
5791     */
5792    @ViewDebug.ExportedProperty(category = "drawing")
5793    public boolean willNotDraw() {
5794        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
5795    }
5796
5797    /**
5798     * When a View's drawing cache is enabled, drawing is redirected to an
5799     * offscreen bitmap. Some views, like an ImageView, must be able to
5800     * bypass this mechanism if they already draw a single bitmap, to avoid
5801     * unnecessary usage of the memory.
5802     *
5803     * @param willNotCacheDrawing true if this view does not cache its
5804     *        drawing, false otherwise
5805     */
5806    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
5807        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
5808    }
5809
5810    /**
5811     * Returns whether or not this View can cache its drawing or not.
5812     *
5813     * @return true if this view does not cache its drawing, false otherwise
5814     */
5815    @ViewDebug.ExportedProperty(category = "drawing")
5816    public boolean willNotCacheDrawing() {
5817        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
5818    }
5819
5820    /**
5821     * Indicates whether this view reacts to click events or not.
5822     *
5823     * @return true if the view is clickable, false otherwise
5824     *
5825     * @see #setClickable(boolean)
5826     * @attr ref android.R.styleable#View_clickable
5827     */
5828    @ViewDebug.ExportedProperty
5829    public boolean isClickable() {
5830        return (mViewFlags & CLICKABLE) == CLICKABLE;
5831    }
5832
5833    /**
5834     * Enables or disables click events for this view. When a view
5835     * is clickable it will change its state to "pressed" on every click.
5836     * Subclasses should set the view clickable to visually react to
5837     * user's clicks.
5838     *
5839     * @param clickable true to make the view clickable, false otherwise
5840     *
5841     * @see #isClickable()
5842     * @attr ref android.R.styleable#View_clickable
5843     */
5844    public void setClickable(boolean clickable) {
5845        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
5846    }
5847
5848    /**
5849     * Indicates whether this view reacts to long click events or not.
5850     *
5851     * @return true if the view is long clickable, false otherwise
5852     *
5853     * @see #setLongClickable(boolean)
5854     * @attr ref android.R.styleable#View_longClickable
5855     */
5856    public boolean isLongClickable() {
5857        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
5858    }
5859
5860    /**
5861     * Enables or disables long click events for this view. When a view is long
5862     * clickable it reacts to the user holding down the button for a longer
5863     * duration than a tap. This event can either launch the listener or a
5864     * context menu.
5865     *
5866     * @param longClickable true to make the view long clickable, false otherwise
5867     * @see #isLongClickable()
5868     * @attr ref android.R.styleable#View_longClickable
5869     */
5870    public void setLongClickable(boolean longClickable) {
5871        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
5872    }
5873
5874    /**
5875     * Sets the pressed state for this view.
5876     *
5877     * @see #isClickable()
5878     * @see #setClickable(boolean)
5879     *
5880     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
5881     *        the View's internal state from a previously set "pressed" state.
5882     */
5883    public void setPressed(boolean pressed) {
5884        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
5885
5886        if (pressed) {
5887            mPrivateFlags |= PFLAG_PRESSED;
5888        } else {
5889            mPrivateFlags &= ~PFLAG_PRESSED;
5890        }
5891
5892        if (needsRefresh) {
5893            refreshDrawableState();
5894        }
5895        dispatchSetPressed(pressed);
5896    }
5897
5898    /**
5899     * Dispatch setPressed to all of this View's children.
5900     *
5901     * @see #setPressed(boolean)
5902     *
5903     * @param pressed The new pressed state
5904     */
5905    protected void dispatchSetPressed(boolean pressed) {
5906    }
5907
5908    /**
5909     * Indicates whether the view is currently in pressed state. Unless
5910     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
5911     * the pressed state.
5912     *
5913     * @see #setPressed(boolean)
5914     * @see #isClickable()
5915     * @see #setClickable(boolean)
5916     *
5917     * @return true if the view is currently pressed, false otherwise
5918     */
5919    public boolean isPressed() {
5920        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
5921    }
5922
5923    /**
5924     * Indicates whether this view will save its state (that is,
5925     * whether its {@link #onSaveInstanceState} method will be called).
5926     *
5927     * @return Returns true if the view state saving is enabled, else false.
5928     *
5929     * @see #setSaveEnabled(boolean)
5930     * @attr ref android.R.styleable#View_saveEnabled
5931     */
5932    public boolean isSaveEnabled() {
5933        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
5934    }
5935
5936    /**
5937     * Controls whether the saving of this view's state is
5938     * enabled (that is, whether its {@link #onSaveInstanceState} method
5939     * will be called).  Note that even if freezing is enabled, the
5940     * view still must have an id assigned to it (via {@link #setId(int)})
5941     * for its state to be saved.  This flag can only disable the
5942     * saving of this view; any child views may still have their state saved.
5943     *
5944     * @param enabled Set to false to <em>disable</em> state saving, or true
5945     * (the default) to allow it.
5946     *
5947     * @see #isSaveEnabled()
5948     * @see #setId(int)
5949     * @see #onSaveInstanceState()
5950     * @attr ref android.R.styleable#View_saveEnabled
5951     */
5952    public void setSaveEnabled(boolean enabled) {
5953        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
5954    }
5955
5956    /**
5957     * Gets whether the framework should discard touches when the view's
5958     * window is obscured by another visible window.
5959     * Refer to the {@link View} security documentation for more details.
5960     *
5961     * @return True if touch filtering is enabled.
5962     *
5963     * @see #setFilterTouchesWhenObscured(boolean)
5964     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
5965     */
5966    @ViewDebug.ExportedProperty
5967    public boolean getFilterTouchesWhenObscured() {
5968        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
5969    }
5970
5971    /**
5972     * Sets whether the framework should discard touches when the view's
5973     * window is obscured by another visible window.
5974     * Refer to the {@link View} security documentation for more details.
5975     *
5976     * @param enabled True if touch filtering should be enabled.
5977     *
5978     * @see #getFilterTouchesWhenObscured
5979     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
5980     */
5981    public void setFilterTouchesWhenObscured(boolean enabled) {
5982        setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
5983                FILTER_TOUCHES_WHEN_OBSCURED);
5984    }
5985
5986    /**
5987     * Indicates whether the entire hierarchy under this view will save its
5988     * state when a state saving traversal occurs from its parent.  The default
5989     * is true; if false, these views will not be saved unless
5990     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
5991     *
5992     * @return Returns true if the view state saving from parent is enabled, else false.
5993     *
5994     * @see #setSaveFromParentEnabled(boolean)
5995     */
5996    public boolean isSaveFromParentEnabled() {
5997        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
5998    }
5999
6000    /**
6001     * Controls whether the entire hierarchy under this view will save its
6002     * state when a state saving traversal occurs from its parent.  The default
6003     * is true; if false, these views will not be saved unless
6004     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
6005     *
6006     * @param enabled Set to false to <em>disable</em> state saving, or true
6007     * (the default) to allow it.
6008     *
6009     * @see #isSaveFromParentEnabled()
6010     * @see #setId(int)
6011     * @see #onSaveInstanceState()
6012     */
6013    public void setSaveFromParentEnabled(boolean enabled) {
6014        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
6015    }
6016
6017
6018    /**
6019     * Returns whether this View is able to take focus.
6020     *
6021     * @return True if this view can take focus, or false otherwise.
6022     * @attr ref android.R.styleable#View_focusable
6023     */
6024    @ViewDebug.ExportedProperty(category = "focus")
6025    public final boolean isFocusable() {
6026        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
6027    }
6028
6029    /**
6030     * When a view is focusable, it may not want to take focus when in touch mode.
6031     * For example, a button would like focus when the user is navigating via a D-pad
6032     * so that the user can click on it, but once the user starts touching the screen,
6033     * the button shouldn't take focus
6034     * @return Whether the view is focusable in touch mode.
6035     * @attr ref android.R.styleable#View_focusableInTouchMode
6036     */
6037    @ViewDebug.ExportedProperty
6038    public final boolean isFocusableInTouchMode() {
6039        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
6040    }
6041
6042    /**
6043     * Find the nearest view in the specified direction that can take focus.
6044     * This does not actually give focus to that view.
6045     *
6046     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6047     *
6048     * @return The nearest focusable in the specified direction, or null if none
6049     *         can be found.
6050     */
6051    public View focusSearch(int direction) {
6052        if (mParent != null) {
6053            return mParent.focusSearch(this, direction);
6054        } else {
6055            return null;
6056        }
6057    }
6058
6059    /**
6060     * This method is the last chance for the focused view and its ancestors to
6061     * respond to an arrow key. This is called when the focused view did not
6062     * consume the key internally, nor could the view system find a new view in
6063     * the requested direction to give focus to.
6064     *
6065     * @param focused The currently focused view.
6066     * @param direction The direction focus wants to move. One of FOCUS_UP,
6067     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
6068     * @return True if the this view consumed this unhandled move.
6069     */
6070    public boolean dispatchUnhandledMove(View focused, int direction) {
6071        return false;
6072    }
6073
6074    /**
6075     * If a user manually specified the next view id for a particular direction,
6076     * use the root to look up the view.
6077     * @param root The root view of the hierarchy containing this view.
6078     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
6079     * or FOCUS_BACKWARD.
6080     * @return The user specified next view, or null if there is none.
6081     */
6082    View findUserSetNextFocus(View root, int direction) {
6083        switch (direction) {
6084            case FOCUS_LEFT:
6085                if (mNextFocusLeftId == View.NO_ID) return null;
6086                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
6087            case FOCUS_RIGHT:
6088                if (mNextFocusRightId == View.NO_ID) return null;
6089                return findViewInsideOutShouldExist(root, mNextFocusRightId);
6090            case FOCUS_UP:
6091                if (mNextFocusUpId == View.NO_ID) return null;
6092                return findViewInsideOutShouldExist(root, mNextFocusUpId);
6093            case FOCUS_DOWN:
6094                if (mNextFocusDownId == View.NO_ID) return null;
6095                return findViewInsideOutShouldExist(root, mNextFocusDownId);
6096            case FOCUS_FORWARD:
6097                if (mNextFocusForwardId == View.NO_ID) return null;
6098                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
6099            case FOCUS_BACKWARD: {
6100                if (mID == View.NO_ID) return null;
6101                final int id = mID;
6102                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
6103                    @Override
6104                    public boolean apply(View t) {
6105                        return t.mNextFocusForwardId == id;
6106                    }
6107                });
6108            }
6109        }
6110        return null;
6111    }
6112
6113    private View findViewInsideOutShouldExist(View root, final int childViewId) {
6114        View result = root.findViewByPredicateInsideOut(this, new Predicate<View>() {
6115            @Override
6116            public boolean apply(View t) {
6117                return t.mID == childViewId;
6118            }
6119        });
6120
6121        if (result == null) {
6122            Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
6123                    + "by user for id " + childViewId);
6124        }
6125        return result;
6126    }
6127
6128    /**
6129     * Find and return all focusable views that are descendants of this view,
6130     * possibly including this view if it is focusable itself.
6131     *
6132     * @param direction The direction of the focus
6133     * @return A list of focusable views
6134     */
6135    public ArrayList<View> getFocusables(int direction) {
6136        ArrayList<View> result = new ArrayList<View>(24);
6137        addFocusables(result, direction);
6138        return result;
6139    }
6140
6141    /**
6142     * Add any focusable views that are descendants of this view (possibly
6143     * including this view if it is focusable itself) to views.  If we are in touch mode,
6144     * only add views that are also focusable in touch mode.
6145     *
6146     * @param views Focusable views found so far
6147     * @param direction The direction of the focus
6148     */
6149    public void addFocusables(ArrayList<View> views, int direction) {
6150        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
6151    }
6152
6153    /**
6154     * Adds any focusable views that are descendants of this view (possibly
6155     * including this view if it is focusable itself) to views. This method
6156     * adds all focusable views regardless if we are in touch mode or
6157     * only views focusable in touch mode if we are in touch mode or
6158     * only views that can take accessibility focus if accessibility is enabeld
6159     * depending on the focusable mode paramater.
6160     *
6161     * @param views Focusable views found so far or null if all we are interested is
6162     *        the number of focusables.
6163     * @param direction The direction of the focus.
6164     * @param focusableMode The type of focusables to be added.
6165     *
6166     * @see #FOCUSABLES_ALL
6167     * @see #FOCUSABLES_TOUCH_MODE
6168     */
6169    public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
6170        if (views == null) {
6171            return;
6172        }
6173        if (!isFocusable()) {
6174            return;
6175        }
6176        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
6177                && isInTouchMode() && !isFocusableInTouchMode()) {
6178            return;
6179        }
6180        views.add(this);
6181    }
6182
6183    /**
6184     * Finds the Views that contain given text. The containment is case insensitive.
6185     * The search is performed by either the text that the View renders or the content
6186     * description that describes the view for accessibility purposes and the view does
6187     * not render or both. Clients can specify how the search is to be performed via
6188     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
6189     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
6190     *
6191     * @param outViews The output list of matching Views.
6192     * @param searched The text to match against.
6193     *
6194     * @see #FIND_VIEWS_WITH_TEXT
6195     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
6196     * @see #setContentDescription(CharSequence)
6197     */
6198    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
6199        if (getAccessibilityNodeProvider() != null) {
6200            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
6201                outViews.add(this);
6202            }
6203        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
6204                && (searched != null && searched.length() > 0)
6205                && (mContentDescription != null && mContentDescription.length() > 0)) {
6206            String searchedLowerCase = searched.toString().toLowerCase();
6207            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
6208            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
6209                outViews.add(this);
6210            }
6211        }
6212    }
6213
6214    /**
6215     * Find and return all touchable views that are descendants of this view,
6216     * possibly including this view if it is touchable itself.
6217     *
6218     * @return A list of touchable views
6219     */
6220    public ArrayList<View> getTouchables() {
6221        ArrayList<View> result = new ArrayList<View>();
6222        addTouchables(result);
6223        return result;
6224    }
6225
6226    /**
6227     * Add any touchable views that are descendants of this view (possibly
6228     * including this view if it is touchable itself) to views.
6229     *
6230     * @param views Touchable views found so far
6231     */
6232    public void addTouchables(ArrayList<View> views) {
6233        final int viewFlags = mViewFlags;
6234
6235        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
6236                && (viewFlags & ENABLED_MASK) == ENABLED) {
6237            views.add(this);
6238        }
6239    }
6240
6241    /**
6242     * Returns whether this View is accessibility focused.
6243     *
6244     * @return True if this View is accessibility focused.
6245     */
6246    boolean isAccessibilityFocused() {
6247        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
6248    }
6249
6250    /**
6251     * Call this to try to give accessibility focus to this view.
6252     *
6253     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
6254     * returns false or the view is no visible or the view already has accessibility
6255     * focus.
6256     *
6257     * See also {@link #focusSearch(int)}, which is what you call to say that you
6258     * have focus, and you want your parent to look for the next one.
6259     *
6260     * @return Whether this view actually took accessibility focus.
6261     *
6262     * @hide
6263     */
6264    public boolean requestAccessibilityFocus() {
6265        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
6266        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
6267            return false;
6268        }
6269        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6270            return false;
6271        }
6272        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
6273            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
6274            ViewRootImpl viewRootImpl = getViewRootImpl();
6275            if (viewRootImpl != null) {
6276                viewRootImpl.setAccessibilityFocus(this, null);
6277            }
6278            if (mAttachInfo != null) {
6279                Rect rectangle = mAttachInfo.mTmpInvalRect;
6280                getDrawingRect(rectangle);
6281                requestRectangleOnScreen(rectangle);
6282            }
6283            invalidate();
6284            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
6285            notifyAccessibilityStateChanged();
6286            return true;
6287        }
6288        return false;
6289    }
6290
6291    /**
6292     * Call this to try to clear accessibility focus of this view.
6293     *
6294     * See also {@link #focusSearch(int)}, which is what you call to say that you
6295     * have focus, and you want your parent to look for the next one.
6296     *
6297     * @hide
6298     */
6299    public void clearAccessibilityFocus() {
6300        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
6301            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
6302            invalidate();
6303            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
6304            notifyAccessibilityStateChanged();
6305        }
6306        // Clear the global reference of accessibility focus if this
6307        // view or any of its descendants had accessibility focus.
6308        ViewRootImpl viewRootImpl = getViewRootImpl();
6309        if (viewRootImpl != null) {
6310            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
6311            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
6312                viewRootImpl.setAccessibilityFocus(null, null);
6313            }
6314        }
6315    }
6316
6317    private void sendAccessibilityHoverEvent(int eventType) {
6318        // Since we are not delivering to a client accessibility events from not
6319        // important views (unless the clinet request that) we need to fire the
6320        // event from the deepest view exposed to the client. As a consequence if
6321        // the user crosses a not exposed view the client will see enter and exit
6322        // of the exposed predecessor followed by and enter and exit of that same
6323        // predecessor when entering and exiting the not exposed descendant. This
6324        // is fine since the client has a clear idea which view is hovered at the
6325        // price of a couple more events being sent. This is a simple and
6326        // working solution.
6327        View source = this;
6328        while (true) {
6329            if (source.includeForAccessibility()) {
6330                source.sendAccessibilityEvent(eventType);
6331                return;
6332            }
6333            ViewParent parent = source.getParent();
6334            if (parent instanceof View) {
6335                source = (View) parent;
6336            } else {
6337                return;
6338            }
6339        }
6340    }
6341
6342    /**
6343     * Clears accessibility focus without calling any callback methods
6344     * normally invoked in {@link #clearAccessibilityFocus()}. This method
6345     * is used for clearing accessibility focus when giving this focus to
6346     * another view.
6347     */
6348    void clearAccessibilityFocusNoCallbacks() {
6349        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
6350            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
6351            invalidate();
6352        }
6353    }
6354
6355    /**
6356     * Call this to try to give focus to a specific view or to one of its
6357     * descendants.
6358     *
6359     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6360     * false), or if it is focusable and it is not focusable in touch mode
6361     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
6362     *
6363     * See also {@link #focusSearch(int)}, which is what you call to say that you
6364     * have focus, and you want your parent to look for the next one.
6365     *
6366     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
6367     * {@link #FOCUS_DOWN} and <code>null</code>.
6368     *
6369     * @return Whether this view or one of its descendants actually took focus.
6370     */
6371    public final boolean requestFocus() {
6372        return requestFocus(View.FOCUS_DOWN);
6373    }
6374
6375    /**
6376     * Call this to try to give focus to a specific view or to one of its
6377     * descendants and give it a hint about what direction focus is heading.
6378     *
6379     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6380     * false), or if it is focusable and it is not focusable in touch mode
6381     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
6382     *
6383     * See also {@link #focusSearch(int)}, which is what you call to say that you
6384     * have focus, and you want your parent to look for the next one.
6385     *
6386     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
6387     * <code>null</code> set for the previously focused rectangle.
6388     *
6389     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6390     * @return Whether this view or one of its descendants actually took focus.
6391     */
6392    public final boolean requestFocus(int direction) {
6393        return requestFocus(direction, null);
6394    }
6395
6396    /**
6397     * Call this to try to give focus to a specific view or to one of its descendants
6398     * and give it hints about the direction and a specific rectangle that the focus
6399     * is coming from.  The rectangle can help give larger views a finer grained hint
6400     * about where focus is coming from, and therefore, where to show selection, or
6401     * forward focus change internally.
6402     *
6403     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6404     * false), or if it is focusable and it is not focusable in touch mode
6405     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
6406     *
6407     * A View will not take focus if it is not visible.
6408     *
6409     * A View will not take focus if one of its parents has
6410     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
6411     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
6412     *
6413     * See also {@link #focusSearch(int)}, which is what you call to say that you
6414     * have focus, and you want your parent to look for the next one.
6415     *
6416     * You may wish to override this method if your custom {@link View} has an internal
6417     * {@link View} that it wishes to forward the request to.
6418     *
6419     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6420     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
6421     *        to give a finer grained hint about where focus is coming from.  May be null
6422     *        if there is no hint.
6423     * @return Whether this view or one of its descendants actually took focus.
6424     */
6425    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
6426        return requestFocusNoSearch(direction, previouslyFocusedRect);
6427    }
6428
6429    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
6430        // need to be focusable
6431        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
6432                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6433            return false;
6434        }
6435
6436        // need to be focusable in touch mode if in touch mode
6437        if (isInTouchMode() &&
6438            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
6439               return false;
6440        }
6441
6442        // need to not have any parents blocking us
6443        if (hasAncestorThatBlocksDescendantFocus()) {
6444            return false;
6445        }
6446
6447        handleFocusGainInternal(direction, previouslyFocusedRect);
6448        return true;
6449    }
6450
6451    /**
6452     * Call this to try to give focus to a specific view or to one of its descendants. This is a
6453     * special variant of {@link #requestFocus() } that will allow views that are not focuable in
6454     * touch mode to request focus when they are touched.
6455     *
6456     * @return Whether this view or one of its descendants actually took focus.
6457     *
6458     * @see #isInTouchMode()
6459     *
6460     */
6461    public final boolean requestFocusFromTouch() {
6462        // Leave touch mode if we need to
6463        if (isInTouchMode()) {
6464            ViewRootImpl viewRoot = getViewRootImpl();
6465            if (viewRoot != null) {
6466                viewRoot.ensureTouchMode(false);
6467            }
6468        }
6469        return requestFocus(View.FOCUS_DOWN);
6470    }
6471
6472    /**
6473     * @return Whether any ancestor of this view blocks descendant focus.
6474     */
6475    private boolean hasAncestorThatBlocksDescendantFocus() {
6476        ViewParent ancestor = mParent;
6477        while (ancestor instanceof ViewGroup) {
6478            final ViewGroup vgAncestor = (ViewGroup) ancestor;
6479            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
6480                return true;
6481            } else {
6482                ancestor = vgAncestor.getParent();
6483            }
6484        }
6485        return false;
6486    }
6487
6488    /**
6489     * Gets the mode for determining whether this View is important for accessibility
6490     * which is if it fires accessibility events and if it is reported to
6491     * accessibility services that query the screen.
6492     *
6493     * @return The mode for determining whether a View is important for accessibility.
6494     *
6495     * @attr ref android.R.styleable#View_importantForAccessibility
6496     *
6497     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6498     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6499     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6500     */
6501    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
6502            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
6503            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
6504            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
6505        })
6506    public int getImportantForAccessibility() {
6507        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
6508                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
6509    }
6510
6511    /**
6512     * Sets how to determine whether this view is important for accessibility
6513     * which is if it fires accessibility events and if it is reported to
6514     * accessibility services that query the screen.
6515     *
6516     * @param mode How to determine whether this view is important for accessibility.
6517     *
6518     * @attr ref android.R.styleable#View_importantForAccessibility
6519     *
6520     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6521     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6522     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6523     */
6524    public void setImportantForAccessibility(int mode) {
6525        if (mode != getImportantForAccessibility()) {
6526            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
6527            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
6528                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
6529            notifyAccessibilityStateChanged();
6530        }
6531    }
6532
6533    /**
6534     * Gets whether this view should be exposed for accessibility.
6535     *
6536     * @return Whether the view is exposed for accessibility.
6537     *
6538     * @hide
6539     */
6540    public boolean isImportantForAccessibility() {
6541        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
6542                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
6543        switch (mode) {
6544            case IMPORTANT_FOR_ACCESSIBILITY_YES:
6545                return true;
6546            case IMPORTANT_FOR_ACCESSIBILITY_NO:
6547                return false;
6548            case IMPORTANT_FOR_ACCESSIBILITY_AUTO:
6549                return isActionableForAccessibility() || hasListenersForAccessibility()
6550                        || getAccessibilityNodeProvider() != null;
6551            default:
6552                throw new IllegalArgumentException("Unknow important for accessibility mode: "
6553                        + mode);
6554        }
6555    }
6556
6557    /**
6558     * Gets the parent for accessibility purposes. Note that the parent for
6559     * accessibility is not necessary the immediate parent. It is the first
6560     * predecessor that is important for accessibility.
6561     *
6562     * @return The parent for accessibility purposes.
6563     */
6564    public ViewParent getParentForAccessibility() {
6565        if (mParent instanceof View) {
6566            View parentView = (View) mParent;
6567            if (parentView.includeForAccessibility()) {
6568                return mParent;
6569            } else {
6570                return mParent.getParentForAccessibility();
6571            }
6572        }
6573        return null;
6574    }
6575
6576    /**
6577     * Adds the children of a given View for accessibility. Since some Views are
6578     * not important for accessibility the children for accessibility are not
6579     * necessarily direct children of the riew, rather they are the first level of
6580     * descendants important for accessibility.
6581     *
6582     * @param children The list of children for accessibility.
6583     */
6584    public void addChildrenForAccessibility(ArrayList<View> children) {
6585        if (includeForAccessibility()) {
6586            children.add(this);
6587        }
6588    }
6589
6590    /**
6591     * Whether to regard this view for accessibility. A view is regarded for
6592     * accessibility if it is important for accessibility or the querying
6593     * accessibility service has explicitly requested that view not
6594     * important for accessibility are regarded.
6595     *
6596     * @return Whether to regard the view for accessibility.
6597     *
6598     * @hide
6599     */
6600    public boolean includeForAccessibility() {
6601        if (mAttachInfo != null) {
6602            return mAttachInfo.mIncludeNotImportantViews || isImportantForAccessibility();
6603        }
6604        return false;
6605    }
6606
6607    /**
6608     * Returns whether the View is considered actionable from
6609     * accessibility perspective. Such view are important for
6610     * accessiiblity.
6611     *
6612     * @return True if the view is actionable for accessibility.
6613     *
6614     * @hide
6615     */
6616    public boolean isActionableForAccessibility() {
6617        return (isClickable() || isLongClickable() || isFocusable());
6618    }
6619
6620    /**
6621     * Returns whether the View has registered callbacks wich makes it
6622     * important for accessiiblity.
6623     *
6624     * @return True if the view is actionable for accessibility.
6625     */
6626    private boolean hasListenersForAccessibility() {
6627        ListenerInfo info = getListenerInfo();
6628        return mTouchDelegate != null || info.mOnKeyListener != null
6629                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
6630                || info.mOnHoverListener != null || info.mOnDragListener != null;
6631    }
6632
6633    /**
6634     * Notifies accessibility services that some view's important for
6635     * accessibility state has changed. Note that such notifications
6636     * are made at most once every
6637     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
6638     * to avoid unnecessary load to the system. Also once a view has
6639     * made a notifucation this method is a NOP until the notification has
6640     * been sent to clients.
6641     *
6642     * @hide
6643     *
6644     * TODO: Makse sure this method is called for any view state change
6645     *       that is interesting for accessilility purposes.
6646     */
6647    public void notifyAccessibilityStateChanged() {
6648        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
6649            return;
6650        }
6651        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_STATE_CHANGED) == 0) {
6652            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_STATE_CHANGED;
6653            if (mParent != null) {
6654                mParent.childAccessibilityStateChanged(this);
6655            }
6656        }
6657    }
6658
6659    /**
6660     * Reset the state indicating the this view has requested clients
6661     * interested in its accessiblity state to be notified.
6662     *
6663     * @hide
6664     */
6665    public void resetAccessibilityStateChanged() {
6666        mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_STATE_CHANGED;
6667    }
6668
6669    /**
6670     * Performs the specified accessibility action on the view. For
6671     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
6672    * <p>
6673    * If an {@link AccessibilityDelegate} has been specified via calling
6674    * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6675    * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
6676    * is responsible for handling this call.
6677    * </p>
6678     *
6679     * @param action The action to perform.
6680     * @param arguments Optional action arguments.
6681     * @return Whether the action was performed.
6682     */
6683    public boolean performAccessibilityAction(int action, Bundle arguments) {
6684      if (mAccessibilityDelegate != null) {
6685          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
6686      } else {
6687          return performAccessibilityActionInternal(action, arguments);
6688      }
6689    }
6690
6691   /**
6692    * @see #performAccessibilityAction(int, Bundle)
6693    *
6694    * Note: Called from the default {@link AccessibilityDelegate}.
6695    */
6696    boolean performAccessibilityActionInternal(int action, Bundle arguments) {
6697        switch (action) {
6698            case AccessibilityNodeInfo.ACTION_CLICK: {
6699                if (isClickable()) {
6700                    return performClick();
6701                }
6702            } break;
6703            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
6704                if (isLongClickable()) {
6705                    return performLongClick();
6706                }
6707            } break;
6708            case AccessibilityNodeInfo.ACTION_FOCUS: {
6709                if (!hasFocus()) {
6710                    // Get out of touch mode since accessibility
6711                    // wants to move focus around.
6712                    getViewRootImpl().ensureTouchMode(false);
6713                    return requestFocus();
6714                }
6715            } break;
6716            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
6717                if (hasFocus()) {
6718                    clearFocus();
6719                    return !isFocused();
6720                }
6721            } break;
6722            case AccessibilityNodeInfo.ACTION_SELECT: {
6723                if (!isSelected()) {
6724                    setSelected(true);
6725                    return isSelected();
6726                }
6727            } break;
6728            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
6729                if (isSelected()) {
6730                    setSelected(false);
6731                    return !isSelected();
6732                }
6733            } break;
6734            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
6735                if (!isAccessibilityFocused()) {
6736                    return requestAccessibilityFocus();
6737                }
6738            } break;
6739            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
6740                if (isAccessibilityFocused()) {
6741                    clearAccessibilityFocus();
6742                    return true;
6743                }
6744            } break;
6745            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
6746                if (arguments != null) {
6747                    final int granularity = arguments.getInt(
6748                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
6749                    return nextAtGranularity(granularity);
6750                }
6751            } break;
6752            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
6753                if (arguments != null) {
6754                    final int granularity = arguments.getInt(
6755                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
6756                    return previousAtGranularity(granularity);
6757                }
6758            } break;
6759        }
6760        return false;
6761    }
6762
6763    private boolean nextAtGranularity(int granularity) {
6764        CharSequence text = getIterableTextForAccessibility();
6765        if (text == null || text.length() == 0) {
6766            return false;
6767        }
6768        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
6769        if (iterator == null) {
6770            return false;
6771        }
6772        final int current = getAccessibilityCursorPosition();
6773        final int[] range = iterator.following(current);
6774        if (range == null) {
6775            return false;
6776        }
6777        final int start = range[0];
6778        final int end = range[1];
6779        setAccessibilityCursorPosition(end);
6780        sendViewTextTraversedAtGranularityEvent(
6781                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
6782                granularity, start, end);
6783        return true;
6784    }
6785
6786    private boolean previousAtGranularity(int granularity) {
6787        CharSequence text = getIterableTextForAccessibility();
6788        if (text == null || text.length() == 0) {
6789            return false;
6790        }
6791        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
6792        if (iterator == null) {
6793            return false;
6794        }
6795        int current = getAccessibilityCursorPosition();
6796        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
6797            current = text.length();
6798        } else if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
6799            // When traversing by character we always put the cursor after the character
6800            // to ease edit and have to compensate before asking the for previous segment.
6801            current--;
6802        }
6803        final int[] range = iterator.preceding(current);
6804        if (range == null) {
6805            return false;
6806        }
6807        final int start = range[0];
6808        final int end = range[1];
6809        // Always put the cursor after the character to ease edit.
6810        if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
6811            setAccessibilityCursorPosition(end);
6812        } else {
6813            setAccessibilityCursorPosition(start);
6814        }
6815        sendViewTextTraversedAtGranularityEvent(
6816                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
6817                granularity, start, end);
6818        return true;
6819    }
6820
6821    /**
6822     * Gets the text reported for accessibility purposes.
6823     *
6824     * @return The accessibility text.
6825     *
6826     * @hide
6827     */
6828    public CharSequence getIterableTextForAccessibility() {
6829        return getContentDescription();
6830    }
6831
6832    /**
6833     * @hide
6834     */
6835    public int getAccessibilityCursorPosition() {
6836        return mAccessibilityCursorPosition;
6837    }
6838
6839    /**
6840     * @hide
6841     */
6842    public void setAccessibilityCursorPosition(int position) {
6843        mAccessibilityCursorPosition = position;
6844    }
6845
6846    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
6847            int fromIndex, int toIndex) {
6848        if (mParent == null) {
6849            return;
6850        }
6851        AccessibilityEvent event = AccessibilityEvent.obtain(
6852                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
6853        onInitializeAccessibilityEvent(event);
6854        onPopulateAccessibilityEvent(event);
6855        event.setFromIndex(fromIndex);
6856        event.setToIndex(toIndex);
6857        event.setAction(action);
6858        event.setMovementGranularity(granularity);
6859        mParent.requestSendAccessibilityEvent(this, event);
6860    }
6861
6862    /**
6863     * @hide
6864     */
6865    public TextSegmentIterator getIteratorForGranularity(int granularity) {
6866        switch (granularity) {
6867            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
6868                CharSequence text = getIterableTextForAccessibility();
6869                if (text != null && text.length() > 0) {
6870                    CharacterTextSegmentIterator iterator =
6871                        CharacterTextSegmentIterator.getInstance(
6872                                mContext.getResources().getConfiguration().locale);
6873                    iterator.initialize(text.toString());
6874                    return iterator;
6875                }
6876            } break;
6877            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
6878                CharSequence text = getIterableTextForAccessibility();
6879                if (text != null && text.length() > 0) {
6880                    WordTextSegmentIterator iterator =
6881                        WordTextSegmentIterator.getInstance(
6882                                mContext.getResources().getConfiguration().locale);
6883                    iterator.initialize(text.toString());
6884                    return iterator;
6885                }
6886            } break;
6887            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
6888                CharSequence text = getIterableTextForAccessibility();
6889                if (text != null && text.length() > 0) {
6890                    ParagraphTextSegmentIterator iterator =
6891                        ParagraphTextSegmentIterator.getInstance();
6892                    iterator.initialize(text.toString());
6893                    return iterator;
6894                }
6895            } break;
6896        }
6897        return null;
6898    }
6899
6900    /**
6901     * @hide
6902     */
6903    public void dispatchStartTemporaryDetach() {
6904        clearAccessibilityFocus();
6905        clearDisplayList();
6906
6907        onStartTemporaryDetach();
6908    }
6909
6910    /**
6911     * This is called when a container is going to temporarily detach a child, with
6912     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
6913     * It will either be followed by {@link #onFinishTemporaryDetach()} or
6914     * {@link #onDetachedFromWindow()} when the container is done.
6915     */
6916    public void onStartTemporaryDetach() {
6917        removeUnsetPressCallback();
6918        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
6919    }
6920
6921    /**
6922     * @hide
6923     */
6924    public void dispatchFinishTemporaryDetach() {
6925        onFinishTemporaryDetach();
6926    }
6927
6928    /**
6929     * Called after {@link #onStartTemporaryDetach} when the container is done
6930     * changing the view.
6931     */
6932    public void onFinishTemporaryDetach() {
6933    }
6934
6935    /**
6936     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
6937     * for this view's window.  Returns null if the view is not currently attached
6938     * to the window.  Normally you will not need to use this directly, but
6939     * just use the standard high-level event callbacks like
6940     * {@link #onKeyDown(int, KeyEvent)}.
6941     */
6942    public KeyEvent.DispatcherState getKeyDispatcherState() {
6943        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
6944    }
6945
6946    /**
6947     * Dispatch a key event before it is processed by any input method
6948     * associated with the view hierarchy.  This can be used to intercept
6949     * key events in special situations before the IME consumes them; a
6950     * typical example would be handling the BACK key to update the application's
6951     * UI instead of allowing the IME to see it and close itself.
6952     *
6953     * @param event The key event to be dispatched.
6954     * @return True if the event was handled, false otherwise.
6955     */
6956    public boolean dispatchKeyEventPreIme(KeyEvent event) {
6957        return onKeyPreIme(event.getKeyCode(), event);
6958    }
6959
6960    /**
6961     * Dispatch a key event to the next view on the focus path. This path runs
6962     * from the top of the view tree down to the currently focused view. If this
6963     * view has focus, it will dispatch to itself. Otherwise it will dispatch
6964     * the next node down the focus path. This method also fires any key
6965     * listeners.
6966     *
6967     * @param event The key event to be dispatched.
6968     * @return True if the event was handled, false otherwise.
6969     */
6970    public boolean dispatchKeyEvent(KeyEvent event) {
6971        if (mInputEventConsistencyVerifier != null) {
6972            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
6973        }
6974
6975        // Give any attached key listener a first crack at the event.
6976        //noinspection SimplifiableIfStatement
6977        ListenerInfo li = mListenerInfo;
6978        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
6979                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
6980            return true;
6981        }
6982
6983        if (event.dispatch(this, mAttachInfo != null
6984                ? mAttachInfo.mKeyDispatchState : null, this)) {
6985            return true;
6986        }
6987
6988        if (mInputEventConsistencyVerifier != null) {
6989            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
6990        }
6991        return false;
6992    }
6993
6994    /**
6995     * Dispatches a key shortcut event.
6996     *
6997     * @param event The key event to be dispatched.
6998     * @return True if the event was handled by the view, false otherwise.
6999     */
7000    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7001        return onKeyShortcut(event.getKeyCode(), event);
7002    }
7003
7004    /**
7005     * Pass the touch screen motion event down to the target view, or this
7006     * view if it is the target.
7007     *
7008     * @param event The motion event to be dispatched.
7009     * @return True if the event was handled by the view, false otherwise.
7010     */
7011    public boolean dispatchTouchEvent(MotionEvent event) {
7012        if (mInputEventConsistencyVerifier != null) {
7013            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
7014        }
7015
7016        if (onFilterTouchEventForSecurity(event)) {
7017            //noinspection SimplifiableIfStatement
7018            ListenerInfo li = mListenerInfo;
7019            if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
7020                    && li.mOnTouchListener.onTouch(this, event)) {
7021                return true;
7022            }
7023
7024            if (onTouchEvent(event)) {
7025                return true;
7026            }
7027        }
7028
7029        if (mInputEventConsistencyVerifier != null) {
7030            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7031        }
7032        return false;
7033    }
7034
7035    /**
7036     * Filter the touch event to apply security policies.
7037     *
7038     * @param event The motion event to be filtered.
7039     * @return True if the event should be dispatched, false if the event should be dropped.
7040     *
7041     * @see #getFilterTouchesWhenObscured
7042     */
7043    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
7044        //noinspection RedundantIfStatement
7045        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
7046                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
7047            // Window is obscured, drop this touch.
7048            return false;
7049        }
7050        return true;
7051    }
7052
7053    /**
7054     * Pass a trackball motion event down to the focused view.
7055     *
7056     * @param event The motion event to be dispatched.
7057     * @return True if the event was handled by the view, false otherwise.
7058     */
7059    public boolean dispatchTrackballEvent(MotionEvent event) {
7060        if (mInputEventConsistencyVerifier != null) {
7061            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
7062        }
7063
7064        return onTrackballEvent(event);
7065    }
7066
7067    /**
7068     * Dispatch a generic motion event.
7069     * <p>
7070     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
7071     * are delivered to the view under the pointer.  All other generic motion events are
7072     * delivered to the focused view.  Hover events are handled specially and are delivered
7073     * to {@link #onHoverEvent(MotionEvent)}.
7074     * </p>
7075     *
7076     * @param event The motion event to be dispatched.
7077     * @return True if the event was handled by the view, false otherwise.
7078     */
7079    public boolean dispatchGenericMotionEvent(MotionEvent event) {
7080        if (mInputEventConsistencyVerifier != null) {
7081            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
7082        }
7083
7084        final int source = event.getSource();
7085        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
7086            final int action = event.getAction();
7087            if (action == MotionEvent.ACTION_HOVER_ENTER
7088                    || action == MotionEvent.ACTION_HOVER_MOVE
7089                    || action == MotionEvent.ACTION_HOVER_EXIT) {
7090                if (dispatchHoverEvent(event)) {
7091                    return true;
7092                }
7093            } else if (dispatchGenericPointerEvent(event)) {
7094                return true;
7095            }
7096        } else if (dispatchGenericFocusedEvent(event)) {
7097            return true;
7098        }
7099
7100        if (dispatchGenericMotionEventInternal(event)) {
7101            return true;
7102        }
7103
7104        if (mInputEventConsistencyVerifier != null) {
7105            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7106        }
7107        return false;
7108    }
7109
7110    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
7111        //noinspection SimplifiableIfStatement
7112        ListenerInfo li = mListenerInfo;
7113        if (li != null && li.mOnGenericMotionListener != null
7114                && (mViewFlags & ENABLED_MASK) == ENABLED
7115                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
7116            return true;
7117        }
7118
7119        if (onGenericMotionEvent(event)) {
7120            return true;
7121        }
7122
7123        if (mInputEventConsistencyVerifier != null) {
7124            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7125        }
7126        return false;
7127    }
7128
7129    /**
7130     * Dispatch a hover event.
7131     * <p>
7132     * Do not call this method directly.
7133     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
7134     * </p>
7135     *
7136     * @param event The motion event to be dispatched.
7137     * @return True if the event was handled by the view, false otherwise.
7138     */
7139    protected boolean dispatchHoverEvent(MotionEvent event) {
7140        //noinspection SimplifiableIfStatement
7141        ListenerInfo li = mListenerInfo;
7142        if (li != null && li.mOnHoverListener != null
7143                && (mViewFlags & ENABLED_MASK) == ENABLED
7144                && li.mOnHoverListener.onHover(this, event)) {
7145            return true;
7146        }
7147
7148        return onHoverEvent(event);
7149    }
7150
7151    /**
7152     * Returns true if the view has a child to which it has recently sent
7153     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
7154     * it does not have a hovered child, then it must be the innermost hovered view.
7155     * @hide
7156     */
7157    protected boolean hasHoveredChild() {
7158        return false;
7159    }
7160
7161    /**
7162     * Dispatch a generic motion event to the view under the first pointer.
7163     * <p>
7164     * Do not call this method directly.
7165     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
7166     * </p>
7167     *
7168     * @param event The motion event to be dispatched.
7169     * @return True if the event was handled by the view, false otherwise.
7170     */
7171    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
7172        return false;
7173    }
7174
7175    /**
7176     * Dispatch a generic motion event to the currently focused view.
7177     * <p>
7178     * Do not call this method directly.
7179     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
7180     * </p>
7181     *
7182     * @param event The motion event to be dispatched.
7183     * @return True if the event was handled by the view, false otherwise.
7184     */
7185    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
7186        return false;
7187    }
7188
7189    /**
7190     * Dispatch a pointer event.
7191     * <p>
7192     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
7193     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
7194     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
7195     * and should not be expected to handle other pointing device features.
7196     * </p>
7197     *
7198     * @param event The motion event to be dispatched.
7199     * @return True if the event was handled by the view, false otherwise.
7200     * @hide
7201     */
7202    public final boolean dispatchPointerEvent(MotionEvent event) {
7203        if (event.isTouchEvent()) {
7204            return dispatchTouchEvent(event);
7205        } else {
7206            return dispatchGenericMotionEvent(event);
7207        }
7208    }
7209
7210    /**
7211     * Called when the window containing this view gains or loses window focus.
7212     * ViewGroups should override to route to their children.
7213     *
7214     * @param hasFocus True if the window containing this view now has focus,
7215     *        false otherwise.
7216     */
7217    public void dispatchWindowFocusChanged(boolean hasFocus) {
7218        onWindowFocusChanged(hasFocus);
7219    }
7220
7221    /**
7222     * Called when the window containing this view gains or loses focus.  Note
7223     * that this is separate from view focus: to receive key events, both
7224     * your view and its window must have focus.  If a window is displayed
7225     * on top of yours that takes input focus, then your own window will lose
7226     * focus but the view focus will remain unchanged.
7227     *
7228     * @param hasWindowFocus True if the window containing this view now has
7229     *        focus, false otherwise.
7230     */
7231    public void onWindowFocusChanged(boolean hasWindowFocus) {
7232        InputMethodManager imm = InputMethodManager.peekInstance();
7233        if (!hasWindowFocus) {
7234            if (isPressed()) {
7235                setPressed(false);
7236            }
7237            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
7238                imm.focusOut(this);
7239            }
7240            removeLongPressCallback();
7241            removeTapCallback();
7242            onFocusLost();
7243        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
7244            imm.focusIn(this);
7245        }
7246        refreshDrawableState();
7247    }
7248
7249    /**
7250     * Returns true if this view is in a window that currently has window focus.
7251     * Note that this is not the same as the view itself having focus.
7252     *
7253     * @return True if this view is in a window that currently has window focus.
7254     */
7255    public boolean hasWindowFocus() {
7256        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
7257    }
7258
7259    /**
7260     * Dispatch a view visibility change down the view hierarchy.
7261     * ViewGroups should override to route to their children.
7262     * @param changedView The view whose visibility changed. Could be 'this' or
7263     * an ancestor view.
7264     * @param visibility The new visibility of changedView: {@link #VISIBLE},
7265     * {@link #INVISIBLE} or {@link #GONE}.
7266     */
7267    protected void dispatchVisibilityChanged(View changedView, int visibility) {
7268        onVisibilityChanged(changedView, visibility);
7269    }
7270
7271    /**
7272     * Called when the visibility of the view or an ancestor of the view is changed.
7273     * @param changedView The view whose visibility changed. Could be 'this' or
7274     * an ancestor view.
7275     * @param visibility The new visibility of changedView: {@link #VISIBLE},
7276     * {@link #INVISIBLE} or {@link #GONE}.
7277     */
7278    protected void onVisibilityChanged(View changedView, int visibility) {
7279        if (visibility == VISIBLE) {
7280            if (mAttachInfo != null) {
7281                initialAwakenScrollBars();
7282            } else {
7283                mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
7284            }
7285        }
7286    }
7287
7288    /**
7289     * Dispatch a hint about whether this view is displayed. For instance, when
7290     * a View moves out of the screen, it might receives a display hint indicating
7291     * the view is not displayed. Applications should not <em>rely</em> on this hint
7292     * as there is no guarantee that they will receive one.
7293     *
7294     * @param hint A hint about whether or not this view is displayed:
7295     * {@link #VISIBLE} or {@link #INVISIBLE}.
7296     */
7297    public void dispatchDisplayHint(int hint) {
7298        onDisplayHint(hint);
7299    }
7300
7301    /**
7302     * Gives this view a hint about whether is displayed or not. For instance, when
7303     * a View moves out of the screen, it might receives a display hint indicating
7304     * the view is not displayed. Applications should not <em>rely</em> on this hint
7305     * as there is no guarantee that they will receive one.
7306     *
7307     * @param hint A hint about whether or not this view is displayed:
7308     * {@link #VISIBLE} or {@link #INVISIBLE}.
7309     */
7310    protected void onDisplayHint(int hint) {
7311    }
7312
7313    /**
7314     * Dispatch a window visibility change down the view hierarchy.
7315     * ViewGroups should override to route to their children.
7316     *
7317     * @param visibility The new visibility of the window.
7318     *
7319     * @see #onWindowVisibilityChanged(int)
7320     */
7321    public void dispatchWindowVisibilityChanged(int visibility) {
7322        onWindowVisibilityChanged(visibility);
7323    }
7324
7325    /**
7326     * Called when the window containing has change its visibility
7327     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
7328     * that this tells you whether or not your window is being made visible
7329     * to the window manager; this does <em>not</em> tell you whether or not
7330     * your window is obscured by other windows on the screen, even if it
7331     * is itself visible.
7332     *
7333     * @param visibility The new visibility of the window.
7334     */
7335    protected void onWindowVisibilityChanged(int visibility) {
7336        if (visibility == VISIBLE) {
7337            initialAwakenScrollBars();
7338        }
7339    }
7340
7341    /**
7342     * Returns the current visibility of the window this view is attached to
7343     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
7344     *
7345     * @return Returns the current visibility of the view's window.
7346     */
7347    public int getWindowVisibility() {
7348        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
7349    }
7350
7351    /**
7352     * Retrieve the overall visible display size in which the window this view is
7353     * attached to has been positioned in.  This takes into account screen
7354     * decorations above the window, for both cases where the window itself
7355     * is being position inside of them or the window is being placed under
7356     * then and covered insets are used for the window to position its content
7357     * inside.  In effect, this tells you the available area where content can
7358     * be placed and remain visible to users.
7359     *
7360     * <p>This function requires an IPC back to the window manager to retrieve
7361     * the requested information, so should not be used in performance critical
7362     * code like drawing.
7363     *
7364     * @param outRect Filled in with the visible display frame.  If the view
7365     * is not attached to a window, this is simply the raw display size.
7366     */
7367    public void getWindowVisibleDisplayFrame(Rect outRect) {
7368        if (mAttachInfo != null) {
7369            try {
7370                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
7371            } catch (RemoteException e) {
7372                return;
7373            }
7374            // XXX This is really broken, and probably all needs to be done
7375            // in the window manager, and we need to know more about whether
7376            // we want the area behind or in front of the IME.
7377            final Rect insets = mAttachInfo.mVisibleInsets;
7378            outRect.left += insets.left;
7379            outRect.top += insets.top;
7380            outRect.right -= insets.right;
7381            outRect.bottom -= insets.bottom;
7382            return;
7383        }
7384        // The view is not attached to a display so we don't have a context.
7385        // Make a best guess about the display size.
7386        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
7387        d.getRectSize(outRect);
7388    }
7389
7390    /**
7391     * Dispatch a notification about a resource configuration change down
7392     * the view hierarchy.
7393     * ViewGroups should override to route to their children.
7394     *
7395     * @param newConfig The new resource configuration.
7396     *
7397     * @see #onConfigurationChanged(android.content.res.Configuration)
7398     */
7399    public void dispatchConfigurationChanged(Configuration newConfig) {
7400        onConfigurationChanged(newConfig);
7401    }
7402
7403    /**
7404     * Called when the current configuration of the resources being used
7405     * by the application have changed.  You can use this to decide when
7406     * to reload resources that can changed based on orientation and other
7407     * configuration characterstics.  You only need to use this if you are
7408     * not relying on the normal {@link android.app.Activity} mechanism of
7409     * recreating the activity instance upon a configuration change.
7410     *
7411     * @param newConfig The new resource configuration.
7412     */
7413    protected void onConfigurationChanged(Configuration newConfig) {
7414    }
7415
7416    /**
7417     * Private function to aggregate all per-view attributes in to the view
7418     * root.
7419     */
7420    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7421        performCollectViewAttributes(attachInfo, visibility);
7422    }
7423
7424    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7425        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
7426            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
7427                attachInfo.mKeepScreenOn = true;
7428            }
7429            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
7430            ListenerInfo li = mListenerInfo;
7431            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
7432                attachInfo.mHasSystemUiListeners = true;
7433            }
7434        }
7435    }
7436
7437    void needGlobalAttributesUpdate(boolean force) {
7438        final AttachInfo ai = mAttachInfo;
7439        if (ai != null && !ai.mRecomputeGlobalAttributes) {
7440            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
7441                    || ai.mHasSystemUiListeners) {
7442                ai.mRecomputeGlobalAttributes = true;
7443            }
7444        }
7445    }
7446
7447    /**
7448     * Returns whether the device is currently in touch mode.  Touch mode is entered
7449     * once the user begins interacting with the device by touch, and affects various
7450     * things like whether focus is always visible to the user.
7451     *
7452     * @return Whether the device is in touch mode.
7453     */
7454    @ViewDebug.ExportedProperty
7455    public boolean isInTouchMode() {
7456        if (mAttachInfo != null) {
7457            return mAttachInfo.mInTouchMode;
7458        } else {
7459            return ViewRootImpl.isInTouchMode();
7460        }
7461    }
7462
7463    /**
7464     * Returns the context the view is running in, through which it can
7465     * access the current theme, resources, etc.
7466     *
7467     * @return The view's Context.
7468     */
7469    @ViewDebug.CapturedViewProperty
7470    public final Context getContext() {
7471        return mContext;
7472    }
7473
7474    /**
7475     * Handle a key event before it is processed by any input method
7476     * associated with the view hierarchy.  This can be used to intercept
7477     * key events in special situations before the IME consumes them; a
7478     * typical example would be handling the BACK key to update the application's
7479     * UI instead of allowing the IME to see it and close itself.
7480     *
7481     * @param keyCode The value in event.getKeyCode().
7482     * @param event Description of the key event.
7483     * @return If you handled the event, return true. If you want to allow the
7484     *         event to be handled by the next receiver, return false.
7485     */
7486    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
7487        return false;
7488    }
7489
7490    /**
7491     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
7492     * KeyEvent.Callback.onKeyDown()}: perform press of the view
7493     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
7494     * is released, if the view is enabled and clickable.
7495     *
7496     * <p>Key presses in software keyboards will generally NOT trigger this listener,
7497     * although some may elect to do so in some situations. Do not rely on this to
7498     * catch software key presses.
7499     *
7500     * @param keyCode A key code that represents the button pressed, from
7501     *                {@link android.view.KeyEvent}.
7502     * @param event   The KeyEvent object that defines the button action.
7503     */
7504    public boolean onKeyDown(int keyCode, KeyEvent event) {
7505        boolean result = false;
7506
7507        switch (keyCode) {
7508            case KeyEvent.KEYCODE_DPAD_CENTER:
7509            case KeyEvent.KEYCODE_ENTER: {
7510                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7511                    return true;
7512                }
7513                // Long clickable items don't necessarily have to be clickable
7514                if (((mViewFlags & CLICKABLE) == CLICKABLE ||
7515                        (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
7516                        (event.getRepeatCount() == 0)) {
7517                    setPressed(true);
7518                    checkForLongClick(0);
7519                    return true;
7520                }
7521                break;
7522            }
7523        }
7524        return result;
7525    }
7526
7527    /**
7528     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
7529     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
7530     * the event).
7531     * <p>Key presses in software keyboards will generally NOT trigger this listener,
7532     * although some may elect to do so in some situations. Do not rely on this to
7533     * catch software key presses.
7534     */
7535    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
7536        return false;
7537    }
7538
7539    /**
7540     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
7541     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
7542     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
7543     * {@link KeyEvent#KEYCODE_ENTER} is released.
7544     * <p>Key presses in software keyboards will generally NOT trigger this listener,
7545     * although some may elect to do so in some situations. Do not rely on this to
7546     * catch software key presses.
7547     *
7548     * @param keyCode A key code that represents the button pressed, from
7549     *                {@link android.view.KeyEvent}.
7550     * @param event   The KeyEvent object that defines the button action.
7551     */
7552    public boolean onKeyUp(int keyCode, KeyEvent event) {
7553        boolean result = false;
7554
7555        switch (keyCode) {
7556            case KeyEvent.KEYCODE_DPAD_CENTER:
7557            case KeyEvent.KEYCODE_ENTER: {
7558                if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7559                    return true;
7560                }
7561                if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
7562                    setPressed(false);
7563
7564                    if (!mHasPerformedLongPress) {
7565                        // This is a tap, so remove the longpress check
7566                        removeLongPressCallback();
7567
7568                        result = performClick();
7569                    }
7570                }
7571                break;
7572            }
7573        }
7574        return result;
7575    }
7576
7577    /**
7578     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
7579     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
7580     * the event).
7581     * <p>Key presses in software keyboards will generally NOT trigger this listener,
7582     * although some may elect to do so in some situations. Do not rely on this to
7583     * catch software key presses.
7584     *
7585     * @param keyCode     A key code that represents the button pressed, from
7586     *                    {@link android.view.KeyEvent}.
7587     * @param repeatCount The number of times the action was made.
7588     * @param event       The KeyEvent object that defines the button action.
7589     */
7590    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
7591        return false;
7592    }
7593
7594    /**
7595     * Called on the focused view when a key shortcut event is not handled.
7596     * Override this method to implement local key shortcuts for the View.
7597     * Key shortcuts can also be implemented by setting the
7598     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
7599     *
7600     * @param keyCode The value in event.getKeyCode().
7601     * @param event Description of the key event.
7602     * @return If you handled the event, return true. If you want to allow the
7603     *         event to be handled by the next receiver, return false.
7604     */
7605    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
7606        return false;
7607    }
7608
7609    /**
7610     * Check whether the called view is a text editor, in which case it
7611     * would make sense to automatically display a soft input window for
7612     * it.  Subclasses should override this if they implement
7613     * {@link #onCreateInputConnection(EditorInfo)} to return true if
7614     * a call on that method would return a non-null InputConnection, and
7615     * they are really a first-class editor that the user would normally
7616     * start typing on when the go into a window containing your view.
7617     *
7618     * <p>The default implementation always returns false.  This does
7619     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
7620     * will not be called or the user can not otherwise perform edits on your
7621     * view; it is just a hint to the system that this is not the primary
7622     * purpose of this view.
7623     *
7624     * @return Returns true if this view is a text editor, else false.
7625     */
7626    public boolean onCheckIsTextEditor() {
7627        return false;
7628    }
7629
7630    /**
7631     * Create a new InputConnection for an InputMethod to interact
7632     * with the view.  The default implementation returns null, since it doesn't
7633     * support input methods.  You can override this to implement such support.
7634     * This is only needed for views that take focus and text input.
7635     *
7636     * <p>When implementing this, you probably also want to implement
7637     * {@link #onCheckIsTextEditor()} to indicate you will return a
7638     * non-null InputConnection.
7639     *
7640     * @param outAttrs Fill in with attribute information about the connection.
7641     */
7642    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
7643        return null;
7644    }
7645
7646    /**
7647     * Called by the {@link android.view.inputmethod.InputMethodManager}
7648     * when a view who is not the current
7649     * input connection target is trying to make a call on the manager.  The
7650     * default implementation returns false; you can override this to return
7651     * true for certain views if you are performing InputConnection proxying
7652     * to them.
7653     * @param view The View that is making the InputMethodManager call.
7654     * @return Return true to allow the call, false to reject.
7655     */
7656    public boolean checkInputConnectionProxy(View view) {
7657        return false;
7658    }
7659
7660    /**
7661     * Show the context menu for this view. It is not safe to hold on to the
7662     * menu after returning from this method.
7663     *
7664     * You should normally not overload this method. Overload
7665     * {@link #onCreateContextMenu(ContextMenu)} or define an
7666     * {@link OnCreateContextMenuListener} to add items to the context menu.
7667     *
7668     * @param menu The context menu to populate
7669     */
7670    public void createContextMenu(ContextMenu menu) {
7671        ContextMenuInfo menuInfo = getContextMenuInfo();
7672
7673        // Sets the current menu info so all items added to menu will have
7674        // my extra info set.
7675        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
7676
7677        onCreateContextMenu(menu);
7678        ListenerInfo li = mListenerInfo;
7679        if (li != null && li.mOnCreateContextMenuListener != null) {
7680            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
7681        }
7682
7683        // Clear the extra information so subsequent items that aren't mine don't
7684        // have my extra info.
7685        ((MenuBuilder)menu).setCurrentMenuInfo(null);
7686
7687        if (mParent != null) {
7688            mParent.createContextMenu(menu);
7689        }
7690    }
7691
7692    /**
7693     * Views should implement this if they have extra information to associate
7694     * with the context menu. The return result is supplied as a parameter to
7695     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
7696     * callback.
7697     *
7698     * @return Extra information about the item for which the context menu
7699     *         should be shown. This information will vary across different
7700     *         subclasses of View.
7701     */
7702    protected ContextMenuInfo getContextMenuInfo() {
7703        return null;
7704    }
7705
7706    /**
7707     * Views should implement this if the view itself is going to add items to
7708     * the context menu.
7709     *
7710     * @param menu the context menu to populate
7711     */
7712    protected void onCreateContextMenu(ContextMenu menu) {
7713    }
7714
7715    /**
7716     * Implement this method to handle trackball motion events.  The
7717     * <em>relative</em> movement of the trackball since the last event
7718     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
7719     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
7720     * that a movement of 1 corresponds to the user pressing one DPAD key (so
7721     * they will often be fractional values, representing the more fine-grained
7722     * movement information available from a trackball).
7723     *
7724     * @param event The motion event.
7725     * @return True if the event was handled, false otherwise.
7726     */
7727    public boolean onTrackballEvent(MotionEvent event) {
7728        return false;
7729    }
7730
7731    /**
7732     * Implement this method to handle generic motion events.
7733     * <p>
7734     * Generic motion events describe joystick movements, mouse hovers, track pad
7735     * touches, scroll wheel movements and other input events.  The
7736     * {@link MotionEvent#getSource() source} of the motion event specifies
7737     * the class of input that was received.  Implementations of this method
7738     * must examine the bits in the source before processing the event.
7739     * The following code example shows how this is done.
7740     * </p><p>
7741     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
7742     * are delivered to the view under the pointer.  All other generic motion events are
7743     * delivered to the focused view.
7744     * </p>
7745     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
7746     *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
7747     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
7748     *             // process the joystick movement...
7749     *             return true;
7750     *         }
7751     *     }
7752     *     if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_POINTER) != 0) {
7753     *         switch (event.getAction()) {
7754     *             case MotionEvent.ACTION_HOVER_MOVE:
7755     *                 // process the mouse hover movement...
7756     *                 return true;
7757     *             case MotionEvent.ACTION_SCROLL:
7758     *                 // process the scroll wheel movement...
7759     *                 return true;
7760     *         }
7761     *     }
7762     *     return super.onGenericMotionEvent(event);
7763     * }</pre>
7764     *
7765     * @param event The generic motion event being processed.
7766     * @return True if the event was handled, false otherwise.
7767     */
7768    public boolean onGenericMotionEvent(MotionEvent event) {
7769        return false;
7770    }
7771
7772    /**
7773     * Implement this method to handle hover events.
7774     * <p>
7775     * This method is called whenever a pointer is hovering into, over, or out of the
7776     * bounds of a view and the view is not currently being touched.
7777     * Hover events are represented as pointer events with action
7778     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
7779     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
7780     * </p>
7781     * <ul>
7782     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
7783     * when the pointer enters the bounds of the view.</li>
7784     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
7785     * when the pointer has already entered the bounds of the view and has moved.</li>
7786     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
7787     * when the pointer has exited the bounds of the view or when the pointer is
7788     * about to go down due to a button click, tap, or similar user action that
7789     * causes the view to be touched.</li>
7790     * </ul>
7791     * <p>
7792     * The view should implement this method to return true to indicate that it is
7793     * handling the hover event, such as by changing its drawable state.
7794     * </p><p>
7795     * The default implementation calls {@link #setHovered} to update the hovered state
7796     * of the view when a hover enter or hover exit event is received, if the view
7797     * is enabled and is clickable.  The default implementation also sends hover
7798     * accessibility events.
7799     * </p>
7800     *
7801     * @param event The motion event that describes the hover.
7802     * @return True if the view handled the hover event.
7803     *
7804     * @see #isHovered
7805     * @see #setHovered
7806     * @see #onHoverChanged
7807     */
7808    public boolean onHoverEvent(MotionEvent event) {
7809        // The root view may receive hover (or touch) events that are outside the bounds of
7810        // the window.  This code ensures that we only send accessibility events for
7811        // hovers that are actually within the bounds of the root view.
7812        final int action = event.getActionMasked();
7813        if (!mSendingHoverAccessibilityEvents) {
7814            if ((action == MotionEvent.ACTION_HOVER_ENTER
7815                    || action == MotionEvent.ACTION_HOVER_MOVE)
7816                    && !hasHoveredChild()
7817                    && pointInView(event.getX(), event.getY())) {
7818                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
7819                mSendingHoverAccessibilityEvents = true;
7820            }
7821        } else {
7822            if (action == MotionEvent.ACTION_HOVER_EXIT
7823                    || (action == MotionEvent.ACTION_MOVE
7824                            && !pointInView(event.getX(), event.getY()))) {
7825                mSendingHoverAccessibilityEvents = false;
7826                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
7827                // If the window does not have input focus we take away accessibility
7828                // focus as soon as the user stop hovering over the view.
7829                if (mAttachInfo != null && !mAttachInfo.mHasWindowFocus) {
7830                    getViewRootImpl().setAccessibilityFocus(null, null);
7831                }
7832            }
7833        }
7834
7835        if (isHoverable()) {
7836            switch (action) {
7837                case MotionEvent.ACTION_HOVER_ENTER:
7838                    setHovered(true);
7839                    break;
7840                case MotionEvent.ACTION_HOVER_EXIT:
7841                    setHovered(false);
7842                    break;
7843            }
7844
7845            // Dispatch the event to onGenericMotionEvent before returning true.
7846            // This is to provide compatibility with existing applications that
7847            // handled HOVER_MOVE events in onGenericMotionEvent and that would
7848            // break because of the new default handling for hoverable views
7849            // in onHoverEvent.
7850            // Note that onGenericMotionEvent will be called by default when
7851            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
7852            dispatchGenericMotionEventInternal(event);
7853            return true;
7854        }
7855
7856        return false;
7857    }
7858
7859    /**
7860     * Returns true if the view should handle {@link #onHoverEvent}
7861     * by calling {@link #setHovered} to change its hovered state.
7862     *
7863     * @return True if the view is hoverable.
7864     */
7865    private boolean isHoverable() {
7866        final int viewFlags = mViewFlags;
7867        if ((viewFlags & ENABLED_MASK) == DISABLED) {
7868            return false;
7869        }
7870
7871        return (viewFlags & CLICKABLE) == CLICKABLE
7872                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7873    }
7874
7875    /**
7876     * Returns true if the view is currently hovered.
7877     *
7878     * @return True if the view is currently hovered.
7879     *
7880     * @see #setHovered
7881     * @see #onHoverChanged
7882     */
7883    @ViewDebug.ExportedProperty
7884    public boolean isHovered() {
7885        return (mPrivateFlags & PFLAG_HOVERED) != 0;
7886    }
7887
7888    /**
7889     * Sets whether the view is currently hovered.
7890     * <p>
7891     * Calling this method also changes the drawable state of the view.  This
7892     * enables the view to react to hover by using different drawable resources
7893     * to change its appearance.
7894     * </p><p>
7895     * The {@link #onHoverChanged} method is called when the hovered state changes.
7896     * </p>
7897     *
7898     * @param hovered True if the view is hovered.
7899     *
7900     * @see #isHovered
7901     * @see #onHoverChanged
7902     */
7903    public void setHovered(boolean hovered) {
7904        if (hovered) {
7905            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
7906                mPrivateFlags |= PFLAG_HOVERED;
7907                refreshDrawableState();
7908                onHoverChanged(true);
7909            }
7910        } else {
7911            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
7912                mPrivateFlags &= ~PFLAG_HOVERED;
7913                refreshDrawableState();
7914                onHoverChanged(false);
7915            }
7916        }
7917    }
7918
7919    /**
7920     * Implement this method to handle hover state changes.
7921     * <p>
7922     * This method is called whenever the hover state changes as a result of a
7923     * call to {@link #setHovered}.
7924     * </p>
7925     *
7926     * @param hovered The current hover state, as returned by {@link #isHovered}.
7927     *
7928     * @see #isHovered
7929     * @see #setHovered
7930     */
7931    public void onHoverChanged(boolean hovered) {
7932    }
7933
7934    /**
7935     * Implement this method to handle touch screen motion events.
7936     *
7937     * @param event The motion event.
7938     * @return True if the event was handled, false otherwise.
7939     */
7940    public boolean onTouchEvent(MotionEvent event) {
7941        final int viewFlags = mViewFlags;
7942
7943        if ((viewFlags & ENABLED_MASK) == DISABLED) {
7944            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
7945                setPressed(false);
7946            }
7947            // A disabled view that is clickable still consumes the touch
7948            // events, it just doesn't respond to them.
7949            return (((viewFlags & CLICKABLE) == CLICKABLE ||
7950                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
7951        }
7952
7953        if (mTouchDelegate != null) {
7954            if (mTouchDelegate.onTouchEvent(event)) {
7955                return true;
7956            }
7957        }
7958
7959        if (((viewFlags & CLICKABLE) == CLICKABLE ||
7960                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
7961            switch (event.getAction()) {
7962                case MotionEvent.ACTION_UP:
7963                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
7964                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
7965                        // take focus if we don't have it already and we should in
7966                        // touch mode.
7967                        boolean focusTaken = false;
7968                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
7969                            focusTaken = requestFocus();
7970                        }
7971
7972                        if (prepressed) {
7973                            // The button is being released before we actually
7974                            // showed it as pressed.  Make it show the pressed
7975                            // state now (before scheduling the click) to ensure
7976                            // the user sees it.
7977                            setPressed(true);
7978                       }
7979
7980                        if (!mHasPerformedLongPress) {
7981                            // This is a tap, so remove the longpress check
7982                            removeLongPressCallback();
7983
7984                            // Only perform take click actions if we were in the pressed state
7985                            if (!focusTaken) {
7986                                // Use a Runnable and post this rather than calling
7987                                // performClick directly. This lets other visual state
7988                                // of the view update before click actions start.
7989                                if (mPerformClick == null) {
7990                                    mPerformClick = new PerformClick();
7991                                }
7992                                if (!post(mPerformClick)) {
7993                                    performClick();
7994                                }
7995                            }
7996                        }
7997
7998                        if (mUnsetPressedState == null) {
7999                            mUnsetPressedState = new UnsetPressedState();
8000                        }
8001
8002                        if (prepressed) {
8003                            postDelayed(mUnsetPressedState,
8004                                    ViewConfiguration.getPressedStateDuration());
8005                        } else if (!post(mUnsetPressedState)) {
8006                            // If the post failed, unpress right now
8007                            mUnsetPressedState.run();
8008                        }
8009                        removeTapCallback();
8010                    }
8011                    break;
8012
8013                case MotionEvent.ACTION_DOWN:
8014                    mHasPerformedLongPress = false;
8015
8016                    if (performButtonActionOnTouchDown(event)) {
8017                        break;
8018                    }
8019
8020                    // Walk up the hierarchy to determine if we're inside a scrolling container.
8021                    boolean isInScrollingContainer = isInScrollingContainer();
8022
8023                    // For views inside a scrolling container, delay the pressed feedback for
8024                    // a short period in case this is a scroll.
8025                    if (isInScrollingContainer) {
8026                        mPrivateFlags |= PFLAG_PREPRESSED;
8027                        if (mPendingCheckForTap == null) {
8028                            mPendingCheckForTap = new CheckForTap();
8029                        }
8030                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
8031                    } else {
8032                        // Not inside a scrolling container, so show the feedback right away
8033                        setPressed(true);
8034                        checkForLongClick(0);
8035                    }
8036                    break;
8037
8038                case MotionEvent.ACTION_CANCEL:
8039                    setPressed(false);
8040                    removeTapCallback();
8041                    break;
8042
8043                case MotionEvent.ACTION_MOVE:
8044                    final int x = (int) event.getX();
8045                    final int y = (int) event.getY();
8046
8047                    // Be lenient about moving outside of buttons
8048                    if (!pointInView(x, y, mTouchSlop)) {
8049                        // Outside button
8050                        removeTapCallback();
8051                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
8052                            // Remove any future long press/tap checks
8053                            removeLongPressCallback();
8054
8055                            setPressed(false);
8056                        }
8057                    }
8058                    break;
8059            }
8060            return true;
8061        }
8062
8063        return false;
8064    }
8065
8066    /**
8067     * @hide
8068     */
8069    public boolean isInScrollingContainer() {
8070        ViewParent p = getParent();
8071        while (p != null && p instanceof ViewGroup) {
8072            if (((ViewGroup) p).shouldDelayChildPressedState()) {
8073                return true;
8074            }
8075            p = p.getParent();
8076        }
8077        return false;
8078    }
8079
8080    /**
8081     * Remove the longpress detection timer.
8082     */
8083    private void removeLongPressCallback() {
8084        if (mPendingCheckForLongPress != null) {
8085          removeCallbacks(mPendingCheckForLongPress);
8086        }
8087    }
8088
8089    /**
8090     * Remove the pending click action
8091     */
8092    private void removePerformClickCallback() {
8093        if (mPerformClick != null) {
8094            removeCallbacks(mPerformClick);
8095        }
8096    }
8097
8098    /**
8099     * Remove the prepress detection timer.
8100     */
8101    private void removeUnsetPressCallback() {
8102        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
8103            setPressed(false);
8104            removeCallbacks(mUnsetPressedState);
8105        }
8106    }
8107
8108    /**
8109     * Remove the tap detection timer.
8110     */
8111    private void removeTapCallback() {
8112        if (mPendingCheckForTap != null) {
8113            mPrivateFlags &= ~PFLAG_PREPRESSED;
8114            removeCallbacks(mPendingCheckForTap);
8115        }
8116    }
8117
8118    /**
8119     * Cancels a pending long press.  Your subclass can use this if you
8120     * want the context menu to come up if the user presses and holds
8121     * at the same place, but you don't want it to come up if they press
8122     * and then move around enough to cause scrolling.
8123     */
8124    public void cancelLongPress() {
8125        removeLongPressCallback();
8126
8127        /*
8128         * The prepressed state handled by the tap callback is a display
8129         * construct, but the tap callback will post a long press callback
8130         * less its own timeout. Remove it here.
8131         */
8132        removeTapCallback();
8133    }
8134
8135    /**
8136     * Remove the pending callback for sending a
8137     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
8138     */
8139    private void removeSendViewScrolledAccessibilityEventCallback() {
8140        if (mSendViewScrolledAccessibilityEvent != null) {
8141            removeCallbacks(mSendViewScrolledAccessibilityEvent);
8142            mSendViewScrolledAccessibilityEvent.mIsPending = false;
8143        }
8144    }
8145
8146    /**
8147     * Sets the TouchDelegate for this View.
8148     */
8149    public void setTouchDelegate(TouchDelegate delegate) {
8150        mTouchDelegate = delegate;
8151    }
8152
8153    /**
8154     * Gets the TouchDelegate for this View.
8155     */
8156    public TouchDelegate getTouchDelegate() {
8157        return mTouchDelegate;
8158    }
8159
8160    /**
8161     * Set flags controlling behavior of this view.
8162     *
8163     * @param flags Constant indicating the value which should be set
8164     * @param mask Constant indicating the bit range that should be changed
8165     */
8166    void setFlags(int flags, int mask) {
8167        int old = mViewFlags;
8168        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
8169
8170        int changed = mViewFlags ^ old;
8171        if (changed == 0) {
8172            return;
8173        }
8174        int privateFlags = mPrivateFlags;
8175
8176        /* Check if the FOCUSABLE bit has changed */
8177        if (((changed & FOCUSABLE_MASK) != 0) &&
8178                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
8179            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
8180                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
8181                /* Give up focus if we are no longer focusable */
8182                clearFocus();
8183            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
8184                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
8185                /*
8186                 * Tell the view system that we are now available to take focus
8187                 * if no one else already has it.
8188                 */
8189                if (mParent != null) mParent.focusableViewAvailable(this);
8190            }
8191            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8192                notifyAccessibilityStateChanged();
8193            }
8194        }
8195
8196        if ((flags & VISIBILITY_MASK) == VISIBLE) {
8197            if ((changed & VISIBILITY_MASK) != 0) {
8198                /*
8199                 * If this view is becoming visible, invalidate it in case it changed while
8200                 * it was not visible. Marking it drawn ensures that the invalidation will
8201                 * go through.
8202                 */
8203                mPrivateFlags |= PFLAG_DRAWN;
8204                invalidate(true);
8205
8206                needGlobalAttributesUpdate(true);
8207
8208                // a view becoming visible is worth notifying the parent
8209                // about in case nothing has focus.  even if this specific view
8210                // isn't focusable, it may contain something that is, so let
8211                // the root view try to give this focus if nothing else does.
8212                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
8213                    mParent.focusableViewAvailable(this);
8214                }
8215            }
8216        }
8217
8218        /* Check if the GONE bit has changed */
8219        if ((changed & GONE) != 0) {
8220            needGlobalAttributesUpdate(false);
8221            requestLayout();
8222
8223            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
8224                if (hasFocus()) clearFocus();
8225                clearAccessibilityFocus();
8226                destroyDrawingCache();
8227                if (mParent instanceof View) {
8228                    // GONE views noop invalidation, so invalidate the parent
8229                    ((View) mParent).invalidate(true);
8230                }
8231                // Mark the view drawn to ensure that it gets invalidated properly the next
8232                // time it is visible and gets invalidated
8233                mPrivateFlags |= PFLAG_DRAWN;
8234            }
8235            if (mAttachInfo != null) {
8236                mAttachInfo.mViewVisibilityChanged = true;
8237            }
8238        }
8239
8240        /* Check if the VISIBLE bit has changed */
8241        if ((changed & INVISIBLE) != 0) {
8242            needGlobalAttributesUpdate(false);
8243            /*
8244             * If this view is becoming invisible, set the DRAWN flag so that
8245             * the next invalidate() will not be skipped.
8246             */
8247            mPrivateFlags |= PFLAG_DRAWN;
8248
8249            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
8250                // root view becoming invisible shouldn't clear focus and accessibility focus
8251                if (getRootView() != this) {
8252                    clearFocus();
8253                    clearAccessibilityFocus();
8254                }
8255            }
8256            if (mAttachInfo != null) {
8257                mAttachInfo.mViewVisibilityChanged = true;
8258            }
8259        }
8260
8261        if ((changed & VISIBILITY_MASK) != 0) {
8262            if (mParent instanceof ViewGroup) {
8263                ((ViewGroup) mParent).onChildVisibilityChanged(this,
8264                        (changed & VISIBILITY_MASK), (flags & VISIBILITY_MASK));
8265                ((View) mParent).invalidate(true);
8266            } else if (mParent != null) {
8267                mParent.invalidateChild(this, null);
8268            }
8269            dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
8270        }
8271
8272        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
8273            destroyDrawingCache();
8274        }
8275
8276        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
8277            destroyDrawingCache();
8278            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
8279            invalidateParentCaches();
8280        }
8281
8282        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
8283            destroyDrawingCache();
8284            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
8285        }
8286
8287        if ((changed & DRAW_MASK) != 0) {
8288            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
8289                if (mBackground != null) {
8290                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
8291                    mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
8292                } else {
8293                    mPrivateFlags |= PFLAG_SKIP_DRAW;
8294                }
8295            } else {
8296                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
8297            }
8298            requestLayout();
8299            invalidate(true);
8300        }
8301
8302        if ((changed & KEEP_SCREEN_ON) != 0) {
8303            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
8304                mParent.recomputeViewAttributes(this);
8305            }
8306        }
8307
8308        if (AccessibilityManager.getInstance(mContext).isEnabled()
8309                && ((changed & FOCUSABLE) != 0 || (changed & CLICKABLE) != 0
8310                        || (changed & LONG_CLICKABLE) != 0 || (changed & ENABLED) != 0)) {
8311            notifyAccessibilityStateChanged();
8312        }
8313    }
8314
8315    /**
8316     * Change the view's z order in the tree, so it's on top of other sibling
8317     * views
8318     */
8319    public void bringToFront() {
8320        if (mParent != null) {
8321            mParent.bringChildToFront(this);
8322        }
8323    }
8324
8325    /**
8326     * This is called in response to an internal scroll in this view (i.e., the
8327     * view scrolled its own contents). This is typically as a result of
8328     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
8329     * called.
8330     *
8331     * @param l Current horizontal scroll origin.
8332     * @param t Current vertical scroll origin.
8333     * @param oldl Previous horizontal scroll origin.
8334     * @param oldt Previous vertical scroll origin.
8335     */
8336    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
8337        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8338            postSendViewScrolledAccessibilityEventCallback();
8339        }
8340
8341        mBackgroundSizeChanged = true;
8342
8343        final AttachInfo ai = mAttachInfo;
8344        if (ai != null) {
8345            ai.mViewScrollChanged = true;
8346        }
8347    }
8348
8349    /**
8350     * Interface definition for a callback to be invoked when the layout bounds of a view
8351     * changes due to layout processing.
8352     */
8353    public interface OnLayoutChangeListener {
8354        /**
8355         * Called when the focus state of a view has changed.
8356         *
8357         * @param v The view whose state has changed.
8358         * @param left The new value of the view's left property.
8359         * @param top The new value of the view's top property.
8360         * @param right The new value of the view's right property.
8361         * @param bottom The new value of the view's bottom property.
8362         * @param oldLeft The previous value of the view's left property.
8363         * @param oldTop The previous value of the view's top property.
8364         * @param oldRight The previous value of the view's right property.
8365         * @param oldBottom The previous value of the view's bottom property.
8366         */
8367        void onLayoutChange(View v, int left, int top, int right, int bottom,
8368            int oldLeft, int oldTop, int oldRight, int oldBottom);
8369    }
8370
8371    /**
8372     * This is called during layout when the size of this view has changed. If
8373     * you were just added to the view hierarchy, you're called with the old
8374     * values of 0.
8375     *
8376     * @param w Current width of this view.
8377     * @param h Current height of this view.
8378     * @param oldw Old width of this view.
8379     * @param oldh Old height of this view.
8380     */
8381    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
8382    }
8383
8384    /**
8385     * Called by draw to draw the child views. This may be overridden
8386     * by derived classes to gain control just before its children are drawn
8387     * (but after its own view has been drawn).
8388     * @param canvas the canvas on which to draw the view
8389     */
8390    protected void dispatchDraw(Canvas canvas) {
8391
8392    }
8393
8394    /**
8395     * Gets the parent of this view. Note that the parent is a
8396     * ViewParent and not necessarily a View.
8397     *
8398     * @return Parent of this view.
8399     */
8400    public final ViewParent getParent() {
8401        return mParent;
8402    }
8403
8404    /**
8405     * Set the horizontal scrolled position of your view. This will cause a call to
8406     * {@link #onScrollChanged(int, int, int, int)} and the view will be
8407     * invalidated.
8408     * @param value the x position to scroll to
8409     */
8410    public void setScrollX(int value) {
8411        scrollTo(value, mScrollY);
8412    }
8413
8414    /**
8415     * Set the vertical scrolled position of your view. This will cause a call to
8416     * {@link #onScrollChanged(int, int, int, int)} and the view will be
8417     * invalidated.
8418     * @param value the y position to scroll to
8419     */
8420    public void setScrollY(int value) {
8421        scrollTo(mScrollX, value);
8422    }
8423
8424    /**
8425     * Return the scrolled left position of this view. This is the left edge of
8426     * the displayed part of your view. You do not need to draw any pixels
8427     * farther left, since those are outside of the frame of your view on
8428     * screen.
8429     *
8430     * @return The left edge of the displayed part of your view, in pixels.
8431     */
8432    public final int getScrollX() {
8433        return mScrollX;
8434    }
8435
8436    /**
8437     * Return the scrolled top position of this view. This is the top edge of
8438     * the displayed part of your view. You do not need to draw any pixels above
8439     * it, since those are outside of the frame of your view on screen.
8440     *
8441     * @return The top edge of the displayed part of your view, in pixels.
8442     */
8443    public final int getScrollY() {
8444        return mScrollY;
8445    }
8446
8447    /**
8448     * Return the width of the your view.
8449     *
8450     * @return The width of your view, in pixels.
8451     */
8452    @ViewDebug.ExportedProperty(category = "layout")
8453    public final int getWidth() {
8454        return mRight - mLeft;
8455    }
8456
8457    /**
8458     * Return the height of your view.
8459     *
8460     * @return The height of your view, in pixels.
8461     */
8462    @ViewDebug.ExportedProperty(category = "layout")
8463    public final int getHeight() {
8464        return mBottom - mTop;
8465    }
8466
8467    /**
8468     * Return the visible drawing bounds of your view. Fills in the output
8469     * rectangle with the values from getScrollX(), getScrollY(),
8470     * getWidth(), and getHeight().
8471     *
8472     * @param outRect The (scrolled) drawing bounds of the view.
8473     */
8474    public void getDrawingRect(Rect outRect) {
8475        outRect.left = mScrollX;
8476        outRect.top = mScrollY;
8477        outRect.right = mScrollX + (mRight - mLeft);
8478        outRect.bottom = mScrollY + (mBottom - mTop);
8479    }
8480
8481    /**
8482     * Like {@link #getMeasuredWidthAndState()}, but only returns the
8483     * raw width component (that is the result is masked by
8484     * {@link #MEASURED_SIZE_MASK}).
8485     *
8486     * @return The raw measured width of this view.
8487     */
8488    public final int getMeasuredWidth() {
8489        return mMeasuredWidth & MEASURED_SIZE_MASK;
8490    }
8491
8492    /**
8493     * Return the full width measurement information for this view as computed
8494     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
8495     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
8496     * This should be used during measurement and layout calculations only. Use
8497     * {@link #getWidth()} to see how wide a view is after layout.
8498     *
8499     * @return The measured width of this view as a bit mask.
8500     */
8501    public final int getMeasuredWidthAndState() {
8502        return mMeasuredWidth;
8503    }
8504
8505    /**
8506     * Like {@link #getMeasuredHeightAndState()}, but only returns the
8507     * raw width component (that is the result is masked by
8508     * {@link #MEASURED_SIZE_MASK}).
8509     *
8510     * @return The raw measured height of this view.
8511     */
8512    public final int getMeasuredHeight() {
8513        return mMeasuredHeight & MEASURED_SIZE_MASK;
8514    }
8515
8516    /**
8517     * Return the full height measurement information for this view as computed
8518     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
8519     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
8520     * This should be used during measurement and layout calculations only. Use
8521     * {@link #getHeight()} to see how wide a view is after layout.
8522     *
8523     * @return The measured width of this view as a bit mask.
8524     */
8525    public final int getMeasuredHeightAndState() {
8526        return mMeasuredHeight;
8527    }
8528
8529    /**
8530     * Return only the state bits of {@link #getMeasuredWidthAndState()}
8531     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
8532     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
8533     * and the height component is at the shifted bits
8534     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
8535     */
8536    public final int getMeasuredState() {
8537        return (mMeasuredWidth&MEASURED_STATE_MASK)
8538                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
8539                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
8540    }
8541
8542    /**
8543     * The transform matrix of this view, which is calculated based on the current
8544     * roation, scale, and pivot properties.
8545     *
8546     * @see #getRotation()
8547     * @see #getScaleX()
8548     * @see #getScaleY()
8549     * @see #getPivotX()
8550     * @see #getPivotY()
8551     * @return The current transform matrix for the view
8552     */
8553    public Matrix getMatrix() {
8554        if (mTransformationInfo != null) {
8555            updateMatrix();
8556            return mTransformationInfo.mMatrix;
8557        }
8558        return Matrix.IDENTITY_MATRIX;
8559    }
8560
8561    /**
8562     * Utility function to determine if the value is far enough away from zero to be
8563     * considered non-zero.
8564     * @param value A floating point value to check for zero-ness
8565     * @return whether the passed-in value is far enough away from zero to be considered non-zero
8566     */
8567    private static boolean nonzero(float value) {
8568        return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
8569    }
8570
8571    /**
8572     * Returns true if the transform matrix is the identity matrix.
8573     * Recomputes the matrix if necessary.
8574     *
8575     * @return True if the transform matrix is the identity matrix, false otherwise.
8576     */
8577    final boolean hasIdentityMatrix() {
8578        if (mTransformationInfo != null) {
8579            updateMatrix();
8580            return mTransformationInfo.mMatrixIsIdentity;
8581        }
8582        return true;
8583    }
8584
8585    void ensureTransformationInfo() {
8586        if (mTransformationInfo == null) {
8587            mTransformationInfo = new TransformationInfo();
8588        }
8589    }
8590
8591    /**
8592     * Recomputes the transform matrix if necessary.
8593     */
8594    private void updateMatrix() {
8595        final TransformationInfo info = mTransformationInfo;
8596        if (info == null) {
8597            return;
8598        }
8599        if (info.mMatrixDirty) {
8600            // transform-related properties have changed since the last time someone
8601            // asked for the matrix; recalculate it with the current values
8602
8603            // Figure out if we need to update the pivot point
8604            if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
8605                if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
8606                    info.mPrevWidth = mRight - mLeft;
8607                    info.mPrevHeight = mBottom - mTop;
8608                    info.mPivotX = info.mPrevWidth / 2f;
8609                    info.mPivotY = info.mPrevHeight / 2f;
8610                }
8611            }
8612            info.mMatrix.reset();
8613            if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
8614                info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
8615                info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
8616                info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
8617            } else {
8618                if (info.mCamera == null) {
8619                    info.mCamera = new Camera();
8620                    info.matrix3D = new Matrix();
8621                }
8622                info.mCamera.save();
8623                info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
8624                info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
8625                info.mCamera.getMatrix(info.matrix3D);
8626                info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
8627                info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
8628                        info.mPivotY + info.mTranslationY);
8629                info.mMatrix.postConcat(info.matrix3D);
8630                info.mCamera.restore();
8631            }
8632            info.mMatrixDirty = false;
8633            info.mMatrixIsIdentity = info.mMatrix.isIdentity();
8634            info.mInverseMatrixDirty = true;
8635        }
8636    }
8637
8638    /**
8639     * When searching for a view to focus this rectangle is used when considering if this view is
8640     * a good candidate for receiving focus.
8641     *
8642     * By default, the rectangle is the {@link #getDrawingRect}) of the view.
8643     *
8644     * @param r The rectangle to fill in, in this view's coordinates.
8645     */
8646    public void getFocusRect(Rect r) {
8647        getDrawingRect(r);
8648    }
8649
8650   /**
8651     * Utility method to retrieve the inverse of the current mMatrix property.
8652     * We cache the matrix to avoid recalculating it when transform properties
8653     * have not changed.
8654     *
8655     * @return The inverse of the current matrix of this view.
8656     */
8657    final Matrix getInverseMatrix() {
8658        final TransformationInfo info = mTransformationInfo;
8659        if (info != null) {
8660            updateMatrix();
8661            if (info.mInverseMatrixDirty) {
8662                if (info.mInverseMatrix == null) {
8663                    info.mInverseMatrix = new Matrix();
8664                }
8665                info.mMatrix.invert(info.mInverseMatrix);
8666                info.mInverseMatrixDirty = false;
8667            }
8668            return info.mInverseMatrix;
8669        }
8670        return Matrix.IDENTITY_MATRIX;
8671    }
8672
8673    /**
8674     * Gets the distance along the Z axis from the camera to this view.
8675     *
8676     * @see #setCameraDistance(float)
8677     *
8678     * @return The distance along the Z axis.
8679     */
8680    public float getCameraDistance() {
8681        ensureTransformationInfo();
8682        final float dpi = mResources.getDisplayMetrics().densityDpi;
8683        final TransformationInfo info = mTransformationInfo;
8684        if (info.mCamera == null) {
8685            info.mCamera = new Camera();
8686            info.matrix3D = new Matrix();
8687        }
8688        return -(info.mCamera.getLocationZ() * dpi);
8689    }
8690
8691    /**
8692     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
8693     * views are drawn) from the camera to this view. The camera's distance
8694     * affects 3D transformations, for instance rotations around the X and Y
8695     * axis. If the rotationX or rotationY properties are changed and this view is
8696     * large (more than half the size of the screen), it is recommended to always
8697     * use a camera distance that's greater than the height (X axis rotation) or
8698     * the width (Y axis rotation) of this view.</p>
8699     *
8700     * <p>The distance of the camera from the view plane can have an affect on the
8701     * perspective distortion of the view when it is rotated around the x or y axis.
8702     * For example, a large distance will result in a large viewing angle, and there
8703     * will not be much perspective distortion of the view as it rotates. A short
8704     * distance may cause much more perspective distortion upon rotation, and can
8705     * also result in some drawing artifacts if the rotated view ends up partially
8706     * behind the camera (which is why the recommendation is to use a distance at
8707     * least as far as the size of the view, if the view is to be rotated.)</p>
8708     *
8709     * <p>The distance is expressed in "depth pixels." The default distance depends
8710     * on the screen density. For instance, on a medium density display, the
8711     * default distance is 1280. On a high density display, the default distance
8712     * is 1920.</p>
8713     *
8714     * <p>If you want to specify a distance that leads to visually consistent
8715     * results across various densities, use the following formula:</p>
8716     * <pre>
8717     * float scale = context.getResources().getDisplayMetrics().density;
8718     * view.setCameraDistance(distance * scale);
8719     * </pre>
8720     *
8721     * <p>The density scale factor of a high density display is 1.5,
8722     * and 1920 = 1280 * 1.5.</p>
8723     *
8724     * @param distance The distance in "depth pixels", if negative the opposite
8725     *        value is used
8726     *
8727     * @see #setRotationX(float)
8728     * @see #setRotationY(float)
8729     */
8730    public void setCameraDistance(float distance) {
8731        invalidateViewProperty(true, false);
8732
8733        ensureTransformationInfo();
8734        final float dpi = mResources.getDisplayMetrics().densityDpi;
8735        final TransformationInfo info = mTransformationInfo;
8736        if (info.mCamera == null) {
8737            info.mCamera = new Camera();
8738            info.matrix3D = new Matrix();
8739        }
8740
8741        info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
8742        info.mMatrixDirty = true;
8743
8744        invalidateViewProperty(false, false);
8745        if (mDisplayList != null) {
8746            mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
8747        }
8748        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
8749            // View was rejected last time it was drawn by its parent; this may have changed
8750            invalidateParentIfNeeded();
8751        }
8752    }
8753
8754    /**
8755     * The degrees that the view is rotated around the pivot point.
8756     *
8757     * @see #setRotation(float)
8758     * @see #getPivotX()
8759     * @see #getPivotY()
8760     *
8761     * @return The degrees of rotation.
8762     */
8763    @ViewDebug.ExportedProperty(category = "drawing")
8764    public float getRotation() {
8765        return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
8766    }
8767
8768    /**
8769     * Sets the degrees that the view is rotated around the pivot point. Increasing values
8770     * result in clockwise rotation.
8771     *
8772     * @param rotation The degrees of rotation.
8773     *
8774     * @see #getRotation()
8775     * @see #getPivotX()
8776     * @see #getPivotY()
8777     * @see #setRotationX(float)
8778     * @see #setRotationY(float)
8779     *
8780     * @attr ref android.R.styleable#View_rotation
8781     */
8782    public void setRotation(float rotation) {
8783        ensureTransformationInfo();
8784        final TransformationInfo info = mTransformationInfo;
8785        if (info.mRotation != rotation) {
8786            // Double-invalidation is necessary to capture view's old and new areas
8787            invalidateViewProperty(true, false);
8788            info.mRotation = rotation;
8789            info.mMatrixDirty = true;
8790            invalidateViewProperty(false, true);
8791            if (mDisplayList != null) {
8792                mDisplayList.setRotation(rotation);
8793            }
8794            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
8795                // View was rejected last time it was drawn by its parent; this may have changed
8796                invalidateParentIfNeeded();
8797            }
8798        }
8799    }
8800
8801    /**
8802     * The degrees that the view is rotated around the vertical axis through the pivot point.
8803     *
8804     * @see #getPivotX()
8805     * @see #getPivotY()
8806     * @see #setRotationY(float)
8807     *
8808     * @return The degrees of Y rotation.
8809     */
8810    @ViewDebug.ExportedProperty(category = "drawing")
8811    public float getRotationY() {
8812        return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
8813    }
8814
8815    /**
8816     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
8817     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
8818     * down the y axis.
8819     *
8820     * When rotating large views, it is recommended to adjust the camera distance
8821     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
8822     *
8823     * @param rotationY The degrees of Y rotation.
8824     *
8825     * @see #getRotationY()
8826     * @see #getPivotX()
8827     * @see #getPivotY()
8828     * @see #setRotation(float)
8829     * @see #setRotationX(float)
8830     * @see #setCameraDistance(float)
8831     *
8832     * @attr ref android.R.styleable#View_rotationY
8833     */
8834    public void setRotationY(float rotationY) {
8835        ensureTransformationInfo();
8836        final TransformationInfo info = mTransformationInfo;
8837        if (info.mRotationY != rotationY) {
8838            invalidateViewProperty(true, false);
8839            info.mRotationY = rotationY;
8840            info.mMatrixDirty = true;
8841            invalidateViewProperty(false, true);
8842            if (mDisplayList != null) {
8843                mDisplayList.setRotationY(rotationY);
8844            }
8845            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
8846                // View was rejected last time it was drawn by its parent; this may have changed
8847                invalidateParentIfNeeded();
8848            }
8849        }
8850    }
8851
8852    /**
8853     * The degrees that the view is rotated around the horizontal axis through the pivot point.
8854     *
8855     * @see #getPivotX()
8856     * @see #getPivotY()
8857     * @see #setRotationX(float)
8858     *
8859     * @return The degrees of X rotation.
8860     */
8861    @ViewDebug.ExportedProperty(category = "drawing")
8862    public float getRotationX() {
8863        return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
8864    }
8865
8866    /**
8867     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
8868     * Increasing values result in clockwise rotation from the viewpoint of looking down the
8869     * x axis.
8870     *
8871     * When rotating large views, it is recommended to adjust the camera distance
8872     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
8873     *
8874     * @param rotationX The degrees of X rotation.
8875     *
8876     * @see #getRotationX()
8877     * @see #getPivotX()
8878     * @see #getPivotY()
8879     * @see #setRotation(float)
8880     * @see #setRotationY(float)
8881     * @see #setCameraDistance(float)
8882     *
8883     * @attr ref android.R.styleable#View_rotationX
8884     */
8885    public void setRotationX(float rotationX) {
8886        ensureTransformationInfo();
8887        final TransformationInfo info = mTransformationInfo;
8888        if (info.mRotationX != rotationX) {
8889            invalidateViewProperty(true, false);
8890            info.mRotationX = rotationX;
8891            info.mMatrixDirty = true;
8892            invalidateViewProperty(false, true);
8893            if (mDisplayList != null) {
8894                mDisplayList.setRotationX(rotationX);
8895            }
8896            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
8897                // View was rejected last time it was drawn by its parent; this may have changed
8898                invalidateParentIfNeeded();
8899            }
8900        }
8901    }
8902
8903    /**
8904     * The amount that the view is scaled in x around the pivot point, as a proportion of
8905     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
8906     *
8907     * <p>By default, this is 1.0f.
8908     *
8909     * @see #getPivotX()
8910     * @see #getPivotY()
8911     * @return The scaling factor.
8912     */
8913    @ViewDebug.ExportedProperty(category = "drawing")
8914    public float getScaleX() {
8915        return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
8916    }
8917
8918    /**
8919     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
8920     * the view's unscaled width. A value of 1 means that no scaling is applied.
8921     *
8922     * @param scaleX The scaling factor.
8923     * @see #getPivotX()
8924     * @see #getPivotY()
8925     *
8926     * @attr ref android.R.styleable#View_scaleX
8927     */
8928    public void setScaleX(float scaleX) {
8929        ensureTransformationInfo();
8930        final TransformationInfo info = mTransformationInfo;
8931        if (info.mScaleX != scaleX) {
8932            invalidateViewProperty(true, false);
8933            info.mScaleX = scaleX;
8934            info.mMatrixDirty = true;
8935            invalidateViewProperty(false, true);
8936            if (mDisplayList != null) {
8937                mDisplayList.setScaleX(scaleX);
8938            }
8939            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
8940                // View was rejected last time it was drawn by its parent; this may have changed
8941                invalidateParentIfNeeded();
8942            }
8943        }
8944    }
8945
8946    /**
8947     * The amount that the view is scaled in y around the pivot point, as a proportion of
8948     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
8949     *
8950     * <p>By default, this is 1.0f.
8951     *
8952     * @see #getPivotX()
8953     * @see #getPivotY()
8954     * @return The scaling factor.
8955     */
8956    @ViewDebug.ExportedProperty(category = "drawing")
8957    public float getScaleY() {
8958        return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
8959    }
8960
8961    /**
8962     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
8963     * the view's unscaled width. A value of 1 means that no scaling is applied.
8964     *
8965     * @param scaleY The scaling factor.
8966     * @see #getPivotX()
8967     * @see #getPivotY()
8968     *
8969     * @attr ref android.R.styleable#View_scaleY
8970     */
8971    public void setScaleY(float scaleY) {
8972        ensureTransformationInfo();
8973        final TransformationInfo info = mTransformationInfo;
8974        if (info.mScaleY != scaleY) {
8975            invalidateViewProperty(true, false);
8976            info.mScaleY = scaleY;
8977            info.mMatrixDirty = true;
8978            invalidateViewProperty(false, true);
8979            if (mDisplayList != null) {
8980                mDisplayList.setScaleY(scaleY);
8981            }
8982            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
8983                // View was rejected last time it was drawn by its parent; this may have changed
8984                invalidateParentIfNeeded();
8985            }
8986        }
8987    }
8988
8989    /**
8990     * The x location of the point around which the view is {@link #setRotation(float) rotated}
8991     * and {@link #setScaleX(float) scaled}.
8992     *
8993     * @see #getRotation()
8994     * @see #getScaleX()
8995     * @see #getScaleY()
8996     * @see #getPivotY()
8997     * @return The x location of the pivot point.
8998     *
8999     * @attr ref android.R.styleable#View_transformPivotX
9000     */
9001    @ViewDebug.ExportedProperty(category = "drawing")
9002    public float getPivotX() {
9003        return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
9004    }
9005
9006    /**
9007     * Sets the x location of the point around which the view is
9008     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
9009     * By default, the pivot point is centered on the object.
9010     * Setting this property disables this behavior and causes the view to use only the
9011     * explicitly set pivotX and pivotY values.
9012     *
9013     * @param pivotX The x location of the pivot point.
9014     * @see #getRotation()
9015     * @see #getScaleX()
9016     * @see #getScaleY()
9017     * @see #getPivotY()
9018     *
9019     * @attr ref android.R.styleable#View_transformPivotX
9020     */
9021    public void setPivotX(float pivotX) {
9022        ensureTransformationInfo();
9023        mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
9024        final TransformationInfo info = mTransformationInfo;
9025        if (info.mPivotX != pivotX) {
9026            invalidateViewProperty(true, false);
9027            info.mPivotX = pivotX;
9028            info.mMatrixDirty = true;
9029            invalidateViewProperty(false, true);
9030            if (mDisplayList != null) {
9031                mDisplayList.setPivotX(pivotX);
9032            }
9033            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9034                // View was rejected last time it was drawn by its parent; this may have changed
9035                invalidateParentIfNeeded();
9036            }
9037        }
9038    }
9039
9040    /**
9041     * The y location of the point around which the view is {@link #setRotation(float) rotated}
9042     * and {@link #setScaleY(float) scaled}.
9043     *
9044     * @see #getRotation()
9045     * @see #getScaleX()
9046     * @see #getScaleY()
9047     * @see #getPivotY()
9048     * @return The y location of the pivot point.
9049     *
9050     * @attr ref android.R.styleable#View_transformPivotY
9051     */
9052    @ViewDebug.ExportedProperty(category = "drawing")
9053    public float getPivotY() {
9054        return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
9055    }
9056
9057    /**
9058     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
9059     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
9060     * Setting this property disables this behavior and causes the view to use only the
9061     * explicitly set pivotX and pivotY values.
9062     *
9063     * @param pivotY The y location of the pivot point.
9064     * @see #getRotation()
9065     * @see #getScaleX()
9066     * @see #getScaleY()
9067     * @see #getPivotY()
9068     *
9069     * @attr ref android.R.styleable#View_transformPivotY
9070     */
9071    public void setPivotY(float pivotY) {
9072        ensureTransformationInfo();
9073        mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
9074        final TransformationInfo info = mTransformationInfo;
9075        if (info.mPivotY != pivotY) {
9076            invalidateViewProperty(true, false);
9077            info.mPivotY = pivotY;
9078            info.mMatrixDirty = true;
9079            invalidateViewProperty(false, true);
9080            if (mDisplayList != null) {
9081                mDisplayList.setPivotY(pivotY);
9082            }
9083            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9084                // View was rejected last time it was drawn by its parent; this may have changed
9085                invalidateParentIfNeeded();
9086            }
9087        }
9088    }
9089
9090    /**
9091     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
9092     * completely transparent and 1 means the view is completely opaque.
9093     *
9094     * <p>By default this is 1.0f.
9095     * @return The opacity of the view.
9096     */
9097    @ViewDebug.ExportedProperty(category = "drawing")
9098    public float getAlpha() {
9099        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
9100    }
9101
9102    /**
9103     * Returns whether this View has content which overlaps. This function, intended to be
9104     * overridden by specific View types, is an optimization when alpha is set on a view. If
9105     * rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer
9106     * and then composited it into place, which can be expensive. If the view has no overlapping
9107     * rendering, the view can draw each primitive with the appropriate alpha value directly.
9108     * An example of overlapping rendering is a TextView with a background image, such as a
9109     * Button. An example of non-overlapping rendering is a TextView with no background, or
9110     * an ImageView with only the foreground image. The default implementation returns true;
9111     * subclasses should override if they have cases which can be optimized.
9112     *
9113     * @return true if the content in this view might overlap, false otherwise.
9114     */
9115    public boolean hasOverlappingRendering() {
9116        return true;
9117    }
9118
9119    /**
9120     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
9121     * completely transparent and 1 means the view is completely opaque.</p>
9122     *
9123     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
9124     * responsible for applying the opacity itself. Otherwise, calling this method is
9125     * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
9126     * setting a hardware layer.</p>
9127     *
9128     * <p>Note that setting alpha to a translucent value (0 < alpha < 1) may have
9129     * performance implications. It is generally best to use the alpha property sparingly and
9130     * transiently, as in the case of fading animations.</p>
9131     *
9132     * @param alpha The opacity of the view.
9133     *
9134     * @see #setLayerType(int, android.graphics.Paint)
9135     *
9136     * @attr ref android.R.styleable#View_alpha
9137     */
9138    public void setAlpha(float alpha) {
9139        ensureTransformationInfo();
9140        if (mTransformationInfo.mAlpha != alpha) {
9141            mTransformationInfo.mAlpha = alpha;
9142            if (onSetAlpha((int) (alpha * 255))) {
9143                mPrivateFlags |= PFLAG_ALPHA_SET;
9144                // subclass is handling alpha - don't optimize rendering cache invalidation
9145                invalidateParentCaches();
9146                invalidate(true);
9147            } else {
9148                mPrivateFlags &= ~PFLAG_ALPHA_SET;
9149                invalidateViewProperty(true, false);
9150                if (mDisplayList != null) {
9151                    mDisplayList.setAlpha(alpha);
9152                }
9153            }
9154        }
9155    }
9156
9157    /**
9158     * Faster version of setAlpha() which performs the same steps except there are
9159     * no calls to invalidate(). The caller of this function should perform proper invalidation
9160     * on the parent and this object. The return value indicates whether the subclass handles
9161     * alpha (the return value for onSetAlpha()).
9162     *
9163     * @param alpha The new value for the alpha property
9164     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
9165     *         the new value for the alpha property is different from the old value
9166     */
9167    boolean setAlphaNoInvalidation(float alpha) {
9168        ensureTransformationInfo();
9169        if (mTransformationInfo.mAlpha != alpha) {
9170            mTransformationInfo.mAlpha = alpha;
9171            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
9172            if (subclassHandlesAlpha) {
9173                mPrivateFlags |= PFLAG_ALPHA_SET;
9174                return true;
9175            } else {
9176                mPrivateFlags &= ~PFLAG_ALPHA_SET;
9177                if (mDisplayList != null) {
9178                    mDisplayList.setAlpha(alpha);
9179                }
9180            }
9181        }
9182        return false;
9183    }
9184
9185    /**
9186     * Top position of this view relative to its parent.
9187     *
9188     * @return The top of this view, in pixels.
9189     */
9190    @ViewDebug.CapturedViewProperty
9191    public final int getTop() {
9192        return mTop;
9193    }
9194
9195    /**
9196     * Sets the top position of this view relative to its parent. This method is meant to be called
9197     * by the layout system and should not generally be called otherwise, because the property
9198     * may be changed at any time by the layout.
9199     *
9200     * @param top The top of this view, in pixels.
9201     */
9202    public final void setTop(int top) {
9203        if (top != mTop) {
9204            updateMatrix();
9205            final boolean matrixIsIdentity = mTransformationInfo == null
9206                    || mTransformationInfo.mMatrixIsIdentity;
9207            if (matrixIsIdentity) {
9208                if (mAttachInfo != null) {
9209                    int minTop;
9210                    int yLoc;
9211                    if (top < mTop) {
9212                        minTop = top;
9213                        yLoc = top - mTop;
9214                    } else {
9215                        minTop = mTop;
9216                        yLoc = 0;
9217                    }
9218                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
9219                }
9220            } else {
9221                // Double-invalidation is necessary to capture view's old and new areas
9222                invalidate(true);
9223            }
9224
9225            int width = mRight - mLeft;
9226            int oldHeight = mBottom - mTop;
9227
9228            mTop = top;
9229            if (mDisplayList != null) {
9230                mDisplayList.setTop(mTop);
9231            }
9232
9233            onSizeChanged(width, mBottom - mTop, width, oldHeight);
9234
9235            if (!matrixIsIdentity) {
9236                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9237                    // A change in dimension means an auto-centered pivot point changes, too
9238                    mTransformationInfo.mMatrixDirty = true;
9239                }
9240                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9241                invalidate(true);
9242            }
9243            mBackgroundSizeChanged = true;
9244            invalidateParentIfNeeded();
9245            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9246                // View was rejected last time it was drawn by its parent; this may have changed
9247                invalidateParentIfNeeded();
9248            }
9249        }
9250    }
9251
9252    /**
9253     * Bottom position of this view relative to its parent.
9254     *
9255     * @return The bottom of this view, in pixels.
9256     */
9257    @ViewDebug.CapturedViewProperty
9258    public final int getBottom() {
9259        return mBottom;
9260    }
9261
9262    /**
9263     * True if this view has changed since the last time being drawn.
9264     *
9265     * @return The dirty state of this view.
9266     */
9267    public boolean isDirty() {
9268        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
9269    }
9270
9271    /**
9272     * Sets the bottom position of this view relative to its parent. This method is meant to be
9273     * called by the layout system and should not generally be called otherwise, because the
9274     * property may be changed at any time by the layout.
9275     *
9276     * @param bottom The bottom of this view, in pixels.
9277     */
9278    public final void setBottom(int bottom) {
9279        if (bottom != mBottom) {
9280            updateMatrix();
9281            final boolean matrixIsIdentity = mTransformationInfo == null
9282                    || mTransformationInfo.mMatrixIsIdentity;
9283            if (matrixIsIdentity) {
9284                if (mAttachInfo != null) {
9285                    int maxBottom;
9286                    if (bottom < mBottom) {
9287                        maxBottom = mBottom;
9288                    } else {
9289                        maxBottom = bottom;
9290                    }
9291                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
9292                }
9293            } else {
9294                // Double-invalidation is necessary to capture view's old and new areas
9295                invalidate(true);
9296            }
9297
9298            int width = mRight - mLeft;
9299            int oldHeight = mBottom - mTop;
9300
9301            mBottom = bottom;
9302            if (mDisplayList != null) {
9303                mDisplayList.setBottom(mBottom);
9304            }
9305
9306            onSizeChanged(width, mBottom - mTop, width, oldHeight);
9307
9308            if (!matrixIsIdentity) {
9309                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9310                    // A change in dimension means an auto-centered pivot point changes, too
9311                    mTransformationInfo.mMatrixDirty = true;
9312                }
9313                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9314                invalidate(true);
9315            }
9316            mBackgroundSizeChanged = true;
9317            invalidateParentIfNeeded();
9318            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9319                // View was rejected last time it was drawn by its parent; this may have changed
9320                invalidateParentIfNeeded();
9321            }
9322        }
9323    }
9324
9325    /**
9326     * Left position of this view relative to its parent.
9327     *
9328     * @return The left edge of this view, in pixels.
9329     */
9330    @ViewDebug.CapturedViewProperty
9331    public final int getLeft() {
9332        return mLeft;
9333    }
9334
9335    /**
9336     * Sets the left position of this view relative to its parent. This method is meant to be called
9337     * by the layout system and should not generally be called otherwise, because the property
9338     * may be changed at any time by the layout.
9339     *
9340     * @param left The bottom of this view, in pixels.
9341     */
9342    public final void setLeft(int left) {
9343        if (left != mLeft) {
9344            updateMatrix();
9345            final boolean matrixIsIdentity = mTransformationInfo == null
9346                    || mTransformationInfo.mMatrixIsIdentity;
9347            if (matrixIsIdentity) {
9348                if (mAttachInfo != null) {
9349                    int minLeft;
9350                    int xLoc;
9351                    if (left < mLeft) {
9352                        minLeft = left;
9353                        xLoc = left - mLeft;
9354                    } else {
9355                        minLeft = mLeft;
9356                        xLoc = 0;
9357                    }
9358                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
9359                }
9360            } else {
9361                // Double-invalidation is necessary to capture view's old and new areas
9362                invalidate(true);
9363            }
9364
9365            int oldWidth = mRight - mLeft;
9366            int height = mBottom - mTop;
9367
9368            mLeft = left;
9369            if (mDisplayList != null) {
9370                mDisplayList.setLeft(left);
9371            }
9372
9373            onSizeChanged(mRight - mLeft, height, oldWidth, height);
9374
9375            if (!matrixIsIdentity) {
9376                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9377                    // A change in dimension means an auto-centered pivot point changes, too
9378                    mTransformationInfo.mMatrixDirty = true;
9379                }
9380                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9381                invalidate(true);
9382            }
9383            mBackgroundSizeChanged = true;
9384            invalidateParentIfNeeded();
9385            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9386                // View was rejected last time it was drawn by its parent; this may have changed
9387                invalidateParentIfNeeded();
9388            }
9389        }
9390    }
9391
9392    /**
9393     * Right position of this view relative to its parent.
9394     *
9395     * @return The right edge of this view, in pixels.
9396     */
9397    @ViewDebug.CapturedViewProperty
9398    public final int getRight() {
9399        return mRight;
9400    }
9401
9402    /**
9403     * Sets the right position of this view relative to its parent. This method is meant to be called
9404     * by the layout system and should not generally be called otherwise, because the property
9405     * may be changed at any time by the layout.
9406     *
9407     * @param right The bottom of this view, in pixels.
9408     */
9409    public final void setRight(int right) {
9410        if (right != mRight) {
9411            updateMatrix();
9412            final boolean matrixIsIdentity = mTransformationInfo == null
9413                    || mTransformationInfo.mMatrixIsIdentity;
9414            if (matrixIsIdentity) {
9415                if (mAttachInfo != null) {
9416                    int maxRight;
9417                    if (right < mRight) {
9418                        maxRight = mRight;
9419                    } else {
9420                        maxRight = right;
9421                    }
9422                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
9423                }
9424            } else {
9425                // Double-invalidation is necessary to capture view's old and new areas
9426                invalidate(true);
9427            }
9428
9429            int oldWidth = mRight - mLeft;
9430            int height = mBottom - mTop;
9431
9432            mRight = right;
9433            if (mDisplayList != null) {
9434                mDisplayList.setRight(mRight);
9435            }
9436
9437            onSizeChanged(mRight - mLeft, height, oldWidth, height);
9438
9439            if (!matrixIsIdentity) {
9440                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
9441                    // A change in dimension means an auto-centered pivot point changes, too
9442                    mTransformationInfo.mMatrixDirty = true;
9443                }
9444                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
9445                invalidate(true);
9446            }
9447            mBackgroundSizeChanged = true;
9448            invalidateParentIfNeeded();
9449            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9450                // View was rejected last time it was drawn by its parent; this may have changed
9451                invalidateParentIfNeeded();
9452            }
9453        }
9454    }
9455
9456    /**
9457     * The visual x position of this view, in pixels. This is equivalent to the
9458     * {@link #setTranslationX(float) translationX} property plus the current
9459     * {@link #getLeft() left} property.
9460     *
9461     * @return The visual x position of this view, in pixels.
9462     */
9463    @ViewDebug.ExportedProperty(category = "drawing")
9464    public float getX() {
9465        return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
9466    }
9467
9468    /**
9469     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
9470     * {@link #setTranslationX(float) translationX} property to be the difference between
9471     * the x value passed in and the current {@link #getLeft() left} property.
9472     *
9473     * @param x The visual x position of this view, in pixels.
9474     */
9475    public void setX(float x) {
9476        setTranslationX(x - mLeft);
9477    }
9478
9479    /**
9480     * The visual y position of this view, in pixels. This is equivalent to the
9481     * {@link #setTranslationY(float) translationY} property plus the current
9482     * {@link #getTop() top} property.
9483     *
9484     * @return The visual y position of this view, in pixels.
9485     */
9486    @ViewDebug.ExportedProperty(category = "drawing")
9487    public float getY() {
9488        return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
9489    }
9490
9491    /**
9492     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
9493     * {@link #setTranslationY(float) translationY} property to be the difference between
9494     * the y value passed in and the current {@link #getTop() top} property.
9495     *
9496     * @param y The visual y position of this view, in pixels.
9497     */
9498    public void setY(float y) {
9499        setTranslationY(y - mTop);
9500    }
9501
9502
9503    /**
9504     * The horizontal location of this view relative to its {@link #getLeft() left} position.
9505     * This position is post-layout, in addition to wherever the object's
9506     * layout placed it.
9507     *
9508     * @return The horizontal position of this view relative to its left position, in pixels.
9509     */
9510    @ViewDebug.ExportedProperty(category = "drawing")
9511    public float getTranslationX() {
9512        return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
9513    }
9514
9515    /**
9516     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
9517     * This effectively positions the object post-layout, in addition to wherever the object's
9518     * layout placed it.
9519     *
9520     * @param translationX The horizontal position of this view relative to its left position,
9521     * in pixels.
9522     *
9523     * @attr ref android.R.styleable#View_translationX
9524     */
9525    public void setTranslationX(float translationX) {
9526        ensureTransformationInfo();
9527        final TransformationInfo info = mTransformationInfo;
9528        if (info.mTranslationX != translationX) {
9529            // Double-invalidation is necessary to capture view's old and new areas
9530            invalidateViewProperty(true, false);
9531            info.mTranslationX = translationX;
9532            info.mMatrixDirty = true;
9533            invalidateViewProperty(false, true);
9534            if (mDisplayList != null) {
9535                mDisplayList.setTranslationX(translationX);
9536            }
9537            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9538                // View was rejected last time it was drawn by its parent; this may have changed
9539                invalidateParentIfNeeded();
9540            }
9541        }
9542    }
9543
9544    /**
9545     * The horizontal location of this view relative to its {@link #getTop() top} position.
9546     * This position is post-layout, in addition to wherever the object's
9547     * layout placed it.
9548     *
9549     * @return The vertical position of this view relative to its top position,
9550     * in pixels.
9551     */
9552    @ViewDebug.ExportedProperty(category = "drawing")
9553    public float getTranslationY() {
9554        return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
9555    }
9556
9557    /**
9558     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
9559     * This effectively positions the object post-layout, in addition to wherever the object's
9560     * layout placed it.
9561     *
9562     * @param translationY The vertical position of this view relative to its top position,
9563     * in pixels.
9564     *
9565     * @attr ref android.R.styleable#View_translationY
9566     */
9567    public void setTranslationY(float translationY) {
9568        ensureTransformationInfo();
9569        final TransformationInfo info = mTransformationInfo;
9570        if (info.mTranslationY != translationY) {
9571            invalidateViewProperty(true, false);
9572            info.mTranslationY = translationY;
9573            info.mMatrixDirty = true;
9574            invalidateViewProperty(false, true);
9575            if (mDisplayList != null) {
9576                mDisplayList.setTranslationY(translationY);
9577            }
9578            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
9579                // View was rejected last time it was drawn by its parent; this may have changed
9580                invalidateParentIfNeeded();
9581            }
9582        }
9583    }
9584
9585    /**
9586     * Hit rectangle in parent's coordinates
9587     *
9588     * @param outRect The hit rectangle of the view.
9589     */
9590    public void getHitRect(Rect outRect) {
9591        updateMatrix();
9592        final TransformationInfo info = mTransformationInfo;
9593        if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
9594            outRect.set(mLeft, mTop, mRight, mBottom);
9595        } else {
9596            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
9597            tmpRect.set(-info.mPivotX, -info.mPivotY,
9598                    getWidth() - info.mPivotX, getHeight() - info.mPivotY);
9599            info.mMatrix.mapRect(tmpRect);
9600            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
9601                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
9602        }
9603    }
9604
9605    /**
9606     * Determines whether the given point, in local coordinates is inside the view.
9607     */
9608    /*package*/ final boolean pointInView(float localX, float localY) {
9609        return localX >= 0 && localX < (mRight - mLeft)
9610                && localY >= 0 && localY < (mBottom - mTop);
9611    }
9612
9613    /**
9614     * Utility method to determine whether the given point, in local coordinates,
9615     * is inside the view, where the area of the view is expanded by the slop factor.
9616     * This method is called while processing touch-move events to determine if the event
9617     * is still within the view.
9618     */
9619    private boolean pointInView(float localX, float localY, float slop) {
9620        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
9621                localY < ((mBottom - mTop) + slop);
9622    }
9623
9624    /**
9625     * When a view has focus and the user navigates away from it, the next view is searched for
9626     * starting from the rectangle filled in by this method.
9627     *
9628     * By default, the rectange is the {@link #getDrawingRect(android.graphics.Rect)})
9629     * of the view.  However, if your view maintains some idea of internal selection,
9630     * such as a cursor, or a selected row or column, you should override this method and
9631     * fill in a more specific rectangle.
9632     *
9633     * @param r The rectangle to fill in, in this view's coordinates.
9634     */
9635    public void getFocusedRect(Rect r) {
9636        getDrawingRect(r);
9637    }
9638
9639    /**
9640     * If some part of this view is not clipped by any of its parents, then
9641     * return that area in r in global (root) coordinates. To convert r to local
9642     * coordinates (without taking possible View rotations into account), offset
9643     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
9644     * If the view is completely clipped or translated out, return false.
9645     *
9646     * @param r If true is returned, r holds the global coordinates of the
9647     *        visible portion of this view.
9648     * @param globalOffset If true is returned, globalOffset holds the dx,dy
9649     *        between this view and its root. globalOffet may be null.
9650     * @return true if r is non-empty (i.e. part of the view is visible at the
9651     *         root level.
9652     */
9653    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
9654        int width = mRight - mLeft;
9655        int height = mBottom - mTop;
9656        if (width > 0 && height > 0) {
9657            r.set(0, 0, width, height);
9658            if (globalOffset != null) {
9659                globalOffset.set(-mScrollX, -mScrollY);
9660            }
9661            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
9662        }
9663        return false;
9664    }
9665
9666    public final boolean getGlobalVisibleRect(Rect r) {
9667        return getGlobalVisibleRect(r, null);
9668    }
9669
9670    public final boolean getLocalVisibleRect(Rect r) {
9671        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
9672        if (getGlobalVisibleRect(r, offset)) {
9673            r.offset(-offset.x, -offset.y); // make r local
9674            return true;
9675        }
9676        return false;
9677    }
9678
9679    /**
9680     * Offset this view's vertical location by the specified number of pixels.
9681     *
9682     * @param offset the number of pixels to offset the view by
9683     */
9684    public void offsetTopAndBottom(int offset) {
9685        if (offset != 0) {
9686            updateMatrix();
9687            final boolean matrixIsIdentity = mTransformationInfo == null
9688                    || mTransformationInfo.mMatrixIsIdentity;
9689            if (matrixIsIdentity) {
9690                if (mDisplayList != null) {
9691                    invalidateViewProperty(false, false);
9692                } else {
9693                    final ViewParent p = mParent;
9694                    if (p != null && mAttachInfo != null) {
9695                        final Rect r = mAttachInfo.mTmpInvalRect;
9696                        int minTop;
9697                        int maxBottom;
9698                        int yLoc;
9699                        if (offset < 0) {
9700                            minTop = mTop + offset;
9701                            maxBottom = mBottom;
9702                            yLoc = offset;
9703                        } else {
9704                            minTop = mTop;
9705                            maxBottom = mBottom + offset;
9706                            yLoc = 0;
9707                        }
9708                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
9709                        p.invalidateChild(this, r);
9710                    }
9711                }
9712            } else {
9713                invalidateViewProperty(false, false);
9714            }
9715
9716            mTop += offset;
9717            mBottom += offset;
9718            if (mDisplayList != null) {
9719                mDisplayList.offsetTopBottom(offset);
9720                invalidateViewProperty(false, false);
9721            } else {
9722                if (!matrixIsIdentity) {
9723                    invalidateViewProperty(false, true);
9724                }
9725                invalidateParentIfNeeded();
9726            }
9727        }
9728    }
9729
9730    /**
9731     * Offset this view's horizontal location by the specified amount of pixels.
9732     *
9733     * @param offset the numer of pixels to offset the view by
9734     */
9735    public void offsetLeftAndRight(int offset) {
9736        if (offset != 0) {
9737            updateMatrix();
9738            final boolean matrixIsIdentity = mTransformationInfo == null
9739                    || mTransformationInfo.mMatrixIsIdentity;
9740            if (matrixIsIdentity) {
9741                if (mDisplayList != null) {
9742                    invalidateViewProperty(false, false);
9743                } else {
9744                    final ViewParent p = mParent;
9745                    if (p != null && mAttachInfo != null) {
9746                        final Rect r = mAttachInfo.mTmpInvalRect;
9747                        int minLeft;
9748                        int maxRight;
9749                        if (offset < 0) {
9750                            minLeft = mLeft + offset;
9751                            maxRight = mRight;
9752                        } else {
9753                            minLeft = mLeft;
9754                            maxRight = mRight + offset;
9755                        }
9756                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
9757                        p.invalidateChild(this, r);
9758                    }
9759                }
9760            } else {
9761                invalidateViewProperty(false, false);
9762            }
9763
9764            mLeft += offset;
9765            mRight += offset;
9766            if (mDisplayList != null) {
9767                mDisplayList.offsetLeftRight(offset);
9768                invalidateViewProperty(false, false);
9769            } else {
9770                if (!matrixIsIdentity) {
9771                    invalidateViewProperty(false, true);
9772                }
9773                invalidateParentIfNeeded();
9774            }
9775        }
9776    }
9777
9778    /**
9779     * Get the LayoutParams associated with this view. All views should have
9780     * layout parameters. These supply parameters to the <i>parent</i> of this
9781     * view specifying how it should be arranged. There are many subclasses of
9782     * ViewGroup.LayoutParams, and these correspond to the different subclasses
9783     * of ViewGroup that are responsible for arranging their children.
9784     *
9785     * This method may return null if this View is not attached to a parent
9786     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
9787     * was not invoked successfully. When a View is attached to a parent
9788     * ViewGroup, this method must not return null.
9789     *
9790     * @return The LayoutParams associated with this view, or null if no
9791     *         parameters have been set yet
9792     */
9793    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
9794    public ViewGroup.LayoutParams getLayoutParams() {
9795        return mLayoutParams;
9796    }
9797
9798    /**
9799     * Set the layout parameters associated with this view. These supply
9800     * parameters to the <i>parent</i> of this view specifying how it should be
9801     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
9802     * correspond to the different subclasses of ViewGroup that are responsible
9803     * for arranging their children.
9804     *
9805     * @param params The layout parameters for this view, cannot be null
9806     */
9807    public void setLayoutParams(ViewGroup.LayoutParams params) {
9808        if (params == null) {
9809            throw new NullPointerException("Layout parameters cannot be null");
9810        }
9811        mLayoutParams = params;
9812        resolveLayoutParams();
9813        if (mParent instanceof ViewGroup) {
9814            ((ViewGroup) mParent).onSetLayoutParams(this, params);
9815        }
9816        requestLayout();
9817    }
9818
9819    /**
9820     * Resolve the layout parameters depending on the resolved layout direction
9821     */
9822    private void resolveLayoutParams() {
9823        if (mLayoutParams != null) {
9824            mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
9825        }
9826    }
9827
9828    /**
9829     * Set the scrolled position of your view. This will cause a call to
9830     * {@link #onScrollChanged(int, int, int, int)} and the view will be
9831     * invalidated.
9832     * @param x the x position to scroll to
9833     * @param y the y position to scroll to
9834     */
9835    public void scrollTo(int x, int y) {
9836        if (mScrollX != x || mScrollY != y) {
9837            int oldX = mScrollX;
9838            int oldY = mScrollY;
9839            mScrollX = x;
9840            mScrollY = y;
9841            invalidateParentCaches();
9842            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
9843            if (!awakenScrollBars()) {
9844                postInvalidateOnAnimation();
9845            }
9846        }
9847    }
9848
9849    /**
9850     * Move the scrolled position of your view. This will cause a call to
9851     * {@link #onScrollChanged(int, int, int, int)} and the view will be
9852     * invalidated.
9853     * @param x the amount of pixels to scroll by horizontally
9854     * @param y the amount of pixels to scroll by vertically
9855     */
9856    public void scrollBy(int x, int y) {
9857        scrollTo(mScrollX + x, mScrollY + y);
9858    }
9859
9860    /**
9861     * <p>Trigger the scrollbars to draw. When invoked this method starts an
9862     * animation to fade the scrollbars out after a default delay. If a subclass
9863     * provides animated scrolling, the start delay should equal the duration
9864     * of the scrolling animation.</p>
9865     *
9866     * <p>The animation starts only if at least one of the scrollbars is
9867     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
9868     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
9869     * this method returns true, and false otherwise. If the animation is
9870     * started, this method calls {@link #invalidate()}; in that case the
9871     * caller should not call {@link #invalidate()}.</p>
9872     *
9873     * <p>This method should be invoked every time a subclass directly updates
9874     * the scroll parameters.</p>
9875     *
9876     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
9877     * and {@link #scrollTo(int, int)}.</p>
9878     *
9879     * @return true if the animation is played, false otherwise
9880     *
9881     * @see #awakenScrollBars(int)
9882     * @see #scrollBy(int, int)
9883     * @see #scrollTo(int, int)
9884     * @see #isHorizontalScrollBarEnabled()
9885     * @see #isVerticalScrollBarEnabled()
9886     * @see #setHorizontalScrollBarEnabled(boolean)
9887     * @see #setVerticalScrollBarEnabled(boolean)
9888     */
9889    protected boolean awakenScrollBars() {
9890        return mScrollCache != null &&
9891                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
9892    }
9893
9894    /**
9895     * Trigger the scrollbars to draw.
9896     * This method differs from awakenScrollBars() only in its default duration.
9897     * initialAwakenScrollBars() will show the scroll bars for longer than
9898     * usual to give the user more of a chance to notice them.
9899     *
9900     * @return true if the animation is played, false otherwise.
9901     */
9902    private boolean initialAwakenScrollBars() {
9903        return mScrollCache != null &&
9904                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
9905    }
9906
9907    /**
9908     * <p>
9909     * Trigger the scrollbars to draw. When invoked this method starts an
9910     * animation to fade the scrollbars out after a fixed delay. If a subclass
9911     * provides animated scrolling, the start delay should equal the duration of
9912     * the scrolling animation.
9913     * </p>
9914     *
9915     * <p>
9916     * The animation starts only if at least one of the scrollbars is enabled,
9917     * as specified by {@link #isHorizontalScrollBarEnabled()} and
9918     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
9919     * this method returns true, and false otherwise. If the animation is
9920     * started, this method calls {@link #invalidate()}; in that case the caller
9921     * should not call {@link #invalidate()}.
9922     * </p>
9923     *
9924     * <p>
9925     * This method should be invoked everytime a subclass directly updates the
9926     * scroll parameters.
9927     * </p>
9928     *
9929     * @param startDelay the delay, in milliseconds, after which the animation
9930     *        should start; when the delay is 0, the animation starts
9931     *        immediately
9932     * @return true if the animation is played, false otherwise
9933     *
9934     * @see #scrollBy(int, int)
9935     * @see #scrollTo(int, int)
9936     * @see #isHorizontalScrollBarEnabled()
9937     * @see #isVerticalScrollBarEnabled()
9938     * @see #setHorizontalScrollBarEnabled(boolean)
9939     * @see #setVerticalScrollBarEnabled(boolean)
9940     */
9941    protected boolean awakenScrollBars(int startDelay) {
9942        return awakenScrollBars(startDelay, true);
9943    }
9944
9945    /**
9946     * <p>
9947     * Trigger the scrollbars to draw. When invoked this method starts an
9948     * animation to fade the scrollbars out after a fixed delay. If a subclass
9949     * provides animated scrolling, the start delay should equal the duration of
9950     * the scrolling animation.
9951     * </p>
9952     *
9953     * <p>
9954     * The animation starts only if at least one of the scrollbars is enabled,
9955     * as specified by {@link #isHorizontalScrollBarEnabled()} and
9956     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
9957     * this method returns true, and false otherwise. If the animation is
9958     * started, this method calls {@link #invalidate()} if the invalidate parameter
9959     * is set to true; in that case the caller
9960     * should not call {@link #invalidate()}.
9961     * </p>
9962     *
9963     * <p>
9964     * This method should be invoked everytime a subclass directly updates the
9965     * scroll parameters.
9966     * </p>
9967     *
9968     * @param startDelay the delay, in milliseconds, after which the animation
9969     *        should start; when the delay is 0, the animation starts
9970     *        immediately
9971     *
9972     * @param invalidate Wheter this method should call invalidate
9973     *
9974     * @return true if the animation is played, false otherwise
9975     *
9976     * @see #scrollBy(int, int)
9977     * @see #scrollTo(int, int)
9978     * @see #isHorizontalScrollBarEnabled()
9979     * @see #isVerticalScrollBarEnabled()
9980     * @see #setHorizontalScrollBarEnabled(boolean)
9981     * @see #setVerticalScrollBarEnabled(boolean)
9982     */
9983    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
9984        final ScrollabilityCache scrollCache = mScrollCache;
9985
9986        if (scrollCache == null || !scrollCache.fadeScrollBars) {
9987            return false;
9988        }
9989
9990        if (scrollCache.scrollBar == null) {
9991            scrollCache.scrollBar = new ScrollBarDrawable();
9992        }
9993
9994        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
9995
9996            if (invalidate) {
9997                // Invalidate to show the scrollbars
9998                postInvalidateOnAnimation();
9999            }
10000
10001            if (scrollCache.state == ScrollabilityCache.OFF) {
10002                // FIXME: this is copied from WindowManagerService.
10003                // We should get this value from the system when it
10004                // is possible to do so.
10005                final int KEY_REPEAT_FIRST_DELAY = 750;
10006                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
10007            }
10008
10009            // Tell mScrollCache when we should start fading. This may
10010            // extend the fade start time if one was already scheduled
10011            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
10012            scrollCache.fadeStartTime = fadeStartTime;
10013            scrollCache.state = ScrollabilityCache.ON;
10014
10015            // Schedule our fader to run, unscheduling any old ones first
10016            if (mAttachInfo != null) {
10017                mAttachInfo.mHandler.removeCallbacks(scrollCache);
10018                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
10019            }
10020
10021            return true;
10022        }
10023
10024        return false;
10025    }
10026
10027    /**
10028     * Do not invalidate views which are not visible and which are not running an animation. They
10029     * will not get drawn and they should not set dirty flags as if they will be drawn
10030     */
10031    private boolean skipInvalidate() {
10032        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
10033                (!(mParent instanceof ViewGroup) ||
10034                        !((ViewGroup) mParent).isViewTransitioning(this));
10035    }
10036    /**
10037     * Mark the area defined by dirty as needing to be drawn. If the view is
10038     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
10039     * in the future. This must be called from a UI thread. To call from a non-UI
10040     * thread, call {@link #postInvalidate()}.
10041     *
10042     * WARNING: This method is destructive to dirty.
10043     * @param dirty the rectangle representing the bounds of the dirty region
10044     */
10045    public void invalidate(Rect dirty) {
10046        if (skipInvalidate()) {
10047            return;
10048        }
10049        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10050                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
10051                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
10052            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10053            mPrivateFlags |= PFLAG_INVALIDATED;
10054            mPrivateFlags |= PFLAG_DIRTY;
10055            final ViewParent p = mParent;
10056            final AttachInfo ai = mAttachInfo;
10057            //noinspection PointlessBooleanExpression,ConstantConditions
10058            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10059                if (p != null && ai != null && ai.mHardwareAccelerated) {
10060                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10061                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
10062                    p.invalidateChild(this, null);
10063                    return;
10064                }
10065            }
10066            if (p != null && ai != null) {
10067                final int scrollX = mScrollX;
10068                final int scrollY = mScrollY;
10069                final Rect r = ai.mTmpInvalRect;
10070                r.set(dirty.left - scrollX, dirty.top - scrollY,
10071                        dirty.right - scrollX, dirty.bottom - scrollY);
10072                mParent.invalidateChild(this, r);
10073            }
10074        }
10075    }
10076
10077    /**
10078     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn.
10079     * The coordinates of the dirty rect are relative to the view.
10080     * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
10081     * will be called at some point in the future. This must be called from
10082     * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
10083     * @param l the left position of the dirty region
10084     * @param t the top position of the dirty region
10085     * @param r the right position of the dirty region
10086     * @param b the bottom position of the dirty region
10087     */
10088    public void invalidate(int l, int t, int r, int b) {
10089        if (skipInvalidate()) {
10090            return;
10091        }
10092        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10093                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
10094                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
10095            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10096            mPrivateFlags |= PFLAG_INVALIDATED;
10097            mPrivateFlags |= PFLAG_DIRTY;
10098            final ViewParent p = mParent;
10099            final AttachInfo ai = mAttachInfo;
10100            //noinspection PointlessBooleanExpression,ConstantConditions
10101            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10102                if (p != null && ai != null && ai.mHardwareAccelerated) {
10103                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10104                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
10105                    p.invalidateChild(this, null);
10106                    return;
10107                }
10108            }
10109            if (p != null && ai != null && l < r && t < b) {
10110                final int scrollX = mScrollX;
10111                final int scrollY = mScrollY;
10112                final Rect tmpr = ai.mTmpInvalRect;
10113                tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
10114                p.invalidateChild(this, tmpr);
10115            }
10116        }
10117    }
10118
10119    /**
10120     * Invalidate the whole view. If the view is visible,
10121     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
10122     * the future. This must be called from a UI thread. To call from a non-UI thread,
10123     * call {@link #postInvalidate()}.
10124     */
10125    public void invalidate() {
10126        invalidate(true);
10127    }
10128
10129    /**
10130     * This is where the invalidate() work actually happens. A full invalidate()
10131     * causes the drawing cache to be invalidated, but this function can be called with
10132     * invalidateCache set to false to skip that invalidation step for cases that do not
10133     * need it (for example, a component that remains at the same dimensions with the same
10134     * content).
10135     *
10136     * @param invalidateCache Whether the drawing cache for this view should be invalidated as
10137     * well. This is usually true for a full invalidate, but may be set to false if the
10138     * View's contents or dimensions have not changed.
10139     */
10140    void invalidate(boolean invalidateCache) {
10141        if (skipInvalidate()) {
10142            return;
10143        }
10144        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10145                (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
10146                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
10147            mLastIsOpaque = isOpaque();
10148            mPrivateFlags &= ~PFLAG_DRAWN;
10149            mPrivateFlags |= PFLAG_DIRTY;
10150            if (invalidateCache) {
10151                mPrivateFlags |= PFLAG_INVALIDATED;
10152                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10153            }
10154            final AttachInfo ai = mAttachInfo;
10155            final ViewParent p = mParent;
10156            //noinspection PointlessBooleanExpression,ConstantConditions
10157            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10158                if (p != null && ai != null && ai.mHardwareAccelerated) {
10159                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
10160                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
10161                    p.invalidateChild(this, null);
10162                    return;
10163                }
10164            }
10165
10166            if (p != null && ai != null) {
10167                final Rect r = ai.mTmpInvalRect;
10168                r.set(0, 0, mRight - mLeft, mBottom - mTop);
10169                // Don't call invalidate -- we don't want to internally scroll
10170                // our own bounds
10171                p.invalidateChild(this, r);
10172            }
10173        }
10174    }
10175
10176    /**
10177     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
10178     * set any flags or handle all of the cases handled by the default invalidation methods.
10179     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
10180     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
10181     * walk up the hierarchy, transforming the dirty rect as necessary.
10182     *
10183     * The method also handles normal invalidation logic if display list properties are not
10184     * being used in this view. The invalidateParent and forceRedraw flags are used by that
10185     * backup approach, to handle these cases used in the various property-setting methods.
10186     *
10187     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
10188     * are not being used in this view
10189     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
10190     * list properties are not being used in this view
10191     */
10192    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
10193        if (mDisplayList == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) {
10194            if (invalidateParent) {
10195                invalidateParentCaches();
10196            }
10197            if (forceRedraw) {
10198                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10199            }
10200            invalidate(false);
10201        } else {
10202            final AttachInfo ai = mAttachInfo;
10203            final ViewParent p = mParent;
10204            if (p != null && ai != null) {
10205                final Rect r = ai.mTmpInvalRect;
10206                r.set(0, 0, mRight - mLeft, mBottom - mTop);
10207                if (mParent instanceof ViewGroup) {
10208                    ((ViewGroup) mParent).invalidateChildFast(this, r);
10209                } else {
10210                    mParent.invalidateChild(this, r);
10211                }
10212            }
10213        }
10214    }
10215
10216    /**
10217     * Utility method to transform a given Rect by the current matrix of this view.
10218     */
10219    void transformRect(final Rect rect) {
10220        if (!getMatrix().isIdentity()) {
10221            RectF boundingRect = mAttachInfo.mTmpTransformRect;
10222            boundingRect.set(rect);
10223            getMatrix().mapRect(boundingRect);
10224            rect.set((int) (boundingRect.left - 0.5f),
10225                    (int) (boundingRect.top - 0.5f),
10226                    (int) (boundingRect.right + 0.5f),
10227                    (int) (boundingRect.bottom + 0.5f));
10228        }
10229    }
10230
10231    /**
10232     * Used to indicate that the parent of this view should clear its caches. This functionality
10233     * is used to force the parent to rebuild its display list (when hardware-accelerated),
10234     * which is necessary when various parent-managed properties of the view change, such as
10235     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
10236     * clears the parent caches and does not causes an invalidate event.
10237     *
10238     * @hide
10239     */
10240    protected void invalidateParentCaches() {
10241        if (mParent instanceof View) {
10242            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
10243        }
10244    }
10245
10246    /**
10247     * Used to indicate that the parent of this view should be invalidated. This functionality
10248     * is used to force the parent to rebuild its display list (when hardware-accelerated),
10249     * which is necessary when various parent-managed properties of the view change, such as
10250     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
10251     * an invalidation event to the parent.
10252     *
10253     * @hide
10254     */
10255    protected void invalidateParentIfNeeded() {
10256        if (isHardwareAccelerated() && mParent instanceof View) {
10257            ((View) mParent).invalidate(true);
10258        }
10259    }
10260
10261    /**
10262     * Indicates whether this View is opaque. An opaque View guarantees that it will
10263     * draw all the pixels overlapping its bounds using a fully opaque color.
10264     *
10265     * Subclasses of View should override this method whenever possible to indicate
10266     * whether an instance is opaque. Opaque Views are treated in a special way by
10267     * the View hierarchy, possibly allowing it to perform optimizations during
10268     * invalidate/draw passes.
10269     *
10270     * @return True if this View is guaranteed to be fully opaque, false otherwise.
10271     */
10272    @ViewDebug.ExportedProperty(category = "drawing")
10273    public boolean isOpaque() {
10274        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
10275                ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f);
10276    }
10277
10278    /**
10279     * @hide
10280     */
10281    protected void computeOpaqueFlags() {
10282        // Opaque if:
10283        //   - Has a background
10284        //   - Background is opaque
10285        //   - Doesn't have scrollbars or scrollbars are inside overlay
10286
10287        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
10288            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
10289        } else {
10290            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
10291        }
10292
10293        final int flags = mViewFlags;
10294        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
10295                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
10296            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
10297        } else {
10298            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
10299        }
10300    }
10301
10302    /**
10303     * @hide
10304     */
10305    protected boolean hasOpaqueScrollbars() {
10306        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
10307    }
10308
10309    /**
10310     * @return A handler associated with the thread running the View. This
10311     * handler can be used to pump events in the UI events queue.
10312     */
10313    public Handler getHandler() {
10314        if (mAttachInfo != null) {
10315            return mAttachInfo.mHandler;
10316        }
10317        return null;
10318    }
10319
10320    /**
10321     * Gets the view root associated with the View.
10322     * @return The view root, or null if none.
10323     * @hide
10324     */
10325    public ViewRootImpl getViewRootImpl() {
10326        if (mAttachInfo != null) {
10327            return mAttachInfo.mViewRootImpl;
10328        }
10329        return null;
10330    }
10331
10332    /**
10333     * <p>Causes the Runnable to be added to the message queue.
10334     * The runnable will be run on the user interface thread.</p>
10335     *
10336     * <p>This method can be invoked from outside of the UI thread
10337     * only when this View is attached to a window.</p>
10338     *
10339     * @param action The Runnable that will be executed.
10340     *
10341     * @return Returns true if the Runnable was successfully placed in to the
10342     *         message queue.  Returns false on failure, usually because the
10343     *         looper processing the message queue is exiting.
10344     *
10345     * @see #postDelayed
10346     * @see #removeCallbacks
10347     */
10348    public boolean post(Runnable action) {
10349        final AttachInfo attachInfo = mAttachInfo;
10350        if (attachInfo != null) {
10351            return attachInfo.mHandler.post(action);
10352        }
10353        // Assume that post will succeed later
10354        ViewRootImpl.getRunQueue().post(action);
10355        return true;
10356    }
10357
10358    /**
10359     * <p>Causes the Runnable to be added to the message queue, to be run
10360     * after the specified amount of time elapses.
10361     * The runnable will be run on the user interface thread.</p>
10362     *
10363     * <p>This method can be invoked from outside of the UI thread
10364     * only when this View is attached to a window.</p>
10365     *
10366     * @param action The Runnable that will be executed.
10367     * @param delayMillis The delay (in milliseconds) until the Runnable
10368     *        will be executed.
10369     *
10370     * @return true if the Runnable was successfully placed in to the
10371     *         message queue.  Returns false on failure, usually because the
10372     *         looper processing the message queue is exiting.  Note that a
10373     *         result of true does not mean the Runnable will be processed --
10374     *         if the looper is quit before the delivery time of the message
10375     *         occurs then the message will be dropped.
10376     *
10377     * @see #post
10378     * @see #removeCallbacks
10379     */
10380    public boolean postDelayed(Runnable action, long delayMillis) {
10381        final AttachInfo attachInfo = mAttachInfo;
10382        if (attachInfo != null) {
10383            return attachInfo.mHandler.postDelayed(action, delayMillis);
10384        }
10385        // Assume that post will succeed later
10386        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10387        return true;
10388    }
10389
10390    /**
10391     * <p>Causes the Runnable to execute on the next animation time step.
10392     * The runnable will be run on the user interface thread.</p>
10393     *
10394     * <p>This method can be invoked from outside of the UI thread
10395     * only when this View is attached to a window.</p>
10396     *
10397     * @param action The Runnable that will be executed.
10398     *
10399     * @see #postOnAnimationDelayed
10400     * @see #removeCallbacks
10401     */
10402    public void postOnAnimation(Runnable action) {
10403        final AttachInfo attachInfo = mAttachInfo;
10404        if (attachInfo != null) {
10405            attachInfo.mViewRootImpl.mChoreographer.postCallback(
10406                    Choreographer.CALLBACK_ANIMATION, action, null);
10407        } else {
10408            // Assume that post will succeed later
10409            ViewRootImpl.getRunQueue().post(action);
10410        }
10411    }
10412
10413    /**
10414     * <p>Causes the Runnable to execute on the next animation time step,
10415     * after the specified amount of time elapses.
10416     * The runnable will be run on the user interface thread.</p>
10417     *
10418     * <p>This method can be invoked from outside of the UI thread
10419     * only when this View is attached to a window.</p>
10420     *
10421     * @param action The Runnable that will be executed.
10422     * @param delayMillis The delay (in milliseconds) until the Runnable
10423     *        will be executed.
10424     *
10425     * @see #postOnAnimation
10426     * @see #removeCallbacks
10427     */
10428    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
10429        final AttachInfo attachInfo = mAttachInfo;
10430        if (attachInfo != null) {
10431            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
10432                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
10433        } else {
10434            // Assume that post will succeed later
10435            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10436        }
10437    }
10438
10439    /**
10440     * <p>Removes the specified Runnable from the message queue.</p>
10441     *
10442     * <p>This method can be invoked from outside of the UI thread
10443     * only when this View is attached to a window.</p>
10444     *
10445     * @param action The Runnable to remove from the message handling queue
10446     *
10447     * @return true if this view could ask the Handler to remove the Runnable,
10448     *         false otherwise. When the returned value is true, the Runnable
10449     *         may or may not have been actually removed from the message queue
10450     *         (for instance, if the Runnable was not in the queue already.)
10451     *
10452     * @see #post
10453     * @see #postDelayed
10454     * @see #postOnAnimation
10455     * @see #postOnAnimationDelayed
10456     */
10457    public boolean removeCallbacks(Runnable action) {
10458        if (action != null) {
10459            final AttachInfo attachInfo = mAttachInfo;
10460            if (attachInfo != null) {
10461                attachInfo.mHandler.removeCallbacks(action);
10462                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
10463                        Choreographer.CALLBACK_ANIMATION, action, null);
10464            } else {
10465                // Assume that post will succeed later
10466                ViewRootImpl.getRunQueue().removeCallbacks(action);
10467            }
10468        }
10469        return true;
10470    }
10471
10472    /**
10473     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
10474     * Use this to invalidate the View from a non-UI thread.</p>
10475     *
10476     * <p>This method can be invoked from outside of the UI thread
10477     * only when this View is attached to a window.</p>
10478     *
10479     * @see #invalidate()
10480     * @see #postInvalidateDelayed(long)
10481     */
10482    public void postInvalidate() {
10483        postInvalidateDelayed(0);
10484    }
10485
10486    /**
10487     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10488     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
10489     *
10490     * <p>This method can be invoked from outside of the UI thread
10491     * only when this View is attached to a window.</p>
10492     *
10493     * @param left The left coordinate of the rectangle to invalidate.
10494     * @param top The top coordinate of the rectangle to invalidate.
10495     * @param right The right coordinate of the rectangle to invalidate.
10496     * @param bottom The bottom coordinate of the rectangle to invalidate.
10497     *
10498     * @see #invalidate(int, int, int, int)
10499     * @see #invalidate(Rect)
10500     * @see #postInvalidateDelayed(long, int, int, int, int)
10501     */
10502    public void postInvalidate(int left, int top, int right, int bottom) {
10503        postInvalidateDelayed(0, left, top, right, bottom);
10504    }
10505
10506    /**
10507     * <p>Cause an invalidate to happen on a subsequent cycle through the event
10508     * loop. Waits for the specified amount of time.</p>
10509     *
10510     * <p>This method can be invoked from outside of the UI thread
10511     * only when this View is attached to a window.</p>
10512     *
10513     * @param delayMilliseconds the duration in milliseconds to delay the
10514     *         invalidation by
10515     *
10516     * @see #invalidate()
10517     * @see #postInvalidate()
10518     */
10519    public void postInvalidateDelayed(long delayMilliseconds) {
10520        // We try only with the AttachInfo because there's no point in invalidating
10521        // if we are not attached to our window
10522        final AttachInfo attachInfo = mAttachInfo;
10523        if (attachInfo != null) {
10524            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
10525        }
10526    }
10527
10528    /**
10529     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10530     * through the event loop. Waits for the specified amount of time.</p>
10531     *
10532     * <p>This method can be invoked from outside of the UI thread
10533     * only when this View is attached to a window.</p>
10534     *
10535     * @param delayMilliseconds the duration in milliseconds to delay the
10536     *         invalidation by
10537     * @param left The left coordinate of the rectangle to invalidate.
10538     * @param top The top coordinate of the rectangle to invalidate.
10539     * @param right The right coordinate of the rectangle to invalidate.
10540     * @param bottom The bottom coordinate of the rectangle to invalidate.
10541     *
10542     * @see #invalidate(int, int, int, int)
10543     * @see #invalidate(Rect)
10544     * @see #postInvalidate(int, int, int, int)
10545     */
10546    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
10547            int right, int bottom) {
10548
10549        // We try only with the AttachInfo because there's no point in invalidating
10550        // if we are not attached to our window
10551        final AttachInfo attachInfo = mAttachInfo;
10552        if (attachInfo != null) {
10553            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
10554            info.target = this;
10555            info.left = left;
10556            info.top = top;
10557            info.right = right;
10558            info.bottom = bottom;
10559
10560            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
10561        }
10562    }
10563
10564    /**
10565     * <p>Cause an invalidate to happen on the next animation time step, typically the
10566     * next display frame.</p>
10567     *
10568     * <p>This method can be invoked from outside of the UI thread
10569     * only when this View is attached to a window.</p>
10570     *
10571     * @see #invalidate()
10572     */
10573    public void postInvalidateOnAnimation() {
10574        // We try only with the AttachInfo because there's no point in invalidating
10575        // if we are not attached to our window
10576        final AttachInfo attachInfo = mAttachInfo;
10577        if (attachInfo != null) {
10578            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
10579        }
10580    }
10581
10582    /**
10583     * <p>Cause an invalidate of the specified area to happen on the next animation
10584     * time step, typically the next display frame.</p>
10585     *
10586     * <p>This method can be invoked from outside of the UI thread
10587     * only when this View is attached to a window.</p>
10588     *
10589     * @param left The left coordinate of the rectangle to invalidate.
10590     * @param top The top coordinate of the rectangle to invalidate.
10591     * @param right The right coordinate of the rectangle to invalidate.
10592     * @param bottom The bottom coordinate of the rectangle to invalidate.
10593     *
10594     * @see #invalidate(int, int, int, int)
10595     * @see #invalidate(Rect)
10596     */
10597    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
10598        // We try only with the AttachInfo because there's no point in invalidating
10599        // if we are not attached to our window
10600        final AttachInfo attachInfo = mAttachInfo;
10601        if (attachInfo != null) {
10602            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
10603            info.target = this;
10604            info.left = left;
10605            info.top = top;
10606            info.right = right;
10607            info.bottom = bottom;
10608
10609            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
10610        }
10611    }
10612
10613    /**
10614     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
10615     * This event is sent at most once every
10616     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
10617     */
10618    private void postSendViewScrolledAccessibilityEventCallback() {
10619        if (mSendViewScrolledAccessibilityEvent == null) {
10620            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
10621        }
10622        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
10623            mSendViewScrolledAccessibilityEvent.mIsPending = true;
10624            postDelayed(mSendViewScrolledAccessibilityEvent,
10625                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
10626        }
10627    }
10628
10629    /**
10630     * Called by a parent to request that a child update its values for mScrollX
10631     * and mScrollY if necessary. This will typically be done if the child is
10632     * animating a scroll using a {@link android.widget.Scroller Scroller}
10633     * object.
10634     */
10635    public void computeScroll() {
10636    }
10637
10638    /**
10639     * <p>Indicate whether the horizontal edges are faded when the view is
10640     * scrolled horizontally.</p>
10641     *
10642     * @return true if the horizontal edges should are faded on scroll, false
10643     *         otherwise
10644     *
10645     * @see #setHorizontalFadingEdgeEnabled(boolean)
10646     *
10647     * @attr ref android.R.styleable#View_requiresFadingEdge
10648     */
10649    public boolean isHorizontalFadingEdgeEnabled() {
10650        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
10651    }
10652
10653    /**
10654     * <p>Define whether the horizontal edges should be faded when this view
10655     * is scrolled horizontally.</p>
10656     *
10657     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
10658     *                                    be faded when the view is scrolled
10659     *                                    horizontally
10660     *
10661     * @see #isHorizontalFadingEdgeEnabled()
10662     *
10663     * @attr ref android.R.styleable#View_requiresFadingEdge
10664     */
10665    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
10666        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
10667            if (horizontalFadingEdgeEnabled) {
10668                initScrollCache();
10669            }
10670
10671            mViewFlags ^= FADING_EDGE_HORIZONTAL;
10672        }
10673    }
10674
10675    /**
10676     * <p>Indicate whether the vertical edges are faded when the view is
10677     * scrolled horizontally.</p>
10678     *
10679     * @return true if the vertical edges should are faded on scroll, false
10680     *         otherwise
10681     *
10682     * @see #setVerticalFadingEdgeEnabled(boolean)
10683     *
10684     * @attr ref android.R.styleable#View_requiresFadingEdge
10685     */
10686    public boolean isVerticalFadingEdgeEnabled() {
10687        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
10688    }
10689
10690    /**
10691     * <p>Define whether the vertical edges should be faded when this view
10692     * is scrolled vertically.</p>
10693     *
10694     * @param verticalFadingEdgeEnabled true if the vertical edges should
10695     *                                  be faded when the view is scrolled
10696     *                                  vertically
10697     *
10698     * @see #isVerticalFadingEdgeEnabled()
10699     *
10700     * @attr ref android.R.styleable#View_requiresFadingEdge
10701     */
10702    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
10703        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
10704            if (verticalFadingEdgeEnabled) {
10705                initScrollCache();
10706            }
10707
10708            mViewFlags ^= FADING_EDGE_VERTICAL;
10709        }
10710    }
10711
10712    /**
10713     * Returns the strength, or intensity, of the top faded edge. The strength is
10714     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10715     * returns 0.0 or 1.0 but no value in between.
10716     *
10717     * Subclasses should override this method to provide a smoother fade transition
10718     * when scrolling occurs.
10719     *
10720     * @return the intensity of the top fade as a float between 0.0f and 1.0f
10721     */
10722    protected float getTopFadingEdgeStrength() {
10723        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
10724    }
10725
10726    /**
10727     * Returns the strength, or intensity, of the bottom faded edge. The strength is
10728     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10729     * returns 0.0 or 1.0 but no value in between.
10730     *
10731     * Subclasses should override this method to provide a smoother fade transition
10732     * when scrolling occurs.
10733     *
10734     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
10735     */
10736    protected float getBottomFadingEdgeStrength() {
10737        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
10738                computeVerticalScrollRange() ? 1.0f : 0.0f;
10739    }
10740
10741    /**
10742     * Returns the strength, or intensity, of the left faded edge. The strength is
10743     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10744     * returns 0.0 or 1.0 but no value in between.
10745     *
10746     * Subclasses should override this method to provide a smoother fade transition
10747     * when scrolling occurs.
10748     *
10749     * @return the intensity of the left fade as a float between 0.0f and 1.0f
10750     */
10751    protected float getLeftFadingEdgeStrength() {
10752        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
10753    }
10754
10755    /**
10756     * Returns the strength, or intensity, of the right faded edge. The strength is
10757     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10758     * returns 0.0 or 1.0 but no value in between.
10759     *
10760     * Subclasses should override this method to provide a smoother fade transition
10761     * when scrolling occurs.
10762     *
10763     * @return the intensity of the right fade as a float between 0.0f and 1.0f
10764     */
10765    protected float getRightFadingEdgeStrength() {
10766        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
10767                computeHorizontalScrollRange() ? 1.0f : 0.0f;
10768    }
10769
10770    /**
10771     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
10772     * scrollbar is not drawn by default.</p>
10773     *
10774     * @return true if the horizontal scrollbar should be painted, false
10775     *         otherwise
10776     *
10777     * @see #setHorizontalScrollBarEnabled(boolean)
10778     */
10779    public boolean isHorizontalScrollBarEnabled() {
10780        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
10781    }
10782
10783    /**
10784     * <p>Define whether the horizontal scrollbar should be drawn or not. The
10785     * scrollbar is not drawn by default.</p>
10786     *
10787     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
10788     *                                   be painted
10789     *
10790     * @see #isHorizontalScrollBarEnabled()
10791     */
10792    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
10793        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
10794            mViewFlags ^= SCROLLBARS_HORIZONTAL;
10795            computeOpaqueFlags();
10796            resolvePadding();
10797        }
10798    }
10799
10800    /**
10801     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
10802     * scrollbar is not drawn by default.</p>
10803     *
10804     * @return true if the vertical scrollbar should be painted, false
10805     *         otherwise
10806     *
10807     * @see #setVerticalScrollBarEnabled(boolean)
10808     */
10809    public boolean isVerticalScrollBarEnabled() {
10810        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
10811    }
10812
10813    /**
10814     * <p>Define whether the vertical scrollbar should be drawn or not. The
10815     * scrollbar is not drawn by default.</p>
10816     *
10817     * @param verticalScrollBarEnabled true if the vertical scrollbar should
10818     *                                 be painted
10819     *
10820     * @see #isVerticalScrollBarEnabled()
10821     */
10822    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
10823        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
10824            mViewFlags ^= SCROLLBARS_VERTICAL;
10825            computeOpaqueFlags();
10826            resolvePadding();
10827        }
10828    }
10829
10830    /**
10831     * @hide
10832     */
10833    protected void recomputePadding() {
10834        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
10835    }
10836
10837    /**
10838     * Define whether scrollbars will fade when the view is not scrolling.
10839     *
10840     * @param fadeScrollbars wheter to enable fading
10841     *
10842     * @attr ref android.R.styleable#View_fadeScrollbars
10843     */
10844    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
10845        initScrollCache();
10846        final ScrollabilityCache scrollabilityCache = mScrollCache;
10847        scrollabilityCache.fadeScrollBars = fadeScrollbars;
10848        if (fadeScrollbars) {
10849            scrollabilityCache.state = ScrollabilityCache.OFF;
10850        } else {
10851            scrollabilityCache.state = ScrollabilityCache.ON;
10852        }
10853    }
10854
10855    /**
10856     *
10857     * Returns true if scrollbars will fade when this view is not scrolling
10858     *
10859     * @return true if scrollbar fading is enabled
10860     *
10861     * @attr ref android.R.styleable#View_fadeScrollbars
10862     */
10863    public boolean isScrollbarFadingEnabled() {
10864        return mScrollCache != null && mScrollCache.fadeScrollBars;
10865    }
10866
10867    /**
10868     *
10869     * Returns the delay before scrollbars fade.
10870     *
10871     * @return the delay before scrollbars fade
10872     *
10873     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
10874     */
10875    public int getScrollBarDefaultDelayBeforeFade() {
10876        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
10877                mScrollCache.scrollBarDefaultDelayBeforeFade;
10878    }
10879
10880    /**
10881     * Define the delay before scrollbars fade.
10882     *
10883     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
10884     *
10885     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
10886     */
10887    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
10888        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
10889    }
10890
10891    /**
10892     *
10893     * Returns the scrollbar fade duration.
10894     *
10895     * @return the scrollbar fade duration
10896     *
10897     * @attr ref android.R.styleable#View_scrollbarFadeDuration
10898     */
10899    public int getScrollBarFadeDuration() {
10900        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
10901                mScrollCache.scrollBarFadeDuration;
10902    }
10903
10904    /**
10905     * Define the scrollbar fade duration.
10906     *
10907     * @param scrollBarFadeDuration - the scrollbar fade duration
10908     *
10909     * @attr ref android.R.styleable#View_scrollbarFadeDuration
10910     */
10911    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
10912        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
10913    }
10914
10915    /**
10916     *
10917     * Returns the scrollbar size.
10918     *
10919     * @return the scrollbar size
10920     *
10921     * @attr ref android.R.styleable#View_scrollbarSize
10922     */
10923    public int getScrollBarSize() {
10924        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
10925                mScrollCache.scrollBarSize;
10926    }
10927
10928    /**
10929     * Define the scrollbar size.
10930     *
10931     * @param scrollBarSize - the scrollbar size
10932     *
10933     * @attr ref android.R.styleable#View_scrollbarSize
10934     */
10935    public void setScrollBarSize(int scrollBarSize) {
10936        getScrollCache().scrollBarSize = scrollBarSize;
10937    }
10938
10939    /**
10940     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
10941     * inset. When inset, they add to the padding of the view. And the scrollbars
10942     * can be drawn inside the padding area or on the edge of the view. For example,
10943     * if a view has a background drawable and you want to draw the scrollbars
10944     * inside the padding specified by the drawable, you can use
10945     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
10946     * appear at the edge of the view, ignoring the padding, then you can use
10947     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
10948     * @param style the style of the scrollbars. Should be one of
10949     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
10950     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
10951     * @see #SCROLLBARS_INSIDE_OVERLAY
10952     * @see #SCROLLBARS_INSIDE_INSET
10953     * @see #SCROLLBARS_OUTSIDE_OVERLAY
10954     * @see #SCROLLBARS_OUTSIDE_INSET
10955     *
10956     * @attr ref android.R.styleable#View_scrollbarStyle
10957     */
10958    public void setScrollBarStyle(int style) {
10959        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
10960            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
10961            computeOpaqueFlags();
10962            resolvePadding();
10963        }
10964    }
10965
10966    /**
10967     * <p>Returns the current scrollbar style.</p>
10968     * @return the current scrollbar style
10969     * @see #SCROLLBARS_INSIDE_OVERLAY
10970     * @see #SCROLLBARS_INSIDE_INSET
10971     * @see #SCROLLBARS_OUTSIDE_OVERLAY
10972     * @see #SCROLLBARS_OUTSIDE_INSET
10973     *
10974     * @attr ref android.R.styleable#View_scrollbarStyle
10975     */
10976    @ViewDebug.ExportedProperty(mapping = {
10977            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
10978            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
10979            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
10980            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
10981    })
10982    public int getScrollBarStyle() {
10983        return mViewFlags & SCROLLBARS_STYLE_MASK;
10984    }
10985
10986    /**
10987     * <p>Compute the horizontal range that the horizontal scrollbar
10988     * represents.</p>
10989     *
10990     * <p>The range is expressed in arbitrary units that must be the same as the
10991     * units used by {@link #computeHorizontalScrollExtent()} and
10992     * {@link #computeHorizontalScrollOffset()}.</p>
10993     *
10994     * <p>The default range is the drawing width of this view.</p>
10995     *
10996     * @return the total horizontal range represented by the horizontal
10997     *         scrollbar
10998     *
10999     * @see #computeHorizontalScrollExtent()
11000     * @see #computeHorizontalScrollOffset()
11001     * @see android.widget.ScrollBarDrawable
11002     */
11003    protected int computeHorizontalScrollRange() {
11004        return getWidth();
11005    }
11006
11007    /**
11008     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
11009     * within the horizontal range. This value is used to compute the position
11010     * of the thumb within the scrollbar's track.</p>
11011     *
11012     * <p>The range is expressed in arbitrary units that must be the same as the
11013     * units used by {@link #computeHorizontalScrollRange()} and
11014     * {@link #computeHorizontalScrollExtent()}.</p>
11015     *
11016     * <p>The default offset is the scroll offset of this view.</p>
11017     *
11018     * @return the horizontal offset of the scrollbar's thumb
11019     *
11020     * @see #computeHorizontalScrollRange()
11021     * @see #computeHorizontalScrollExtent()
11022     * @see android.widget.ScrollBarDrawable
11023     */
11024    protected int computeHorizontalScrollOffset() {
11025        return mScrollX;
11026    }
11027
11028    /**
11029     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
11030     * within the horizontal range. This value is used to compute the length
11031     * of the thumb within the scrollbar's track.</p>
11032     *
11033     * <p>The range is expressed in arbitrary units that must be the same as the
11034     * units used by {@link #computeHorizontalScrollRange()} and
11035     * {@link #computeHorizontalScrollOffset()}.</p>
11036     *
11037     * <p>The default extent is the drawing width of this view.</p>
11038     *
11039     * @return the horizontal extent of the scrollbar's thumb
11040     *
11041     * @see #computeHorizontalScrollRange()
11042     * @see #computeHorizontalScrollOffset()
11043     * @see android.widget.ScrollBarDrawable
11044     */
11045    protected int computeHorizontalScrollExtent() {
11046        return getWidth();
11047    }
11048
11049    /**
11050     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
11051     *
11052     * <p>The range is expressed in arbitrary units that must be the same as the
11053     * units used by {@link #computeVerticalScrollExtent()} and
11054     * {@link #computeVerticalScrollOffset()}.</p>
11055     *
11056     * @return the total vertical range represented by the vertical scrollbar
11057     *
11058     * <p>The default range is the drawing height of this view.</p>
11059     *
11060     * @see #computeVerticalScrollExtent()
11061     * @see #computeVerticalScrollOffset()
11062     * @see android.widget.ScrollBarDrawable
11063     */
11064    protected int computeVerticalScrollRange() {
11065        return getHeight();
11066    }
11067
11068    /**
11069     * <p>Compute the vertical offset of the vertical scrollbar's thumb
11070     * within the horizontal range. This value is used to compute the position
11071     * of the thumb within the scrollbar's track.</p>
11072     *
11073     * <p>The range is expressed in arbitrary units that must be the same as the
11074     * units used by {@link #computeVerticalScrollRange()} and
11075     * {@link #computeVerticalScrollExtent()}.</p>
11076     *
11077     * <p>The default offset is the scroll offset of this view.</p>
11078     *
11079     * @return the vertical offset of the scrollbar's thumb
11080     *
11081     * @see #computeVerticalScrollRange()
11082     * @see #computeVerticalScrollExtent()
11083     * @see android.widget.ScrollBarDrawable
11084     */
11085    protected int computeVerticalScrollOffset() {
11086        return mScrollY;
11087    }
11088
11089    /**
11090     * <p>Compute the vertical extent of the horizontal scrollbar's thumb
11091     * within the vertical range. This value is used to compute the length
11092     * of the thumb within the scrollbar's track.</p>
11093     *
11094     * <p>The range is expressed in arbitrary units that must be the same as the
11095     * units used by {@link #computeVerticalScrollRange()} and
11096     * {@link #computeVerticalScrollOffset()}.</p>
11097     *
11098     * <p>The default extent is the drawing height of this view.</p>
11099     *
11100     * @return the vertical extent of the scrollbar's thumb
11101     *
11102     * @see #computeVerticalScrollRange()
11103     * @see #computeVerticalScrollOffset()
11104     * @see android.widget.ScrollBarDrawable
11105     */
11106    protected int computeVerticalScrollExtent() {
11107        return getHeight();
11108    }
11109
11110    /**
11111     * Check if this view can be scrolled horizontally in a certain direction.
11112     *
11113     * @param direction Negative to check scrolling left, positive to check scrolling right.
11114     * @return true if this view can be scrolled in the specified direction, false otherwise.
11115     */
11116    public boolean canScrollHorizontally(int direction) {
11117        final int offset = computeHorizontalScrollOffset();
11118        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
11119        if (range == 0) return false;
11120        if (direction < 0) {
11121            return offset > 0;
11122        } else {
11123            return offset < range - 1;
11124        }
11125    }
11126
11127    /**
11128     * Check if this view can be scrolled vertically in a certain direction.
11129     *
11130     * @param direction Negative to check scrolling up, positive to check scrolling down.
11131     * @return true if this view can be scrolled in the specified direction, false otherwise.
11132     */
11133    public boolean canScrollVertically(int direction) {
11134        final int offset = computeVerticalScrollOffset();
11135        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
11136        if (range == 0) return false;
11137        if (direction < 0) {
11138            return offset > 0;
11139        } else {
11140            return offset < range - 1;
11141        }
11142    }
11143
11144    /**
11145     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
11146     * scrollbars are painted only if they have been awakened first.</p>
11147     *
11148     * @param canvas the canvas on which to draw the scrollbars
11149     *
11150     * @see #awakenScrollBars(int)
11151     */
11152    protected final void onDrawScrollBars(Canvas canvas) {
11153        // scrollbars are drawn only when the animation is running
11154        final ScrollabilityCache cache = mScrollCache;
11155        if (cache != null) {
11156
11157            int state = cache.state;
11158
11159            if (state == ScrollabilityCache.OFF) {
11160                return;
11161            }
11162
11163            boolean invalidate = false;
11164
11165            if (state == ScrollabilityCache.FADING) {
11166                // We're fading -- get our fade interpolation
11167                if (cache.interpolatorValues == null) {
11168                    cache.interpolatorValues = new float[1];
11169                }
11170
11171                float[] values = cache.interpolatorValues;
11172
11173                // Stops the animation if we're done
11174                if (cache.scrollBarInterpolator.timeToValues(values) ==
11175                        Interpolator.Result.FREEZE_END) {
11176                    cache.state = ScrollabilityCache.OFF;
11177                } else {
11178                    cache.scrollBar.setAlpha(Math.round(values[0]));
11179                }
11180
11181                // This will make the scroll bars inval themselves after
11182                // drawing. We only want this when we're fading so that
11183                // we prevent excessive redraws
11184                invalidate = true;
11185            } else {
11186                // We're just on -- but we may have been fading before so
11187                // reset alpha
11188                cache.scrollBar.setAlpha(255);
11189            }
11190
11191
11192            final int viewFlags = mViewFlags;
11193
11194            final boolean drawHorizontalScrollBar =
11195                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
11196            final boolean drawVerticalScrollBar =
11197                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
11198                && !isVerticalScrollBarHidden();
11199
11200            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
11201                final int width = mRight - mLeft;
11202                final int height = mBottom - mTop;
11203
11204                final ScrollBarDrawable scrollBar = cache.scrollBar;
11205
11206                final int scrollX = mScrollX;
11207                final int scrollY = mScrollY;
11208                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
11209
11210                int left, top, right, bottom;
11211
11212                if (drawHorizontalScrollBar) {
11213                    int size = scrollBar.getSize(false);
11214                    if (size <= 0) {
11215                        size = cache.scrollBarSize;
11216                    }
11217
11218                    scrollBar.setParameters(computeHorizontalScrollRange(),
11219                                            computeHorizontalScrollOffset(),
11220                                            computeHorizontalScrollExtent(), false);
11221                    final int verticalScrollBarGap = drawVerticalScrollBar ?
11222                            getVerticalScrollbarWidth() : 0;
11223                    top = scrollY + height - size - (mUserPaddingBottom & inside);
11224                    left = scrollX + (mPaddingLeft & inside);
11225                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
11226                    bottom = top + size;
11227                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
11228                    if (invalidate) {
11229                        invalidate(left, top, right, bottom);
11230                    }
11231                }
11232
11233                if (drawVerticalScrollBar) {
11234                    int size = scrollBar.getSize(true);
11235                    if (size <= 0) {
11236                        size = cache.scrollBarSize;
11237                    }
11238
11239                    scrollBar.setParameters(computeVerticalScrollRange(),
11240                                            computeVerticalScrollOffset(),
11241                                            computeVerticalScrollExtent(), true);
11242                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
11243                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
11244                        verticalScrollbarPosition = isLayoutRtl() ?
11245                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
11246                    }
11247                    switch (verticalScrollbarPosition) {
11248                        default:
11249                        case SCROLLBAR_POSITION_RIGHT:
11250                            left = scrollX + width - size - (mUserPaddingRight & inside);
11251                            break;
11252                        case SCROLLBAR_POSITION_LEFT:
11253                            left = scrollX + (mUserPaddingLeft & inside);
11254                            break;
11255                    }
11256                    top = scrollY + (mPaddingTop & inside);
11257                    right = left + size;
11258                    bottom = scrollY + height - (mUserPaddingBottom & inside);
11259                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
11260                    if (invalidate) {
11261                        invalidate(left, top, right, bottom);
11262                    }
11263                }
11264            }
11265        }
11266    }
11267
11268    /**
11269     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
11270     * FastScroller is visible.
11271     * @return whether to temporarily hide the vertical scrollbar
11272     * @hide
11273     */
11274    protected boolean isVerticalScrollBarHidden() {
11275        return false;
11276    }
11277
11278    /**
11279     * <p>Draw the horizontal scrollbar if
11280     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
11281     *
11282     * @param canvas the canvas on which to draw the scrollbar
11283     * @param scrollBar the scrollbar's drawable
11284     *
11285     * @see #isHorizontalScrollBarEnabled()
11286     * @see #computeHorizontalScrollRange()
11287     * @see #computeHorizontalScrollExtent()
11288     * @see #computeHorizontalScrollOffset()
11289     * @see android.widget.ScrollBarDrawable
11290     * @hide
11291     */
11292    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
11293            int l, int t, int r, int b) {
11294        scrollBar.setBounds(l, t, r, b);
11295        scrollBar.draw(canvas);
11296    }
11297
11298    /**
11299     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
11300     * returns true.</p>
11301     *
11302     * @param canvas the canvas on which to draw the scrollbar
11303     * @param scrollBar the scrollbar's drawable
11304     *
11305     * @see #isVerticalScrollBarEnabled()
11306     * @see #computeVerticalScrollRange()
11307     * @see #computeVerticalScrollExtent()
11308     * @see #computeVerticalScrollOffset()
11309     * @see android.widget.ScrollBarDrawable
11310     * @hide
11311     */
11312    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
11313            int l, int t, int r, int b) {
11314        scrollBar.setBounds(l, t, r, b);
11315        scrollBar.draw(canvas);
11316    }
11317
11318    /**
11319     * Implement this to do your drawing.
11320     *
11321     * @param canvas the canvas on which the background will be drawn
11322     */
11323    protected void onDraw(Canvas canvas) {
11324    }
11325
11326    /*
11327     * Caller is responsible for calling requestLayout if necessary.
11328     * (This allows addViewInLayout to not request a new layout.)
11329     */
11330    void assignParent(ViewParent parent) {
11331        if (mParent == null) {
11332            mParent = parent;
11333        } else if (parent == null) {
11334            mParent = null;
11335        } else {
11336            throw new RuntimeException("view " + this + " being added, but"
11337                    + " it already has a parent");
11338        }
11339    }
11340
11341    /**
11342     * This is called when the view is attached to a window.  At this point it
11343     * has a Surface and will start drawing.  Note that this function is
11344     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
11345     * however it may be called any time before the first onDraw -- including
11346     * before or after {@link #onMeasure(int, int)}.
11347     *
11348     * @see #onDetachedFromWindow()
11349     */
11350    protected void onAttachedToWindow() {
11351        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
11352            mParent.requestTransparentRegion(this);
11353        }
11354
11355        if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
11356            initialAwakenScrollBars();
11357            mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
11358        }
11359
11360        jumpDrawablesToCurrentState();
11361
11362        resolveRtlProperties();
11363
11364        clearAccessibilityFocus();
11365        if (isFocused()) {
11366            InputMethodManager imm = InputMethodManager.peekInstance();
11367            imm.focusIn(this);
11368        }
11369
11370        if (mAttachInfo != null && mDisplayList != null) {
11371            mAttachInfo.mViewRootImpl.dequeueDisplayList(mDisplayList);
11372        }
11373    }
11374
11375    void resolveRtlProperties() {
11376        // Order is important here: LayoutDirection MUST be resolved first...
11377        resolveLayoutDirection();
11378        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
11379        resolvePadding();
11380        resolveLayoutParams();
11381        resolveTextDirection();
11382        resolveTextAlignment();
11383        resolveDrawables();
11384    }
11385
11386    /**
11387     * @see #onScreenStateChanged(int)
11388     */
11389    void dispatchScreenStateChanged(int screenState) {
11390        onScreenStateChanged(screenState);
11391    }
11392
11393    /**
11394     * This method is called whenever the state of the screen this view is
11395     * attached to changes. A state change will usually occurs when the screen
11396     * turns on or off (whether it happens automatically or the user does it
11397     * manually.)
11398     *
11399     * @param screenState The new state of the screen. Can be either
11400     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
11401     */
11402    public void onScreenStateChanged(int screenState) {
11403    }
11404
11405    /**
11406     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
11407     */
11408    private boolean hasRtlSupport() {
11409        return mContext.getApplicationInfo().hasRtlSupport();
11410    }
11411
11412    /**
11413     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
11414     * that the parent directionality can and will be resolved before its children.
11415     * Will call {@link View#onResolvedLayoutDirectionChanged} when resolution is done.
11416     */
11417    public void resolveLayoutDirection() {
11418        // Clear any previous layout direction resolution
11419        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
11420
11421        if (hasRtlSupport()) {
11422            // Set resolved depending on layout direction
11423            switch (getLayoutDirection()) {
11424                case LAYOUT_DIRECTION_INHERIT:
11425                    // We cannot resolve yet. LTR is by default and let the resolution happen again
11426                    // later to get the correct resolved value
11427                    if (!canResolveLayoutDirection()) return;
11428
11429                    ViewGroup viewGroup = ((ViewGroup) mParent);
11430
11431                    // We cannot resolve yet on the parent too. LTR is by default and let the
11432                    // resolution happen again later
11433                    if (!viewGroup.canResolveLayoutDirection()) return;
11434
11435                    if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
11436                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
11437                    }
11438                    break;
11439                case LAYOUT_DIRECTION_RTL:
11440                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
11441                    break;
11442                case LAYOUT_DIRECTION_LOCALE:
11443                    if(isLayoutDirectionRtl(Locale.getDefault())) {
11444                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
11445                    }
11446                    break;
11447                default:
11448                    // Nothing to do, LTR by default
11449            }
11450        }
11451
11452        // Set to resolved
11453        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
11454        onResolvedLayoutDirectionChanged();
11455    }
11456
11457    /**
11458     * Called when layout direction has been resolved.
11459     *
11460     * The default implementation does nothing.
11461     */
11462    public void onResolvedLayoutDirectionChanged() {
11463    }
11464
11465    /**
11466     * Return if padding has been resolved
11467     */
11468    boolean isPaddingResolved() {
11469        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) != 0;
11470    }
11471
11472    /**
11473     * Resolve padding depending on layout direction.
11474     */
11475    public void resolvePadding() {
11476        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
11477        if (targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport()) {
11478            // Pre Jelly Bean MR1 case (compatibility mode) OR no RTL support case:
11479            // left / right padding are used if defined. If they are not defined and start / end
11480            // padding are defined (e.g. in Frameworks resources), then we use start / end and
11481            // resolve them as left / right (layout direction is not taken into account).
11482            if (!mUserPaddingLeftDefined && mUserPaddingStart != UNDEFINED_PADDING) {
11483                mUserPaddingLeft = mUserPaddingStart;
11484            }
11485            if (!mUserPaddingRightDefined && mUserPaddingEnd != UNDEFINED_PADDING) {
11486                mUserPaddingRight = mUserPaddingEnd;
11487            }
11488
11489            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11490
11491            internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11492                    mUserPaddingBottom);
11493        } else {
11494            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
11495            // If start / end padding are defined, they will be resolved (hence overriding) to
11496            // left / right or right / left depending on the resolved layout direction.
11497            // If start / end padding are not defined, use the left / right ones.
11498            int resolvedLayoutDirection = getResolvedLayoutDirection();
11499            switch (resolvedLayoutDirection) {
11500                case LAYOUT_DIRECTION_RTL:
11501                    if (mUserPaddingStart != UNDEFINED_PADDING) {
11502                        mUserPaddingRight = mUserPaddingStart;
11503                    }
11504                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
11505                        mUserPaddingLeft = mUserPaddingEnd;
11506                    }
11507                    break;
11508                case LAYOUT_DIRECTION_LTR:
11509                default:
11510                    if (mUserPaddingStart != UNDEFINED_PADDING) {
11511                        mUserPaddingLeft = mUserPaddingStart;
11512                    }
11513                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
11514                        mUserPaddingRight = mUserPaddingEnd;
11515                    }
11516            }
11517
11518            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11519
11520            internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11521                    mUserPaddingBottom);
11522            onPaddingChanged(resolvedLayoutDirection);
11523        }
11524
11525        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
11526    }
11527
11528    /**
11529     * Resolve padding depending on the layout direction. Subclasses that care about
11530     * padding resolution should override this method. The default implementation does
11531     * nothing.
11532     *
11533     * @param layoutDirection the direction of the layout
11534     *
11535     * @see {@link #LAYOUT_DIRECTION_LTR}
11536     * @see {@link #LAYOUT_DIRECTION_RTL}
11537     */
11538    public void onPaddingChanged(int layoutDirection) {
11539    }
11540
11541    /**
11542     * Check if layout direction resolution can be done.
11543     *
11544     * @return true if layout direction resolution can be done otherwise return false.
11545     */
11546    public boolean canResolveLayoutDirection() {
11547        switch (getLayoutDirection()) {
11548            case LAYOUT_DIRECTION_INHERIT:
11549                return (mParent != null) && (mParent instanceof ViewGroup);
11550            default:
11551                return true;
11552        }
11553    }
11554
11555    /**
11556     * Reset the resolved layout direction. Will call {@link View#onResolvedLayoutDirectionReset}
11557     * when reset is done.
11558     */
11559    public void resetResolvedLayoutDirection() {
11560        // Reset the current resolved bits
11561        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
11562        onResolvedLayoutDirectionReset();
11563        // Reset also the text direction
11564        resetResolvedTextDirection();
11565    }
11566
11567    /**
11568     * Called during reset of resolved layout direction.
11569     *
11570     * Subclasses need to override this method to clear cached information that depends on the
11571     * resolved layout direction, or to inform child views that inherit their layout direction.
11572     *
11573     * The default implementation does nothing.
11574     */
11575    public void onResolvedLayoutDirectionReset() {
11576    }
11577
11578    /**
11579     * Check if a Locale uses an RTL script.
11580     *
11581     * @param locale Locale to check
11582     * @return true if the Locale uses an RTL script.
11583     */
11584    protected static boolean isLayoutDirectionRtl(Locale locale) {
11585        return (LAYOUT_DIRECTION_RTL == LocaleUtil.getLayoutDirectionFromLocale(locale));
11586    }
11587
11588    /**
11589     * This is called when the view is detached from a window.  At this point it
11590     * no longer has a surface for drawing.
11591     *
11592     * @see #onAttachedToWindow()
11593     */
11594    protected void onDetachedFromWindow() {
11595        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
11596
11597        removeUnsetPressCallback();
11598        removeLongPressCallback();
11599        removePerformClickCallback();
11600        removeSendViewScrolledAccessibilityEventCallback();
11601
11602        destroyDrawingCache();
11603
11604        destroyLayer(false);
11605
11606        if (mAttachInfo != null) {
11607            if (mDisplayList != null) {
11608                mAttachInfo.mViewRootImpl.enqueueDisplayList(mDisplayList);
11609            }
11610            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
11611        } else {
11612            // Should never happen
11613            clearDisplayList();
11614        }
11615
11616        mCurrentAnimation = null;
11617
11618        resetResolvedLayoutDirection();
11619        resetResolvedTextAlignment();
11620        resetAccessibilityStateChanged();
11621        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
11622    }
11623
11624    /**
11625     * @return The number of times this view has been attached to a window
11626     */
11627    protected int getWindowAttachCount() {
11628        return mWindowAttachCount;
11629    }
11630
11631    /**
11632     * Retrieve a unique token identifying the window this view is attached to.
11633     * @return Return the window's token for use in
11634     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
11635     */
11636    public IBinder getWindowToken() {
11637        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
11638    }
11639
11640    /**
11641     * Retrieve a unique token identifying the top-level "real" window of
11642     * the window that this view is attached to.  That is, this is like
11643     * {@link #getWindowToken}, except if the window this view in is a panel
11644     * window (attached to another containing window), then the token of
11645     * the containing window is returned instead.
11646     *
11647     * @return Returns the associated window token, either
11648     * {@link #getWindowToken()} or the containing window's token.
11649     */
11650    public IBinder getApplicationWindowToken() {
11651        AttachInfo ai = mAttachInfo;
11652        if (ai != null) {
11653            IBinder appWindowToken = ai.mPanelParentWindowToken;
11654            if (appWindowToken == null) {
11655                appWindowToken = ai.mWindowToken;
11656            }
11657            return appWindowToken;
11658        }
11659        return null;
11660    }
11661
11662    /**
11663     * Gets the logical display to which the view's window has been attached.
11664     *
11665     * @return The logical display, or null if the view is not currently attached to a window.
11666     */
11667    public Display getDisplay() {
11668        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
11669    }
11670
11671    /**
11672     * Retrieve private session object this view hierarchy is using to
11673     * communicate with the window manager.
11674     * @return the session object to communicate with the window manager
11675     */
11676    /*package*/ IWindowSession getWindowSession() {
11677        return mAttachInfo != null ? mAttachInfo.mSession : null;
11678    }
11679
11680    /**
11681     * @param info the {@link android.view.View.AttachInfo} to associated with
11682     *        this view
11683     */
11684    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
11685        //System.out.println("Attached! " + this);
11686        mAttachInfo = info;
11687        mWindowAttachCount++;
11688        // We will need to evaluate the drawable state at least once.
11689        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
11690        if (mFloatingTreeObserver != null) {
11691            info.mTreeObserver.merge(mFloatingTreeObserver);
11692            mFloatingTreeObserver = null;
11693        }
11694        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
11695            mAttachInfo.mScrollContainers.add(this);
11696            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
11697        }
11698        performCollectViewAttributes(mAttachInfo, visibility);
11699        onAttachedToWindow();
11700
11701        ListenerInfo li = mListenerInfo;
11702        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
11703                li != null ? li.mOnAttachStateChangeListeners : null;
11704        if (listeners != null && listeners.size() > 0) {
11705            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
11706            // perform the dispatching. The iterator is a safe guard against listeners that
11707            // could mutate the list by calling the various add/remove methods. This prevents
11708            // the array from being modified while we iterate it.
11709            for (OnAttachStateChangeListener listener : listeners) {
11710                listener.onViewAttachedToWindow(this);
11711            }
11712        }
11713
11714        int vis = info.mWindowVisibility;
11715        if (vis != GONE) {
11716            onWindowVisibilityChanged(vis);
11717        }
11718        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
11719            // If nobody has evaluated the drawable state yet, then do it now.
11720            refreshDrawableState();
11721        }
11722        needGlobalAttributesUpdate(false);
11723    }
11724
11725    void dispatchDetachedFromWindow() {
11726        AttachInfo info = mAttachInfo;
11727        if (info != null) {
11728            int vis = info.mWindowVisibility;
11729            if (vis != GONE) {
11730                onWindowVisibilityChanged(GONE);
11731            }
11732        }
11733
11734        onDetachedFromWindow();
11735
11736        ListenerInfo li = mListenerInfo;
11737        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
11738                li != null ? li.mOnAttachStateChangeListeners : null;
11739        if (listeners != null && listeners.size() > 0) {
11740            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
11741            // perform the dispatching. The iterator is a safe guard against listeners that
11742            // could mutate the list by calling the various add/remove methods. This prevents
11743            // the array from being modified while we iterate it.
11744            for (OnAttachStateChangeListener listener : listeners) {
11745                listener.onViewDetachedFromWindow(this);
11746            }
11747        }
11748
11749        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
11750            mAttachInfo.mScrollContainers.remove(this);
11751            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
11752        }
11753
11754        mAttachInfo = null;
11755    }
11756
11757    /**
11758     * Store this view hierarchy's frozen state into the given container.
11759     *
11760     * @param container The SparseArray in which to save the view's state.
11761     *
11762     * @see #restoreHierarchyState(android.util.SparseArray)
11763     * @see #dispatchSaveInstanceState(android.util.SparseArray)
11764     * @see #onSaveInstanceState()
11765     */
11766    public void saveHierarchyState(SparseArray<Parcelable> container) {
11767        dispatchSaveInstanceState(container);
11768    }
11769
11770    /**
11771     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
11772     * this view and its children. May be overridden to modify how freezing happens to a
11773     * view's children; for example, some views may want to not store state for their children.
11774     *
11775     * @param container The SparseArray in which to save the view's state.
11776     *
11777     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
11778     * @see #saveHierarchyState(android.util.SparseArray)
11779     * @see #onSaveInstanceState()
11780     */
11781    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
11782        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
11783            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
11784            Parcelable state = onSaveInstanceState();
11785            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
11786                throw new IllegalStateException(
11787                        "Derived class did not call super.onSaveInstanceState()");
11788            }
11789            if (state != null) {
11790                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
11791                // + ": " + state);
11792                container.put(mID, state);
11793            }
11794        }
11795    }
11796
11797    /**
11798     * Hook allowing a view to generate a representation of its internal state
11799     * that can later be used to create a new instance with that same state.
11800     * This state should only contain information that is not persistent or can
11801     * not be reconstructed later. For example, you will never store your
11802     * current position on screen because that will be computed again when a
11803     * new instance of the view is placed in its view hierarchy.
11804     * <p>
11805     * Some examples of things you may store here: the current cursor position
11806     * in a text view (but usually not the text itself since that is stored in a
11807     * content provider or other persistent storage), the currently selected
11808     * item in a list view.
11809     *
11810     * @return Returns a Parcelable object containing the view's current dynamic
11811     *         state, or null if there is nothing interesting to save. The
11812     *         default implementation returns null.
11813     * @see #onRestoreInstanceState(android.os.Parcelable)
11814     * @see #saveHierarchyState(android.util.SparseArray)
11815     * @see #dispatchSaveInstanceState(android.util.SparseArray)
11816     * @see #setSaveEnabled(boolean)
11817     */
11818    protected Parcelable onSaveInstanceState() {
11819        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
11820        return BaseSavedState.EMPTY_STATE;
11821    }
11822
11823    /**
11824     * Restore this view hierarchy's frozen state from the given container.
11825     *
11826     * @param container The SparseArray which holds previously frozen states.
11827     *
11828     * @see #saveHierarchyState(android.util.SparseArray)
11829     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
11830     * @see #onRestoreInstanceState(android.os.Parcelable)
11831     */
11832    public void restoreHierarchyState(SparseArray<Parcelable> container) {
11833        dispatchRestoreInstanceState(container);
11834    }
11835
11836    /**
11837     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
11838     * state for this view and its children. May be overridden to modify how restoring
11839     * happens to a view's children; for example, some views may want to not store state
11840     * for their children.
11841     *
11842     * @param container The SparseArray which holds previously saved state.
11843     *
11844     * @see #dispatchSaveInstanceState(android.util.SparseArray)
11845     * @see #restoreHierarchyState(android.util.SparseArray)
11846     * @see #onRestoreInstanceState(android.os.Parcelable)
11847     */
11848    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
11849        if (mID != NO_ID) {
11850            Parcelable state = container.get(mID);
11851            if (state != null) {
11852                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
11853                // + ": " + state);
11854                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
11855                onRestoreInstanceState(state);
11856                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
11857                    throw new IllegalStateException(
11858                            "Derived class did not call super.onRestoreInstanceState()");
11859                }
11860            }
11861        }
11862    }
11863
11864    /**
11865     * Hook allowing a view to re-apply a representation of its internal state that had previously
11866     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
11867     * null state.
11868     *
11869     * @param state The frozen state that had previously been returned by
11870     *        {@link #onSaveInstanceState}.
11871     *
11872     * @see #onSaveInstanceState()
11873     * @see #restoreHierarchyState(android.util.SparseArray)
11874     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
11875     */
11876    protected void onRestoreInstanceState(Parcelable state) {
11877        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
11878        if (state != BaseSavedState.EMPTY_STATE && state != null) {
11879            throw new IllegalArgumentException("Wrong state class, expecting View State but "
11880                    + "received " + state.getClass().toString() + " instead. This usually happens "
11881                    + "when two views of different type have the same id in the same hierarchy. "
11882                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
11883                    + "other views do not use the same id.");
11884        }
11885    }
11886
11887    /**
11888     * <p>Return the time at which the drawing of the view hierarchy started.</p>
11889     *
11890     * @return the drawing start time in milliseconds
11891     */
11892    public long getDrawingTime() {
11893        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
11894    }
11895
11896    /**
11897     * <p>Enables or disables the duplication of the parent's state into this view. When
11898     * duplication is enabled, this view gets its drawable state from its parent rather
11899     * than from its own internal properties.</p>
11900     *
11901     * <p>Note: in the current implementation, setting this property to true after the
11902     * view was added to a ViewGroup might have no effect at all. This property should
11903     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
11904     *
11905     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
11906     * property is enabled, an exception will be thrown.</p>
11907     *
11908     * <p>Note: if the child view uses and updates additionnal states which are unknown to the
11909     * parent, these states should not be affected by this method.</p>
11910     *
11911     * @param enabled True to enable duplication of the parent's drawable state, false
11912     *                to disable it.
11913     *
11914     * @see #getDrawableState()
11915     * @see #isDuplicateParentStateEnabled()
11916     */
11917    public void setDuplicateParentStateEnabled(boolean enabled) {
11918        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
11919    }
11920
11921    /**
11922     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
11923     *
11924     * @return True if this view's drawable state is duplicated from the parent,
11925     *         false otherwise
11926     *
11927     * @see #getDrawableState()
11928     * @see #setDuplicateParentStateEnabled(boolean)
11929     */
11930    public boolean isDuplicateParentStateEnabled() {
11931        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
11932    }
11933
11934    /**
11935     * <p>Specifies the type of layer backing this view. The layer can be
11936     * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
11937     * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
11938     *
11939     * <p>A layer is associated with an optional {@link android.graphics.Paint}
11940     * instance that controls how the layer is composed on screen. The following
11941     * properties of the paint are taken into account when composing the layer:</p>
11942     * <ul>
11943     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
11944     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
11945     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
11946     * </ul>
11947     *
11948     * <p>If this view has an alpha value set to < 1.0 by calling
11949     * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
11950     * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
11951     * equivalent to setting a hardware layer on this view and providing a paint with
11952     * the desired alpha value.</p>
11953     *
11954     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
11955     * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
11956     * for more information on when and how to use layers.</p>
11957     *
11958     * @param layerType The type of layer to use with this view, must be one of
11959     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
11960     *        {@link #LAYER_TYPE_HARDWARE}
11961     * @param paint The paint used to compose the layer. This argument is optional
11962     *        and can be null. It is ignored when the layer type is
11963     *        {@link #LAYER_TYPE_NONE}
11964     *
11965     * @see #getLayerType()
11966     * @see #LAYER_TYPE_NONE
11967     * @see #LAYER_TYPE_SOFTWARE
11968     * @see #LAYER_TYPE_HARDWARE
11969     * @see #setAlpha(float)
11970     *
11971     * @attr ref android.R.styleable#View_layerType
11972     */
11973    public void setLayerType(int layerType, Paint paint) {
11974        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
11975            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
11976                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
11977        }
11978
11979        if (layerType == mLayerType) {
11980            if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
11981                mLayerPaint = paint == null ? new Paint() : paint;
11982                invalidateParentCaches();
11983                invalidate(true);
11984            }
11985            return;
11986        }
11987
11988        // Destroy any previous software drawing cache if needed
11989        switch (mLayerType) {
11990            case LAYER_TYPE_HARDWARE:
11991                destroyLayer(false);
11992                // fall through - non-accelerated views may use software layer mechanism instead
11993            case LAYER_TYPE_SOFTWARE:
11994                destroyDrawingCache();
11995                break;
11996            default:
11997                break;
11998        }
11999
12000        mLayerType = layerType;
12001        final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
12002        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
12003        mLocalDirtyRect = layerDisabled ? null : new Rect();
12004
12005        invalidateParentCaches();
12006        invalidate(true);
12007    }
12008
12009    /**
12010     * Updates the {@link Paint} object used with the current layer (used only if the current
12011     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
12012     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
12013     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
12014     * ensure that the view gets redrawn immediately.
12015     *
12016     * <p>A layer is associated with an optional {@link android.graphics.Paint}
12017     * instance that controls how the layer is composed on screen. The following
12018     * properties of the paint are taken into account when composing the layer:</p>
12019     * <ul>
12020     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
12021     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
12022     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
12023     * </ul>
12024     *
12025     * <p>If this view has an alpha value set to < 1.0 by calling
12026     * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
12027     * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
12028     * equivalent to setting a hardware layer on this view and providing a paint with
12029     * the desired alpha value.</p>
12030     *
12031     * @param paint The paint used to compose the layer. This argument is optional
12032     *        and can be null. It is ignored when the layer type is
12033     *        {@link #LAYER_TYPE_NONE}
12034     *
12035     * @see #setLayerType(int, android.graphics.Paint)
12036     */
12037    public void setLayerPaint(Paint paint) {
12038        int layerType = getLayerType();
12039        if (layerType != LAYER_TYPE_NONE) {
12040            mLayerPaint = paint == null ? new Paint() : paint;
12041            if (layerType == LAYER_TYPE_HARDWARE) {
12042                HardwareLayer layer = getHardwareLayer();
12043                if (layer != null) {
12044                    layer.setLayerPaint(paint);
12045                }
12046                invalidateViewProperty(false, false);
12047            } else {
12048                invalidate();
12049            }
12050        }
12051    }
12052
12053    /**
12054     * Indicates whether this view has a static layer. A view with layer type
12055     * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
12056     * dynamic.
12057     */
12058    boolean hasStaticLayer() {
12059        return true;
12060    }
12061
12062    /**
12063     * Indicates what type of layer is currently associated with this view. By default
12064     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
12065     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
12066     * for more information on the different types of layers.
12067     *
12068     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
12069     *         {@link #LAYER_TYPE_HARDWARE}
12070     *
12071     * @see #setLayerType(int, android.graphics.Paint)
12072     * @see #buildLayer()
12073     * @see #LAYER_TYPE_NONE
12074     * @see #LAYER_TYPE_SOFTWARE
12075     * @see #LAYER_TYPE_HARDWARE
12076     */
12077    public int getLayerType() {
12078        return mLayerType;
12079    }
12080
12081    /**
12082     * Forces this view's layer to be created and this view to be rendered
12083     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
12084     * invoking this method will have no effect.
12085     *
12086     * This method can for instance be used to render a view into its layer before
12087     * starting an animation. If this view is complex, rendering into the layer
12088     * before starting the animation will avoid skipping frames.
12089     *
12090     * @throws IllegalStateException If this view is not attached to a window
12091     *
12092     * @see #setLayerType(int, android.graphics.Paint)
12093     */
12094    public void buildLayer() {
12095        if (mLayerType == LAYER_TYPE_NONE) return;
12096
12097        if (mAttachInfo == null) {
12098            throw new IllegalStateException("This view must be attached to a window first");
12099        }
12100
12101        switch (mLayerType) {
12102            case LAYER_TYPE_HARDWARE:
12103                if (mAttachInfo.mHardwareRenderer != null &&
12104                        mAttachInfo.mHardwareRenderer.isEnabled() &&
12105                        mAttachInfo.mHardwareRenderer.validate()) {
12106                    getHardwareLayer();
12107                }
12108                break;
12109            case LAYER_TYPE_SOFTWARE:
12110                buildDrawingCache(true);
12111                break;
12112        }
12113    }
12114
12115    /**
12116     * <p>Returns a hardware layer that can be used to draw this view again
12117     * without executing its draw method.</p>
12118     *
12119     * @return A HardwareLayer ready to render, or null if an error occurred.
12120     */
12121    HardwareLayer getHardwareLayer() {
12122        if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
12123                !mAttachInfo.mHardwareRenderer.isEnabled()) {
12124            return null;
12125        }
12126
12127        if (!mAttachInfo.mHardwareRenderer.validate()) return null;
12128
12129        final int width = mRight - mLeft;
12130        final int height = mBottom - mTop;
12131
12132        if (width == 0 || height == 0) {
12133            return null;
12134        }
12135
12136        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
12137            if (mHardwareLayer == null) {
12138                mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
12139                        width, height, isOpaque());
12140                mLocalDirtyRect.set(0, 0, width, height);
12141            } else {
12142                if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
12143                    mHardwareLayer.resize(width, height);
12144                    mLocalDirtyRect.set(0, 0, width, height);
12145                }
12146
12147                // This should not be necessary but applications that change
12148                // the parameters of their background drawable without calling
12149                // this.setBackground(Drawable) can leave the view in a bad state
12150                // (for instance isOpaque() returns true, but the background is
12151                // not opaque.)
12152                computeOpaqueFlags();
12153
12154                final boolean opaque = isOpaque();
12155                if (mHardwareLayer.isOpaque() != opaque) {
12156                    mHardwareLayer.setOpaque(opaque);
12157                    mLocalDirtyRect.set(0, 0, width, height);
12158                }
12159            }
12160
12161            // The layer is not valid if the underlying GPU resources cannot be allocated
12162            if (!mHardwareLayer.isValid()) {
12163                return null;
12164            }
12165            mHardwareLayer.setLayerPaint(mLayerPaint);
12166
12167            mHardwareLayer.redraw(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
12168            mLocalDirtyRect.setEmpty();
12169        }
12170
12171        return mHardwareLayer;
12172    }
12173
12174    /**
12175     * Destroys this View's hardware layer if possible.
12176     *
12177     * @return True if the layer was destroyed, false otherwise.
12178     *
12179     * @see #setLayerType(int, android.graphics.Paint)
12180     * @see #LAYER_TYPE_HARDWARE
12181     */
12182    boolean destroyLayer(boolean valid) {
12183        if (mHardwareLayer != null) {
12184            AttachInfo info = mAttachInfo;
12185            if (info != null && info.mHardwareRenderer != null &&
12186                    info.mHardwareRenderer.isEnabled() &&
12187                    (valid || info.mHardwareRenderer.validate())) {
12188                mHardwareLayer.destroy();
12189                mHardwareLayer = null;
12190
12191                invalidate(true);
12192                invalidateParentCaches();
12193            }
12194            return true;
12195        }
12196        return false;
12197    }
12198
12199    /**
12200     * Destroys all hardware rendering resources. This method is invoked
12201     * when the system needs to reclaim resources. Upon execution of this
12202     * method, you should free any OpenGL resources created by the view.
12203     *
12204     * Note: you <strong>must</strong> call
12205     * <code>super.destroyHardwareResources()</code> when overriding
12206     * this method.
12207     *
12208     * @hide
12209     */
12210    protected void destroyHardwareResources() {
12211        destroyLayer(true);
12212    }
12213
12214    /**
12215     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
12216     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
12217     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
12218     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
12219     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
12220     * null.</p>
12221     *
12222     * <p>Enabling the drawing cache is similar to
12223     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
12224     * acceleration is turned off. When hardware acceleration is turned on, enabling the
12225     * drawing cache has no effect on rendering because the system uses a different mechanism
12226     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
12227     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
12228     * for information on how to enable software and hardware layers.</p>
12229     *
12230     * <p>This API can be used to manually generate
12231     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
12232     * {@link #getDrawingCache()}.</p>
12233     *
12234     * @param enabled true to enable the drawing cache, false otherwise
12235     *
12236     * @see #isDrawingCacheEnabled()
12237     * @see #getDrawingCache()
12238     * @see #buildDrawingCache()
12239     * @see #setLayerType(int, android.graphics.Paint)
12240     */
12241    public void setDrawingCacheEnabled(boolean enabled) {
12242        mCachingFailed = false;
12243        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
12244    }
12245
12246    /**
12247     * <p>Indicates whether the drawing cache is enabled for this view.</p>
12248     *
12249     * @return true if the drawing cache is enabled
12250     *
12251     * @see #setDrawingCacheEnabled(boolean)
12252     * @see #getDrawingCache()
12253     */
12254    @ViewDebug.ExportedProperty(category = "drawing")
12255    public boolean isDrawingCacheEnabled() {
12256        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
12257    }
12258
12259    /**
12260     * Debugging utility which recursively outputs the dirty state of a view and its
12261     * descendants.
12262     *
12263     * @hide
12264     */
12265    @SuppressWarnings({"UnusedDeclaration"})
12266    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
12267        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
12268                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
12269                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
12270                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
12271        if (clear) {
12272            mPrivateFlags &= clearMask;
12273        }
12274        if (this instanceof ViewGroup) {
12275            ViewGroup parent = (ViewGroup) this;
12276            final int count = parent.getChildCount();
12277            for (int i = 0; i < count; i++) {
12278                final View child = parent.getChildAt(i);
12279                child.outputDirtyFlags(indent + "  ", clear, clearMask);
12280            }
12281        }
12282    }
12283
12284    /**
12285     * This method is used by ViewGroup to cause its children to restore or recreate their
12286     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
12287     * to recreate its own display list, which would happen if it went through the normal
12288     * draw/dispatchDraw mechanisms.
12289     *
12290     * @hide
12291     */
12292    protected void dispatchGetDisplayList() {}
12293
12294    /**
12295     * A view that is not attached or hardware accelerated cannot create a display list.
12296     * This method checks these conditions and returns the appropriate result.
12297     *
12298     * @return true if view has the ability to create a display list, false otherwise.
12299     *
12300     * @hide
12301     */
12302    public boolean canHaveDisplayList() {
12303        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
12304    }
12305
12306    /**
12307     * @return The HardwareRenderer associated with that view or null if hardware rendering
12308     * is not supported or this this has not been attached to a window.
12309     *
12310     * @hide
12311     */
12312    public HardwareRenderer getHardwareRenderer() {
12313        if (mAttachInfo != null) {
12314            return mAttachInfo.mHardwareRenderer;
12315        }
12316        return null;
12317    }
12318
12319    /**
12320     * Returns a DisplayList. If the incoming displayList is null, one will be created.
12321     * Otherwise, the same display list will be returned (after having been rendered into
12322     * along the way, depending on the invalidation state of the view).
12323     *
12324     * @param displayList The previous version of this displayList, could be null.
12325     * @param isLayer Whether the requester of the display list is a layer. If so,
12326     * the view will avoid creating a layer inside the resulting display list.
12327     * @return A new or reused DisplayList object.
12328     */
12329    private DisplayList getDisplayList(DisplayList displayList, boolean isLayer) {
12330        if (!canHaveDisplayList()) {
12331            return null;
12332        }
12333
12334        if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 ||
12335                displayList == null || !displayList.isValid() ||
12336                (!isLayer && mRecreateDisplayList))) {
12337            // Don't need to recreate the display list, just need to tell our
12338            // children to restore/recreate theirs
12339            if (displayList != null && displayList.isValid() &&
12340                    !isLayer && !mRecreateDisplayList) {
12341                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12342                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12343                dispatchGetDisplayList();
12344
12345                return displayList;
12346            }
12347
12348            if (!isLayer) {
12349                // If we got here, we're recreating it. Mark it as such to ensure that
12350                // we copy in child display lists into ours in drawChild()
12351                mRecreateDisplayList = true;
12352            }
12353            if (displayList == null) {
12354                final String name = getClass().getSimpleName();
12355                displayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
12356                // If we're creating a new display list, make sure our parent gets invalidated
12357                // since they will need to recreate their display list to account for this
12358                // new child display list.
12359                invalidateParentCaches();
12360            }
12361
12362            boolean caching = false;
12363            final HardwareCanvas canvas = displayList.start();
12364            int width = mRight - mLeft;
12365            int height = mBottom - mTop;
12366
12367            try {
12368                canvas.setViewport(width, height);
12369                // The dirty rect should always be null for a display list
12370                canvas.onPreDraw(null);
12371                int layerType = getLayerType();
12372                if (!isLayer && layerType != LAYER_TYPE_NONE) {
12373                    if (layerType == LAYER_TYPE_HARDWARE) {
12374                        final HardwareLayer layer = getHardwareLayer();
12375                        if (layer != null && layer.isValid()) {
12376                            canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
12377                        } else {
12378                            canvas.saveLayer(0, 0, mRight - mLeft, mBottom - mTop, mLayerPaint,
12379                                    Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
12380                                            Canvas.CLIP_TO_LAYER_SAVE_FLAG);
12381                        }
12382                        caching = true;
12383                    } else {
12384                        buildDrawingCache(true);
12385                        Bitmap cache = getDrawingCache(true);
12386                        if (cache != null) {
12387                            canvas.drawBitmap(cache, 0, 0, mLayerPaint);
12388                            caching = true;
12389                        }
12390                    }
12391                } else {
12392
12393                    computeScroll();
12394
12395                    canvas.translate(-mScrollX, -mScrollY);
12396                    if (!isLayer) {
12397                        mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12398                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12399                    }
12400
12401                    // Fast path for layouts with no backgrounds
12402                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
12403                        dispatchDraw(canvas);
12404                    } else {
12405                        draw(canvas);
12406                    }
12407                }
12408            } finally {
12409                canvas.onPostDraw();
12410
12411                displayList.end();
12412                displayList.setCaching(caching);
12413                if (isLayer) {
12414                    displayList.setLeftTopRightBottom(0, 0, width, height);
12415                } else {
12416                    setDisplayListProperties(displayList);
12417                }
12418            }
12419        } else if (!isLayer) {
12420            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12421            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12422        }
12423
12424        return displayList;
12425    }
12426
12427    /**
12428     * Get the DisplayList for the HardwareLayer
12429     *
12430     * @param layer The HardwareLayer whose DisplayList we want
12431     * @return A DisplayList fopr the specified HardwareLayer
12432     */
12433    private DisplayList getHardwareLayerDisplayList(HardwareLayer layer) {
12434        DisplayList displayList = getDisplayList(layer.getDisplayList(), true);
12435        layer.setDisplayList(displayList);
12436        return displayList;
12437    }
12438
12439
12440    /**
12441     * <p>Returns a display list that can be used to draw this view again
12442     * without executing its draw method.</p>
12443     *
12444     * @return A DisplayList ready to replay, or null if caching is not enabled.
12445     *
12446     * @hide
12447     */
12448    public DisplayList getDisplayList() {
12449        mDisplayList = getDisplayList(mDisplayList, false);
12450        return mDisplayList;
12451    }
12452
12453    private void clearDisplayList() {
12454        if (mDisplayList != null) {
12455            mDisplayList.invalidate();
12456            mDisplayList.clear();
12457        }
12458    }
12459
12460    /**
12461     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
12462     *
12463     * @return A non-scaled bitmap representing this view or null if cache is disabled.
12464     *
12465     * @see #getDrawingCache(boolean)
12466     */
12467    public Bitmap getDrawingCache() {
12468        return getDrawingCache(false);
12469    }
12470
12471    /**
12472     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
12473     * is null when caching is disabled. If caching is enabled and the cache is not ready,
12474     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
12475     * draw from the cache when the cache is enabled. To benefit from the cache, you must
12476     * request the drawing cache by calling this method and draw it on screen if the
12477     * returned bitmap is not null.</p>
12478     *
12479     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12480     * this method will create a bitmap of the same size as this view. Because this bitmap
12481     * will be drawn scaled by the parent ViewGroup, the result on screen might show
12482     * scaling artifacts. To avoid such artifacts, you should call this method by setting
12483     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12484     * size than the view. This implies that your application must be able to handle this
12485     * size.</p>
12486     *
12487     * @param autoScale Indicates whether the generated bitmap should be scaled based on
12488     *        the current density of the screen when the application is in compatibility
12489     *        mode.
12490     *
12491     * @return A bitmap representing this view or null if cache is disabled.
12492     *
12493     * @see #setDrawingCacheEnabled(boolean)
12494     * @see #isDrawingCacheEnabled()
12495     * @see #buildDrawingCache(boolean)
12496     * @see #destroyDrawingCache()
12497     */
12498    public Bitmap getDrawingCache(boolean autoScale) {
12499        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
12500            return null;
12501        }
12502        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
12503            buildDrawingCache(autoScale);
12504        }
12505        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
12506    }
12507
12508    /**
12509     * <p>Frees the resources used by the drawing cache. If you call
12510     * {@link #buildDrawingCache()} manually without calling
12511     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12512     * should cleanup the cache with this method afterwards.</p>
12513     *
12514     * @see #setDrawingCacheEnabled(boolean)
12515     * @see #buildDrawingCache()
12516     * @see #getDrawingCache()
12517     */
12518    public void destroyDrawingCache() {
12519        if (mDrawingCache != null) {
12520            mDrawingCache.recycle();
12521            mDrawingCache = null;
12522        }
12523        if (mUnscaledDrawingCache != null) {
12524            mUnscaledDrawingCache.recycle();
12525            mUnscaledDrawingCache = null;
12526        }
12527    }
12528
12529    /**
12530     * Setting a solid background color for the drawing cache's bitmaps will improve
12531     * performance and memory usage. Note, though that this should only be used if this
12532     * view will always be drawn on top of a solid color.
12533     *
12534     * @param color The background color to use for the drawing cache's bitmap
12535     *
12536     * @see #setDrawingCacheEnabled(boolean)
12537     * @see #buildDrawingCache()
12538     * @see #getDrawingCache()
12539     */
12540    public void setDrawingCacheBackgroundColor(int color) {
12541        if (color != mDrawingCacheBackgroundColor) {
12542            mDrawingCacheBackgroundColor = color;
12543            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12544        }
12545    }
12546
12547    /**
12548     * @see #setDrawingCacheBackgroundColor(int)
12549     *
12550     * @return The background color to used for the drawing cache's bitmap
12551     */
12552    public int getDrawingCacheBackgroundColor() {
12553        return mDrawingCacheBackgroundColor;
12554    }
12555
12556    /**
12557     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
12558     *
12559     * @see #buildDrawingCache(boolean)
12560     */
12561    public void buildDrawingCache() {
12562        buildDrawingCache(false);
12563    }
12564
12565    /**
12566     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
12567     *
12568     * <p>If you call {@link #buildDrawingCache()} manually without calling
12569     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12570     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
12571     *
12572     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12573     * this method will create a bitmap of the same size as this view. Because this bitmap
12574     * will be drawn scaled by the parent ViewGroup, the result on screen might show
12575     * scaling artifacts. To avoid such artifacts, you should call this method by setting
12576     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12577     * size than the view. This implies that your application must be able to handle this
12578     * size.</p>
12579     *
12580     * <p>You should avoid calling this method when hardware acceleration is enabled. If
12581     * you do not need the drawing cache bitmap, calling this method will increase memory
12582     * usage and cause the view to be rendered in software once, thus negatively impacting
12583     * performance.</p>
12584     *
12585     * @see #getDrawingCache()
12586     * @see #destroyDrawingCache()
12587     */
12588    public void buildDrawingCache(boolean autoScale) {
12589        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
12590                mDrawingCache == null : mUnscaledDrawingCache == null)) {
12591            mCachingFailed = false;
12592
12593            int width = mRight - mLeft;
12594            int height = mBottom - mTop;
12595
12596            final AttachInfo attachInfo = mAttachInfo;
12597            final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
12598
12599            if (autoScale && scalingRequired) {
12600                width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
12601                height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
12602            }
12603
12604            final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
12605            final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
12606            final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
12607
12608            final int projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
12609            final int drawingCacheSize =
12610                    ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
12611            if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
12612                if (width > 0 && height > 0) {
12613                    Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
12614                            + projectedBitmapSize + " bytes, only "
12615                            + drawingCacheSize + " available");
12616                }
12617                destroyDrawingCache();
12618                mCachingFailed = true;
12619                return;
12620            }
12621
12622            boolean clear = true;
12623            Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
12624
12625            if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
12626                Bitmap.Config quality;
12627                if (!opaque) {
12628                    // Never pick ARGB_4444 because it looks awful
12629                    // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
12630                    switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
12631                        case DRAWING_CACHE_QUALITY_AUTO:
12632                            quality = Bitmap.Config.ARGB_8888;
12633                            break;
12634                        case DRAWING_CACHE_QUALITY_LOW:
12635                            quality = Bitmap.Config.ARGB_8888;
12636                            break;
12637                        case DRAWING_CACHE_QUALITY_HIGH:
12638                            quality = Bitmap.Config.ARGB_8888;
12639                            break;
12640                        default:
12641                            quality = Bitmap.Config.ARGB_8888;
12642                            break;
12643                    }
12644                } else {
12645                    // Optimization for translucent windows
12646                    // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
12647                    quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
12648                }
12649
12650                // Try to cleanup memory
12651                if (bitmap != null) bitmap.recycle();
12652
12653                try {
12654                    bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
12655                            width, height, quality);
12656                    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
12657                    if (autoScale) {
12658                        mDrawingCache = bitmap;
12659                    } else {
12660                        mUnscaledDrawingCache = bitmap;
12661                    }
12662                    if (opaque && use32BitCache) bitmap.setHasAlpha(false);
12663                } catch (OutOfMemoryError e) {
12664                    // If there is not enough memory to create the bitmap cache, just
12665                    // ignore the issue as bitmap caches are not required to draw the
12666                    // view hierarchy
12667                    if (autoScale) {
12668                        mDrawingCache = null;
12669                    } else {
12670                        mUnscaledDrawingCache = null;
12671                    }
12672                    mCachingFailed = true;
12673                    return;
12674                }
12675
12676                clear = drawingCacheBackgroundColor != 0;
12677            }
12678
12679            Canvas canvas;
12680            if (attachInfo != null) {
12681                canvas = attachInfo.mCanvas;
12682                if (canvas == null) {
12683                    canvas = new Canvas();
12684                }
12685                canvas.setBitmap(bitmap);
12686                // Temporarily clobber the cached Canvas in case one of our children
12687                // is also using a drawing cache. Without this, the children would
12688                // steal the canvas by attaching their own bitmap to it and bad, bad
12689                // thing would happen (invisible views, corrupted drawings, etc.)
12690                attachInfo.mCanvas = null;
12691            } else {
12692                // This case should hopefully never or seldom happen
12693                canvas = new Canvas(bitmap);
12694            }
12695
12696            if (clear) {
12697                bitmap.eraseColor(drawingCacheBackgroundColor);
12698            }
12699
12700            computeScroll();
12701            final int restoreCount = canvas.save();
12702
12703            if (autoScale && scalingRequired) {
12704                final float scale = attachInfo.mApplicationScale;
12705                canvas.scale(scale, scale);
12706            }
12707
12708            canvas.translate(-mScrollX, -mScrollY);
12709
12710            mPrivateFlags |= PFLAG_DRAWN;
12711            if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
12712                    mLayerType != LAYER_TYPE_NONE) {
12713                mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
12714            }
12715
12716            // Fast path for layouts with no backgrounds
12717            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
12718                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12719                dispatchDraw(canvas);
12720            } else {
12721                draw(canvas);
12722            }
12723
12724            canvas.restoreToCount(restoreCount);
12725            canvas.setBitmap(null);
12726
12727            if (attachInfo != null) {
12728                // Restore the cached Canvas for our siblings
12729                attachInfo.mCanvas = canvas;
12730            }
12731        }
12732    }
12733
12734    /**
12735     * Create a snapshot of the view into a bitmap.  We should probably make
12736     * some form of this public, but should think about the API.
12737     */
12738    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
12739        int width = mRight - mLeft;
12740        int height = mBottom - mTop;
12741
12742        final AttachInfo attachInfo = mAttachInfo;
12743        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
12744        width = (int) ((width * scale) + 0.5f);
12745        height = (int) ((height * scale) + 0.5f);
12746
12747        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
12748                width > 0 ? width : 1, height > 0 ? height : 1, quality);
12749        if (bitmap == null) {
12750            throw new OutOfMemoryError();
12751        }
12752
12753        Resources resources = getResources();
12754        if (resources != null) {
12755            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
12756        }
12757
12758        Canvas canvas;
12759        if (attachInfo != null) {
12760            canvas = attachInfo.mCanvas;
12761            if (canvas == null) {
12762                canvas = new Canvas();
12763            }
12764            canvas.setBitmap(bitmap);
12765            // Temporarily clobber the cached Canvas in case one of our children
12766            // is also using a drawing cache. Without this, the children would
12767            // steal the canvas by attaching their own bitmap to it and bad, bad
12768            // things would happen (invisible views, corrupted drawings, etc.)
12769            attachInfo.mCanvas = null;
12770        } else {
12771            // This case should hopefully never or seldom happen
12772            canvas = new Canvas(bitmap);
12773        }
12774
12775        if ((backgroundColor & 0xff000000) != 0) {
12776            bitmap.eraseColor(backgroundColor);
12777        }
12778
12779        computeScroll();
12780        final int restoreCount = canvas.save();
12781        canvas.scale(scale, scale);
12782        canvas.translate(-mScrollX, -mScrollY);
12783
12784        // Temporarily remove the dirty mask
12785        int flags = mPrivateFlags;
12786        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
12787
12788        // Fast path for layouts with no backgrounds
12789        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
12790            dispatchDraw(canvas);
12791        } else {
12792            draw(canvas);
12793        }
12794
12795        mPrivateFlags = flags;
12796
12797        canvas.restoreToCount(restoreCount);
12798        canvas.setBitmap(null);
12799
12800        if (attachInfo != null) {
12801            // Restore the cached Canvas for our siblings
12802            attachInfo.mCanvas = canvas;
12803        }
12804
12805        return bitmap;
12806    }
12807
12808    /**
12809     * Indicates whether this View is currently in edit mode. A View is usually
12810     * in edit mode when displayed within a developer tool. For instance, if
12811     * this View is being drawn by a visual user interface builder, this method
12812     * should return true.
12813     *
12814     * Subclasses should check the return value of this method to provide
12815     * different behaviors if their normal behavior might interfere with the
12816     * host environment. For instance: the class spawns a thread in its
12817     * constructor, the drawing code relies on device-specific features, etc.
12818     *
12819     * This method is usually checked in the drawing code of custom widgets.
12820     *
12821     * @return True if this View is in edit mode, false otherwise.
12822     */
12823    public boolean isInEditMode() {
12824        return false;
12825    }
12826
12827    /**
12828     * If the View draws content inside its padding and enables fading edges,
12829     * it needs to support padding offsets. Padding offsets are added to the
12830     * fading edges to extend the length of the fade so that it covers pixels
12831     * drawn inside the padding.
12832     *
12833     * Subclasses of this class should override this method if they need
12834     * to draw content inside the padding.
12835     *
12836     * @return True if padding offset must be applied, false otherwise.
12837     *
12838     * @see #getLeftPaddingOffset()
12839     * @see #getRightPaddingOffset()
12840     * @see #getTopPaddingOffset()
12841     * @see #getBottomPaddingOffset()
12842     *
12843     * @since CURRENT
12844     */
12845    protected boolean isPaddingOffsetRequired() {
12846        return false;
12847    }
12848
12849    /**
12850     * Amount by which to extend the left fading region. Called only when
12851     * {@link #isPaddingOffsetRequired()} returns true.
12852     *
12853     * @return The left padding offset in pixels.
12854     *
12855     * @see #isPaddingOffsetRequired()
12856     *
12857     * @since CURRENT
12858     */
12859    protected int getLeftPaddingOffset() {
12860        return 0;
12861    }
12862
12863    /**
12864     * Amount by which to extend the right fading region. Called only when
12865     * {@link #isPaddingOffsetRequired()} returns true.
12866     *
12867     * @return The right padding offset in pixels.
12868     *
12869     * @see #isPaddingOffsetRequired()
12870     *
12871     * @since CURRENT
12872     */
12873    protected int getRightPaddingOffset() {
12874        return 0;
12875    }
12876
12877    /**
12878     * Amount by which to extend the top fading region. Called only when
12879     * {@link #isPaddingOffsetRequired()} returns true.
12880     *
12881     * @return The top padding offset in pixels.
12882     *
12883     * @see #isPaddingOffsetRequired()
12884     *
12885     * @since CURRENT
12886     */
12887    protected int getTopPaddingOffset() {
12888        return 0;
12889    }
12890
12891    /**
12892     * Amount by which to extend the bottom fading region. Called only when
12893     * {@link #isPaddingOffsetRequired()} returns true.
12894     *
12895     * @return The bottom padding offset in pixels.
12896     *
12897     * @see #isPaddingOffsetRequired()
12898     *
12899     * @since CURRENT
12900     */
12901    protected int getBottomPaddingOffset() {
12902        return 0;
12903    }
12904
12905    /**
12906     * @hide
12907     * @param offsetRequired
12908     */
12909    protected int getFadeTop(boolean offsetRequired) {
12910        int top = mPaddingTop;
12911        if (offsetRequired) top += getTopPaddingOffset();
12912        return top;
12913    }
12914
12915    /**
12916     * @hide
12917     * @param offsetRequired
12918     */
12919    protected int getFadeHeight(boolean offsetRequired) {
12920        int padding = mPaddingTop;
12921        if (offsetRequired) padding += getTopPaddingOffset();
12922        return mBottom - mTop - mPaddingBottom - padding;
12923    }
12924
12925    /**
12926     * <p>Indicates whether this view is attached to a hardware accelerated
12927     * window or not.</p>
12928     *
12929     * <p>Even if this method returns true, it does not mean that every call
12930     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
12931     * accelerated {@link android.graphics.Canvas}. For instance, if this view
12932     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
12933     * window is hardware accelerated,
12934     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
12935     * return false, and this method will return true.</p>
12936     *
12937     * @return True if the view is attached to a window and the window is
12938     *         hardware accelerated; false in any other case.
12939     */
12940    public boolean isHardwareAccelerated() {
12941        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
12942    }
12943
12944    /**
12945     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
12946     * case of an active Animation being run on the view.
12947     */
12948    private boolean drawAnimation(ViewGroup parent, long drawingTime,
12949            Animation a, boolean scalingRequired) {
12950        Transformation invalidationTransform;
12951        final int flags = parent.mGroupFlags;
12952        final boolean initialized = a.isInitialized();
12953        if (!initialized) {
12954            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
12955            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
12956            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
12957            onAnimationStart();
12958        }
12959
12960        boolean more = a.getTransformation(drawingTime, parent.mChildTransformation, 1f);
12961        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
12962            if (parent.mInvalidationTransformation == null) {
12963                parent.mInvalidationTransformation = new Transformation();
12964            }
12965            invalidationTransform = parent.mInvalidationTransformation;
12966            a.getTransformation(drawingTime, invalidationTransform, 1f);
12967        } else {
12968            invalidationTransform = parent.mChildTransformation;
12969        }
12970
12971        if (more) {
12972            if (!a.willChangeBounds()) {
12973                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
12974                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
12975                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
12976                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
12977                    // The child need to draw an animation, potentially offscreen, so
12978                    // make sure we do not cancel invalidate requests
12979                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
12980                    parent.invalidate(mLeft, mTop, mRight, mBottom);
12981                }
12982            } else {
12983                if (parent.mInvalidateRegion == null) {
12984                    parent.mInvalidateRegion = new RectF();
12985                }
12986                final RectF region = parent.mInvalidateRegion;
12987                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
12988                        invalidationTransform);
12989
12990                // The child need to draw an animation, potentially offscreen, so
12991                // make sure we do not cancel invalidate requests
12992                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
12993
12994                final int left = mLeft + (int) region.left;
12995                final int top = mTop + (int) region.top;
12996                parent.invalidate(left, top, left + (int) (region.width() + .5f),
12997                        top + (int) (region.height() + .5f));
12998            }
12999        }
13000        return more;
13001    }
13002
13003    /**
13004     * This method is called by getDisplayList() when a display list is created or re-rendered.
13005     * It sets or resets the current value of all properties on that display list (resetting is
13006     * necessary when a display list is being re-created, because we need to make sure that
13007     * previously-set transform values
13008     */
13009    void setDisplayListProperties(DisplayList displayList) {
13010        if (displayList != null) {
13011            displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
13012            displayList.setHasOverlappingRendering(hasOverlappingRendering());
13013            if (mParent instanceof ViewGroup) {
13014                displayList.setClipChildren(
13015                        (((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
13016            }
13017            float alpha = 1;
13018            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
13019                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
13020                ViewGroup parentVG = (ViewGroup) mParent;
13021                final boolean hasTransform =
13022                        parentVG.getChildStaticTransformation(this, parentVG.mChildTransformation);
13023                if (hasTransform) {
13024                    Transformation transform = parentVG.mChildTransformation;
13025                    final int transformType = parentVG.mChildTransformation.getTransformationType();
13026                    if (transformType != Transformation.TYPE_IDENTITY) {
13027                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
13028                            alpha = transform.getAlpha();
13029                        }
13030                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
13031                            displayList.setStaticMatrix(transform.getMatrix());
13032                        }
13033                    }
13034                }
13035            }
13036            if (mTransformationInfo != null) {
13037                alpha *= mTransformationInfo.mAlpha;
13038                if (alpha < 1) {
13039                    final int multipliedAlpha = (int) (255 * alpha);
13040                    if (onSetAlpha(multipliedAlpha)) {
13041                        alpha = 1;
13042                    }
13043                }
13044                displayList.setTransformationInfo(alpha,
13045                        mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY,
13046                        mTransformationInfo.mRotation, mTransformationInfo.mRotationX,
13047                        mTransformationInfo.mRotationY, mTransformationInfo.mScaleX,
13048                        mTransformationInfo.mScaleY);
13049                if (mTransformationInfo.mCamera == null) {
13050                    mTransformationInfo.mCamera = new Camera();
13051                    mTransformationInfo.matrix3D = new Matrix();
13052                }
13053                displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ());
13054                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) {
13055                    displayList.setPivotX(getPivotX());
13056                    displayList.setPivotY(getPivotY());
13057                }
13058            } else if (alpha < 1) {
13059                displayList.setAlpha(alpha);
13060            }
13061        }
13062    }
13063
13064    /**
13065     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
13066     * This draw() method is an implementation detail and is not intended to be overridden or
13067     * to be called from anywhere else other than ViewGroup.drawChild().
13068     */
13069    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
13070        boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
13071        boolean more = false;
13072        final boolean childHasIdentityMatrix = hasIdentityMatrix();
13073        final int flags = parent.mGroupFlags;
13074
13075        if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
13076            parent.mChildTransformation.clear();
13077            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13078        }
13079
13080        Transformation transformToApply = null;
13081        boolean concatMatrix = false;
13082
13083        boolean scalingRequired = false;
13084        boolean caching;
13085        int layerType = getLayerType();
13086
13087        final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
13088        if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
13089                (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
13090            caching = true;
13091            // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
13092            if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
13093        } else {
13094            caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
13095        }
13096
13097        final Animation a = getAnimation();
13098        if (a != null) {
13099            more = drawAnimation(parent, drawingTime, a, scalingRequired);
13100            concatMatrix = a.willChangeTransformationMatrix();
13101            if (concatMatrix) {
13102                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
13103            }
13104            transformToApply = parent.mChildTransformation;
13105        } else {
13106            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) == PFLAG3_VIEW_IS_ANIMATING_TRANSFORM &&
13107                    mDisplayList != null) {
13108                // No longer animating: clear out old animation matrix
13109                mDisplayList.setAnimationMatrix(null);
13110                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
13111            }
13112            if (!useDisplayListProperties &&
13113                    (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
13114                final boolean hasTransform =
13115                        parent.getChildStaticTransformation(this, parent.mChildTransformation);
13116                if (hasTransform) {
13117                    final int transformType = parent.mChildTransformation.getTransformationType();
13118                    transformToApply = transformType != Transformation.TYPE_IDENTITY ?
13119                            parent.mChildTransformation : null;
13120                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
13121                }
13122            }
13123        }
13124
13125        concatMatrix |= !childHasIdentityMatrix;
13126
13127        // Sets the flag as early as possible to allow draw() implementations
13128        // to call invalidate() successfully when doing animations
13129        mPrivateFlags |= PFLAG_DRAWN;
13130
13131        if (!concatMatrix &&
13132                (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
13133                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
13134                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
13135                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
13136            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
13137            return more;
13138        }
13139        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
13140
13141        if (hardwareAccelerated) {
13142            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
13143            // retain the flag's value temporarily in the mRecreateDisplayList flag
13144            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
13145            mPrivateFlags &= ~PFLAG_INVALIDATED;
13146        }
13147
13148        DisplayList displayList = null;
13149        Bitmap cache = null;
13150        boolean hasDisplayList = false;
13151        if (caching) {
13152            if (!hardwareAccelerated) {
13153                if (layerType != LAYER_TYPE_NONE) {
13154                    layerType = LAYER_TYPE_SOFTWARE;
13155                    buildDrawingCache(true);
13156                }
13157                cache = getDrawingCache(true);
13158            } else {
13159                switch (layerType) {
13160                    case LAYER_TYPE_SOFTWARE:
13161                        if (useDisplayListProperties) {
13162                            hasDisplayList = canHaveDisplayList();
13163                        } else {
13164                            buildDrawingCache(true);
13165                            cache = getDrawingCache(true);
13166                        }
13167                        break;
13168                    case LAYER_TYPE_HARDWARE:
13169                        if (useDisplayListProperties) {
13170                            hasDisplayList = canHaveDisplayList();
13171                        }
13172                        break;
13173                    case LAYER_TYPE_NONE:
13174                        // Delay getting the display list until animation-driven alpha values are
13175                        // set up and possibly passed on to the view
13176                        hasDisplayList = canHaveDisplayList();
13177                        break;
13178                }
13179            }
13180        }
13181        useDisplayListProperties &= hasDisplayList;
13182        if (useDisplayListProperties) {
13183            displayList = getDisplayList();
13184            if (!displayList.isValid()) {
13185                // Uncommon, but possible. If a view is removed from the hierarchy during the call
13186                // to getDisplayList(), the display list will be marked invalid and we should not
13187                // try to use it again.
13188                displayList = null;
13189                hasDisplayList = false;
13190                useDisplayListProperties = false;
13191            }
13192        }
13193
13194        int sx = 0;
13195        int sy = 0;
13196        if (!hasDisplayList) {
13197            computeScroll();
13198            sx = mScrollX;
13199            sy = mScrollY;
13200        }
13201
13202        final boolean hasNoCache = cache == null || hasDisplayList;
13203        final boolean offsetForScroll = cache == null && !hasDisplayList &&
13204                layerType != LAYER_TYPE_HARDWARE;
13205
13206        int restoreTo = -1;
13207        if (!useDisplayListProperties || transformToApply != null) {
13208            restoreTo = canvas.save();
13209        }
13210        if (offsetForScroll) {
13211            canvas.translate(mLeft - sx, mTop - sy);
13212        } else {
13213            if (!useDisplayListProperties) {
13214                canvas.translate(mLeft, mTop);
13215            }
13216            if (scalingRequired) {
13217                if (useDisplayListProperties) {
13218                    // TODO: Might not need this if we put everything inside the DL
13219                    restoreTo = canvas.save();
13220                }
13221                // mAttachInfo cannot be null, otherwise scalingRequired == false
13222                final float scale = 1.0f / mAttachInfo.mApplicationScale;
13223                canvas.scale(scale, scale);
13224            }
13225        }
13226
13227        float alpha = useDisplayListProperties ? 1 : getAlpha();
13228        if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
13229                (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
13230            if (transformToApply != null || !childHasIdentityMatrix) {
13231                int transX = 0;
13232                int transY = 0;
13233
13234                if (offsetForScroll) {
13235                    transX = -sx;
13236                    transY = -sy;
13237                }
13238
13239                if (transformToApply != null) {
13240                    if (concatMatrix) {
13241                        if (useDisplayListProperties) {
13242                            displayList.setAnimationMatrix(transformToApply.getMatrix());
13243                        } else {
13244                            // Undo the scroll translation, apply the transformation matrix,
13245                            // then redo the scroll translate to get the correct result.
13246                            canvas.translate(-transX, -transY);
13247                            canvas.concat(transformToApply.getMatrix());
13248                            canvas.translate(transX, transY);
13249                        }
13250                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13251                    }
13252
13253                    float transformAlpha = transformToApply.getAlpha();
13254                    if (transformAlpha < 1) {
13255                        alpha *= transformAlpha;
13256                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13257                    }
13258                }
13259
13260                if (!childHasIdentityMatrix && !useDisplayListProperties) {
13261                    canvas.translate(-transX, -transY);
13262                    canvas.concat(getMatrix());
13263                    canvas.translate(transX, transY);
13264                }
13265            }
13266
13267            // Deal with alpha if it is or used to be <1
13268            if (alpha < 1 ||
13269                    (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
13270                if (alpha < 1) {
13271                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
13272                } else {
13273                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
13274                }
13275                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
13276                if (hasNoCache) {
13277                    final int multipliedAlpha = (int) (255 * alpha);
13278                    if (!onSetAlpha(multipliedAlpha)) {
13279                        int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
13280                        if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
13281                                layerType != LAYER_TYPE_NONE) {
13282                            layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
13283                        }
13284                        if (useDisplayListProperties) {
13285                            displayList.setAlpha(alpha * getAlpha());
13286                        } else  if (layerType == LAYER_TYPE_NONE) {
13287                            final int scrollX = hasDisplayList ? 0 : sx;
13288                            final int scrollY = hasDisplayList ? 0 : sy;
13289                            canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
13290                                    scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
13291                        }
13292                    } else {
13293                        // Alpha is handled by the child directly, clobber the layer's alpha
13294                        mPrivateFlags |= PFLAG_ALPHA_SET;
13295                    }
13296                }
13297            }
13298        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
13299            onSetAlpha(255);
13300            mPrivateFlags &= ~PFLAG_ALPHA_SET;
13301        }
13302
13303        if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
13304                !useDisplayListProperties) {
13305            if (offsetForScroll) {
13306                canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
13307            } else {
13308                if (!scalingRequired || cache == null) {
13309                    canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
13310                } else {
13311                    canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
13312                }
13313            }
13314        }
13315
13316        if (!useDisplayListProperties && hasDisplayList) {
13317            displayList = getDisplayList();
13318            if (!displayList.isValid()) {
13319                // Uncommon, but possible. If a view is removed from the hierarchy during the call
13320                // to getDisplayList(), the display list will be marked invalid and we should not
13321                // try to use it again.
13322                displayList = null;
13323                hasDisplayList = false;
13324            }
13325        }
13326
13327        if (hasNoCache) {
13328            boolean layerRendered = false;
13329            if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) {
13330                final HardwareLayer layer = getHardwareLayer();
13331                if (layer != null && layer.isValid()) {
13332                    mLayerPaint.setAlpha((int) (alpha * 255));
13333                    ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
13334                    layerRendered = true;
13335                } else {
13336                    final int scrollX = hasDisplayList ? 0 : sx;
13337                    final int scrollY = hasDisplayList ? 0 : sy;
13338                    canvas.saveLayer(scrollX, scrollY,
13339                            scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
13340                            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
13341                }
13342            }
13343
13344            if (!layerRendered) {
13345                if (!hasDisplayList) {
13346                    // Fast path for layouts with no backgrounds
13347                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13348                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13349                        dispatchDraw(canvas);
13350                    } else {
13351                        draw(canvas);
13352                    }
13353                } else {
13354                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13355                    ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
13356                }
13357            }
13358        } else if (cache != null) {
13359            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13360            Paint cachePaint;
13361
13362            if (layerType == LAYER_TYPE_NONE) {
13363                cachePaint = parent.mCachePaint;
13364                if (cachePaint == null) {
13365                    cachePaint = new Paint();
13366                    cachePaint.setDither(false);
13367                    parent.mCachePaint = cachePaint;
13368                }
13369                if (alpha < 1) {
13370                    cachePaint.setAlpha((int) (alpha * 255));
13371                    parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
13372                } else if  ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) {
13373                    cachePaint.setAlpha(255);
13374                    parent.mGroupFlags &= ~ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
13375                }
13376            } else {
13377                cachePaint = mLayerPaint;
13378                cachePaint.setAlpha((int) (alpha * 255));
13379            }
13380            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
13381        }
13382
13383        if (restoreTo >= 0) {
13384            canvas.restoreToCount(restoreTo);
13385        }
13386
13387        if (a != null && !more) {
13388            if (!hardwareAccelerated && !a.getFillAfter()) {
13389                onSetAlpha(255);
13390            }
13391            parent.finishAnimatingView(this, a);
13392        }
13393
13394        if (more && hardwareAccelerated) {
13395            // invalidation is the trigger to recreate display lists, so if we're using
13396            // display lists to render, force an invalidate to allow the animation to
13397            // continue drawing another frame
13398            parent.invalidate(true);
13399            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
13400                // alpha animations should cause the child to recreate its display list
13401                invalidate(true);
13402            }
13403        }
13404
13405        mRecreateDisplayList = false;
13406
13407        return more;
13408    }
13409
13410    /**
13411     * Manually render this view (and all of its children) to the given Canvas.
13412     * The view must have already done a full layout before this function is
13413     * called.  When implementing a view, implement
13414     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
13415     * If you do need to override this method, call the superclass version.
13416     *
13417     * @param canvas The Canvas to which the View is rendered.
13418     */
13419    public void draw(Canvas canvas) {
13420        final int privateFlags = mPrivateFlags;
13421        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
13422                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
13423        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
13424
13425        /*
13426         * Draw traversal performs several drawing steps which must be executed
13427         * in the appropriate order:
13428         *
13429         *      1. Draw the background
13430         *      2. If necessary, save the canvas' layers to prepare for fading
13431         *      3. Draw view's content
13432         *      4. Draw children
13433         *      5. If necessary, draw the fading edges and restore layers
13434         *      6. Draw decorations (scrollbars for instance)
13435         */
13436
13437        // Step 1, draw the background, if needed
13438        int saveCount;
13439
13440        if (!dirtyOpaque) {
13441            final Drawable background = mBackground;
13442            if (background != null) {
13443                final int scrollX = mScrollX;
13444                final int scrollY = mScrollY;
13445
13446                if (mBackgroundSizeChanged) {
13447                    background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
13448                    mBackgroundSizeChanged = false;
13449                }
13450
13451                if ((scrollX | scrollY) == 0) {
13452                    background.draw(canvas);
13453                } else {
13454                    canvas.translate(scrollX, scrollY);
13455                    background.draw(canvas);
13456                    canvas.translate(-scrollX, -scrollY);
13457                }
13458            }
13459        }
13460
13461        // skip step 2 & 5 if possible (common case)
13462        final int viewFlags = mViewFlags;
13463        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
13464        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
13465        if (!verticalEdges && !horizontalEdges) {
13466            // Step 3, draw the content
13467            if (!dirtyOpaque) onDraw(canvas);
13468
13469            // Step 4, draw the children
13470            dispatchDraw(canvas);
13471
13472            // Step 6, draw decorations (scrollbars)
13473            onDrawScrollBars(canvas);
13474
13475            // we're done...
13476            return;
13477        }
13478
13479        /*
13480         * Here we do the full fledged routine...
13481         * (this is an uncommon case where speed matters less,
13482         * this is why we repeat some of the tests that have been
13483         * done above)
13484         */
13485
13486        boolean drawTop = false;
13487        boolean drawBottom = false;
13488        boolean drawLeft = false;
13489        boolean drawRight = false;
13490
13491        float topFadeStrength = 0.0f;
13492        float bottomFadeStrength = 0.0f;
13493        float leftFadeStrength = 0.0f;
13494        float rightFadeStrength = 0.0f;
13495
13496        // Step 2, save the canvas' layers
13497        int paddingLeft = mPaddingLeft;
13498
13499        final boolean offsetRequired = isPaddingOffsetRequired();
13500        if (offsetRequired) {
13501            paddingLeft += getLeftPaddingOffset();
13502        }
13503
13504        int left = mScrollX + paddingLeft;
13505        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
13506        int top = mScrollY + getFadeTop(offsetRequired);
13507        int bottom = top + getFadeHeight(offsetRequired);
13508
13509        if (offsetRequired) {
13510            right += getRightPaddingOffset();
13511            bottom += getBottomPaddingOffset();
13512        }
13513
13514        final ScrollabilityCache scrollabilityCache = mScrollCache;
13515        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
13516        int length = (int) fadeHeight;
13517
13518        // clip the fade length if top and bottom fades overlap
13519        // overlapping fades produce odd-looking artifacts
13520        if (verticalEdges && (top + length > bottom - length)) {
13521            length = (bottom - top) / 2;
13522        }
13523
13524        // also clip horizontal fades if necessary
13525        if (horizontalEdges && (left + length > right - length)) {
13526            length = (right - left) / 2;
13527        }
13528
13529        if (verticalEdges) {
13530            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
13531            drawTop = topFadeStrength * fadeHeight > 1.0f;
13532            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
13533            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
13534        }
13535
13536        if (horizontalEdges) {
13537            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
13538            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
13539            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
13540            drawRight = rightFadeStrength * fadeHeight > 1.0f;
13541        }
13542
13543        saveCount = canvas.getSaveCount();
13544
13545        int solidColor = getSolidColor();
13546        if (solidColor == 0) {
13547            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
13548
13549            if (drawTop) {
13550                canvas.saveLayer(left, top, right, top + length, null, flags);
13551            }
13552
13553            if (drawBottom) {
13554                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
13555            }
13556
13557            if (drawLeft) {
13558                canvas.saveLayer(left, top, left + length, bottom, null, flags);
13559            }
13560
13561            if (drawRight) {
13562                canvas.saveLayer(right - length, top, right, bottom, null, flags);
13563            }
13564        } else {
13565            scrollabilityCache.setFadeColor(solidColor);
13566        }
13567
13568        // Step 3, draw the content
13569        if (!dirtyOpaque) onDraw(canvas);
13570
13571        // Step 4, draw the children
13572        dispatchDraw(canvas);
13573
13574        // Step 5, draw the fade effect and restore layers
13575        final Paint p = scrollabilityCache.paint;
13576        final Matrix matrix = scrollabilityCache.matrix;
13577        final Shader fade = scrollabilityCache.shader;
13578
13579        if (drawTop) {
13580            matrix.setScale(1, fadeHeight * topFadeStrength);
13581            matrix.postTranslate(left, top);
13582            fade.setLocalMatrix(matrix);
13583            canvas.drawRect(left, top, right, top + length, p);
13584        }
13585
13586        if (drawBottom) {
13587            matrix.setScale(1, fadeHeight * bottomFadeStrength);
13588            matrix.postRotate(180);
13589            matrix.postTranslate(left, bottom);
13590            fade.setLocalMatrix(matrix);
13591            canvas.drawRect(left, bottom - length, right, bottom, p);
13592        }
13593
13594        if (drawLeft) {
13595            matrix.setScale(1, fadeHeight * leftFadeStrength);
13596            matrix.postRotate(-90);
13597            matrix.postTranslate(left, top);
13598            fade.setLocalMatrix(matrix);
13599            canvas.drawRect(left, top, left + length, bottom, p);
13600        }
13601
13602        if (drawRight) {
13603            matrix.setScale(1, fadeHeight * rightFadeStrength);
13604            matrix.postRotate(90);
13605            matrix.postTranslate(right, top);
13606            fade.setLocalMatrix(matrix);
13607            canvas.drawRect(right - length, top, right, bottom, p);
13608        }
13609
13610        canvas.restoreToCount(saveCount);
13611
13612        // Step 6, draw decorations (scrollbars)
13613        onDrawScrollBars(canvas);
13614    }
13615
13616    /**
13617     * Override this if your view is known to always be drawn on top of a solid color background,
13618     * and needs to draw fading edges. Returning a non-zero color enables the view system to
13619     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
13620     * should be set to 0xFF.
13621     *
13622     * @see #setVerticalFadingEdgeEnabled(boolean)
13623     * @see #setHorizontalFadingEdgeEnabled(boolean)
13624     *
13625     * @return The known solid color background for this view, or 0 if the color may vary
13626     */
13627    @ViewDebug.ExportedProperty(category = "drawing")
13628    public int getSolidColor() {
13629        return 0;
13630    }
13631
13632    /**
13633     * Build a human readable string representation of the specified view flags.
13634     *
13635     * @param flags the view flags to convert to a string
13636     * @return a String representing the supplied flags
13637     */
13638    private static String printFlags(int flags) {
13639        String output = "";
13640        int numFlags = 0;
13641        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
13642            output += "TAKES_FOCUS";
13643            numFlags++;
13644        }
13645
13646        switch (flags & VISIBILITY_MASK) {
13647        case INVISIBLE:
13648            if (numFlags > 0) {
13649                output += " ";
13650            }
13651            output += "INVISIBLE";
13652            // USELESS HERE numFlags++;
13653            break;
13654        case GONE:
13655            if (numFlags > 0) {
13656                output += " ";
13657            }
13658            output += "GONE";
13659            // USELESS HERE numFlags++;
13660            break;
13661        default:
13662            break;
13663        }
13664        return output;
13665    }
13666
13667    /**
13668     * Build a human readable string representation of the specified private
13669     * view flags.
13670     *
13671     * @param privateFlags the private view flags to convert to a string
13672     * @return a String representing the supplied flags
13673     */
13674    private static String printPrivateFlags(int privateFlags) {
13675        String output = "";
13676        int numFlags = 0;
13677
13678        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
13679            output += "WANTS_FOCUS";
13680            numFlags++;
13681        }
13682
13683        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
13684            if (numFlags > 0) {
13685                output += " ";
13686            }
13687            output += "FOCUSED";
13688            numFlags++;
13689        }
13690
13691        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
13692            if (numFlags > 0) {
13693                output += " ";
13694            }
13695            output += "SELECTED";
13696            numFlags++;
13697        }
13698
13699        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
13700            if (numFlags > 0) {
13701                output += " ";
13702            }
13703            output += "IS_ROOT_NAMESPACE";
13704            numFlags++;
13705        }
13706
13707        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
13708            if (numFlags > 0) {
13709                output += " ";
13710            }
13711            output += "HAS_BOUNDS";
13712            numFlags++;
13713        }
13714
13715        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
13716            if (numFlags > 0) {
13717                output += " ";
13718            }
13719            output += "DRAWN";
13720            // USELESS HERE numFlags++;
13721        }
13722        return output;
13723    }
13724
13725    /**
13726     * <p>Indicates whether or not this view's layout will be requested during
13727     * the next hierarchy layout pass.</p>
13728     *
13729     * @return true if the layout will be forced during next layout pass
13730     */
13731    public boolean isLayoutRequested() {
13732        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
13733    }
13734
13735    /**
13736     * Assign a size and position to a view and all of its
13737     * descendants
13738     *
13739     * <p>This is the second phase of the layout mechanism.
13740     * (The first is measuring). In this phase, each parent calls
13741     * layout on all of its children to position them.
13742     * This is typically done using the child measurements
13743     * that were stored in the measure pass().</p>
13744     *
13745     * <p>Derived classes should not override this method.
13746     * Derived classes with children should override
13747     * onLayout. In that method, they should
13748     * call layout on each of their children.</p>
13749     *
13750     * @param l Left position, relative to parent
13751     * @param t Top position, relative to parent
13752     * @param r Right position, relative to parent
13753     * @param b Bottom position, relative to parent
13754     */
13755    @SuppressWarnings({"unchecked"})
13756    public void layout(int l, int t, int r, int b) {
13757        int oldL = mLeft;
13758        int oldT = mTop;
13759        int oldB = mBottom;
13760        int oldR = mRight;
13761        boolean changed = setFrame(l, t, r, b);
13762        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
13763            onLayout(changed, l, t, r, b);
13764            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
13765
13766            ListenerInfo li = mListenerInfo;
13767            if (li != null && li.mOnLayoutChangeListeners != null) {
13768                ArrayList<OnLayoutChangeListener> listenersCopy =
13769                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
13770                int numListeners = listenersCopy.size();
13771                for (int i = 0; i < numListeners; ++i) {
13772                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
13773                }
13774            }
13775        }
13776        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
13777    }
13778
13779    /**
13780     * Called from layout when this view should
13781     * assign a size and position to each of its children.
13782     *
13783     * Derived classes with children should override
13784     * this method and call layout on each of
13785     * their children.
13786     * @param changed This is a new size or position for this view
13787     * @param left Left position, relative to parent
13788     * @param top Top position, relative to parent
13789     * @param right Right position, relative to parent
13790     * @param bottom Bottom position, relative to parent
13791     */
13792    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
13793    }
13794
13795    /**
13796     * Assign a size and position to this view.
13797     *
13798     * This is called from layout.
13799     *
13800     * @param left Left position, relative to parent
13801     * @param top Top position, relative to parent
13802     * @param right Right position, relative to parent
13803     * @param bottom Bottom position, relative to parent
13804     * @return true if the new size and position are different than the
13805     *         previous ones
13806     * {@hide}
13807     */
13808    protected boolean setFrame(int left, int top, int right, int bottom) {
13809        boolean changed = false;
13810
13811        if (DBG) {
13812            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
13813                    + right + "," + bottom + ")");
13814        }
13815
13816        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
13817            changed = true;
13818
13819            // Remember our drawn bit
13820            int drawn = mPrivateFlags & PFLAG_DRAWN;
13821
13822            int oldWidth = mRight - mLeft;
13823            int oldHeight = mBottom - mTop;
13824            int newWidth = right - left;
13825            int newHeight = bottom - top;
13826            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
13827
13828            // Invalidate our old position
13829            invalidate(sizeChanged);
13830
13831            mLeft = left;
13832            mTop = top;
13833            mRight = right;
13834            mBottom = bottom;
13835            if (mDisplayList != null) {
13836                mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
13837            }
13838
13839            mPrivateFlags |= PFLAG_HAS_BOUNDS;
13840
13841
13842            if (sizeChanged) {
13843                if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
13844                    // A change in dimension means an auto-centered pivot point changes, too
13845                    if (mTransformationInfo != null) {
13846                        mTransformationInfo.mMatrixDirty = true;
13847                    }
13848                }
13849                onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
13850            }
13851
13852            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
13853                // If we are visible, force the DRAWN bit to on so that
13854                // this invalidate will go through (at least to our parent).
13855                // This is because someone may have invalidated this view
13856                // before this call to setFrame came in, thereby clearing
13857                // the DRAWN bit.
13858                mPrivateFlags |= PFLAG_DRAWN;
13859                invalidate(sizeChanged);
13860                // parent display list may need to be recreated based on a change in the bounds
13861                // of any child
13862                invalidateParentCaches();
13863            }
13864
13865            // Reset drawn bit to original value (invalidate turns it off)
13866            mPrivateFlags |= drawn;
13867
13868            mBackgroundSizeChanged = true;
13869        }
13870        return changed;
13871    }
13872
13873    /**
13874     * Finalize inflating a view from XML.  This is called as the last phase
13875     * of inflation, after all child views have been added.
13876     *
13877     * <p>Even if the subclass overrides onFinishInflate, they should always be
13878     * sure to call the super method, so that we get called.
13879     */
13880    protected void onFinishInflate() {
13881    }
13882
13883    /**
13884     * Returns the resources associated with this view.
13885     *
13886     * @return Resources object.
13887     */
13888    public Resources getResources() {
13889        return mResources;
13890    }
13891
13892    /**
13893     * Invalidates the specified Drawable.
13894     *
13895     * @param drawable the drawable to invalidate
13896     */
13897    public void invalidateDrawable(Drawable drawable) {
13898        if (verifyDrawable(drawable)) {
13899            final Rect dirty = drawable.getBounds();
13900            final int scrollX = mScrollX;
13901            final int scrollY = mScrollY;
13902
13903            invalidate(dirty.left + scrollX, dirty.top + scrollY,
13904                    dirty.right + scrollX, dirty.bottom + scrollY);
13905        }
13906    }
13907
13908    /**
13909     * Schedules an action on a drawable to occur at a specified time.
13910     *
13911     * @param who the recipient of the action
13912     * @param what the action to run on the drawable
13913     * @param when the time at which the action must occur. Uses the
13914     *        {@link SystemClock#uptimeMillis} timebase.
13915     */
13916    public void scheduleDrawable(Drawable who, Runnable what, long when) {
13917        if (verifyDrawable(who) && what != null) {
13918            final long delay = when - SystemClock.uptimeMillis();
13919            if (mAttachInfo != null) {
13920                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13921                        Choreographer.CALLBACK_ANIMATION, what, who,
13922                        Choreographer.subtractFrameDelay(delay));
13923            } else {
13924                ViewRootImpl.getRunQueue().postDelayed(what, delay);
13925            }
13926        }
13927    }
13928
13929    /**
13930     * Cancels a scheduled action on a drawable.
13931     *
13932     * @param who the recipient of the action
13933     * @param what the action to cancel
13934     */
13935    public void unscheduleDrawable(Drawable who, Runnable what) {
13936        if (verifyDrawable(who) && what != null) {
13937            if (mAttachInfo != null) {
13938                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13939                        Choreographer.CALLBACK_ANIMATION, what, who);
13940            } else {
13941                ViewRootImpl.getRunQueue().removeCallbacks(what);
13942            }
13943        }
13944    }
13945
13946    /**
13947     * Unschedule any events associated with the given Drawable.  This can be
13948     * used when selecting a new Drawable into a view, so that the previous
13949     * one is completely unscheduled.
13950     *
13951     * @param who The Drawable to unschedule.
13952     *
13953     * @see #drawableStateChanged
13954     */
13955    public void unscheduleDrawable(Drawable who) {
13956        if (mAttachInfo != null && who != null) {
13957            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13958                    Choreographer.CALLBACK_ANIMATION, null, who);
13959        }
13960    }
13961
13962    /**
13963     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
13964     * that the View directionality can and will be resolved before its Drawables.
13965     *
13966     * Will call {@link View#onResolveDrawables} when resolution is done.
13967     */
13968    public void resolveDrawables() {
13969        if (mBackground != null) {
13970            mBackground.setLayoutDirection(getResolvedLayoutDirection());
13971        }
13972        onResolveDrawables(getResolvedLayoutDirection());
13973    }
13974
13975    /**
13976     * Called when layout direction has been resolved.
13977     *
13978     * The default implementation does nothing.
13979     *
13980     * @param layoutDirection The resolved layout direction.
13981     *
13982     * @see {@link #LAYOUT_DIRECTION_LTR}
13983     * @see {@link #LAYOUT_DIRECTION_RTL}
13984     */
13985    public void onResolveDrawables(int layoutDirection) {
13986    }
13987
13988    /**
13989     * If your view subclass is displaying its own Drawable objects, it should
13990     * override this function and return true for any Drawable it is
13991     * displaying.  This allows animations for those drawables to be
13992     * scheduled.
13993     *
13994     * <p>Be sure to call through to the super class when overriding this
13995     * function.
13996     *
13997     * @param who The Drawable to verify.  Return true if it is one you are
13998     *            displaying, else return the result of calling through to the
13999     *            super class.
14000     *
14001     * @return boolean If true than the Drawable is being displayed in the
14002     *         view; else false and it is not allowed to animate.
14003     *
14004     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
14005     * @see #drawableStateChanged()
14006     */
14007    protected boolean verifyDrawable(Drawable who) {
14008        return who == mBackground;
14009    }
14010
14011    /**
14012     * This function is called whenever the state of the view changes in such
14013     * a way that it impacts the state of drawables being shown.
14014     *
14015     * <p>Be sure to call through to the superclass when overriding this
14016     * function.
14017     *
14018     * @see Drawable#setState(int[])
14019     */
14020    protected void drawableStateChanged() {
14021        Drawable d = mBackground;
14022        if (d != null && d.isStateful()) {
14023            d.setState(getDrawableState());
14024        }
14025    }
14026
14027    /**
14028     * Call this to force a view to update its drawable state. This will cause
14029     * drawableStateChanged to be called on this view. Views that are interested
14030     * in the new state should call getDrawableState.
14031     *
14032     * @see #drawableStateChanged
14033     * @see #getDrawableState
14034     */
14035    public void refreshDrawableState() {
14036        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14037        drawableStateChanged();
14038
14039        ViewParent parent = mParent;
14040        if (parent != null) {
14041            parent.childDrawableStateChanged(this);
14042        }
14043    }
14044
14045    /**
14046     * Return an array of resource IDs of the drawable states representing the
14047     * current state of the view.
14048     *
14049     * @return The current drawable state
14050     *
14051     * @see Drawable#setState(int[])
14052     * @see #drawableStateChanged()
14053     * @see #onCreateDrawableState(int)
14054     */
14055    public final int[] getDrawableState() {
14056        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
14057            return mDrawableState;
14058        } else {
14059            mDrawableState = onCreateDrawableState(0);
14060            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
14061            return mDrawableState;
14062        }
14063    }
14064
14065    /**
14066     * Generate the new {@link android.graphics.drawable.Drawable} state for
14067     * this view. This is called by the view
14068     * system when the cached Drawable state is determined to be invalid.  To
14069     * retrieve the current state, you should use {@link #getDrawableState}.
14070     *
14071     * @param extraSpace if non-zero, this is the number of extra entries you
14072     * would like in the returned array in which you can place your own
14073     * states.
14074     *
14075     * @return Returns an array holding the current {@link Drawable} state of
14076     * the view.
14077     *
14078     * @see #mergeDrawableStates(int[], int[])
14079     */
14080    protected int[] onCreateDrawableState(int extraSpace) {
14081        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
14082                mParent instanceof View) {
14083            return ((View) mParent).onCreateDrawableState(extraSpace);
14084        }
14085
14086        int[] drawableState;
14087
14088        int privateFlags = mPrivateFlags;
14089
14090        int viewStateIndex = 0;
14091        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
14092        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
14093        if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
14094        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
14095        if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
14096        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
14097        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
14098                HardwareRenderer.isAvailable()) {
14099            // This is set if HW acceleration is requested, even if the current
14100            // process doesn't allow it.  This is just to allow app preview
14101            // windows to better match their app.
14102            viewStateIndex |= VIEW_STATE_ACCELERATED;
14103        }
14104        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
14105
14106        final int privateFlags2 = mPrivateFlags2;
14107        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
14108        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
14109
14110        drawableState = VIEW_STATE_SETS[viewStateIndex];
14111
14112        //noinspection ConstantIfStatement
14113        if (false) {
14114            Log.i("View", "drawableStateIndex=" + viewStateIndex);
14115            Log.i("View", toString()
14116                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
14117                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
14118                    + " fo=" + hasFocus()
14119                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
14120                    + " wf=" + hasWindowFocus()
14121                    + ": " + Arrays.toString(drawableState));
14122        }
14123
14124        if (extraSpace == 0) {
14125            return drawableState;
14126        }
14127
14128        final int[] fullState;
14129        if (drawableState != null) {
14130            fullState = new int[drawableState.length + extraSpace];
14131            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
14132        } else {
14133            fullState = new int[extraSpace];
14134        }
14135
14136        return fullState;
14137    }
14138
14139    /**
14140     * Merge your own state values in <var>additionalState</var> into the base
14141     * state values <var>baseState</var> that were returned by
14142     * {@link #onCreateDrawableState(int)}.
14143     *
14144     * @param baseState The base state values returned by
14145     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
14146     * own additional state values.
14147     *
14148     * @param additionalState The additional state values you would like
14149     * added to <var>baseState</var>; this array is not modified.
14150     *
14151     * @return As a convenience, the <var>baseState</var> array you originally
14152     * passed into the function is returned.
14153     *
14154     * @see #onCreateDrawableState(int)
14155     */
14156    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
14157        final int N = baseState.length;
14158        int i = N - 1;
14159        while (i >= 0 && baseState[i] == 0) {
14160            i--;
14161        }
14162        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
14163        return baseState;
14164    }
14165
14166    /**
14167     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
14168     * on all Drawable objects associated with this view.
14169     */
14170    public void jumpDrawablesToCurrentState() {
14171        if (mBackground != null) {
14172            mBackground.jumpToCurrentState();
14173        }
14174    }
14175
14176    /**
14177     * Sets the background color for this view.
14178     * @param color the color of the background
14179     */
14180    @RemotableViewMethod
14181    public void setBackgroundColor(int color) {
14182        if (mBackground instanceof ColorDrawable) {
14183            ((ColorDrawable) mBackground.mutate()).setColor(color);
14184            computeOpaqueFlags();
14185        } else {
14186            setBackground(new ColorDrawable(color));
14187        }
14188    }
14189
14190    /**
14191     * Set the background to a given resource. The resource should refer to
14192     * a Drawable object or 0 to remove the background.
14193     * @param resid The identifier of the resource.
14194     *
14195     * @attr ref android.R.styleable#View_background
14196     */
14197    @RemotableViewMethod
14198    public void setBackgroundResource(int resid) {
14199        if (resid != 0 && resid == mBackgroundResource) {
14200            return;
14201        }
14202
14203        Drawable d= null;
14204        if (resid != 0) {
14205            d = mResources.getDrawable(resid);
14206        }
14207        setBackground(d);
14208
14209        mBackgroundResource = resid;
14210    }
14211
14212    /**
14213     * Set the background to a given Drawable, or remove the background. If the
14214     * background has padding, this View's padding is set to the background's
14215     * padding. However, when a background is removed, this View's padding isn't
14216     * touched. If setting the padding is desired, please use
14217     * {@link #setPadding(int, int, int, int)}.
14218     *
14219     * @param background The Drawable to use as the background, or null to remove the
14220     *        background
14221     */
14222    public void setBackground(Drawable background) {
14223        //noinspection deprecation
14224        setBackgroundDrawable(background);
14225    }
14226
14227    /**
14228     * @deprecated use {@link #setBackground(Drawable)} instead
14229     */
14230    @Deprecated
14231    public void setBackgroundDrawable(Drawable background) {
14232        computeOpaqueFlags();
14233
14234        if (background == mBackground) {
14235            return;
14236        }
14237
14238        boolean requestLayout = false;
14239
14240        mBackgroundResource = 0;
14241
14242        /*
14243         * Regardless of whether we're setting a new background or not, we want
14244         * to clear the previous drawable.
14245         */
14246        if (mBackground != null) {
14247            mBackground.setCallback(null);
14248            unscheduleDrawable(mBackground);
14249        }
14250
14251        if (background != null) {
14252            Rect padding = sThreadLocal.get();
14253            if (padding == null) {
14254                padding = new Rect();
14255                sThreadLocal.set(padding);
14256            }
14257            background.setLayoutDirection(getResolvedLayoutDirection());
14258            if (background.getPadding(padding)) {
14259                // Reset padding resolution
14260                mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14261                switch (background.getLayoutDirection()) {
14262                    case LAYOUT_DIRECTION_RTL:
14263                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
14264                        break;
14265                    case LAYOUT_DIRECTION_LTR:
14266                    default:
14267                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
14268                }
14269            }
14270
14271            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
14272            // if it has a different minimum size, we should layout again
14273            if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() ||
14274                    mBackground.getMinimumWidth() != background.getMinimumWidth()) {
14275                requestLayout = true;
14276            }
14277
14278            background.setCallback(this);
14279            if (background.isStateful()) {
14280                background.setState(getDrawableState());
14281            }
14282            background.setVisible(getVisibility() == VISIBLE, false);
14283            mBackground = background;
14284
14285            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
14286                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
14287                mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
14288                requestLayout = true;
14289            }
14290        } else {
14291            /* Remove the background */
14292            mBackground = null;
14293
14294            if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
14295                /*
14296                 * This view ONLY drew the background before and we're removing
14297                 * the background, so now it won't draw anything
14298                 * (hence we SKIP_DRAW)
14299                 */
14300                mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
14301                mPrivateFlags |= PFLAG_SKIP_DRAW;
14302            }
14303
14304            /*
14305             * When the background is set, we try to apply its padding to this
14306             * View. When the background is removed, we don't touch this View's
14307             * padding. This is noted in the Javadocs. Hence, we don't need to
14308             * requestLayout(), the invalidate() below is sufficient.
14309             */
14310
14311            // The old background's minimum size could have affected this
14312            // View's layout, so let's requestLayout
14313            requestLayout = true;
14314        }
14315
14316        computeOpaqueFlags();
14317
14318        if (requestLayout) {
14319            requestLayout();
14320        }
14321
14322        mBackgroundSizeChanged = true;
14323        invalidate(true);
14324    }
14325
14326    /**
14327     * Gets the background drawable
14328     *
14329     * @return The drawable used as the background for this view, if any.
14330     *
14331     * @see #setBackground(Drawable)
14332     *
14333     * @attr ref android.R.styleable#View_background
14334     */
14335    public Drawable getBackground() {
14336        return mBackground;
14337    }
14338
14339    /**
14340     * Sets the padding. The view may add on the space required to display
14341     * the scrollbars, depending on the style and visibility of the scrollbars.
14342     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
14343     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
14344     * from the values set in this call.
14345     *
14346     * @attr ref android.R.styleable#View_padding
14347     * @attr ref android.R.styleable#View_paddingBottom
14348     * @attr ref android.R.styleable#View_paddingLeft
14349     * @attr ref android.R.styleable#View_paddingRight
14350     * @attr ref android.R.styleable#View_paddingTop
14351     * @param left the left padding in pixels
14352     * @param top the top padding in pixels
14353     * @param right the right padding in pixels
14354     * @param bottom the bottom padding in pixels
14355     */
14356    public void setPadding(int left, int top, int right, int bottom) {
14357        // Reset padding resolution
14358        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14359
14360        mUserPaddingStart = UNDEFINED_PADDING;
14361        mUserPaddingEnd = UNDEFINED_PADDING;
14362
14363        internalSetPadding(left, top, right, bottom);
14364    }
14365
14366    /**
14367     * @hide
14368     */
14369    protected void internalSetPadding(int left, int top, int right, int bottom) {
14370        mUserPaddingLeft = left;
14371        mUserPaddingRight = right;
14372        mUserPaddingBottom = bottom;
14373
14374        final int viewFlags = mViewFlags;
14375        boolean changed = false;
14376
14377        // Common case is there are no scroll bars.
14378        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
14379            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
14380                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
14381                        ? 0 : getVerticalScrollbarWidth();
14382                switch (mVerticalScrollbarPosition) {
14383                    case SCROLLBAR_POSITION_DEFAULT:
14384                        if (isLayoutRtl()) {
14385                            left += offset;
14386                        } else {
14387                            right += offset;
14388                        }
14389                        break;
14390                    case SCROLLBAR_POSITION_RIGHT:
14391                        right += offset;
14392                        break;
14393                    case SCROLLBAR_POSITION_LEFT:
14394                        left += offset;
14395                        break;
14396                }
14397            }
14398            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
14399                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
14400                        ? 0 : getHorizontalScrollbarHeight();
14401            }
14402        }
14403
14404        if (mPaddingLeft != left) {
14405            changed = true;
14406            mPaddingLeft = left;
14407        }
14408        if (mPaddingTop != top) {
14409            changed = true;
14410            mPaddingTop = top;
14411        }
14412        if (mPaddingRight != right) {
14413            changed = true;
14414            mPaddingRight = right;
14415        }
14416        if (mPaddingBottom != bottom) {
14417            changed = true;
14418            mPaddingBottom = bottom;
14419        }
14420
14421        if (changed) {
14422            requestLayout();
14423        }
14424    }
14425
14426    /**
14427     * Sets the relative padding. The view may add on the space required to display
14428     * the scrollbars, depending on the style and visibility of the scrollbars.
14429     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
14430     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
14431     * from the values set in this call.
14432     *
14433     * @attr ref android.R.styleable#View_padding
14434     * @attr ref android.R.styleable#View_paddingBottom
14435     * @attr ref android.R.styleable#View_paddingStart
14436     * @attr ref android.R.styleable#View_paddingEnd
14437     * @attr ref android.R.styleable#View_paddingTop
14438     * @param start the start padding in pixels
14439     * @param top the top padding in pixels
14440     * @param end the end padding in pixels
14441     * @param bottom the bottom padding in pixels
14442     */
14443    public void setPaddingRelative(int start, int top, int end, int bottom) {
14444        // Reset padding resolution
14445        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14446
14447        mUserPaddingStart = start;
14448        mUserPaddingEnd = end;
14449
14450        switch(getResolvedLayoutDirection()) {
14451            case LAYOUT_DIRECTION_RTL:
14452                internalSetPadding(end, top, start, bottom);
14453                break;
14454            case LAYOUT_DIRECTION_LTR:
14455            default:
14456                internalSetPadding(start, top, end, bottom);
14457        }
14458    }
14459
14460    /**
14461     * Returns the top padding of this view.
14462     *
14463     * @return the top padding in pixels
14464     */
14465    public int getPaddingTop() {
14466        return mPaddingTop;
14467    }
14468
14469    /**
14470     * Returns the bottom padding of this view. If there are inset and enabled
14471     * scrollbars, this value may include the space required to display the
14472     * scrollbars as well.
14473     *
14474     * @return the bottom padding in pixels
14475     */
14476    public int getPaddingBottom() {
14477        return mPaddingBottom;
14478    }
14479
14480    /**
14481     * Returns the left padding of this view. If there are inset and enabled
14482     * scrollbars, this value may include the space required to display the
14483     * scrollbars as well.
14484     *
14485     * @return the left padding in pixels
14486     */
14487    public int getPaddingLeft() {
14488        if (!isPaddingResolved()) {
14489            resolvePadding();
14490        }
14491        return mPaddingLeft;
14492    }
14493
14494    /**
14495     * Returns the start padding of this view depending on its resolved layout direction.
14496     * If there are inset and enabled scrollbars, this value may include the space
14497     * required to display the scrollbars as well.
14498     *
14499     * @return the start padding in pixels
14500     */
14501    public int getPaddingStart() {
14502        if (!isPaddingResolved()) {
14503            resolvePadding();
14504        }
14505        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
14506                mPaddingRight : mPaddingLeft;
14507    }
14508
14509    /**
14510     * Returns the right padding of this view. If there are inset and enabled
14511     * scrollbars, this value may include the space required to display the
14512     * scrollbars as well.
14513     *
14514     * @return the right padding in pixels
14515     */
14516    public int getPaddingRight() {
14517        if (!isPaddingResolved()) {
14518            resolvePadding();
14519        }
14520        return mPaddingRight;
14521    }
14522
14523    /**
14524     * Returns the end padding of this view depending on its resolved layout direction.
14525     * If there are inset and enabled scrollbars, this value may include the space
14526     * required to display the scrollbars as well.
14527     *
14528     * @return the end padding in pixels
14529     */
14530    public int getPaddingEnd() {
14531        if (!isPaddingResolved()) {
14532            resolvePadding();
14533        }
14534        return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
14535                mPaddingLeft : mPaddingRight;
14536    }
14537
14538    /**
14539     * Return if the padding as been set thru relative values
14540     * {@link #setPaddingRelative(int, int, int, int)} or thru
14541     * @attr ref android.R.styleable#View_paddingStart or
14542     * @attr ref android.R.styleable#View_paddingEnd
14543     *
14544     * @return true if the padding is relative or false if it is not.
14545     */
14546    public boolean isPaddingRelative() {
14547        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
14548    }
14549
14550    /**
14551     * @hide
14552     */
14553    public Insets getOpticalInsets() {
14554        if (mLayoutInsets == null) {
14555            mLayoutInsets = (mBackground == null) ? Insets.NONE : mBackground.getLayoutInsets();
14556        }
14557        return mLayoutInsets;
14558    }
14559
14560    /**
14561     * @hide
14562     */
14563    public void setLayoutInsets(Insets layoutInsets) {
14564        mLayoutInsets = layoutInsets;
14565    }
14566
14567    /**
14568     * Changes the selection state of this view. A view can be selected or not.
14569     * Note that selection is not the same as focus. Views are typically
14570     * selected in the context of an AdapterView like ListView or GridView;
14571     * the selected view is the view that is highlighted.
14572     *
14573     * @param selected true if the view must be selected, false otherwise
14574     */
14575    public void setSelected(boolean selected) {
14576        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
14577            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
14578            if (!selected) resetPressedState();
14579            invalidate(true);
14580            refreshDrawableState();
14581            dispatchSetSelected(selected);
14582            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
14583                notifyAccessibilityStateChanged();
14584            }
14585        }
14586    }
14587
14588    /**
14589     * Dispatch setSelected to all of this View's children.
14590     *
14591     * @see #setSelected(boolean)
14592     *
14593     * @param selected The new selected state
14594     */
14595    protected void dispatchSetSelected(boolean selected) {
14596    }
14597
14598    /**
14599     * Indicates the selection state of this view.
14600     *
14601     * @return true if the view is selected, false otherwise
14602     */
14603    @ViewDebug.ExportedProperty
14604    public boolean isSelected() {
14605        return (mPrivateFlags & PFLAG_SELECTED) != 0;
14606    }
14607
14608    /**
14609     * Changes the activated state of this view. A view can be activated or not.
14610     * Note that activation is not the same as selection.  Selection is
14611     * a transient property, representing the view (hierarchy) the user is
14612     * currently interacting with.  Activation is a longer-term state that the
14613     * user can move views in and out of.  For example, in a list view with
14614     * single or multiple selection enabled, the views in the current selection
14615     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
14616     * here.)  The activated state is propagated down to children of the view it
14617     * is set on.
14618     *
14619     * @param activated true if the view must be activated, false otherwise
14620     */
14621    public void setActivated(boolean activated) {
14622        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
14623            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
14624            invalidate(true);
14625            refreshDrawableState();
14626            dispatchSetActivated(activated);
14627        }
14628    }
14629
14630    /**
14631     * Dispatch setActivated to all of this View's children.
14632     *
14633     * @see #setActivated(boolean)
14634     *
14635     * @param activated The new activated state
14636     */
14637    protected void dispatchSetActivated(boolean activated) {
14638    }
14639
14640    /**
14641     * Indicates the activation state of this view.
14642     *
14643     * @return true if the view is activated, false otherwise
14644     */
14645    @ViewDebug.ExportedProperty
14646    public boolean isActivated() {
14647        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
14648    }
14649
14650    /**
14651     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
14652     * observer can be used to get notifications when global events, like
14653     * layout, happen.
14654     *
14655     * The returned ViewTreeObserver observer is not guaranteed to remain
14656     * valid for the lifetime of this View. If the caller of this method keeps
14657     * a long-lived reference to ViewTreeObserver, it should always check for
14658     * the return value of {@link ViewTreeObserver#isAlive()}.
14659     *
14660     * @return The ViewTreeObserver for this view's hierarchy.
14661     */
14662    public ViewTreeObserver getViewTreeObserver() {
14663        if (mAttachInfo != null) {
14664            return mAttachInfo.mTreeObserver;
14665        }
14666        if (mFloatingTreeObserver == null) {
14667            mFloatingTreeObserver = new ViewTreeObserver();
14668        }
14669        return mFloatingTreeObserver;
14670    }
14671
14672    /**
14673     * <p>Finds the topmost view in the current view hierarchy.</p>
14674     *
14675     * @return the topmost view containing this view
14676     */
14677    public View getRootView() {
14678        if (mAttachInfo != null) {
14679            final View v = mAttachInfo.mRootView;
14680            if (v != null) {
14681                return v;
14682            }
14683        }
14684
14685        View parent = this;
14686
14687        while (parent.mParent != null && parent.mParent instanceof View) {
14688            parent = (View) parent.mParent;
14689        }
14690
14691        return parent;
14692    }
14693
14694    /**
14695     * <p>Computes the coordinates of this view on the screen. The argument
14696     * must be an array of two integers. After the method returns, the array
14697     * contains the x and y location in that order.</p>
14698     *
14699     * @param location an array of two integers in which to hold the coordinates
14700     */
14701    public void getLocationOnScreen(int[] location) {
14702        getLocationInWindow(location);
14703
14704        final AttachInfo info = mAttachInfo;
14705        if (info != null) {
14706            location[0] += info.mWindowLeft;
14707            location[1] += info.mWindowTop;
14708        }
14709    }
14710
14711    /**
14712     * <p>Computes the coordinates of this view in its window. The argument
14713     * must be an array of two integers. After the method returns, the array
14714     * contains the x and y location in that order.</p>
14715     *
14716     * @param location an array of two integers in which to hold the coordinates
14717     */
14718    public void getLocationInWindow(int[] location) {
14719        if (location == null || location.length < 2) {
14720            throw new IllegalArgumentException("location must be an array of two integers");
14721        }
14722
14723        if (mAttachInfo == null) {
14724            // When the view is not attached to a window, this method does not make sense
14725            location[0] = location[1] = 0;
14726            return;
14727        }
14728
14729        float[] position = mAttachInfo.mTmpTransformLocation;
14730        position[0] = position[1] = 0.0f;
14731
14732        if (!hasIdentityMatrix()) {
14733            getMatrix().mapPoints(position);
14734        }
14735
14736        position[0] += mLeft;
14737        position[1] += mTop;
14738
14739        ViewParent viewParent = mParent;
14740        while (viewParent instanceof View) {
14741            final View view = (View) viewParent;
14742
14743            position[0] -= view.mScrollX;
14744            position[1] -= view.mScrollY;
14745
14746            if (!view.hasIdentityMatrix()) {
14747                view.getMatrix().mapPoints(position);
14748            }
14749
14750            position[0] += view.mLeft;
14751            position[1] += view.mTop;
14752
14753            viewParent = view.mParent;
14754         }
14755
14756        if (viewParent instanceof ViewRootImpl) {
14757            // *cough*
14758            final ViewRootImpl vr = (ViewRootImpl) viewParent;
14759            position[1] -= vr.mCurScrollY;
14760        }
14761
14762        location[0] = (int) (position[0] + 0.5f);
14763        location[1] = (int) (position[1] + 0.5f);
14764    }
14765
14766    /**
14767     * {@hide}
14768     * @param id the id of the view to be found
14769     * @return the view of the specified id, null if cannot be found
14770     */
14771    protected View findViewTraversal(int id) {
14772        if (id == mID) {
14773            return this;
14774        }
14775        return null;
14776    }
14777
14778    /**
14779     * {@hide}
14780     * @param tag the tag of the view to be found
14781     * @return the view of specified tag, null if cannot be found
14782     */
14783    protected View findViewWithTagTraversal(Object tag) {
14784        if (tag != null && tag.equals(mTag)) {
14785            return this;
14786        }
14787        return null;
14788    }
14789
14790    /**
14791     * {@hide}
14792     * @param predicate The predicate to evaluate.
14793     * @param childToSkip If not null, ignores this child during the recursive traversal.
14794     * @return The first view that matches the predicate or null.
14795     */
14796    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
14797        if (predicate.apply(this)) {
14798            return this;
14799        }
14800        return null;
14801    }
14802
14803    /**
14804     * Look for a child view with the given id.  If this view has the given
14805     * id, return this view.
14806     *
14807     * @param id The id to search for.
14808     * @return The view that has the given id in the hierarchy or null
14809     */
14810    public final View findViewById(int id) {
14811        if (id < 0) {
14812            return null;
14813        }
14814        return findViewTraversal(id);
14815    }
14816
14817    /**
14818     * Finds a view by its unuque and stable accessibility id.
14819     *
14820     * @param accessibilityId The searched accessibility id.
14821     * @return The found view.
14822     */
14823    final View findViewByAccessibilityId(int accessibilityId) {
14824        if (accessibilityId < 0) {
14825            return null;
14826        }
14827        return findViewByAccessibilityIdTraversal(accessibilityId);
14828    }
14829
14830    /**
14831     * Performs the traversal to find a view by its unuque and stable accessibility id.
14832     *
14833     * <strong>Note:</strong>This method does not stop at the root namespace
14834     * boundary since the user can touch the screen at an arbitrary location
14835     * potentially crossing the root namespace bounday which will send an
14836     * accessibility event to accessibility services and they should be able
14837     * to obtain the event source. Also accessibility ids are guaranteed to be
14838     * unique in the window.
14839     *
14840     * @param accessibilityId The accessibility id.
14841     * @return The found view.
14842     */
14843    View findViewByAccessibilityIdTraversal(int accessibilityId) {
14844        if (getAccessibilityViewId() == accessibilityId) {
14845            return this;
14846        }
14847        return null;
14848    }
14849
14850    /**
14851     * Look for a child view with the given tag.  If this view has the given
14852     * tag, return this view.
14853     *
14854     * @param tag The tag to search for, using "tag.equals(getTag())".
14855     * @return The View that has the given tag in the hierarchy or null
14856     */
14857    public final View findViewWithTag(Object tag) {
14858        if (tag == null) {
14859            return null;
14860        }
14861        return findViewWithTagTraversal(tag);
14862    }
14863
14864    /**
14865     * {@hide}
14866     * Look for a child view that matches the specified predicate.
14867     * If this view matches the predicate, return this view.
14868     *
14869     * @param predicate The predicate to evaluate.
14870     * @return The first view that matches the predicate or null.
14871     */
14872    public final View findViewByPredicate(Predicate<View> predicate) {
14873        return findViewByPredicateTraversal(predicate, null);
14874    }
14875
14876    /**
14877     * {@hide}
14878     * Look for a child view that matches the specified predicate,
14879     * starting with the specified view and its descendents and then
14880     * recusively searching the ancestors and siblings of that view
14881     * until this view is reached.
14882     *
14883     * This method is useful in cases where the predicate does not match
14884     * a single unique view (perhaps multiple views use the same id)
14885     * and we are trying to find the view that is "closest" in scope to the
14886     * starting view.
14887     *
14888     * @param start The view to start from.
14889     * @param predicate The predicate to evaluate.
14890     * @return The first view that matches the predicate or null.
14891     */
14892    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
14893        View childToSkip = null;
14894        for (;;) {
14895            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
14896            if (view != null || start == this) {
14897                return view;
14898            }
14899
14900            ViewParent parent = start.getParent();
14901            if (parent == null || !(parent instanceof View)) {
14902                return null;
14903            }
14904
14905            childToSkip = start;
14906            start = (View) parent;
14907        }
14908    }
14909
14910    /**
14911     * Sets the identifier for this view. The identifier does not have to be
14912     * unique in this view's hierarchy. The identifier should be a positive
14913     * number.
14914     *
14915     * @see #NO_ID
14916     * @see #getId()
14917     * @see #findViewById(int)
14918     *
14919     * @param id a number used to identify the view
14920     *
14921     * @attr ref android.R.styleable#View_id
14922     */
14923    public void setId(int id) {
14924        mID = id;
14925    }
14926
14927    /**
14928     * {@hide}
14929     *
14930     * @param isRoot true if the view belongs to the root namespace, false
14931     *        otherwise
14932     */
14933    public void setIsRootNamespace(boolean isRoot) {
14934        if (isRoot) {
14935            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
14936        } else {
14937            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
14938        }
14939    }
14940
14941    /**
14942     * {@hide}
14943     *
14944     * @return true if the view belongs to the root namespace, false otherwise
14945     */
14946    public boolean isRootNamespace() {
14947        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
14948    }
14949
14950    /**
14951     * Returns this view's identifier.
14952     *
14953     * @return a positive integer used to identify the view or {@link #NO_ID}
14954     *         if the view has no ID
14955     *
14956     * @see #setId(int)
14957     * @see #findViewById(int)
14958     * @attr ref android.R.styleable#View_id
14959     */
14960    @ViewDebug.CapturedViewProperty
14961    public int getId() {
14962        return mID;
14963    }
14964
14965    /**
14966     * Returns this view's tag.
14967     *
14968     * @return the Object stored in this view as a tag
14969     *
14970     * @see #setTag(Object)
14971     * @see #getTag(int)
14972     */
14973    @ViewDebug.ExportedProperty
14974    public Object getTag() {
14975        return mTag;
14976    }
14977
14978    /**
14979     * Sets the tag associated with this view. A tag can be used to mark
14980     * a view in its hierarchy and does not have to be unique within the
14981     * hierarchy. Tags can also be used to store data within a view without
14982     * resorting to another data structure.
14983     *
14984     * @param tag an Object to tag the view with
14985     *
14986     * @see #getTag()
14987     * @see #setTag(int, Object)
14988     */
14989    public void setTag(final Object tag) {
14990        mTag = tag;
14991    }
14992
14993    /**
14994     * Returns the tag associated with this view and the specified key.
14995     *
14996     * @param key The key identifying the tag
14997     *
14998     * @return the Object stored in this view as a tag
14999     *
15000     * @see #setTag(int, Object)
15001     * @see #getTag()
15002     */
15003    public Object getTag(int key) {
15004        if (mKeyedTags != null) return mKeyedTags.get(key);
15005        return null;
15006    }
15007
15008    /**
15009     * Sets a tag associated with this view and a key. A tag can be used
15010     * to mark a view in its hierarchy and does not have to be unique within
15011     * the hierarchy. Tags can also be used to store data within a view
15012     * without resorting to another data structure.
15013     *
15014     * The specified key should be an id declared in the resources of the
15015     * application to ensure it is unique (see the <a
15016     * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
15017     * Keys identified as belonging to
15018     * the Android framework or not associated with any package will cause
15019     * an {@link IllegalArgumentException} to be thrown.
15020     *
15021     * @param key The key identifying the tag
15022     * @param tag An Object to tag the view with
15023     *
15024     * @throws IllegalArgumentException If they specified key is not valid
15025     *
15026     * @see #setTag(Object)
15027     * @see #getTag(int)
15028     */
15029    public void setTag(int key, final Object tag) {
15030        // If the package id is 0x00 or 0x01, it's either an undefined package
15031        // or a framework id
15032        if ((key >>> 24) < 2) {
15033            throw new IllegalArgumentException("The key must be an application-specific "
15034                    + "resource id.");
15035        }
15036
15037        setKeyedTag(key, tag);
15038    }
15039
15040    /**
15041     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
15042     * framework id.
15043     *
15044     * @hide
15045     */
15046    public void setTagInternal(int key, Object tag) {
15047        if ((key >>> 24) != 0x1) {
15048            throw new IllegalArgumentException("The key must be a framework-specific "
15049                    + "resource id.");
15050        }
15051
15052        setKeyedTag(key, tag);
15053    }
15054
15055    private void setKeyedTag(int key, Object tag) {
15056        if (mKeyedTags == null) {
15057            mKeyedTags = new SparseArray<Object>();
15058        }
15059
15060        mKeyedTags.put(key, tag);
15061    }
15062
15063    /**
15064     * Prints information about this view in the log output, with the tag
15065     * {@link #VIEW_LOG_TAG}.
15066     *
15067     * @hide
15068     */
15069    public void debug() {
15070        debug(0);
15071    }
15072
15073    /**
15074     * Prints information about this view in the log output, with the tag
15075     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
15076     * indentation defined by the <code>depth</code>.
15077     *
15078     * @param depth the indentation level
15079     *
15080     * @hide
15081     */
15082    protected void debug(int depth) {
15083        String output = debugIndent(depth - 1);
15084
15085        output += "+ " + this;
15086        int id = getId();
15087        if (id != -1) {
15088            output += " (id=" + id + ")";
15089        }
15090        Object tag = getTag();
15091        if (tag != null) {
15092            output += " (tag=" + tag + ")";
15093        }
15094        Log.d(VIEW_LOG_TAG, output);
15095
15096        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
15097            output = debugIndent(depth) + " FOCUSED";
15098            Log.d(VIEW_LOG_TAG, output);
15099        }
15100
15101        output = debugIndent(depth);
15102        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
15103                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
15104                + "} ";
15105        Log.d(VIEW_LOG_TAG, output);
15106
15107        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
15108                || mPaddingBottom != 0) {
15109            output = debugIndent(depth);
15110            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
15111                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
15112            Log.d(VIEW_LOG_TAG, output);
15113        }
15114
15115        output = debugIndent(depth);
15116        output += "mMeasureWidth=" + mMeasuredWidth +
15117                " mMeasureHeight=" + mMeasuredHeight;
15118        Log.d(VIEW_LOG_TAG, output);
15119
15120        output = debugIndent(depth);
15121        if (mLayoutParams == null) {
15122            output += "BAD! no layout params";
15123        } else {
15124            output = mLayoutParams.debug(output);
15125        }
15126        Log.d(VIEW_LOG_TAG, output);
15127
15128        output = debugIndent(depth);
15129        output += "flags={";
15130        output += View.printFlags(mViewFlags);
15131        output += "}";
15132        Log.d(VIEW_LOG_TAG, output);
15133
15134        output = debugIndent(depth);
15135        output += "privateFlags={";
15136        output += View.printPrivateFlags(mPrivateFlags);
15137        output += "}";
15138        Log.d(VIEW_LOG_TAG, output);
15139    }
15140
15141    /**
15142     * Creates a string of whitespaces used for indentation.
15143     *
15144     * @param depth the indentation level
15145     * @return a String containing (depth * 2 + 3) * 2 white spaces
15146     *
15147     * @hide
15148     */
15149    protected static String debugIndent(int depth) {
15150        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
15151        for (int i = 0; i < (depth * 2) + 3; i++) {
15152            spaces.append(' ').append(' ');
15153        }
15154        return spaces.toString();
15155    }
15156
15157    /**
15158     * <p>Return the offset of the widget's text baseline from the widget's top
15159     * boundary. If this widget does not support baseline alignment, this
15160     * method returns -1. </p>
15161     *
15162     * @return the offset of the baseline within the widget's bounds or -1
15163     *         if baseline alignment is not supported
15164     */
15165    @ViewDebug.ExportedProperty(category = "layout")
15166    public int getBaseline() {
15167        return -1;
15168    }
15169
15170    /**
15171     * Call this when something has changed which has invalidated the
15172     * layout of this view. This will schedule a layout pass of the view
15173     * tree.
15174     */
15175    public void requestLayout() {
15176        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
15177        mPrivateFlags |= PFLAG_INVALIDATED;
15178
15179        if (mParent != null && !mParent.isLayoutRequested()) {
15180            mParent.requestLayout();
15181        }
15182    }
15183
15184    /**
15185     * Forces this view to be laid out during the next layout pass.
15186     * This method does not call requestLayout() or forceLayout()
15187     * on the parent.
15188     */
15189    public void forceLayout() {
15190        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
15191        mPrivateFlags |= PFLAG_INVALIDATED;
15192    }
15193
15194    /**
15195     * <p>
15196     * This is called to find out how big a view should be. The parent
15197     * supplies constraint information in the width and height parameters.
15198     * </p>
15199     *
15200     * <p>
15201     * The actual measurement work of a view is performed in
15202     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
15203     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
15204     * </p>
15205     *
15206     *
15207     * @param widthMeasureSpec Horizontal space requirements as imposed by the
15208     *        parent
15209     * @param heightMeasureSpec Vertical space requirements as imposed by the
15210     *        parent
15211     *
15212     * @see #onMeasure(int, int)
15213     */
15214    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
15215        if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
15216                widthMeasureSpec != mOldWidthMeasureSpec ||
15217                heightMeasureSpec != mOldHeightMeasureSpec) {
15218
15219            // first clears the measured dimension flag
15220            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
15221
15222            if (!isPaddingResolved()) {
15223                resolvePadding();
15224            }
15225
15226            // measure ourselves, this should set the measured dimension flag back
15227            onMeasure(widthMeasureSpec, heightMeasureSpec);
15228
15229            // flag not set, setMeasuredDimension() was not invoked, we raise
15230            // an exception to warn the developer
15231            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
15232                throw new IllegalStateException("onMeasure() did not set the"
15233                        + " measured dimension by calling"
15234                        + " setMeasuredDimension()");
15235            }
15236
15237            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
15238        }
15239
15240        mOldWidthMeasureSpec = widthMeasureSpec;
15241        mOldHeightMeasureSpec = heightMeasureSpec;
15242    }
15243
15244    /**
15245     * <p>
15246     * Measure the view and its content to determine the measured width and the
15247     * measured height. This method is invoked by {@link #measure(int, int)} and
15248     * should be overriden by subclasses to provide accurate and efficient
15249     * measurement of their contents.
15250     * </p>
15251     *
15252     * <p>
15253     * <strong>CONTRACT:</strong> When overriding this method, you
15254     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
15255     * measured width and height of this view. Failure to do so will trigger an
15256     * <code>IllegalStateException</code>, thrown by
15257     * {@link #measure(int, int)}. Calling the superclass'
15258     * {@link #onMeasure(int, int)} is a valid use.
15259     * </p>
15260     *
15261     * <p>
15262     * The base class implementation of measure defaults to the background size,
15263     * unless a larger size is allowed by the MeasureSpec. Subclasses should
15264     * override {@link #onMeasure(int, int)} to provide better measurements of
15265     * their content.
15266     * </p>
15267     *
15268     * <p>
15269     * If this method is overridden, it is the subclass's responsibility to make
15270     * sure the measured height and width are at least the view's minimum height
15271     * and width ({@link #getSuggestedMinimumHeight()} and
15272     * {@link #getSuggestedMinimumWidth()}).
15273     * </p>
15274     *
15275     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
15276     *                         The requirements are encoded with
15277     *                         {@link android.view.View.MeasureSpec}.
15278     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
15279     *                         The requirements are encoded with
15280     *                         {@link android.view.View.MeasureSpec}.
15281     *
15282     * @see #getMeasuredWidth()
15283     * @see #getMeasuredHeight()
15284     * @see #setMeasuredDimension(int, int)
15285     * @see #getSuggestedMinimumHeight()
15286     * @see #getSuggestedMinimumWidth()
15287     * @see android.view.View.MeasureSpec#getMode(int)
15288     * @see android.view.View.MeasureSpec#getSize(int)
15289     */
15290    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
15291        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
15292                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
15293    }
15294
15295    /**
15296     * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
15297     * measured width and measured height. Failing to do so will trigger an
15298     * exception at measurement time.</p>
15299     *
15300     * @param measuredWidth The measured width of this view.  May be a complex
15301     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15302     * {@link #MEASURED_STATE_TOO_SMALL}.
15303     * @param measuredHeight The measured height of this view.  May be a complex
15304     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15305     * {@link #MEASURED_STATE_TOO_SMALL}.
15306     */
15307    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
15308        mMeasuredWidth = measuredWidth;
15309        mMeasuredHeight = measuredHeight;
15310
15311        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
15312    }
15313
15314    /**
15315     * Merge two states as returned by {@link #getMeasuredState()}.
15316     * @param curState The current state as returned from a view or the result
15317     * of combining multiple views.
15318     * @param newState The new view state to combine.
15319     * @return Returns a new integer reflecting the combination of the two
15320     * states.
15321     */
15322    public static int combineMeasuredStates(int curState, int newState) {
15323        return curState | newState;
15324    }
15325
15326    /**
15327     * Version of {@link #resolveSizeAndState(int, int, int)}
15328     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
15329     */
15330    public static int resolveSize(int size, int measureSpec) {
15331        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
15332    }
15333
15334    /**
15335     * Utility to reconcile a desired size and state, with constraints imposed
15336     * by a MeasureSpec.  Will take the desired size, unless a different size
15337     * is imposed by the constraints.  The returned value is a compound integer,
15338     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
15339     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
15340     * size is smaller than the size the view wants to be.
15341     *
15342     * @param size How big the view wants to be
15343     * @param measureSpec Constraints imposed by the parent
15344     * @return Size information bit mask as defined by
15345     * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
15346     */
15347    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
15348        int result = size;
15349        int specMode = MeasureSpec.getMode(measureSpec);
15350        int specSize =  MeasureSpec.getSize(measureSpec);
15351        switch (specMode) {
15352        case MeasureSpec.UNSPECIFIED:
15353            result = size;
15354            break;
15355        case MeasureSpec.AT_MOST:
15356            if (specSize < size) {
15357                result = specSize | MEASURED_STATE_TOO_SMALL;
15358            } else {
15359                result = size;
15360            }
15361            break;
15362        case MeasureSpec.EXACTLY:
15363            result = specSize;
15364            break;
15365        }
15366        return result | (childMeasuredState&MEASURED_STATE_MASK);
15367    }
15368
15369    /**
15370     * Utility to return a default size. Uses the supplied size if the
15371     * MeasureSpec imposed no constraints. Will get larger if allowed
15372     * by the MeasureSpec.
15373     *
15374     * @param size Default size for this view
15375     * @param measureSpec Constraints imposed by the parent
15376     * @return The size this view should be.
15377     */
15378    public static int getDefaultSize(int size, int measureSpec) {
15379        int result = size;
15380        int specMode = MeasureSpec.getMode(measureSpec);
15381        int specSize = MeasureSpec.getSize(measureSpec);
15382
15383        switch (specMode) {
15384        case MeasureSpec.UNSPECIFIED:
15385            result = size;
15386            break;
15387        case MeasureSpec.AT_MOST:
15388        case MeasureSpec.EXACTLY:
15389            result = specSize;
15390            break;
15391        }
15392        return result;
15393    }
15394
15395    /**
15396     * Returns the suggested minimum height that the view should use. This
15397     * returns the maximum of the view's minimum height
15398     * and the background's minimum height
15399     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
15400     * <p>
15401     * When being used in {@link #onMeasure(int, int)}, the caller should still
15402     * ensure the returned height is within the requirements of the parent.
15403     *
15404     * @return The suggested minimum height of the view.
15405     */
15406    protected int getSuggestedMinimumHeight() {
15407        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
15408
15409    }
15410
15411    /**
15412     * Returns the suggested minimum width that the view should use. This
15413     * returns the maximum of the view's minimum width)
15414     * and the background's minimum width
15415     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
15416     * <p>
15417     * When being used in {@link #onMeasure(int, int)}, the caller should still
15418     * ensure the returned width is within the requirements of the parent.
15419     *
15420     * @return The suggested minimum width of the view.
15421     */
15422    protected int getSuggestedMinimumWidth() {
15423        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
15424    }
15425
15426    /**
15427     * Returns the minimum height of the view.
15428     *
15429     * @return the minimum height the view will try to be.
15430     *
15431     * @see #setMinimumHeight(int)
15432     *
15433     * @attr ref android.R.styleable#View_minHeight
15434     */
15435    public int getMinimumHeight() {
15436        return mMinHeight;
15437    }
15438
15439    /**
15440     * Sets the minimum height of the view. It is not guaranteed the view will
15441     * be able to achieve this minimum height (for example, if its parent layout
15442     * constrains it with less available height).
15443     *
15444     * @param minHeight The minimum height the view will try to be.
15445     *
15446     * @see #getMinimumHeight()
15447     *
15448     * @attr ref android.R.styleable#View_minHeight
15449     */
15450    public void setMinimumHeight(int minHeight) {
15451        mMinHeight = minHeight;
15452        requestLayout();
15453    }
15454
15455    /**
15456     * Returns the minimum width of the view.
15457     *
15458     * @return the minimum width the view will try to be.
15459     *
15460     * @see #setMinimumWidth(int)
15461     *
15462     * @attr ref android.R.styleable#View_minWidth
15463     */
15464    public int getMinimumWidth() {
15465        return mMinWidth;
15466    }
15467
15468    /**
15469     * Sets the minimum width of the view. It is not guaranteed the view will
15470     * be able to achieve this minimum width (for example, if its parent layout
15471     * constrains it with less available width).
15472     *
15473     * @param minWidth The minimum width the view will try to be.
15474     *
15475     * @see #getMinimumWidth()
15476     *
15477     * @attr ref android.R.styleable#View_minWidth
15478     */
15479    public void setMinimumWidth(int minWidth) {
15480        mMinWidth = minWidth;
15481        requestLayout();
15482
15483    }
15484
15485    /**
15486     * Get the animation currently associated with this view.
15487     *
15488     * @return The animation that is currently playing or
15489     *         scheduled to play for this view.
15490     */
15491    public Animation getAnimation() {
15492        return mCurrentAnimation;
15493    }
15494
15495    /**
15496     * Start the specified animation now.
15497     *
15498     * @param animation the animation to start now
15499     */
15500    public void startAnimation(Animation animation) {
15501        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
15502        setAnimation(animation);
15503        invalidateParentCaches();
15504        invalidate(true);
15505    }
15506
15507    /**
15508     * Cancels any animations for this view.
15509     */
15510    public void clearAnimation() {
15511        if (mCurrentAnimation != null) {
15512            mCurrentAnimation.detach();
15513        }
15514        mCurrentAnimation = null;
15515        invalidateParentIfNeeded();
15516    }
15517
15518    /**
15519     * Sets the next animation to play for this view.
15520     * If you want the animation to play immediately, use
15521     * {@link #startAnimation(android.view.animation.Animation)} instead.
15522     * This method provides allows fine-grained
15523     * control over the start time and invalidation, but you
15524     * must make sure that 1) the animation has a start time set, and
15525     * 2) the view's parent (which controls animations on its children)
15526     * will be invalidated when the animation is supposed to
15527     * start.
15528     *
15529     * @param animation The next animation, or null.
15530     */
15531    public void setAnimation(Animation animation) {
15532        mCurrentAnimation = animation;
15533
15534        if (animation != null) {
15535            // If the screen is off assume the animation start time is now instead of
15536            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
15537            // would cause the animation to start when the screen turns back on
15538            if (mAttachInfo != null && !mAttachInfo.mScreenOn &&
15539                    animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
15540                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
15541            }
15542            animation.reset();
15543        }
15544    }
15545
15546    /**
15547     * Invoked by a parent ViewGroup to notify the start of the animation
15548     * currently associated with this view. If you override this method,
15549     * always call super.onAnimationStart();
15550     *
15551     * @see #setAnimation(android.view.animation.Animation)
15552     * @see #getAnimation()
15553     */
15554    protected void onAnimationStart() {
15555        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
15556    }
15557
15558    /**
15559     * Invoked by a parent ViewGroup to notify the end of the animation
15560     * currently associated with this view. If you override this method,
15561     * always call super.onAnimationEnd();
15562     *
15563     * @see #setAnimation(android.view.animation.Animation)
15564     * @see #getAnimation()
15565     */
15566    protected void onAnimationEnd() {
15567        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
15568    }
15569
15570    /**
15571     * Invoked if there is a Transform that involves alpha. Subclass that can
15572     * draw themselves with the specified alpha should return true, and then
15573     * respect that alpha when their onDraw() is called. If this returns false
15574     * then the view may be redirected to draw into an offscreen buffer to
15575     * fulfill the request, which will look fine, but may be slower than if the
15576     * subclass handles it internally. The default implementation returns false.
15577     *
15578     * @param alpha The alpha (0..255) to apply to the view's drawing
15579     * @return true if the view can draw with the specified alpha.
15580     */
15581    protected boolean onSetAlpha(int alpha) {
15582        return false;
15583    }
15584
15585    /**
15586     * This is used by the RootView to perform an optimization when
15587     * the view hierarchy contains one or several SurfaceView.
15588     * SurfaceView is always considered transparent, but its children are not,
15589     * therefore all View objects remove themselves from the global transparent
15590     * region (passed as a parameter to this function).
15591     *
15592     * @param region The transparent region for this ViewAncestor (window).
15593     *
15594     * @return Returns true if the effective visibility of the view at this
15595     * point is opaque, regardless of the transparent region; returns false
15596     * if it is possible for underlying windows to be seen behind the view.
15597     *
15598     * {@hide}
15599     */
15600    public boolean gatherTransparentRegion(Region region) {
15601        final AttachInfo attachInfo = mAttachInfo;
15602        if (region != null && attachInfo != null) {
15603            final int pflags = mPrivateFlags;
15604            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
15605                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
15606                // remove it from the transparent region.
15607                final int[] location = attachInfo.mTransparentLocation;
15608                getLocationInWindow(location);
15609                region.op(location[0], location[1], location[0] + mRight - mLeft,
15610                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
15611            } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
15612                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
15613                // exists, so we remove the background drawable's non-transparent
15614                // parts from this transparent region.
15615                applyDrawableToTransparentRegion(mBackground, region);
15616            }
15617        }
15618        return true;
15619    }
15620
15621    /**
15622     * Play a sound effect for this view.
15623     *
15624     * <p>The framework will play sound effects for some built in actions, such as
15625     * clicking, but you may wish to play these effects in your widget,
15626     * for instance, for internal navigation.
15627     *
15628     * <p>The sound effect will only be played if sound effects are enabled by the user, and
15629     * {@link #isSoundEffectsEnabled()} is true.
15630     *
15631     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
15632     */
15633    public void playSoundEffect(int soundConstant) {
15634        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
15635            return;
15636        }
15637        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
15638    }
15639
15640    /**
15641     * BZZZTT!!1!
15642     *
15643     * <p>Provide haptic feedback to the user for this view.
15644     *
15645     * <p>The framework will provide haptic feedback for some built in actions,
15646     * such as long presses, but you may wish to provide feedback for your
15647     * own widget.
15648     *
15649     * <p>The feedback will only be performed if
15650     * {@link #isHapticFeedbackEnabled()} is true.
15651     *
15652     * @param feedbackConstant One of the constants defined in
15653     * {@link HapticFeedbackConstants}
15654     */
15655    public boolean performHapticFeedback(int feedbackConstant) {
15656        return performHapticFeedback(feedbackConstant, 0);
15657    }
15658
15659    /**
15660     * BZZZTT!!1!
15661     *
15662     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
15663     *
15664     * @param feedbackConstant One of the constants defined in
15665     * {@link HapticFeedbackConstants}
15666     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
15667     */
15668    public boolean performHapticFeedback(int feedbackConstant, int flags) {
15669        if (mAttachInfo == null) {
15670            return false;
15671        }
15672        //noinspection SimplifiableIfStatement
15673        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
15674                && !isHapticFeedbackEnabled()) {
15675            return false;
15676        }
15677        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
15678                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
15679    }
15680
15681    /**
15682     * Request that the visibility of the status bar or other screen/window
15683     * decorations be changed.
15684     *
15685     * <p>This method is used to put the over device UI into temporary modes
15686     * where the user's attention is focused more on the application content,
15687     * by dimming or hiding surrounding system affordances.  This is typically
15688     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
15689     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
15690     * to be placed behind the action bar (and with these flags other system
15691     * affordances) so that smooth transitions between hiding and showing them
15692     * can be done.
15693     *
15694     * <p>Two representative examples of the use of system UI visibility is
15695     * implementing a content browsing application (like a magazine reader)
15696     * and a video playing application.
15697     *
15698     * <p>The first code shows a typical implementation of a View in a content
15699     * browsing application.  In this implementation, the application goes
15700     * into a content-oriented mode by hiding the status bar and action bar,
15701     * and putting the navigation elements into lights out mode.  The user can
15702     * then interact with content while in this mode.  Such an application should
15703     * provide an easy way for the user to toggle out of the mode (such as to
15704     * check information in the status bar or access notifications).  In the
15705     * implementation here, this is done simply by tapping on the content.
15706     *
15707     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
15708     *      content}
15709     *
15710     * <p>This second code sample shows a typical implementation of a View
15711     * in a video playing application.  In this situation, while the video is
15712     * playing the application would like to go into a complete full-screen mode,
15713     * to use as much of the display as possible for the video.  When in this state
15714     * the user can not interact with the application; the system intercepts
15715     * touching on the screen to pop the UI out of full screen mode.  See
15716     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
15717     *
15718     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
15719     *      content}
15720     *
15721     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
15722     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
15723     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
15724     * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
15725     */
15726    public void setSystemUiVisibility(int visibility) {
15727        if (visibility != mSystemUiVisibility) {
15728            mSystemUiVisibility = visibility;
15729            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
15730                mParent.recomputeViewAttributes(this);
15731            }
15732        }
15733    }
15734
15735    /**
15736     * Returns the last {@link #setSystemUiVisibility(int) that this view has requested.
15737     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
15738     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
15739     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
15740     * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
15741     */
15742    public int getSystemUiVisibility() {
15743        return mSystemUiVisibility;
15744    }
15745
15746    /**
15747     * Returns the current system UI visibility that is currently set for
15748     * the entire window.  This is the combination of the
15749     * {@link #setSystemUiVisibility(int)} values supplied by all of the
15750     * views in the window.
15751     */
15752    public int getWindowSystemUiVisibility() {
15753        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
15754    }
15755
15756    /**
15757     * Override to find out when the window's requested system UI visibility
15758     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
15759     * This is different from the callbacks recieved through
15760     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
15761     * in that this is only telling you about the local request of the window,
15762     * not the actual values applied by the system.
15763     */
15764    public void onWindowSystemUiVisibilityChanged(int visible) {
15765    }
15766
15767    /**
15768     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
15769     * the view hierarchy.
15770     */
15771    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
15772        onWindowSystemUiVisibilityChanged(visible);
15773    }
15774
15775    /**
15776     * Set a listener to receive callbacks when the visibility of the system bar changes.
15777     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
15778     */
15779    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
15780        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
15781        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
15782            mParent.recomputeViewAttributes(this);
15783        }
15784    }
15785
15786    /**
15787     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
15788     * the view hierarchy.
15789     */
15790    public void dispatchSystemUiVisibilityChanged(int visibility) {
15791        ListenerInfo li = mListenerInfo;
15792        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
15793            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
15794                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
15795        }
15796    }
15797
15798    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
15799        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
15800        if (val != mSystemUiVisibility) {
15801            setSystemUiVisibility(val);
15802            return true;
15803        }
15804        return false;
15805    }
15806
15807    /** @hide */
15808    public void setDisabledSystemUiVisibility(int flags) {
15809        if (mAttachInfo != null) {
15810            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
15811                mAttachInfo.mDisabledSystemUiVisibility = flags;
15812                if (mParent != null) {
15813                    mParent.recomputeViewAttributes(this);
15814                }
15815            }
15816        }
15817    }
15818
15819    /**
15820     * Creates an image that the system displays during the drag and drop
15821     * operation. This is called a &quot;drag shadow&quot;. The default implementation
15822     * for a DragShadowBuilder based on a View returns an image that has exactly the same
15823     * appearance as the given View. The default also positions the center of the drag shadow
15824     * directly under the touch point. If no View is provided (the constructor with no parameters
15825     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
15826     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
15827     * default is an invisible drag shadow.
15828     * <p>
15829     * You are not required to use the View you provide to the constructor as the basis of the
15830     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
15831     * anything you want as the drag shadow.
15832     * </p>
15833     * <p>
15834     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
15835     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
15836     *  size and position of the drag shadow. It uses this data to construct a
15837     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
15838     *  so that your application can draw the shadow image in the Canvas.
15839     * </p>
15840     *
15841     * <div class="special reference">
15842     * <h3>Developer Guides</h3>
15843     * <p>For a guide to implementing drag and drop features, read the
15844     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
15845     * </div>
15846     */
15847    public static class DragShadowBuilder {
15848        private final WeakReference<View> mView;
15849
15850        /**
15851         * Constructs a shadow image builder based on a View. By default, the resulting drag
15852         * shadow will have the same appearance and dimensions as the View, with the touch point
15853         * over the center of the View.
15854         * @param view A View. Any View in scope can be used.
15855         */
15856        public DragShadowBuilder(View view) {
15857            mView = new WeakReference<View>(view);
15858        }
15859
15860        /**
15861         * Construct a shadow builder object with no associated View.  This
15862         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
15863         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
15864         * to supply the drag shadow's dimensions and appearance without
15865         * reference to any View object. If they are not overridden, then the result is an
15866         * invisible drag shadow.
15867         */
15868        public DragShadowBuilder() {
15869            mView = new WeakReference<View>(null);
15870        }
15871
15872        /**
15873         * Returns the View object that had been passed to the
15874         * {@link #View.DragShadowBuilder(View)}
15875         * constructor.  If that View parameter was {@code null} or if the
15876         * {@link #View.DragShadowBuilder()}
15877         * constructor was used to instantiate the builder object, this method will return
15878         * null.
15879         *
15880         * @return The View object associate with this builder object.
15881         */
15882        @SuppressWarnings({"JavadocReference"})
15883        final public View getView() {
15884            return mView.get();
15885        }
15886
15887        /**
15888         * Provides the metrics for the shadow image. These include the dimensions of
15889         * the shadow image, and the point within that shadow that should
15890         * be centered under the touch location while dragging.
15891         * <p>
15892         * The default implementation sets the dimensions of the shadow to be the
15893         * same as the dimensions of the View itself and centers the shadow under
15894         * the touch point.
15895         * </p>
15896         *
15897         * @param shadowSize A {@link android.graphics.Point} containing the width and height
15898         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
15899         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
15900         * image.
15901         *
15902         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
15903         * shadow image that should be underneath the touch point during the drag and drop
15904         * operation. Your application must set {@link android.graphics.Point#x} to the
15905         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
15906         */
15907        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
15908            final View view = mView.get();
15909            if (view != null) {
15910                shadowSize.set(view.getWidth(), view.getHeight());
15911                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
15912            } else {
15913                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
15914            }
15915        }
15916
15917        /**
15918         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
15919         * based on the dimensions it received from the
15920         * {@link #onProvideShadowMetrics(Point, Point)} callback.
15921         *
15922         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
15923         */
15924        public void onDrawShadow(Canvas canvas) {
15925            final View view = mView.get();
15926            if (view != null) {
15927                view.draw(canvas);
15928            } else {
15929                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
15930            }
15931        }
15932    }
15933
15934    /**
15935     * Starts a drag and drop operation. When your application calls this method, it passes a
15936     * {@link android.view.View.DragShadowBuilder} object to the system. The
15937     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
15938     * to get metrics for the drag shadow, and then calls the object's
15939     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
15940     * <p>
15941     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
15942     *  drag events to all the View objects in your application that are currently visible. It does
15943     *  this either by calling the View object's drag listener (an implementation of
15944     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
15945     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
15946     *  Both are passed a {@link android.view.DragEvent} object that has a
15947     *  {@link android.view.DragEvent#getAction()} value of
15948     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
15949     * </p>
15950     * <p>
15951     * Your application can invoke startDrag() on any attached View object. The View object does not
15952     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
15953     * be related to the View the user selected for dragging.
15954     * </p>
15955     * @param data A {@link android.content.ClipData} object pointing to the data to be
15956     * transferred by the drag and drop operation.
15957     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
15958     * drag shadow.
15959     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
15960     * drop operation. This Object is put into every DragEvent object sent by the system during the
15961     * current drag.
15962     * <p>
15963     * myLocalState is a lightweight mechanism for the sending information from the dragged View
15964     * to the target Views. For example, it can contain flags that differentiate between a
15965     * a copy operation and a move operation.
15966     * </p>
15967     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
15968     * so the parameter should be set to 0.
15969     * @return {@code true} if the method completes successfully, or
15970     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
15971     * do a drag, and so no drag operation is in progress.
15972     */
15973    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
15974            Object myLocalState, int flags) {
15975        if (ViewDebug.DEBUG_DRAG) {
15976            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
15977        }
15978        boolean okay = false;
15979
15980        Point shadowSize = new Point();
15981        Point shadowTouchPoint = new Point();
15982        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
15983
15984        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
15985                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
15986            throw new IllegalStateException("Drag shadow dimensions must not be negative");
15987        }
15988
15989        if (ViewDebug.DEBUG_DRAG) {
15990            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
15991                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
15992        }
15993        Surface surface = new Surface();
15994        try {
15995            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
15996                    flags, shadowSize.x, shadowSize.y, surface);
15997            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
15998                    + " surface=" + surface);
15999            if (token != null) {
16000                Canvas canvas = surface.lockCanvas(null);
16001                try {
16002                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
16003                    shadowBuilder.onDrawShadow(canvas);
16004                } finally {
16005                    surface.unlockCanvasAndPost(canvas);
16006                }
16007
16008                final ViewRootImpl root = getViewRootImpl();
16009
16010                // Cache the local state object for delivery with DragEvents
16011                root.setLocalDragState(myLocalState);
16012
16013                // repurpose 'shadowSize' for the last touch point
16014                root.getLastTouchPoint(shadowSize);
16015
16016                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
16017                        shadowSize.x, shadowSize.y,
16018                        shadowTouchPoint.x, shadowTouchPoint.y, data);
16019                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
16020
16021                // Off and running!  Release our local surface instance; the drag
16022                // shadow surface is now managed by the system process.
16023                surface.release();
16024            }
16025        } catch (Exception e) {
16026            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
16027            surface.destroy();
16028        }
16029
16030        return okay;
16031    }
16032
16033    /**
16034     * Handles drag events sent by the system following a call to
16035     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
16036     *<p>
16037     * When the system calls this method, it passes a
16038     * {@link android.view.DragEvent} object. A call to
16039     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
16040     * in DragEvent. The method uses these to determine what is happening in the drag and drop
16041     * operation.
16042     * @param event The {@link android.view.DragEvent} sent by the system.
16043     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
16044     * in DragEvent, indicating the type of drag event represented by this object.
16045     * @return {@code true} if the method was successful, otherwise {@code false}.
16046     * <p>
16047     *  The method should return {@code true} in response to an action type of
16048     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
16049     *  operation.
16050     * </p>
16051     * <p>
16052     *  The method should also return {@code true} in response to an action type of
16053     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
16054     *  {@code false} if it didn't.
16055     * </p>
16056     */
16057    public boolean onDragEvent(DragEvent event) {
16058        return false;
16059    }
16060
16061    /**
16062     * Detects if this View is enabled and has a drag event listener.
16063     * If both are true, then it calls the drag event listener with the
16064     * {@link android.view.DragEvent} it received. If the drag event listener returns
16065     * {@code true}, then dispatchDragEvent() returns {@code true}.
16066     * <p>
16067     * For all other cases, the method calls the
16068     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
16069     * method and returns its result.
16070     * </p>
16071     * <p>
16072     * This ensures that a drag event is always consumed, even if the View does not have a drag
16073     * event listener. However, if the View has a listener and the listener returns true, then
16074     * onDragEvent() is not called.
16075     * </p>
16076     */
16077    public boolean dispatchDragEvent(DragEvent event) {
16078        //noinspection SimplifiableIfStatement
16079        ListenerInfo li = mListenerInfo;
16080        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
16081                && li.mOnDragListener.onDrag(this, event)) {
16082            return true;
16083        }
16084        return onDragEvent(event);
16085    }
16086
16087    boolean canAcceptDrag() {
16088        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
16089    }
16090
16091    /**
16092     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
16093     * it is ever exposed at all.
16094     * @hide
16095     */
16096    public void onCloseSystemDialogs(String reason) {
16097    }
16098
16099    /**
16100     * Given a Drawable whose bounds have been set to draw into this view,
16101     * update a Region being computed for
16102     * {@link #gatherTransparentRegion(android.graphics.Region)} so
16103     * that any non-transparent parts of the Drawable are removed from the
16104     * given transparent region.
16105     *
16106     * @param dr The Drawable whose transparency is to be applied to the region.
16107     * @param region A Region holding the current transparency information,
16108     * where any parts of the region that are set are considered to be
16109     * transparent.  On return, this region will be modified to have the
16110     * transparency information reduced by the corresponding parts of the
16111     * Drawable that are not transparent.
16112     * {@hide}
16113     */
16114    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
16115        if (DBG) {
16116            Log.i("View", "Getting transparent region for: " + this);
16117        }
16118        final Region r = dr.getTransparentRegion();
16119        final Rect db = dr.getBounds();
16120        final AttachInfo attachInfo = mAttachInfo;
16121        if (r != null && attachInfo != null) {
16122            final int w = getRight()-getLeft();
16123            final int h = getBottom()-getTop();
16124            if (db.left > 0) {
16125                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
16126                r.op(0, 0, db.left, h, Region.Op.UNION);
16127            }
16128            if (db.right < w) {
16129                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
16130                r.op(db.right, 0, w, h, Region.Op.UNION);
16131            }
16132            if (db.top > 0) {
16133                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
16134                r.op(0, 0, w, db.top, Region.Op.UNION);
16135            }
16136            if (db.bottom < h) {
16137                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
16138                r.op(0, db.bottom, w, h, Region.Op.UNION);
16139            }
16140            final int[] location = attachInfo.mTransparentLocation;
16141            getLocationInWindow(location);
16142            r.translate(location[0], location[1]);
16143            region.op(r, Region.Op.INTERSECT);
16144        } else {
16145            region.op(db, Region.Op.DIFFERENCE);
16146        }
16147    }
16148
16149    private void checkForLongClick(int delayOffset) {
16150        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
16151            mHasPerformedLongPress = false;
16152
16153            if (mPendingCheckForLongPress == null) {
16154                mPendingCheckForLongPress = new CheckForLongPress();
16155            }
16156            mPendingCheckForLongPress.rememberWindowAttachCount();
16157            postDelayed(mPendingCheckForLongPress,
16158                    ViewConfiguration.getLongPressTimeout() - delayOffset);
16159        }
16160    }
16161
16162    /**
16163     * Inflate a view from an XML resource.  This convenience method wraps the {@link
16164     * LayoutInflater} class, which provides a full range of options for view inflation.
16165     *
16166     * @param context The Context object for your activity or application.
16167     * @param resource The resource ID to inflate
16168     * @param root A view group that will be the parent.  Used to properly inflate the
16169     * layout_* parameters.
16170     * @see LayoutInflater
16171     */
16172    public static View inflate(Context context, int resource, ViewGroup root) {
16173        LayoutInflater factory = LayoutInflater.from(context);
16174        return factory.inflate(resource, root);
16175    }
16176
16177    /**
16178     * Scroll the view with standard behavior for scrolling beyond the normal
16179     * content boundaries. Views that call this method should override
16180     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
16181     * results of an over-scroll operation.
16182     *
16183     * Views can use this method to handle any touch or fling-based scrolling.
16184     *
16185     * @param deltaX Change in X in pixels
16186     * @param deltaY Change in Y in pixels
16187     * @param scrollX Current X scroll value in pixels before applying deltaX
16188     * @param scrollY Current Y scroll value in pixels before applying deltaY
16189     * @param scrollRangeX Maximum content scroll range along the X axis
16190     * @param scrollRangeY Maximum content scroll range along the Y axis
16191     * @param maxOverScrollX Number of pixels to overscroll by in either direction
16192     *          along the X axis.
16193     * @param maxOverScrollY Number of pixels to overscroll by in either direction
16194     *          along the Y axis.
16195     * @param isTouchEvent true if this scroll operation is the result of a touch event.
16196     * @return true if scrolling was clamped to an over-scroll boundary along either
16197     *          axis, false otherwise.
16198     */
16199    @SuppressWarnings({"UnusedParameters"})
16200    protected boolean overScrollBy(int deltaX, int deltaY,
16201            int scrollX, int scrollY,
16202            int scrollRangeX, int scrollRangeY,
16203            int maxOverScrollX, int maxOverScrollY,
16204            boolean isTouchEvent) {
16205        final int overScrollMode = mOverScrollMode;
16206        final boolean canScrollHorizontal =
16207                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
16208        final boolean canScrollVertical =
16209                computeVerticalScrollRange() > computeVerticalScrollExtent();
16210        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
16211                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
16212        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
16213                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
16214
16215        int newScrollX = scrollX + deltaX;
16216        if (!overScrollHorizontal) {
16217            maxOverScrollX = 0;
16218        }
16219
16220        int newScrollY = scrollY + deltaY;
16221        if (!overScrollVertical) {
16222            maxOverScrollY = 0;
16223        }
16224
16225        // Clamp values if at the limits and record
16226        final int left = -maxOverScrollX;
16227        final int right = maxOverScrollX + scrollRangeX;
16228        final int top = -maxOverScrollY;
16229        final int bottom = maxOverScrollY + scrollRangeY;
16230
16231        boolean clampedX = false;
16232        if (newScrollX > right) {
16233            newScrollX = right;
16234            clampedX = true;
16235        } else if (newScrollX < left) {
16236            newScrollX = left;
16237            clampedX = true;
16238        }
16239
16240        boolean clampedY = false;
16241        if (newScrollY > bottom) {
16242            newScrollY = bottom;
16243            clampedY = true;
16244        } else if (newScrollY < top) {
16245            newScrollY = top;
16246            clampedY = true;
16247        }
16248
16249        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
16250
16251        return clampedX || clampedY;
16252    }
16253
16254    /**
16255     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
16256     * respond to the results of an over-scroll operation.
16257     *
16258     * @param scrollX New X scroll value in pixels
16259     * @param scrollY New Y scroll value in pixels
16260     * @param clampedX True if scrollX was clamped to an over-scroll boundary
16261     * @param clampedY True if scrollY was clamped to an over-scroll boundary
16262     */
16263    protected void onOverScrolled(int scrollX, int scrollY,
16264            boolean clampedX, boolean clampedY) {
16265        // Intentionally empty.
16266    }
16267
16268    /**
16269     * Returns the over-scroll mode for this view. The result will be
16270     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16271     * (allow over-scrolling only if the view content is larger than the container),
16272     * or {@link #OVER_SCROLL_NEVER}.
16273     *
16274     * @return This view's over-scroll mode.
16275     */
16276    public int getOverScrollMode() {
16277        return mOverScrollMode;
16278    }
16279
16280    /**
16281     * Set the over-scroll mode for this view. Valid over-scroll modes are
16282     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16283     * (allow over-scrolling only if the view content is larger than the container),
16284     * or {@link #OVER_SCROLL_NEVER}.
16285     *
16286     * Setting the over-scroll mode of a view will have an effect only if the
16287     * view is capable of scrolling.
16288     *
16289     * @param overScrollMode The new over-scroll mode for this view.
16290     */
16291    public void setOverScrollMode(int overScrollMode) {
16292        if (overScrollMode != OVER_SCROLL_ALWAYS &&
16293                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
16294                overScrollMode != OVER_SCROLL_NEVER) {
16295            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
16296        }
16297        mOverScrollMode = overScrollMode;
16298    }
16299
16300    /**
16301     * Gets a scale factor that determines the distance the view should scroll
16302     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
16303     * @return The vertical scroll scale factor.
16304     * @hide
16305     */
16306    protected float getVerticalScrollFactor() {
16307        if (mVerticalScrollFactor == 0) {
16308            TypedValue outValue = new TypedValue();
16309            if (!mContext.getTheme().resolveAttribute(
16310                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
16311                throw new IllegalStateException(
16312                        "Expected theme to define listPreferredItemHeight.");
16313            }
16314            mVerticalScrollFactor = outValue.getDimension(
16315                    mContext.getResources().getDisplayMetrics());
16316        }
16317        return mVerticalScrollFactor;
16318    }
16319
16320    /**
16321     * Gets a scale factor that determines the distance the view should scroll
16322     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
16323     * @return The horizontal scroll scale factor.
16324     * @hide
16325     */
16326    protected float getHorizontalScrollFactor() {
16327        // TODO: Should use something else.
16328        return getVerticalScrollFactor();
16329    }
16330
16331    /**
16332     * Return the value specifying the text direction or policy that was set with
16333     * {@link #setTextDirection(int)}.
16334     *
16335     * @return the defined text direction. It can be one of:
16336     *
16337     * {@link #TEXT_DIRECTION_INHERIT},
16338     * {@link #TEXT_DIRECTION_FIRST_STRONG}
16339     * {@link #TEXT_DIRECTION_ANY_RTL},
16340     * {@link #TEXT_DIRECTION_LTR},
16341     * {@link #TEXT_DIRECTION_RTL},
16342     * {@link #TEXT_DIRECTION_LOCALE}
16343     */
16344    @ViewDebug.ExportedProperty(category = "text", mapping = {
16345            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
16346            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
16347            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
16348            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
16349            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
16350            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
16351    })
16352    public int getTextDirection() {
16353        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
16354    }
16355
16356    /**
16357     * Set the text direction.
16358     *
16359     * @param textDirection the direction to set. Should be one of:
16360     *
16361     * {@link #TEXT_DIRECTION_INHERIT},
16362     * {@link #TEXT_DIRECTION_FIRST_STRONG}
16363     * {@link #TEXT_DIRECTION_ANY_RTL},
16364     * {@link #TEXT_DIRECTION_LTR},
16365     * {@link #TEXT_DIRECTION_RTL},
16366     * {@link #TEXT_DIRECTION_LOCALE}
16367     */
16368    public void setTextDirection(int textDirection) {
16369        if (getTextDirection() != textDirection) {
16370            // Reset the current text direction and the resolved one
16371            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
16372            resetResolvedTextDirection();
16373            // Set the new text direction
16374            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
16375            // Refresh
16376            requestLayout();
16377            invalidate(true);
16378        }
16379    }
16380
16381    /**
16382     * Return the resolved text direction.
16383     *
16384     * This needs resolution if the value is TEXT_DIRECTION_INHERIT. The resolution matches
16385     * {@link #getTextDirection()}if it is not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds
16386     * up the parent chain of the view. if there is no parent, then it will return the default
16387     * {@link #TEXT_DIRECTION_FIRST_STRONG}.
16388     *
16389     * @return the resolved text direction. Returns one of:
16390     *
16391     * {@link #TEXT_DIRECTION_FIRST_STRONG}
16392     * {@link #TEXT_DIRECTION_ANY_RTL},
16393     * {@link #TEXT_DIRECTION_LTR},
16394     * {@link #TEXT_DIRECTION_RTL},
16395     * {@link #TEXT_DIRECTION_LOCALE}
16396     */
16397    public int getResolvedTextDirection() {
16398        // The text direction will be resolved only if needed
16399        if ((mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) != PFLAG2_TEXT_DIRECTION_RESOLVED) {
16400            resolveTextDirection();
16401        }
16402        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
16403    }
16404
16405    /**
16406     * Resolve the text direction. Will call {@link View#onResolvedTextDirectionChanged} when
16407     * resolution is done.
16408     */
16409    public void resolveTextDirection() {
16410        // Reset any previous text direction resolution
16411        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
16412
16413        if (hasRtlSupport()) {
16414            // Set resolved text direction flag depending on text direction flag
16415            final int textDirection = getTextDirection();
16416            switch(textDirection) {
16417                case TEXT_DIRECTION_INHERIT:
16418                    if (canResolveTextDirection()) {
16419                        ViewGroup viewGroup = ((ViewGroup) mParent);
16420
16421                        // Set current resolved direction to the same value as the parent's one
16422                        final int parentResolvedDirection = viewGroup.getResolvedTextDirection();
16423                        switch (parentResolvedDirection) {
16424                            case TEXT_DIRECTION_FIRST_STRONG:
16425                            case TEXT_DIRECTION_ANY_RTL:
16426                            case TEXT_DIRECTION_LTR:
16427                            case TEXT_DIRECTION_RTL:
16428                            case TEXT_DIRECTION_LOCALE:
16429                                mPrivateFlags2 |=
16430                                        (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
16431                                break;
16432                            default:
16433                                // Default resolved direction is "first strong" heuristic
16434                                mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16435                        }
16436                    } else {
16437                        // We cannot do the resolution if there is no parent, so use the default one
16438                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16439                    }
16440                    break;
16441                case TEXT_DIRECTION_FIRST_STRONG:
16442                case TEXT_DIRECTION_ANY_RTL:
16443                case TEXT_DIRECTION_LTR:
16444                case TEXT_DIRECTION_RTL:
16445                case TEXT_DIRECTION_LOCALE:
16446                    // Resolved direction is the same as text direction
16447                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
16448                    break;
16449                default:
16450                    // Default resolved direction is "first strong" heuristic
16451                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16452            }
16453        } else {
16454            // Default resolved direction is "first strong" heuristic
16455            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
16456        }
16457
16458        // Set to resolved
16459        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
16460        onResolvedTextDirectionChanged();
16461    }
16462
16463    /**
16464     * Called when text direction has been resolved. Subclasses that care about text direction
16465     * resolution should override this method.
16466     *
16467     * The default implementation does nothing.
16468     */
16469    public void onResolvedTextDirectionChanged() {
16470    }
16471
16472    /**
16473     * Check if text direction resolution can be done.
16474     *
16475     * @return true if text direction resolution can be done otherwise return false.
16476     */
16477    public boolean canResolveTextDirection() {
16478        switch (getTextDirection()) {
16479            case TEXT_DIRECTION_INHERIT:
16480                return (mParent != null) && (mParent instanceof ViewGroup);
16481            default:
16482                return true;
16483        }
16484    }
16485
16486    /**
16487     * Reset resolved text direction. Text direction can be resolved with a call to
16488     * getResolvedTextDirection(). Will call {@link View#onResolvedTextDirectionReset} when
16489     * reset is done.
16490     */
16491    public void resetResolvedTextDirection() {
16492        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
16493        onResolvedTextDirectionReset();
16494    }
16495
16496    /**
16497     * Called when text direction is reset. Subclasses that care about text direction reset should
16498     * override this method and do a reset of the text direction of their children. The default
16499     * implementation does nothing.
16500     */
16501    public void onResolvedTextDirectionReset() {
16502    }
16503
16504    /**
16505     * Return the value specifying the text alignment or policy that was set with
16506     * {@link #setTextAlignment(int)}.
16507     *
16508     * @return the defined text alignment. It can be one of:
16509     *
16510     * {@link #TEXT_ALIGNMENT_INHERIT},
16511     * {@link #TEXT_ALIGNMENT_GRAVITY},
16512     * {@link #TEXT_ALIGNMENT_CENTER},
16513     * {@link #TEXT_ALIGNMENT_TEXT_START},
16514     * {@link #TEXT_ALIGNMENT_TEXT_END},
16515     * {@link #TEXT_ALIGNMENT_VIEW_START},
16516     * {@link #TEXT_ALIGNMENT_VIEW_END}
16517     */
16518    @ViewDebug.ExportedProperty(category = "text", mapping = {
16519            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
16520            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
16521            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
16522            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
16523            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
16524            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
16525            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
16526    })
16527    public int getTextAlignment() {
16528        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
16529    }
16530
16531    /**
16532     * Set the text alignment.
16533     *
16534     * @param textAlignment The text alignment to set. Should be one of
16535     *
16536     * {@link #TEXT_ALIGNMENT_INHERIT},
16537     * {@link #TEXT_ALIGNMENT_GRAVITY},
16538     * {@link #TEXT_ALIGNMENT_CENTER},
16539     * {@link #TEXT_ALIGNMENT_TEXT_START},
16540     * {@link #TEXT_ALIGNMENT_TEXT_END},
16541     * {@link #TEXT_ALIGNMENT_VIEW_START},
16542     * {@link #TEXT_ALIGNMENT_VIEW_END}
16543     *
16544     * @attr ref android.R.styleable#View_textAlignment
16545     */
16546    public void setTextAlignment(int textAlignment) {
16547        if (textAlignment != getTextAlignment()) {
16548            // Reset the current and resolved text alignment
16549            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
16550            resetResolvedTextAlignment();
16551            // Set the new text alignment
16552            mPrivateFlags2 |= ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
16553            // Refresh
16554            requestLayout();
16555            invalidate(true);
16556        }
16557    }
16558
16559    /**
16560     * Return the resolved text alignment.
16561     *
16562     * The resolved text alignment. This needs resolution if the value is
16563     * TEXT_ALIGNMENT_INHERIT. The resolution matches {@link #setTextAlignment(int)}  if it is
16564     * not TEXT_ALIGNMENT_INHERIT, otherwise resolution proceeds up the parent chain of the view.
16565     *
16566     * @return the resolved text alignment. Returns one of:
16567     *
16568     * {@link #TEXT_ALIGNMENT_GRAVITY},
16569     * {@link #TEXT_ALIGNMENT_CENTER},
16570     * {@link #TEXT_ALIGNMENT_TEXT_START},
16571     * {@link #TEXT_ALIGNMENT_TEXT_END},
16572     * {@link #TEXT_ALIGNMENT_VIEW_START},
16573     * {@link #TEXT_ALIGNMENT_VIEW_END}
16574     */
16575    @ViewDebug.ExportedProperty(category = "text", mapping = {
16576            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
16577            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
16578            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
16579            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
16580            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
16581            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
16582            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
16583    })
16584    public int getResolvedTextAlignment() {
16585        // If text alignment is not resolved, then resolve it
16586        if ((mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) != PFLAG2_TEXT_ALIGNMENT_RESOLVED) {
16587            resolveTextAlignment();
16588        }
16589        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >> PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
16590    }
16591
16592    /**
16593     * Resolve the text alignment. Will call {@link View#onResolvedTextAlignmentChanged} when
16594     * resolution is done.
16595     */
16596    public void resolveTextAlignment() {
16597        // Reset any previous text alignment resolution
16598        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
16599
16600        if (hasRtlSupport()) {
16601            // Set resolved text alignment flag depending on text alignment flag
16602            final int textAlignment = getTextAlignment();
16603            switch (textAlignment) {
16604                case TEXT_ALIGNMENT_INHERIT:
16605                    // Check if we can resolve the text alignment
16606                    if (canResolveLayoutDirection() && mParent instanceof View) {
16607                        View view = (View) mParent;
16608
16609                        final int parentResolvedTextAlignment = view.getResolvedTextAlignment();
16610                        switch (parentResolvedTextAlignment) {
16611                            case TEXT_ALIGNMENT_GRAVITY:
16612                            case TEXT_ALIGNMENT_TEXT_START:
16613                            case TEXT_ALIGNMENT_TEXT_END:
16614                            case TEXT_ALIGNMENT_CENTER:
16615                            case TEXT_ALIGNMENT_VIEW_START:
16616                            case TEXT_ALIGNMENT_VIEW_END:
16617                                // Resolved text alignment is the same as the parent resolved
16618                                // text alignment
16619                                mPrivateFlags2 |=
16620                                        (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
16621                                break;
16622                            default:
16623                                // Use default resolved text alignment
16624                                mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16625                        }
16626                    }
16627                    else {
16628                        // We cannot do the resolution if there is no parent so use the default
16629                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16630                    }
16631                    break;
16632                case TEXT_ALIGNMENT_GRAVITY:
16633                case TEXT_ALIGNMENT_TEXT_START:
16634                case TEXT_ALIGNMENT_TEXT_END:
16635                case TEXT_ALIGNMENT_CENTER:
16636                case TEXT_ALIGNMENT_VIEW_START:
16637                case TEXT_ALIGNMENT_VIEW_END:
16638                    // Resolved text alignment is the same as text alignment
16639                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
16640                    break;
16641                default:
16642                    // Use default resolved text alignment
16643                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16644            }
16645        } else {
16646            // Use default resolved text alignment
16647            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
16648        }
16649
16650        // Set the resolved
16651        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
16652        onResolvedTextAlignmentChanged();
16653    }
16654
16655    /**
16656     * Check if text alignment resolution can be done.
16657     *
16658     * @return true if text alignment resolution can be done otherwise return false.
16659     */
16660    public boolean canResolveTextAlignment() {
16661        switch (getTextAlignment()) {
16662            case TEXT_DIRECTION_INHERIT:
16663                return (mParent != null);
16664            default:
16665                return true;
16666        }
16667    }
16668
16669    /**
16670     * Called when text alignment has been resolved. Subclasses that care about text alignment
16671     * resolution should override this method.
16672     *
16673     * The default implementation does nothing.
16674     */
16675    public void onResolvedTextAlignmentChanged() {
16676    }
16677
16678    /**
16679     * Reset resolved text alignment. Text alignment can be resolved with a call to
16680     * getResolvedTextAlignment(). Will call {@link View#onResolvedTextAlignmentReset} when
16681     * reset is done.
16682     */
16683    public void resetResolvedTextAlignment() {
16684        // Reset any previous text alignment resolution
16685        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
16686        onResolvedTextAlignmentReset();
16687    }
16688
16689    /**
16690     * Called when text alignment is reset. Subclasses that care about text alignment reset should
16691     * override this method and do a reset of the text alignment of their children. The default
16692     * implementation does nothing.
16693     */
16694    public void onResolvedTextAlignmentReset() {
16695    }
16696
16697    /**
16698     * Generate a value suitable for use in {@link #setId(int)}.
16699     * This value will not collide with ID values generated at build time by aapt for R.id.
16700     *
16701     * @return a generated ID value
16702     */
16703    public static int generateViewId() {
16704        for (;;) {
16705            final int result = sNextGeneratedId.get();
16706            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
16707            int newValue = result + 1;
16708            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
16709            if (sNextGeneratedId.compareAndSet(result, newValue)) {
16710                return result;
16711            }
16712        }
16713    }
16714
16715    //
16716    // Properties
16717    //
16718    /**
16719     * A Property wrapper around the <code>alpha</code> functionality handled by the
16720     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
16721     */
16722    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
16723        @Override
16724        public void setValue(View object, float value) {
16725            object.setAlpha(value);
16726        }
16727
16728        @Override
16729        public Float get(View object) {
16730            return object.getAlpha();
16731        }
16732    };
16733
16734    /**
16735     * A Property wrapper around the <code>translationX</code> functionality handled by the
16736     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
16737     */
16738    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
16739        @Override
16740        public void setValue(View object, float value) {
16741            object.setTranslationX(value);
16742        }
16743
16744                @Override
16745        public Float get(View object) {
16746            return object.getTranslationX();
16747        }
16748    };
16749
16750    /**
16751     * A Property wrapper around the <code>translationY</code> functionality handled by the
16752     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
16753     */
16754    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
16755        @Override
16756        public void setValue(View object, float value) {
16757            object.setTranslationY(value);
16758        }
16759
16760        @Override
16761        public Float get(View object) {
16762            return object.getTranslationY();
16763        }
16764    };
16765
16766    /**
16767     * A Property wrapper around the <code>x</code> functionality handled by the
16768     * {@link View#setX(float)} and {@link View#getX()} methods.
16769     */
16770    public static final Property<View, Float> X = new FloatProperty<View>("x") {
16771        @Override
16772        public void setValue(View object, float value) {
16773            object.setX(value);
16774        }
16775
16776        @Override
16777        public Float get(View object) {
16778            return object.getX();
16779        }
16780    };
16781
16782    /**
16783     * A Property wrapper around the <code>y</code> functionality handled by the
16784     * {@link View#setY(float)} and {@link View#getY()} methods.
16785     */
16786    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
16787        @Override
16788        public void setValue(View object, float value) {
16789            object.setY(value);
16790        }
16791
16792        @Override
16793        public Float get(View object) {
16794            return object.getY();
16795        }
16796    };
16797
16798    /**
16799     * A Property wrapper around the <code>rotation</code> functionality handled by the
16800     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
16801     */
16802    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
16803        @Override
16804        public void setValue(View object, float value) {
16805            object.setRotation(value);
16806        }
16807
16808        @Override
16809        public Float get(View object) {
16810            return object.getRotation();
16811        }
16812    };
16813
16814    /**
16815     * A Property wrapper around the <code>rotationX</code> functionality handled by the
16816     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
16817     */
16818    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
16819        @Override
16820        public void setValue(View object, float value) {
16821            object.setRotationX(value);
16822        }
16823
16824        @Override
16825        public Float get(View object) {
16826            return object.getRotationX();
16827        }
16828    };
16829
16830    /**
16831     * A Property wrapper around the <code>rotationY</code> functionality handled by the
16832     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
16833     */
16834    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
16835        @Override
16836        public void setValue(View object, float value) {
16837            object.setRotationY(value);
16838        }
16839
16840        @Override
16841        public Float get(View object) {
16842            return object.getRotationY();
16843        }
16844    };
16845
16846    /**
16847     * A Property wrapper around the <code>scaleX</code> functionality handled by the
16848     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
16849     */
16850    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
16851        @Override
16852        public void setValue(View object, float value) {
16853            object.setScaleX(value);
16854        }
16855
16856        @Override
16857        public Float get(View object) {
16858            return object.getScaleX();
16859        }
16860    };
16861
16862    /**
16863     * A Property wrapper around the <code>scaleY</code> functionality handled by the
16864     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
16865     */
16866    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
16867        @Override
16868        public void setValue(View object, float value) {
16869            object.setScaleY(value);
16870        }
16871
16872        @Override
16873        public Float get(View object) {
16874            return object.getScaleY();
16875        }
16876    };
16877
16878    /**
16879     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
16880     * Each MeasureSpec represents a requirement for either the width or the height.
16881     * A MeasureSpec is comprised of a size and a mode. There are three possible
16882     * modes:
16883     * <dl>
16884     * <dt>UNSPECIFIED</dt>
16885     * <dd>
16886     * The parent has not imposed any constraint on the child. It can be whatever size
16887     * it wants.
16888     * </dd>
16889     *
16890     * <dt>EXACTLY</dt>
16891     * <dd>
16892     * The parent has determined an exact size for the child. The child is going to be
16893     * given those bounds regardless of how big it wants to be.
16894     * </dd>
16895     *
16896     * <dt>AT_MOST</dt>
16897     * <dd>
16898     * The child can be as large as it wants up to the specified size.
16899     * </dd>
16900     * </dl>
16901     *
16902     * MeasureSpecs are implemented as ints to reduce object allocation. This class
16903     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
16904     */
16905    public static class MeasureSpec {
16906        private static final int MODE_SHIFT = 30;
16907        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
16908
16909        /**
16910         * Measure specification mode: The parent has not imposed any constraint
16911         * on the child. It can be whatever size it wants.
16912         */
16913        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
16914
16915        /**
16916         * Measure specification mode: The parent has determined an exact size
16917         * for the child. The child is going to be given those bounds regardless
16918         * of how big it wants to be.
16919         */
16920        public static final int EXACTLY     = 1 << MODE_SHIFT;
16921
16922        /**
16923         * Measure specification mode: The child can be as large as it wants up
16924         * to the specified size.
16925         */
16926        public static final int AT_MOST     = 2 << MODE_SHIFT;
16927
16928        /**
16929         * Creates a measure specification based on the supplied size and mode.
16930         *
16931         * The mode must always be one of the following:
16932         * <ul>
16933         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
16934         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
16935         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
16936         * </ul>
16937         *
16938         * @param size the size of the measure specification
16939         * @param mode the mode of the measure specification
16940         * @return the measure specification based on size and mode
16941         */
16942        public static int makeMeasureSpec(int size, int mode) {
16943            return size + mode;
16944        }
16945
16946        /**
16947         * Extracts the mode from the supplied measure specification.
16948         *
16949         * @param measureSpec the measure specification to extract the mode from
16950         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
16951         *         {@link android.view.View.MeasureSpec#AT_MOST} or
16952         *         {@link android.view.View.MeasureSpec#EXACTLY}
16953         */
16954        public static int getMode(int measureSpec) {
16955            return (measureSpec & MODE_MASK);
16956        }
16957
16958        /**
16959         * Extracts the size from the supplied measure specification.
16960         *
16961         * @param measureSpec the measure specification to extract the size from
16962         * @return the size in pixels defined in the supplied measure specification
16963         */
16964        public static int getSize(int measureSpec) {
16965            return (measureSpec & ~MODE_MASK);
16966        }
16967
16968        /**
16969         * Returns a String representation of the specified measure
16970         * specification.
16971         *
16972         * @param measureSpec the measure specification to convert to a String
16973         * @return a String with the following format: "MeasureSpec: MODE SIZE"
16974         */
16975        public static String toString(int measureSpec) {
16976            int mode = getMode(measureSpec);
16977            int size = getSize(measureSpec);
16978
16979            StringBuilder sb = new StringBuilder("MeasureSpec: ");
16980
16981            if (mode == UNSPECIFIED)
16982                sb.append("UNSPECIFIED ");
16983            else if (mode == EXACTLY)
16984                sb.append("EXACTLY ");
16985            else if (mode == AT_MOST)
16986                sb.append("AT_MOST ");
16987            else
16988                sb.append(mode).append(" ");
16989
16990            sb.append(size);
16991            return sb.toString();
16992        }
16993    }
16994
16995    class CheckForLongPress implements Runnable {
16996
16997        private int mOriginalWindowAttachCount;
16998
16999        public void run() {
17000            if (isPressed() && (mParent != null)
17001                    && mOriginalWindowAttachCount == mWindowAttachCount) {
17002                if (performLongClick()) {
17003                    mHasPerformedLongPress = true;
17004                }
17005            }
17006        }
17007
17008        public void rememberWindowAttachCount() {
17009            mOriginalWindowAttachCount = mWindowAttachCount;
17010        }
17011    }
17012
17013    private final class CheckForTap implements Runnable {
17014        public void run() {
17015            mPrivateFlags &= ~PFLAG_PREPRESSED;
17016            setPressed(true);
17017            checkForLongClick(ViewConfiguration.getTapTimeout());
17018        }
17019    }
17020
17021    private final class PerformClick implements Runnable {
17022        public void run() {
17023            performClick();
17024        }
17025    }
17026
17027    /** @hide */
17028    public void hackTurnOffWindowResizeAnim(boolean off) {
17029        mAttachInfo.mTurnOffWindowResizeAnim = off;
17030    }
17031
17032    /**
17033     * This method returns a ViewPropertyAnimator object, which can be used to animate
17034     * specific properties on this View.
17035     *
17036     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
17037     */
17038    public ViewPropertyAnimator animate() {
17039        if (mAnimator == null) {
17040            mAnimator = new ViewPropertyAnimator(this);
17041        }
17042        return mAnimator;
17043    }
17044
17045    /**
17046     * Interface definition for a callback to be invoked when a hardware key event is
17047     * dispatched to this view. The callback will be invoked before the key event is
17048     * given to the view. This is only useful for hardware keyboards; a software input
17049     * method has no obligation to trigger this listener.
17050     */
17051    public interface OnKeyListener {
17052        /**
17053         * Called when a hardware key is dispatched to a view. This allows listeners to
17054         * get a chance to respond before the target view.
17055         * <p>Key presses in software keyboards will generally NOT trigger this method,
17056         * although some may elect to do so in some situations. Do not assume a
17057         * software input method has to be key-based; even if it is, it may use key presses
17058         * in a different way than you expect, so there is no way to reliably catch soft
17059         * input key presses.
17060         *
17061         * @param v The view the key has been dispatched to.
17062         * @param keyCode The code for the physical key that was pressed
17063         * @param event The KeyEvent object containing full information about
17064         *        the event.
17065         * @return True if the listener has consumed the event, false otherwise.
17066         */
17067        boolean onKey(View v, int keyCode, KeyEvent event);
17068    }
17069
17070    /**
17071     * Interface definition for a callback to be invoked when a touch event is
17072     * dispatched to this view. The callback will be invoked before the touch
17073     * event is given to the view.
17074     */
17075    public interface OnTouchListener {
17076        /**
17077         * Called when a touch event is dispatched to a view. This allows listeners to
17078         * get a chance to respond before the target view.
17079         *
17080         * @param v The view the touch event has been dispatched to.
17081         * @param event The MotionEvent object containing full information about
17082         *        the event.
17083         * @return True if the listener has consumed the event, false otherwise.
17084         */
17085        boolean onTouch(View v, MotionEvent event);
17086    }
17087
17088    /**
17089     * Interface definition for a callback to be invoked when a hover event is
17090     * dispatched to this view. The callback will be invoked before the hover
17091     * event is given to the view.
17092     */
17093    public interface OnHoverListener {
17094        /**
17095         * Called when a hover event is dispatched to a view. This allows listeners to
17096         * get a chance to respond before the target view.
17097         *
17098         * @param v The view the hover event has been dispatched to.
17099         * @param event The MotionEvent object containing full information about
17100         *        the event.
17101         * @return True if the listener has consumed the event, false otherwise.
17102         */
17103        boolean onHover(View v, MotionEvent event);
17104    }
17105
17106    /**
17107     * Interface definition for a callback to be invoked when a generic motion event is
17108     * dispatched to this view. The callback will be invoked before the generic motion
17109     * event is given to the view.
17110     */
17111    public interface OnGenericMotionListener {
17112        /**
17113         * Called when a generic motion event is dispatched to a view. This allows listeners to
17114         * get a chance to respond before the target view.
17115         *
17116         * @param v The view the generic motion event has been dispatched to.
17117         * @param event The MotionEvent object containing full information about
17118         *        the event.
17119         * @return True if the listener has consumed the event, false otherwise.
17120         */
17121        boolean onGenericMotion(View v, MotionEvent event);
17122    }
17123
17124    /**
17125     * Interface definition for a callback to be invoked when a view has been clicked and held.
17126     */
17127    public interface OnLongClickListener {
17128        /**
17129         * Called when a view has been clicked and held.
17130         *
17131         * @param v The view that was clicked and held.
17132         *
17133         * @return true if the callback consumed the long click, false otherwise.
17134         */
17135        boolean onLongClick(View v);
17136    }
17137
17138    /**
17139     * Interface definition for a callback to be invoked when a drag is being dispatched
17140     * to this view.  The callback will be invoked before the hosting view's own
17141     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
17142     * onDrag(event) behavior, it should return 'false' from this callback.
17143     *
17144     * <div class="special reference">
17145     * <h3>Developer Guides</h3>
17146     * <p>For a guide to implementing drag and drop features, read the
17147     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
17148     * </div>
17149     */
17150    public interface OnDragListener {
17151        /**
17152         * Called when a drag event is dispatched to a view. This allows listeners
17153         * to get a chance to override base View behavior.
17154         *
17155         * @param v The View that received the drag event.
17156         * @param event The {@link android.view.DragEvent} object for the drag event.
17157         * @return {@code true} if the drag event was handled successfully, or {@code false}
17158         * if the drag event was not handled. Note that {@code false} will trigger the View
17159         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
17160         */
17161        boolean onDrag(View v, DragEvent event);
17162    }
17163
17164    /**
17165     * Interface definition for a callback to be invoked when the focus state of
17166     * a view changed.
17167     */
17168    public interface OnFocusChangeListener {
17169        /**
17170         * Called when the focus state of a view has changed.
17171         *
17172         * @param v The view whose state has changed.
17173         * @param hasFocus The new focus state of v.
17174         */
17175        void onFocusChange(View v, boolean hasFocus);
17176    }
17177
17178    /**
17179     * Interface definition for a callback to be invoked when a view is clicked.
17180     */
17181    public interface OnClickListener {
17182        /**
17183         * Called when a view has been clicked.
17184         *
17185         * @param v The view that was clicked.
17186         */
17187        void onClick(View v);
17188    }
17189
17190    /**
17191     * Interface definition for a callback to be invoked when the context menu
17192     * for this view is being built.
17193     */
17194    public interface OnCreateContextMenuListener {
17195        /**
17196         * Called when the context menu for this view is being built. It is not
17197         * safe to hold onto the menu after this method returns.
17198         *
17199         * @param menu The context menu that is being built
17200         * @param v The view for which the context menu is being built
17201         * @param menuInfo Extra information about the item for which the
17202         *            context menu should be shown. This information will vary
17203         *            depending on the class of v.
17204         */
17205        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
17206    }
17207
17208    /**
17209     * Interface definition for a callback to be invoked when the status bar changes
17210     * visibility.  This reports <strong>global</strong> changes to the system UI
17211     * state, not what the application is requesting.
17212     *
17213     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
17214     */
17215    public interface OnSystemUiVisibilityChangeListener {
17216        /**
17217         * Called when the status bar changes visibility because of a call to
17218         * {@link View#setSystemUiVisibility(int)}.
17219         *
17220         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17221         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
17222         * This tells you the <strong>global</strong> state of these UI visibility
17223         * flags, not what your app is currently applying.
17224         */
17225        public void onSystemUiVisibilityChange(int visibility);
17226    }
17227
17228    /**
17229     * Interface definition for a callback to be invoked when this view is attached
17230     * or detached from its window.
17231     */
17232    public interface OnAttachStateChangeListener {
17233        /**
17234         * Called when the view is attached to a window.
17235         * @param v The view that was attached
17236         */
17237        public void onViewAttachedToWindow(View v);
17238        /**
17239         * Called when the view is detached from a window.
17240         * @param v The view that was detached
17241         */
17242        public void onViewDetachedFromWindow(View v);
17243    }
17244
17245    private final class UnsetPressedState implements Runnable {
17246        public void run() {
17247            setPressed(false);
17248        }
17249    }
17250
17251    /**
17252     * Base class for derived classes that want to save and restore their own
17253     * state in {@link android.view.View#onSaveInstanceState()}.
17254     */
17255    public static class BaseSavedState extends AbsSavedState {
17256        /**
17257         * Constructor used when reading from a parcel. Reads the state of the superclass.
17258         *
17259         * @param source
17260         */
17261        public BaseSavedState(Parcel source) {
17262            super(source);
17263        }
17264
17265        /**
17266         * Constructor called by derived classes when creating their SavedState objects
17267         *
17268         * @param superState The state of the superclass of this view
17269         */
17270        public BaseSavedState(Parcelable superState) {
17271            super(superState);
17272        }
17273
17274        public static final Parcelable.Creator<BaseSavedState> CREATOR =
17275                new Parcelable.Creator<BaseSavedState>() {
17276            public BaseSavedState createFromParcel(Parcel in) {
17277                return new BaseSavedState(in);
17278            }
17279
17280            public BaseSavedState[] newArray(int size) {
17281                return new BaseSavedState[size];
17282            }
17283        };
17284    }
17285
17286    /**
17287     * A set of information given to a view when it is attached to its parent
17288     * window.
17289     */
17290    static class AttachInfo {
17291        interface Callbacks {
17292            void playSoundEffect(int effectId);
17293            boolean performHapticFeedback(int effectId, boolean always);
17294        }
17295
17296        /**
17297         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
17298         * to a Handler. This class contains the target (View) to invalidate and
17299         * the coordinates of the dirty rectangle.
17300         *
17301         * For performance purposes, this class also implements a pool of up to
17302         * POOL_LIMIT objects that get reused. This reduces memory allocations
17303         * whenever possible.
17304         */
17305        static class InvalidateInfo implements Poolable<InvalidateInfo> {
17306            private static final int POOL_LIMIT = 10;
17307            private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
17308                    Pools.finitePool(new PoolableManager<InvalidateInfo>() {
17309                        public InvalidateInfo newInstance() {
17310                            return new InvalidateInfo();
17311                        }
17312
17313                        public void onAcquired(InvalidateInfo element) {
17314                        }
17315
17316                        public void onReleased(InvalidateInfo element) {
17317                            element.target = null;
17318                        }
17319                    }, POOL_LIMIT)
17320            );
17321
17322            private InvalidateInfo mNext;
17323            private boolean mIsPooled;
17324
17325            View target;
17326
17327            int left;
17328            int top;
17329            int right;
17330            int bottom;
17331
17332            public void setNextPoolable(InvalidateInfo element) {
17333                mNext = element;
17334            }
17335
17336            public InvalidateInfo getNextPoolable() {
17337                return mNext;
17338            }
17339
17340            static InvalidateInfo acquire() {
17341                return sPool.acquire();
17342            }
17343
17344            void release() {
17345                sPool.release(this);
17346            }
17347
17348            public boolean isPooled() {
17349                return mIsPooled;
17350            }
17351
17352            public void setPooled(boolean isPooled) {
17353                mIsPooled = isPooled;
17354            }
17355        }
17356
17357        final IWindowSession mSession;
17358
17359        final IWindow mWindow;
17360
17361        final IBinder mWindowToken;
17362
17363        final Display mDisplay;
17364
17365        final Callbacks mRootCallbacks;
17366
17367        HardwareCanvas mHardwareCanvas;
17368
17369        /**
17370         * The top view of the hierarchy.
17371         */
17372        View mRootView;
17373
17374        IBinder mPanelParentWindowToken;
17375        Surface mSurface;
17376
17377        boolean mHardwareAccelerated;
17378        boolean mHardwareAccelerationRequested;
17379        HardwareRenderer mHardwareRenderer;
17380
17381        boolean mScreenOn;
17382
17383        /**
17384         * Scale factor used by the compatibility mode
17385         */
17386        float mApplicationScale;
17387
17388        /**
17389         * Indicates whether the application is in compatibility mode
17390         */
17391        boolean mScalingRequired;
17392
17393        /**
17394         * If set, ViewAncestor doesn't use its lame animation for when the window resizes.
17395         */
17396        boolean mTurnOffWindowResizeAnim;
17397
17398        /**
17399         * Left position of this view's window
17400         */
17401        int mWindowLeft;
17402
17403        /**
17404         * Top position of this view's window
17405         */
17406        int mWindowTop;
17407
17408        /**
17409         * Indicates whether views need to use 32-bit drawing caches
17410         */
17411        boolean mUse32BitDrawingCache;
17412
17413        /**
17414         * For windows that are full-screen but using insets to layout inside
17415         * of the screen decorations, these are the current insets for the
17416         * content of the window.
17417         */
17418        final Rect mContentInsets = new Rect();
17419
17420        /**
17421         * For windows that are full-screen but using insets to layout inside
17422         * of the screen decorations, these are the current insets for the
17423         * actual visible parts of the window.
17424         */
17425        final Rect mVisibleInsets = new Rect();
17426
17427        /**
17428         * The internal insets given by this window.  This value is
17429         * supplied by the client (through
17430         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
17431         * be given to the window manager when changed to be used in laying
17432         * out windows behind it.
17433         */
17434        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
17435                = new ViewTreeObserver.InternalInsetsInfo();
17436
17437        /**
17438         * All views in the window's hierarchy that serve as scroll containers,
17439         * used to determine if the window can be resized or must be panned
17440         * to adjust for a soft input area.
17441         */
17442        final ArrayList<View> mScrollContainers = new ArrayList<View>();
17443
17444        final KeyEvent.DispatcherState mKeyDispatchState
17445                = new KeyEvent.DispatcherState();
17446
17447        /**
17448         * Indicates whether the view's window currently has the focus.
17449         */
17450        boolean mHasWindowFocus;
17451
17452        /**
17453         * The current visibility of the window.
17454         */
17455        int mWindowVisibility;
17456
17457        /**
17458         * Indicates the time at which drawing started to occur.
17459         */
17460        long mDrawingTime;
17461
17462        /**
17463         * Indicates whether or not ignoring the DIRTY_MASK flags.
17464         */
17465        boolean mIgnoreDirtyState;
17466
17467        /**
17468         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
17469         * to avoid clearing that flag prematurely.
17470         */
17471        boolean mSetIgnoreDirtyState = false;
17472
17473        /**
17474         * Indicates whether the view's window is currently in touch mode.
17475         */
17476        boolean mInTouchMode;
17477
17478        /**
17479         * Indicates that ViewAncestor should trigger a global layout change
17480         * the next time it performs a traversal
17481         */
17482        boolean mRecomputeGlobalAttributes;
17483
17484        /**
17485         * Always report new attributes at next traversal.
17486         */
17487        boolean mForceReportNewAttributes;
17488
17489        /**
17490         * Set during a traveral if any views want to keep the screen on.
17491         */
17492        boolean mKeepScreenOn;
17493
17494        /**
17495         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
17496         */
17497        int mSystemUiVisibility;
17498
17499        /**
17500         * Hack to force certain system UI visibility flags to be cleared.
17501         */
17502        int mDisabledSystemUiVisibility;
17503
17504        /**
17505         * Last global system UI visibility reported by the window manager.
17506         */
17507        int mGlobalSystemUiVisibility;
17508
17509        /**
17510         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
17511         * attached.
17512         */
17513        boolean mHasSystemUiListeners;
17514
17515        /**
17516         * Set if the visibility of any views has changed.
17517         */
17518        boolean mViewVisibilityChanged;
17519
17520        /**
17521         * Set to true if a view has been scrolled.
17522         */
17523        boolean mViewScrollChanged;
17524
17525        /**
17526         * Global to the view hierarchy used as a temporary for dealing with
17527         * x/y points in the transparent region computations.
17528         */
17529        final int[] mTransparentLocation = new int[2];
17530
17531        /**
17532         * Global to the view hierarchy used as a temporary for dealing with
17533         * x/y points in the ViewGroup.invalidateChild implementation.
17534         */
17535        final int[] mInvalidateChildLocation = new int[2];
17536
17537
17538        /**
17539         * Global to the view hierarchy used as a temporary for dealing with
17540         * x/y location when view is transformed.
17541         */
17542        final float[] mTmpTransformLocation = new float[2];
17543
17544        /**
17545         * The view tree observer used to dispatch global events like
17546         * layout, pre-draw, touch mode change, etc.
17547         */
17548        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
17549
17550        /**
17551         * A Canvas used by the view hierarchy to perform bitmap caching.
17552         */
17553        Canvas mCanvas;
17554
17555        /**
17556         * The view root impl.
17557         */
17558        final ViewRootImpl mViewRootImpl;
17559
17560        /**
17561         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
17562         * handler can be used to pump events in the UI events queue.
17563         */
17564        final Handler mHandler;
17565
17566        /**
17567         * Temporary for use in computing invalidate rectangles while
17568         * calling up the hierarchy.
17569         */
17570        final Rect mTmpInvalRect = new Rect();
17571
17572        /**
17573         * Temporary for use in computing hit areas with transformed views
17574         */
17575        final RectF mTmpTransformRect = new RectF();
17576
17577        /**
17578         * Temporary for use in transforming invalidation rect
17579         */
17580        final Matrix mTmpMatrix = new Matrix();
17581
17582        /**
17583         * Temporary for use in transforming invalidation rect
17584         */
17585        final Transformation mTmpTransformation = new Transformation();
17586
17587        /**
17588         * Temporary list for use in collecting focusable descendents of a view.
17589         */
17590        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
17591
17592        /**
17593         * The id of the window for accessibility purposes.
17594         */
17595        int mAccessibilityWindowId = View.NO_ID;
17596
17597        /**
17598         * Whether to ingore not exposed for accessibility Views when
17599         * reporting the view tree to accessibility services.
17600         */
17601        boolean mIncludeNotImportantViews;
17602
17603        /**
17604         * The drawable for highlighting accessibility focus.
17605         */
17606        Drawable mAccessibilityFocusDrawable;
17607
17608        /**
17609         * Show where the margins, bounds and layout bounds are for each view.
17610         */
17611        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
17612
17613        /**
17614         * Point used to compute visible regions.
17615         */
17616        final Point mPoint = new Point();
17617
17618        /**
17619         * Creates a new set of attachment information with the specified
17620         * events handler and thread.
17621         *
17622         * @param handler the events handler the view must use
17623         */
17624        AttachInfo(IWindowSession session, IWindow window, Display display,
17625                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
17626            mSession = session;
17627            mWindow = window;
17628            mWindowToken = window.asBinder();
17629            mDisplay = display;
17630            mViewRootImpl = viewRootImpl;
17631            mHandler = handler;
17632            mRootCallbacks = effectPlayer;
17633        }
17634    }
17635
17636    /**
17637     * <p>ScrollabilityCache holds various fields used by a View when scrolling
17638     * is supported. This avoids keeping too many unused fields in most
17639     * instances of View.</p>
17640     */
17641    private static class ScrollabilityCache implements Runnable {
17642
17643        /**
17644         * Scrollbars are not visible
17645         */
17646        public static final int OFF = 0;
17647
17648        /**
17649         * Scrollbars are visible
17650         */
17651        public static final int ON = 1;
17652
17653        /**
17654         * Scrollbars are fading away
17655         */
17656        public static final int FADING = 2;
17657
17658        public boolean fadeScrollBars;
17659
17660        public int fadingEdgeLength;
17661        public int scrollBarDefaultDelayBeforeFade;
17662        public int scrollBarFadeDuration;
17663
17664        public int scrollBarSize;
17665        public ScrollBarDrawable scrollBar;
17666        public float[] interpolatorValues;
17667        public View host;
17668
17669        public final Paint paint;
17670        public final Matrix matrix;
17671        public Shader shader;
17672
17673        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
17674
17675        private static final float[] OPAQUE = { 255 };
17676        private static final float[] TRANSPARENT = { 0.0f };
17677
17678        /**
17679         * When fading should start. This time moves into the future every time
17680         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
17681         */
17682        public long fadeStartTime;
17683
17684
17685        /**
17686         * The current state of the scrollbars: ON, OFF, or FADING
17687         */
17688        public int state = OFF;
17689
17690        private int mLastColor;
17691
17692        public ScrollabilityCache(ViewConfiguration configuration, View host) {
17693            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
17694            scrollBarSize = configuration.getScaledScrollBarSize();
17695            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
17696            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
17697
17698            paint = new Paint();
17699            matrix = new Matrix();
17700            // use use a height of 1, and then wack the matrix each time we
17701            // actually use it.
17702            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
17703            paint.setShader(shader);
17704            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
17705
17706            this.host = host;
17707        }
17708
17709        public void setFadeColor(int color) {
17710            if (color != mLastColor) {
17711                mLastColor = color;
17712
17713                if (color != 0) {
17714                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
17715                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
17716                    paint.setShader(shader);
17717                    // Restore the default transfer mode (src_over)
17718                    paint.setXfermode(null);
17719                } else {
17720                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
17721                    paint.setShader(shader);
17722                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
17723                }
17724            }
17725        }
17726
17727        public void run() {
17728            long now = AnimationUtils.currentAnimationTimeMillis();
17729            if (now >= fadeStartTime) {
17730
17731                // the animation fades the scrollbars out by changing
17732                // the opacity (alpha) from fully opaque to fully
17733                // transparent
17734                int nextFrame = (int) now;
17735                int framesCount = 0;
17736
17737                Interpolator interpolator = scrollBarInterpolator;
17738
17739                // Start opaque
17740                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
17741
17742                // End transparent
17743                nextFrame += scrollBarFadeDuration;
17744                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
17745
17746                state = FADING;
17747
17748                // Kick off the fade animation
17749                host.invalidate(true);
17750            }
17751        }
17752    }
17753
17754    /**
17755     * Resuable callback for sending
17756     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
17757     */
17758    private class SendViewScrolledAccessibilityEvent implements Runnable {
17759        public volatile boolean mIsPending;
17760
17761        public void run() {
17762            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
17763            mIsPending = false;
17764        }
17765    }
17766
17767    /**
17768     * <p>
17769     * This class represents a delegate that can be registered in a {@link View}
17770     * to enhance accessibility support via composition rather via inheritance.
17771     * It is specifically targeted to widget developers that extend basic View
17772     * classes i.e. classes in package android.view, that would like their
17773     * applications to be backwards compatible.
17774     * </p>
17775     * <div class="special reference">
17776     * <h3>Developer Guides</h3>
17777     * <p>For more information about making applications accessible, read the
17778     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
17779     * developer guide.</p>
17780     * </div>
17781     * <p>
17782     * A scenario in which a developer would like to use an accessibility delegate
17783     * is overriding a method introduced in a later API version then the minimal API
17784     * version supported by the application. For example, the method
17785     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
17786     * in API version 4 when the accessibility APIs were first introduced. If a
17787     * developer would like his application to run on API version 4 devices (assuming
17788     * all other APIs used by the application are version 4 or lower) and take advantage
17789     * of this method, instead of overriding the method which would break the application's
17790     * backwards compatibility, he can override the corresponding method in this
17791     * delegate and register the delegate in the target View if the API version of
17792     * the system is high enough i.e. the API version is same or higher to the API
17793     * version that introduced
17794     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
17795     * </p>
17796     * <p>
17797     * Here is an example implementation:
17798     * </p>
17799     * <code><pre><p>
17800     * if (Build.VERSION.SDK_INT >= 14) {
17801     *     // If the API version is equal of higher than the version in
17802     *     // which onInitializeAccessibilityNodeInfo was introduced we
17803     *     // register a delegate with a customized implementation.
17804     *     View view = findViewById(R.id.view_id);
17805     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
17806     *         public void onInitializeAccessibilityNodeInfo(View host,
17807     *                 AccessibilityNodeInfo info) {
17808     *             // Let the default implementation populate the info.
17809     *             super.onInitializeAccessibilityNodeInfo(host, info);
17810     *             // Set some other information.
17811     *             info.setEnabled(host.isEnabled());
17812     *         }
17813     *     });
17814     * }
17815     * </code></pre></p>
17816     * <p>
17817     * This delegate contains methods that correspond to the accessibility methods
17818     * in View. If a delegate has been specified the implementation in View hands
17819     * off handling to the corresponding method in this delegate. The default
17820     * implementation the delegate methods behaves exactly as the corresponding
17821     * method in View for the case of no accessibility delegate been set. Hence,
17822     * to customize the behavior of a View method, clients can override only the
17823     * corresponding delegate method without altering the behavior of the rest
17824     * accessibility related methods of the host view.
17825     * </p>
17826     */
17827    public static class AccessibilityDelegate {
17828
17829        /**
17830         * Sends an accessibility event of the given type. If accessibility is not
17831         * enabled this method has no effect.
17832         * <p>
17833         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
17834         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
17835         * been set.
17836         * </p>
17837         *
17838         * @param host The View hosting the delegate.
17839         * @param eventType The type of the event to send.
17840         *
17841         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
17842         */
17843        public void sendAccessibilityEvent(View host, int eventType) {
17844            host.sendAccessibilityEventInternal(eventType);
17845        }
17846
17847        /**
17848         * Performs the specified accessibility action on the view. For
17849         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
17850         * <p>
17851         * The default implementation behaves as
17852         * {@link View#performAccessibilityAction(int, Bundle)
17853         *  View#performAccessibilityAction(int, Bundle)} for the case of
17854         *  no accessibility delegate been set.
17855         * </p>
17856         *
17857         * @param action The action to perform.
17858         * @return Whether the action was performed.
17859         *
17860         * @see View#performAccessibilityAction(int, Bundle)
17861         *      View#performAccessibilityAction(int, Bundle)
17862         */
17863        public boolean performAccessibilityAction(View host, int action, Bundle args) {
17864            return host.performAccessibilityActionInternal(action, args);
17865        }
17866
17867        /**
17868         * Sends an accessibility event. This method behaves exactly as
17869         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
17870         * empty {@link AccessibilityEvent} and does not perform a check whether
17871         * accessibility is enabled.
17872         * <p>
17873         * The default implementation behaves as
17874         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
17875         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
17876         * the case of no accessibility delegate been set.
17877         * </p>
17878         *
17879         * @param host The View hosting the delegate.
17880         * @param event The event to send.
17881         *
17882         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
17883         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
17884         */
17885        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
17886            host.sendAccessibilityEventUncheckedInternal(event);
17887        }
17888
17889        /**
17890         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
17891         * to its children for adding their text content to the event.
17892         * <p>
17893         * The default implementation behaves as
17894         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
17895         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
17896         * the case of no accessibility delegate been set.
17897         * </p>
17898         *
17899         * @param host The View hosting the delegate.
17900         * @param event The event.
17901         * @return True if the event population was completed.
17902         *
17903         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
17904         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
17905         */
17906        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
17907            return host.dispatchPopulateAccessibilityEventInternal(event);
17908        }
17909
17910        /**
17911         * Gives a chance to the host View to populate the accessibility event with its
17912         * text content.
17913         * <p>
17914         * The default implementation behaves as
17915         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
17916         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
17917         * the case of no accessibility delegate been set.
17918         * </p>
17919         *
17920         * @param host The View hosting the delegate.
17921         * @param event The accessibility event which to populate.
17922         *
17923         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
17924         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
17925         */
17926        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
17927            host.onPopulateAccessibilityEventInternal(event);
17928        }
17929
17930        /**
17931         * Initializes an {@link AccessibilityEvent} with information about the
17932         * the host View which is the event source.
17933         * <p>
17934         * The default implementation behaves as
17935         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
17936         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
17937         * the case of no accessibility delegate been set.
17938         * </p>
17939         *
17940         * @param host The View hosting the delegate.
17941         * @param event The event to initialize.
17942         *
17943         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
17944         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
17945         */
17946        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
17947            host.onInitializeAccessibilityEventInternal(event);
17948        }
17949
17950        /**
17951         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
17952         * <p>
17953         * The default implementation behaves as
17954         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
17955         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
17956         * the case of no accessibility delegate been set.
17957         * </p>
17958         *
17959         * @param host The View hosting the delegate.
17960         * @param info The instance to initialize.
17961         *
17962         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
17963         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
17964         */
17965        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
17966            host.onInitializeAccessibilityNodeInfoInternal(info);
17967        }
17968
17969        /**
17970         * Called when a child of the host View has requested sending an
17971         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
17972         * to augment the event.
17973         * <p>
17974         * The default implementation behaves as
17975         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
17976         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
17977         * the case of no accessibility delegate been set.
17978         * </p>
17979         *
17980         * @param host The View hosting the delegate.
17981         * @param child The child which requests sending the event.
17982         * @param event The event to be sent.
17983         * @return True if the event should be sent
17984         *
17985         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
17986         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
17987         */
17988        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
17989                AccessibilityEvent event) {
17990            return host.onRequestSendAccessibilityEventInternal(child, event);
17991        }
17992
17993        /**
17994         * Gets the provider for managing a virtual view hierarchy rooted at this View
17995         * and reported to {@link android.accessibilityservice.AccessibilityService}s
17996         * that explore the window content.
17997         * <p>
17998         * The default implementation behaves as
17999         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
18000         * the case of no accessibility delegate been set.
18001         * </p>
18002         *
18003         * @return The provider.
18004         *
18005         * @see AccessibilityNodeProvider
18006         */
18007        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
18008            return null;
18009        }
18010    }
18011}
18012