View.java revision d1ca75bffef070f62ab70ed514f7f91824f73cbc
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.animation.RevealAnimator;
20import android.animation.ValueAnimator;
21import android.annotation.IntDef;
22import android.annotation.NonNull;
23import android.annotation.Nullable;
24import android.content.ClipData;
25import android.content.Context;
26import android.content.res.Configuration;
27import android.content.res.Resources;
28import android.content.res.TypedArray;
29import android.graphics.Bitmap;
30import android.graphics.Canvas;
31import android.graphics.Insets;
32import android.graphics.Interpolator;
33import android.graphics.LinearGradient;
34import android.graphics.Matrix;
35import android.graphics.Outline;
36import android.graphics.Paint;
37import android.graphics.PixelFormat;
38import android.graphics.Point;
39import android.graphics.PorterDuff;
40import android.graphics.PorterDuffXfermode;
41import android.graphics.Rect;
42import android.graphics.RectF;
43import android.graphics.Region;
44import android.graphics.Shader;
45import android.graphics.drawable.ColorDrawable;
46import android.graphics.drawable.Drawable;
47import android.hardware.display.DisplayManagerGlobal;
48import android.os.Bundle;
49import android.os.Handler;
50import android.os.IBinder;
51import android.os.Parcel;
52import android.os.Parcelable;
53import android.os.RemoteException;
54import android.os.SystemClock;
55import android.os.SystemProperties;
56import android.text.TextUtils;
57import android.util.AttributeSet;
58import android.util.FloatProperty;
59import android.util.LayoutDirection;
60import android.util.Log;
61import android.util.LongSparseLongArray;
62import android.util.Pools.SynchronizedPool;
63import android.util.Property;
64import android.util.SparseArray;
65import android.util.SuperNotCalledException;
66import android.util.TypedValue;
67import android.view.ContextMenu.ContextMenuInfo;
68import android.view.AccessibilityIterators.TextSegmentIterator;
69import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
70import android.view.AccessibilityIterators.WordTextSegmentIterator;
71import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
72import android.view.accessibility.AccessibilityEvent;
73import android.view.accessibility.AccessibilityEventSource;
74import android.view.accessibility.AccessibilityManager;
75import android.view.accessibility.AccessibilityNodeInfo;
76import android.view.accessibility.AccessibilityNodeProvider;
77import android.view.animation.Animation;
78import android.view.animation.AnimationUtils;
79import android.view.animation.Transformation;
80import android.view.inputmethod.EditorInfo;
81import android.view.inputmethod.InputConnection;
82import android.view.inputmethod.InputMethodManager;
83import android.widget.ScrollBarDrawable;
84
85import static android.os.Build.VERSION_CODES.*;
86import static java.lang.Math.max;
87
88import com.android.internal.R;
89import com.android.internal.util.Predicate;
90import com.android.internal.view.menu.MenuBuilder;
91import com.google.android.collect.Lists;
92import com.google.android.collect.Maps;
93
94import java.lang.annotation.Retention;
95import java.lang.annotation.RetentionPolicy;
96import java.lang.ref.WeakReference;
97import java.lang.reflect.Field;
98import java.lang.reflect.InvocationTargetException;
99import java.lang.reflect.Method;
100import java.lang.reflect.Modifier;
101import java.util.ArrayList;
102import java.util.Arrays;
103import java.util.Collections;
104import java.util.HashMap;
105import java.util.List;
106import java.util.Locale;
107import java.util.Map;
108import java.util.concurrent.CopyOnWriteArrayList;
109import java.util.concurrent.atomic.AtomicInteger;
110
111/**
112 * <p>
113 * This class represents the basic building block for user interface components. A View
114 * occupies a rectangular area on the screen and is responsible for drawing and
115 * event handling. View is the base class for <em>widgets</em>, which are
116 * used to create interactive UI components (buttons, text fields, etc.). The
117 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
118 * are invisible containers that hold other Views (or other ViewGroups) and define
119 * their layout properties.
120 * </p>
121 *
122 * <div class="special reference">
123 * <h3>Developer Guides</h3>
124 * <p>For information about using this class to develop your application's user interface,
125 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
126 * </div>
127 *
128 * <a name="Using"></a>
129 * <h3>Using Views</h3>
130 * <p>
131 * All of the views in a window are arranged in a single tree. You can add views
132 * either from code or by specifying a tree of views in one or more XML layout
133 * files. There are many specialized subclasses of views that act as controls or
134 * are capable of displaying text, images, or other content.
135 * </p>
136 * <p>
137 * Once you have created a tree of views, there are typically a few types of
138 * common operations you may wish to perform:
139 * <ul>
140 * <li><strong>Set properties:</strong> for example setting the text of a
141 * {@link android.widget.TextView}. The available properties and the methods
142 * that set them will vary among the different subclasses of views. Note that
143 * properties that are known at build time can be set in the XML layout
144 * files.</li>
145 * <li><strong>Set focus:</strong> The framework will handled moving focus in
146 * response to user input. To force focus to a specific view, call
147 * {@link #requestFocus}.</li>
148 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
149 * that will be notified when something interesting happens to the view. For
150 * example, all views will let you set a listener to be notified when the view
151 * gains or loses focus. You can register such a listener using
152 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
153 * Other view subclasses offer more specialized listeners. For example, a Button
154 * exposes a listener to notify clients when the button is clicked.</li>
155 * <li><strong>Set visibility:</strong> You can hide or show views using
156 * {@link #setVisibility(int)}.</li>
157 * </ul>
158 * </p>
159 * <p><em>
160 * Note: The Android framework is responsible for measuring, laying out and
161 * drawing views. You should not call methods that perform these actions on
162 * views yourself unless you are actually implementing a
163 * {@link android.view.ViewGroup}.
164 * </em></p>
165 *
166 * <a name="Lifecycle"></a>
167 * <h3>Implementing a Custom View</h3>
168 *
169 * <p>
170 * To implement a custom view, you will usually begin by providing overrides for
171 * some of the standard methods that the framework calls on all views. You do
172 * not need to override all of these methods. In fact, you can start by just
173 * overriding {@link #onDraw(android.graphics.Canvas)}.
174 * <table border="2" width="85%" align="center" cellpadding="5">
175 *     <thead>
176 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
177 *     </thead>
178 *
179 *     <tbody>
180 *     <tr>
181 *         <td rowspan="2">Creation</td>
182 *         <td>Constructors</td>
183 *         <td>There is a form of the constructor that are called when the view
184 *         is created from code and a form that is called when the view is
185 *         inflated from a layout file. The second form should parse and apply
186 *         any attributes defined in the layout file.
187 *         </td>
188 *     </tr>
189 *     <tr>
190 *         <td><code>{@link #onFinishInflate()}</code></td>
191 *         <td>Called after a view and all of its children has been inflated
192 *         from XML.</td>
193 *     </tr>
194 *
195 *     <tr>
196 *         <td rowspan="3">Layout</td>
197 *         <td><code>{@link #onMeasure(int, int)}</code></td>
198 *         <td>Called to determine the size requirements for this view and all
199 *         of its children.
200 *         </td>
201 *     </tr>
202 *     <tr>
203 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
204 *         <td>Called when this view should assign a size and position to all
205 *         of its children.
206 *         </td>
207 *     </tr>
208 *     <tr>
209 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
210 *         <td>Called when the size of this view has changed.
211 *         </td>
212 *     </tr>
213 *
214 *     <tr>
215 *         <td>Drawing</td>
216 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
217 *         <td>Called when the view should render its content.
218 *         </td>
219 *     </tr>
220 *
221 *     <tr>
222 *         <td rowspan="4">Event processing</td>
223 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
224 *         <td>Called when a new hardware key event occurs.
225 *         </td>
226 *     </tr>
227 *     <tr>
228 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
229 *         <td>Called when a hardware key up event occurs.
230 *         </td>
231 *     </tr>
232 *     <tr>
233 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
234 *         <td>Called when a trackball motion event occurs.
235 *         </td>
236 *     </tr>
237 *     <tr>
238 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
239 *         <td>Called when a touch screen motion event occurs.
240 *         </td>
241 *     </tr>
242 *
243 *     <tr>
244 *         <td rowspan="2">Focus</td>
245 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
246 *         <td>Called when the view gains or loses focus.
247 *         </td>
248 *     </tr>
249 *
250 *     <tr>
251 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
252 *         <td>Called when the window containing the view gains or loses focus.
253 *         </td>
254 *     </tr>
255 *
256 *     <tr>
257 *         <td rowspan="3">Attaching</td>
258 *         <td><code>{@link #onAttachedToWindow()}</code></td>
259 *         <td>Called when the view is attached to a window.
260 *         </td>
261 *     </tr>
262 *
263 *     <tr>
264 *         <td><code>{@link #onDetachedFromWindow}</code></td>
265 *         <td>Called when the view is detached from its window.
266 *         </td>
267 *     </tr>
268 *
269 *     <tr>
270 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
271 *         <td>Called when the visibility of the window containing the view
272 *         has changed.
273 *         </td>
274 *     </tr>
275 *     </tbody>
276 *
277 * </table>
278 * </p>
279 *
280 * <a name="IDs"></a>
281 * <h3>IDs</h3>
282 * Views may have an integer id associated with them. These ids are typically
283 * assigned in the layout XML files, and are used to find specific views within
284 * the view tree. A common pattern is to:
285 * <ul>
286 * <li>Define a Button in the layout file and assign it a unique ID.
287 * <pre>
288 * &lt;Button
289 *     android:id="@+id/my_button"
290 *     android:layout_width="wrap_content"
291 *     android:layout_height="wrap_content"
292 *     android:text="@string/my_button_text"/&gt;
293 * </pre></li>
294 * <li>From the onCreate method of an Activity, find the Button
295 * <pre class="prettyprint">
296 *      Button myButton = (Button) findViewById(R.id.my_button);
297 * </pre></li>
298 * </ul>
299 * <p>
300 * View IDs need not be unique throughout the tree, but it is good practice to
301 * ensure that they are at least unique within the part of the tree you are
302 * searching.
303 * </p>
304 *
305 * <a name="Position"></a>
306 * <h3>Position</h3>
307 * <p>
308 * The geometry of a view is that of a rectangle. A view has a location,
309 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
310 * two dimensions, expressed as a width and a height. The unit for location
311 * and dimensions is the pixel.
312 * </p>
313 *
314 * <p>
315 * It is possible to retrieve the location of a view by invoking the methods
316 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
317 * coordinate of the rectangle representing the view. The latter returns the
318 * top, or Y, coordinate of the rectangle representing the view. These methods
319 * both return the location of the view relative to its parent. For instance,
320 * when getLeft() returns 20, that means the view is located 20 pixels to the
321 * right of the left edge of its direct parent.
322 * </p>
323 *
324 * <p>
325 * In addition, several convenience methods are offered to avoid unnecessary
326 * computations, namely {@link #getRight()} and {@link #getBottom()}.
327 * These methods return the coordinates of the right and bottom edges of the
328 * rectangle representing the view. For instance, calling {@link #getRight()}
329 * is similar to the following computation: <code>getLeft() + getWidth()</code>
330 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
331 * </p>
332 *
333 * <a name="SizePaddingMargins"></a>
334 * <h3>Size, padding and margins</h3>
335 * <p>
336 * The size of a view is expressed with a width and a height. A view actually
337 * possess two pairs of width and height values.
338 * </p>
339 *
340 * <p>
341 * The first pair is known as <em>measured width</em> and
342 * <em>measured height</em>. These dimensions define how big a view wants to be
343 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
344 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
345 * and {@link #getMeasuredHeight()}.
346 * </p>
347 *
348 * <p>
349 * The second pair is simply known as <em>width</em> and <em>height</em>, or
350 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
351 * dimensions define the actual size of the view on screen, at drawing time and
352 * after layout. These values may, but do not have to, be different from the
353 * measured width and height. The width and height can be obtained by calling
354 * {@link #getWidth()} and {@link #getHeight()}.
355 * </p>
356 *
357 * <p>
358 * To measure its dimensions, a view takes into account its padding. The padding
359 * is expressed in pixels for the left, top, right and bottom parts of the view.
360 * Padding can be used to offset the content of the view by a specific amount of
361 * pixels. For instance, a left padding of 2 will push the view's content by
362 * 2 pixels to the right of the left edge. Padding can be set using the
363 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
364 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
365 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
366 * {@link #getPaddingEnd()}.
367 * </p>
368 *
369 * <p>
370 * Even though a view can define a padding, it does not provide any support for
371 * margins. However, view groups provide such a support. Refer to
372 * {@link android.view.ViewGroup} and
373 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
374 * </p>
375 *
376 * <a name="Layout"></a>
377 * <h3>Layout</h3>
378 * <p>
379 * Layout is a two pass process: a measure pass and a layout pass. The measuring
380 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
381 * of the view tree. Each view pushes dimension specifications down the tree
382 * during the recursion. At the end of the measure pass, every view has stored
383 * its measurements. The second pass happens in
384 * {@link #layout(int,int,int,int)} and is also top-down. During
385 * this pass each parent is responsible for positioning all of its children
386 * using the sizes computed in the measure pass.
387 * </p>
388 *
389 * <p>
390 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
391 * {@link #getMeasuredHeight()} values must be set, along with those for all of
392 * that view's descendants. A view's measured width and measured height values
393 * must respect the constraints imposed by the view's parents. This guarantees
394 * that at the end of the measure pass, all parents accept all of their
395 * children's measurements. A parent view may call measure() more than once on
396 * its children. For example, the parent may measure each child once with
397 * unspecified dimensions to find out how big they want to be, then call
398 * measure() on them again with actual numbers if the sum of all the children's
399 * unconstrained sizes is too big or too small.
400 * </p>
401 *
402 * <p>
403 * The measure pass uses two classes to communicate dimensions. The
404 * {@link MeasureSpec} class is used by views to tell their parents how they
405 * want to be measured and positioned. The base LayoutParams class just
406 * describes how big the view wants to be for both width and height. For each
407 * dimension, it can specify one of:
408 * <ul>
409 * <li> an exact number
410 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
411 * (minus padding)
412 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
413 * enclose its content (plus padding).
414 * </ul>
415 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
416 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
417 * an X and Y value.
418 * </p>
419 *
420 * <p>
421 * MeasureSpecs are used to push requirements down the tree from parent to
422 * child. A MeasureSpec can be in one of three modes:
423 * <ul>
424 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
425 * of a child view. For example, a LinearLayout may call measure() on its child
426 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
427 * tall the child view wants to be given a width of 240 pixels.
428 * <li>EXACTLY: This is used by the parent to impose an exact size on the
429 * child. The child must use this size, and guarantee that all of its
430 * descendants will fit within this size.
431 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
432 * child. The child must gurantee that it and all of its descendants will fit
433 * within this size.
434 * </ul>
435 * </p>
436 *
437 * <p>
438 * To intiate a layout, call {@link #requestLayout}. This method is typically
439 * called by a view on itself when it believes that is can no longer fit within
440 * its current bounds.
441 * </p>
442 *
443 * <a name="Drawing"></a>
444 * <h3>Drawing</h3>
445 * <p>
446 * Drawing is handled by walking the tree and rendering each view that
447 * intersects the invalid region. Because the tree is traversed in-order,
448 * this means that parents will draw before (i.e., behind) their children, with
449 * siblings drawn in the order they appear in the tree.
450 * If you set a background drawable for a View, then the View will draw it for you
451 * before calling back to its <code>onDraw()</code> method.
452 * </p>
453 *
454 * <p>
455 * Note that the framework will not draw views that are not in the invalid region.
456 * </p>
457 *
458 * <p>
459 * To force a view to draw, call {@link #invalidate()}.
460 * </p>
461 *
462 * <a name="EventHandlingThreading"></a>
463 * <h3>Event Handling and Threading</h3>
464 * <p>
465 * The basic cycle of a view is as follows:
466 * <ol>
467 * <li>An event comes in and is dispatched to the appropriate view. The view
468 * handles the event and notifies any listeners.</li>
469 * <li>If in the course of processing the event, the view's bounds may need
470 * to be changed, the view will call {@link #requestLayout()}.</li>
471 * <li>Similarly, if in the course of processing the event the view's appearance
472 * may need to be changed, the view will call {@link #invalidate()}.</li>
473 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
474 * the framework will take care of measuring, laying out, and drawing the tree
475 * as appropriate.</li>
476 * </ol>
477 * </p>
478 *
479 * <p><em>Note: The entire view tree is single threaded. You must always be on
480 * the UI thread when calling any method on any view.</em>
481 * If you are doing work on other threads and want to update the state of a view
482 * from that thread, you should use a {@link Handler}.
483 * </p>
484 *
485 * <a name="FocusHandling"></a>
486 * <h3>Focus Handling</h3>
487 * <p>
488 * The framework will handle routine focus movement in response to user input.
489 * This includes changing the focus as views are removed or hidden, or as new
490 * views become available. Views indicate their willingness to take focus
491 * through the {@link #isFocusable} method. To change whether a view can take
492 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
493 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
494 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
495 * </p>
496 * <p>
497 * Focus movement is based on an algorithm which finds the nearest neighbor in a
498 * given direction. In rare cases, the default algorithm may not match the
499 * intended behavior of the developer. In these situations, you can provide
500 * explicit overrides by using these XML attributes in the layout file:
501 * <pre>
502 * nextFocusDown
503 * nextFocusLeft
504 * nextFocusRight
505 * nextFocusUp
506 * </pre>
507 * </p>
508 *
509 *
510 * <p>
511 * To get a particular view to take focus, call {@link #requestFocus()}.
512 * </p>
513 *
514 * <a name="TouchMode"></a>
515 * <h3>Touch Mode</h3>
516 * <p>
517 * When a user is navigating a user interface via directional keys such as a D-pad, it is
518 * necessary to give focus to actionable items such as buttons so the user can see
519 * what will take input.  If the device has touch capabilities, however, and the user
520 * begins interacting with the interface by touching it, it is no longer necessary to
521 * always highlight, or give focus to, a particular view.  This motivates a mode
522 * for interaction named 'touch mode'.
523 * </p>
524 * <p>
525 * For a touch capable device, once the user touches the screen, the device
526 * will enter touch mode.  From this point onward, only views for which
527 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
528 * Other views that are touchable, like buttons, will not take focus when touched; they will
529 * only fire the on click listeners.
530 * </p>
531 * <p>
532 * Any time a user hits a directional key, such as a D-pad direction, the view device will
533 * exit touch mode, and find a view to take focus, so that the user may resume interacting
534 * with the user interface without touching the screen again.
535 * </p>
536 * <p>
537 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
538 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
539 * </p>
540 *
541 * <a name="Scrolling"></a>
542 * <h3>Scrolling</h3>
543 * <p>
544 * The framework provides basic support for views that wish to internally
545 * scroll their content. This includes keeping track of the X and Y scroll
546 * offset as well as mechanisms for drawing scrollbars. See
547 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
548 * {@link #awakenScrollBars()} for more details.
549 * </p>
550 *
551 * <a name="Tags"></a>
552 * <h3>Tags</h3>
553 * <p>
554 * Unlike IDs, tags are not used to identify views. Tags are essentially an
555 * extra piece of information that can be associated with a view. They are most
556 * often used as a convenience to store data related to views in the views
557 * themselves rather than by putting them in a separate structure.
558 * </p>
559 *
560 * <a name="Properties"></a>
561 * <h3>Properties</h3>
562 * <p>
563 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
564 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
565 * available both in the {@link Property} form as well as in similarly-named setter/getter
566 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
567 * be used to set persistent state associated with these rendering-related properties on the view.
568 * The properties and methods can also be used in conjunction with
569 * {@link android.animation.Animator Animator}-based animations, described more in the
570 * <a href="#Animation">Animation</a> section.
571 * </p>
572 *
573 * <a name="Animation"></a>
574 * <h3>Animation</h3>
575 * <p>
576 * Starting with Android 3.0, the preferred way of animating views is to use the
577 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
578 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
579 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
580 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
581 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
582 * makes animating these View properties particularly easy and efficient.
583 * </p>
584 * <p>
585 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
586 * You can attach an {@link Animation} object to a view using
587 * {@link #setAnimation(Animation)} or
588 * {@link #startAnimation(Animation)}. The animation can alter the scale,
589 * rotation, translation and alpha of a view over time. If the animation is
590 * attached to a view that has children, the animation will affect the entire
591 * subtree rooted by that node. When an animation is started, the framework will
592 * take care of redrawing the appropriate views until the animation completes.
593 * </p>
594 *
595 * <a name="Security"></a>
596 * <h3>Security</h3>
597 * <p>
598 * Sometimes it is essential that an application be able to verify that an action
599 * is being performed with the full knowledge and consent of the user, such as
600 * granting a permission request, making a purchase or clicking on an advertisement.
601 * Unfortunately, a malicious application could try to spoof the user into
602 * performing these actions, unaware, by concealing the intended purpose of the view.
603 * As a remedy, the framework offers a touch filtering mechanism that can be used to
604 * improve the security of views that provide access to sensitive functionality.
605 * </p><p>
606 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
607 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
608 * will discard touches that are received whenever the view's window is obscured by
609 * another visible window.  As a result, the view will not receive touches whenever a
610 * toast, dialog or other window appears above the view's window.
611 * </p><p>
612 * For more fine-grained control over security, consider overriding the
613 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
614 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
615 * </p>
616 *
617 * @attr ref android.R.styleable#View_alpha
618 * @attr ref android.R.styleable#View_background
619 * @attr ref android.R.styleable#View_clickable
620 * @attr ref android.R.styleable#View_contentDescription
621 * @attr ref android.R.styleable#View_drawingCacheQuality
622 * @attr ref android.R.styleable#View_duplicateParentState
623 * @attr ref android.R.styleable#View_id
624 * @attr ref android.R.styleable#View_requiresFadingEdge
625 * @attr ref android.R.styleable#View_fadeScrollbars
626 * @attr ref android.R.styleable#View_fadingEdgeLength
627 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
628 * @attr ref android.R.styleable#View_fitsSystemWindows
629 * @attr ref android.R.styleable#View_isScrollContainer
630 * @attr ref android.R.styleable#View_focusable
631 * @attr ref android.R.styleable#View_focusableInTouchMode
632 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
633 * @attr ref android.R.styleable#View_keepScreenOn
634 * @attr ref android.R.styleable#View_layerType
635 * @attr ref android.R.styleable#View_layoutDirection
636 * @attr ref android.R.styleable#View_longClickable
637 * @attr ref android.R.styleable#View_minHeight
638 * @attr ref android.R.styleable#View_minWidth
639 * @attr ref android.R.styleable#View_nextFocusDown
640 * @attr ref android.R.styleable#View_nextFocusLeft
641 * @attr ref android.R.styleable#View_nextFocusRight
642 * @attr ref android.R.styleable#View_nextFocusUp
643 * @attr ref android.R.styleable#View_onClick
644 * @attr ref android.R.styleable#View_padding
645 * @attr ref android.R.styleable#View_paddingBottom
646 * @attr ref android.R.styleable#View_paddingLeft
647 * @attr ref android.R.styleable#View_paddingRight
648 * @attr ref android.R.styleable#View_paddingTop
649 * @attr ref android.R.styleable#View_paddingStart
650 * @attr ref android.R.styleable#View_paddingEnd
651 * @attr ref android.R.styleable#View_saveEnabled
652 * @attr ref android.R.styleable#View_rotation
653 * @attr ref android.R.styleable#View_rotationX
654 * @attr ref android.R.styleable#View_rotationY
655 * @attr ref android.R.styleable#View_scaleX
656 * @attr ref android.R.styleable#View_scaleY
657 * @attr ref android.R.styleable#View_scrollX
658 * @attr ref android.R.styleable#View_scrollY
659 * @attr ref android.R.styleable#View_scrollbarSize
660 * @attr ref android.R.styleable#View_scrollbarStyle
661 * @attr ref android.R.styleable#View_scrollbars
662 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
663 * @attr ref android.R.styleable#View_scrollbarFadeDuration
664 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
665 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
666 * @attr ref android.R.styleable#View_scrollbarThumbVertical
667 * @attr ref android.R.styleable#View_scrollbarTrackVertical
668 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
669 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
670 * @attr ref android.R.styleable#View_sharedElementName
671 * @attr ref android.R.styleable#View_soundEffectsEnabled
672 * @attr ref android.R.styleable#View_tag
673 * @attr ref android.R.styleable#View_textAlignment
674 * @attr ref android.R.styleable#View_textDirection
675 * @attr ref android.R.styleable#View_transformPivotX
676 * @attr ref android.R.styleable#View_transformPivotY
677 * @attr ref android.R.styleable#View_translationX
678 * @attr ref android.R.styleable#View_translationY
679 * @attr ref android.R.styleable#View_translationZ
680 * @attr ref android.R.styleable#View_visibility
681 *
682 * @see android.view.ViewGroup
683 */
684public class View implements Drawable.Callback, KeyEvent.Callback,
685        AccessibilityEventSource {
686    private static final boolean DBG = false;
687
688    /**
689     * The logging tag used by this class with android.util.Log.
690     */
691    protected static final String VIEW_LOG_TAG = "View";
692
693    /**
694     * When set to true, apps will draw debugging information about their layouts.
695     *
696     * @hide
697     */
698    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
699
700    /**
701     * Used to mark a View that has no ID.
702     */
703    public static final int NO_ID = -1;
704
705    /**
706     * Signals that compatibility booleans have been initialized according to
707     * target SDK versions.
708     */
709    private static boolean sCompatibilityDone = false;
710
711    /**
712     * Use the old (broken) way of building MeasureSpecs.
713     */
714    private static boolean sUseBrokenMakeMeasureSpec = false;
715
716    /**
717     * Ignore any optimizations using the measure cache.
718     */
719    private static boolean sIgnoreMeasureCache = false;
720
721    /**
722     * Ignore the clipBounds of this view for the children.
723     */
724    static boolean sIgnoreClipBoundsForChildren = false;
725
726    /**
727     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
728     * calling setFlags.
729     */
730    private static final int NOT_FOCUSABLE = 0x00000000;
731
732    /**
733     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
734     * setFlags.
735     */
736    private static final int FOCUSABLE = 0x00000001;
737
738    /**
739     * Mask for use with setFlags indicating bits used for focus.
740     */
741    private static final int FOCUSABLE_MASK = 0x00000001;
742
743    /**
744     * This view will adjust its padding to fit sytem windows (e.g. status bar)
745     */
746    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
747
748    /** @hide */
749    @IntDef({VISIBLE, INVISIBLE, GONE})
750    @Retention(RetentionPolicy.SOURCE)
751    public @interface Visibility {}
752
753    /**
754     * This view is visible.
755     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
756     * android:visibility}.
757     */
758    public static final int VISIBLE = 0x00000000;
759
760    /**
761     * This view is invisible, but it still takes up space for layout purposes.
762     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
763     * android:visibility}.
764     */
765    public static final int INVISIBLE = 0x00000004;
766
767    /**
768     * This view is invisible, and it doesn't take any space for layout
769     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
770     * android:visibility}.
771     */
772    public static final int GONE = 0x00000008;
773
774    /**
775     * Mask for use with setFlags indicating bits used for visibility.
776     * {@hide}
777     */
778    static final int VISIBILITY_MASK = 0x0000000C;
779
780    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
781
782    /**
783     * This view is enabled. Interpretation varies by subclass.
784     * Use with ENABLED_MASK when calling setFlags.
785     * {@hide}
786     */
787    static final int ENABLED = 0x00000000;
788
789    /**
790     * This view is disabled. Interpretation varies by subclass.
791     * Use with ENABLED_MASK when calling setFlags.
792     * {@hide}
793     */
794    static final int DISABLED = 0x00000020;
795
796   /**
797    * Mask for use with setFlags indicating bits used for indicating whether
798    * this view is enabled
799    * {@hide}
800    */
801    static final int ENABLED_MASK = 0x00000020;
802
803    /**
804     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
805     * called and further optimizations will be performed. It is okay to have
806     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
807     * {@hide}
808     */
809    static final int WILL_NOT_DRAW = 0x00000080;
810
811    /**
812     * Mask for use with setFlags indicating bits used for indicating whether
813     * this view is will draw
814     * {@hide}
815     */
816    static final int DRAW_MASK = 0x00000080;
817
818    /**
819     * <p>This view doesn't show scrollbars.</p>
820     * {@hide}
821     */
822    static final int SCROLLBARS_NONE = 0x00000000;
823
824    /**
825     * <p>This view shows horizontal scrollbars.</p>
826     * {@hide}
827     */
828    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
829
830    /**
831     * <p>This view shows vertical scrollbars.</p>
832     * {@hide}
833     */
834    static final int SCROLLBARS_VERTICAL = 0x00000200;
835
836    /**
837     * <p>Mask for use with setFlags indicating bits used for indicating which
838     * scrollbars are enabled.</p>
839     * {@hide}
840     */
841    static final int SCROLLBARS_MASK = 0x00000300;
842
843    /**
844     * Indicates that the view should filter touches when its window is obscured.
845     * Refer to the class comments for more information about this security feature.
846     * {@hide}
847     */
848    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
849
850    /**
851     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
852     * that they are optional and should be skipped if the window has
853     * requested system UI flags that ignore those insets for layout.
854     */
855    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
856
857    /**
858     * <p>This view doesn't show fading edges.</p>
859     * {@hide}
860     */
861    static final int FADING_EDGE_NONE = 0x00000000;
862
863    /**
864     * <p>This view shows horizontal fading edges.</p>
865     * {@hide}
866     */
867    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
868
869    /**
870     * <p>This view shows vertical fading edges.</p>
871     * {@hide}
872     */
873    static final int FADING_EDGE_VERTICAL = 0x00002000;
874
875    /**
876     * <p>Mask for use with setFlags indicating bits used for indicating which
877     * fading edges are enabled.</p>
878     * {@hide}
879     */
880    static final int FADING_EDGE_MASK = 0x00003000;
881
882    /**
883     * <p>Indicates this view can be clicked. When clickable, a View reacts
884     * to clicks by notifying the OnClickListener.<p>
885     * {@hide}
886     */
887    static final int CLICKABLE = 0x00004000;
888
889    /**
890     * <p>Indicates this view is caching its drawing into a bitmap.</p>
891     * {@hide}
892     */
893    static final int DRAWING_CACHE_ENABLED = 0x00008000;
894
895    /**
896     * <p>Indicates that no icicle should be saved for this view.<p>
897     * {@hide}
898     */
899    static final int SAVE_DISABLED = 0x000010000;
900
901    /**
902     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
903     * property.</p>
904     * {@hide}
905     */
906    static final int SAVE_DISABLED_MASK = 0x000010000;
907
908    /**
909     * <p>Indicates that no drawing cache should ever be created for this view.<p>
910     * {@hide}
911     */
912    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
913
914    /**
915     * <p>Indicates this view can take / keep focus when int touch mode.</p>
916     * {@hide}
917     */
918    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
919
920    /** @hide */
921    @Retention(RetentionPolicy.SOURCE)
922    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
923    public @interface DrawingCacheQuality {}
924
925    /**
926     * <p>Enables low quality mode for the drawing cache.</p>
927     */
928    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
929
930    /**
931     * <p>Enables high quality mode for the drawing cache.</p>
932     */
933    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
934
935    /**
936     * <p>Enables automatic quality mode for the drawing cache.</p>
937     */
938    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
939
940    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
941            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
942    };
943
944    /**
945     * <p>Mask for use with setFlags indicating bits used for the cache
946     * quality property.</p>
947     * {@hide}
948     */
949    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
950
951    /**
952     * <p>
953     * Indicates this view can be long clicked. When long clickable, a View
954     * reacts to long clicks by notifying the OnLongClickListener or showing a
955     * context menu.
956     * </p>
957     * {@hide}
958     */
959    static final int LONG_CLICKABLE = 0x00200000;
960
961    /**
962     * <p>Indicates that this view gets its drawable states from its direct parent
963     * and ignores its original internal states.</p>
964     *
965     * @hide
966     */
967    static final int DUPLICATE_PARENT_STATE = 0x00400000;
968
969    /** @hide */
970    @IntDef({
971        SCROLLBARS_INSIDE_OVERLAY,
972        SCROLLBARS_INSIDE_INSET,
973        SCROLLBARS_OUTSIDE_OVERLAY,
974        SCROLLBARS_OUTSIDE_INSET
975    })
976    @Retention(RetentionPolicy.SOURCE)
977    public @interface ScrollBarStyle {}
978
979    /**
980     * The scrollbar style to display the scrollbars inside the content area,
981     * without increasing the padding. The scrollbars will be overlaid with
982     * translucency on the view's content.
983     */
984    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
985
986    /**
987     * The scrollbar style to display the scrollbars inside the padded area,
988     * increasing the padding of the view. The scrollbars will not overlap the
989     * content area of the view.
990     */
991    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
992
993    /**
994     * The scrollbar style to display the scrollbars at the edge of the view,
995     * without increasing the padding. The scrollbars will be overlaid with
996     * translucency.
997     */
998    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
999
1000    /**
1001     * The scrollbar style to display the scrollbars at the edge of the view,
1002     * increasing the padding of the view. The scrollbars will only overlap the
1003     * background, if any.
1004     */
1005    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1006
1007    /**
1008     * Mask to check if the scrollbar style is overlay or inset.
1009     * {@hide}
1010     */
1011    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1012
1013    /**
1014     * Mask to check if the scrollbar style is inside or outside.
1015     * {@hide}
1016     */
1017    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1018
1019    /**
1020     * Mask for scrollbar style.
1021     * {@hide}
1022     */
1023    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1024
1025    /**
1026     * View flag indicating that the screen should remain on while the
1027     * window containing this view is visible to the user.  This effectively
1028     * takes care of automatically setting the WindowManager's
1029     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1030     */
1031    public static final int KEEP_SCREEN_ON = 0x04000000;
1032
1033    /**
1034     * View flag indicating whether this view should have sound effects enabled
1035     * for events such as clicking and touching.
1036     */
1037    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1038
1039    /**
1040     * View flag indicating whether this view should have haptic feedback
1041     * enabled for events such as long presses.
1042     */
1043    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1044
1045    /**
1046     * <p>Indicates that the view hierarchy should stop saving state when
1047     * it reaches this view.  If state saving is initiated immediately at
1048     * the view, it will be allowed.
1049     * {@hide}
1050     */
1051    static final int PARENT_SAVE_DISABLED = 0x20000000;
1052
1053    /**
1054     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1055     * {@hide}
1056     */
1057    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1058
1059    /** @hide */
1060    @IntDef(flag = true,
1061            value = {
1062                FOCUSABLES_ALL,
1063                FOCUSABLES_TOUCH_MODE
1064            })
1065    @Retention(RetentionPolicy.SOURCE)
1066    public @interface FocusableMode {}
1067
1068    /**
1069     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1070     * should add all focusable Views regardless if they are focusable in touch mode.
1071     */
1072    public static final int FOCUSABLES_ALL = 0x00000000;
1073
1074    /**
1075     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1076     * should add only Views focusable in touch mode.
1077     */
1078    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1079
1080    /** @hide */
1081    @IntDef({
1082            FOCUS_BACKWARD,
1083            FOCUS_FORWARD,
1084            FOCUS_LEFT,
1085            FOCUS_UP,
1086            FOCUS_RIGHT,
1087            FOCUS_DOWN
1088    })
1089    @Retention(RetentionPolicy.SOURCE)
1090    public @interface FocusDirection {}
1091
1092    /** @hide */
1093    @IntDef({
1094            FOCUS_LEFT,
1095            FOCUS_UP,
1096            FOCUS_RIGHT,
1097            FOCUS_DOWN
1098    })
1099    @Retention(RetentionPolicy.SOURCE)
1100    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1101
1102    /**
1103     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1104     * item.
1105     */
1106    public static final int FOCUS_BACKWARD = 0x00000001;
1107
1108    /**
1109     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1110     * item.
1111     */
1112    public static final int FOCUS_FORWARD = 0x00000002;
1113
1114    /**
1115     * Use with {@link #focusSearch(int)}. Move focus to the left.
1116     */
1117    public static final int FOCUS_LEFT = 0x00000011;
1118
1119    /**
1120     * Use with {@link #focusSearch(int)}. Move focus up.
1121     */
1122    public static final int FOCUS_UP = 0x00000021;
1123
1124    /**
1125     * Use with {@link #focusSearch(int)}. Move focus to the right.
1126     */
1127    public static final int FOCUS_RIGHT = 0x00000042;
1128
1129    /**
1130     * Use with {@link #focusSearch(int)}. Move focus down.
1131     */
1132    public static final int FOCUS_DOWN = 0x00000082;
1133
1134    /**
1135     * Bits of {@link #getMeasuredWidthAndState()} and
1136     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1137     */
1138    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1139
1140    /**
1141     * Bits of {@link #getMeasuredWidthAndState()} and
1142     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1143     */
1144    public static final int MEASURED_STATE_MASK = 0xff000000;
1145
1146    /**
1147     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1148     * for functions that combine both width and height into a single int,
1149     * such as {@link #getMeasuredState()} and the childState argument of
1150     * {@link #resolveSizeAndState(int, int, int)}.
1151     */
1152    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1153
1154    /**
1155     * Bit of {@link #getMeasuredWidthAndState()} and
1156     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1157     * is smaller that the space the view would like to have.
1158     */
1159    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1160
1161    /**
1162     * Base View state sets
1163     */
1164    // Singles
1165    /**
1166     * Indicates the view has no states set. States are used with
1167     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1168     * view depending on its state.
1169     *
1170     * @see android.graphics.drawable.Drawable
1171     * @see #getDrawableState()
1172     */
1173    protected static final int[] EMPTY_STATE_SET;
1174    /**
1175     * Indicates the view is enabled. States are used with
1176     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1177     * view depending on its state.
1178     *
1179     * @see android.graphics.drawable.Drawable
1180     * @see #getDrawableState()
1181     */
1182    protected static final int[] ENABLED_STATE_SET;
1183    /**
1184     * Indicates the view is focused. States are used with
1185     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1186     * view depending on its state.
1187     *
1188     * @see android.graphics.drawable.Drawable
1189     * @see #getDrawableState()
1190     */
1191    protected static final int[] FOCUSED_STATE_SET;
1192    /**
1193     * Indicates the view is selected. States are used with
1194     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1195     * view depending on its state.
1196     *
1197     * @see android.graphics.drawable.Drawable
1198     * @see #getDrawableState()
1199     */
1200    protected static final int[] SELECTED_STATE_SET;
1201    /**
1202     * Indicates the view is pressed. States are used with
1203     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1204     * view depending on its state.
1205     *
1206     * @see android.graphics.drawable.Drawable
1207     * @see #getDrawableState()
1208     */
1209    protected static final int[] PRESSED_STATE_SET;
1210    /**
1211     * Indicates the view's window has focus. States are used with
1212     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1213     * view depending on its state.
1214     *
1215     * @see android.graphics.drawable.Drawable
1216     * @see #getDrawableState()
1217     */
1218    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1219    // Doubles
1220    /**
1221     * Indicates the view is enabled and has the focus.
1222     *
1223     * @see #ENABLED_STATE_SET
1224     * @see #FOCUSED_STATE_SET
1225     */
1226    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1227    /**
1228     * Indicates the view is enabled and selected.
1229     *
1230     * @see #ENABLED_STATE_SET
1231     * @see #SELECTED_STATE_SET
1232     */
1233    protected static final int[] ENABLED_SELECTED_STATE_SET;
1234    /**
1235     * Indicates the view is enabled and that its window has focus.
1236     *
1237     * @see #ENABLED_STATE_SET
1238     * @see #WINDOW_FOCUSED_STATE_SET
1239     */
1240    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1241    /**
1242     * Indicates the view is focused and selected.
1243     *
1244     * @see #FOCUSED_STATE_SET
1245     * @see #SELECTED_STATE_SET
1246     */
1247    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1248    /**
1249     * Indicates the view has the focus and that its window has the focus.
1250     *
1251     * @see #FOCUSED_STATE_SET
1252     * @see #WINDOW_FOCUSED_STATE_SET
1253     */
1254    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1255    /**
1256     * Indicates the view is selected and that its window has the focus.
1257     *
1258     * @see #SELECTED_STATE_SET
1259     * @see #WINDOW_FOCUSED_STATE_SET
1260     */
1261    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1262    // Triples
1263    /**
1264     * Indicates the view is enabled, focused and selected.
1265     *
1266     * @see #ENABLED_STATE_SET
1267     * @see #FOCUSED_STATE_SET
1268     * @see #SELECTED_STATE_SET
1269     */
1270    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1271    /**
1272     * Indicates the view is enabled, focused and its window has the focus.
1273     *
1274     * @see #ENABLED_STATE_SET
1275     * @see #FOCUSED_STATE_SET
1276     * @see #WINDOW_FOCUSED_STATE_SET
1277     */
1278    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1279    /**
1280     * Indicates the view is enabled, selected and its window has the focus.
1281     *
1282     * @see #ENABLED_STATE_SET
1283     * @see #SELECTED_STATE_SET
1284     * @see #WINDOW_FOCUSED_STATE_SET
1285     */
1286    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1287    /**
1288     * Indicates the view is focused, selected and its window has the focus.
1289     *
1290     * @see #FOCUSED_STATE_SET
1291     * @see #SELECTED_STATE_SET
1292     * @see #WINDOW_FOCUSED_STATE_SET
1293     */
1294    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1295    /**
1296     * Indicates the view is enabled, focused, selected and its window
1297     * has the focus.
1298     *
1299     * @see #ENABLED_STATE_SET
1300     * @see #FOCUSED_STATE_SET
1301     * @see #SELECTED_STATE_SET
1302     * @see #WINDOW_FOCUSED_STATE_SET
1303     */
1304    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1305    /**
1306     * Indicates the view is pressed and its window has the focus.
1307     *
1308     * @see #PRESSED_STATE_SET
1309     * @see #WINDOW_FOCUSED_STATE_SET
1310     */
1311    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1312    /**
1313     * Indicates the view is pressed and selected.
1314     *
1315     * @see #PRESSED_STATE_SET
1316     * @see #SELECTED_STATE_SET
1317     */
1318    protected static final int[] PRESSED_SELECTED_STATE_SET;
1319    /**
1320     * Indicates the view is pressed, selected and its window has the focus.
1321     *
1322     * @see #PRESSED_STATE_SET
1323     * @see #SELECTED_STATE_SET
1324     * @see #WINDOW_FOCUSED_STATE_SET
1325     */
1326    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1327    /**
1328     * Indicates the view is pressed and focused.
1329     *
1330     * @see #PRESSED_STATE_SET
1331     * @see #FOCUSED_STATE_SET
1332     */
1333    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1334    /**
1335     * Indicates the view is pressed, focused and its window has the focus.
1336     *
1337     * @see #PRESSED_STATE_SET
1338     * @see #FOCUSED_STATE_SET
1339     * @see #WINDOW_FOCUSED_STATE_SET
1340     */
1341    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1342    /**
1343     * Indicates the view is pressed, focused and selected.
1344     *
1345     * @see #PRESSED_STATE_SET
1346     * @see #SELECTED_STATE_SET
1347     * @see #FOCUSED_STATE_SET
1348     */
1349    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1350    /**
1351     * Indicates the view is pressed, focused, selected and its window has the focus.
1352     *
1353     * @see #PRESSED_STATE_SET
1354     * @see #FOCUSED_STATE_SET
1355     * @see #SELECTED_STATE_SET
1356     * @see #WINDOW_FOCUSED_STATE_SET
1357     */
1358    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1359    /**
1360     * Indicates the view is pressed and enabled.
1361     *
1362     * @see #PRESSED_STATE_SET
1363     * @see #ENABLED_STATE_SET
1364     */
1365    protected static final int[] PRESSED_ENABLED_STATE_SET;
1366    /**
1367     * Indicates the view is pressed, enabled and its window has the focus.
1368     *
1369     * @see #PRESSED_STATE_SET
1370     * @see #ENABLED_STATE_SET
1371     * @see #WINDOW_FOCUSED_STATE_SET
1372     */
1373    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1374    /**
1375     * Indicates the view is pressed, enabled and selected.
1376     *
1377     * @see #PRESSED_STATE_SET
1378     * @see #ENABLED_STATE_SET
1379     * @see #SELECTED_STATE_SET
1380     */
1381    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1382    /**
1383     * Indicates the view is pressed, enabled, selected and its window has the
1384     * focus.
1385     *
1386     * @see #PRESSED_STATE_SET
1387     * @see #ENABLED_STATE_SET
1388     * @see #SELECTED_STATE_SET
1389     * @see #WINDOW_FOCUSED_STATE_SET
1390     */
1391    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1392    /**
1393     * Indicates the view is pressed, enabled and focused.
1394     *
1395     * @see #PRESSED_STATE_SET
1396     * @see #ENABLED_STATE_SET
1397     * @see #FOCUSED_STATE_SET
1398     */
1399    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1400    /**
1401     * Indicates the view is pressed, enabled, focused and its window has the
1402     * focus.
1403     *
1404     * @see #PRESSED_STATE_SET
1405     * @see #ENABLED_STATE_SET
1406     * @see #FOCUSED_STATE_SET
1407     * @see #WINDOW_FOCUSED_STATE_SET
1408     */
1409    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1410    /**
1411     * Indicates the view is pressed, enabled, focused and selected.
1412     *
1413     * @see #PRESSED_STATE_SET
1414     * @see #ENABLED_STATE_SET
1415     * @see #SELECTED_STATE_SET
1416     * @see #FOCUSED_STATE_SET
1417     */
1418    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1419    /**
1420     * Indicates the view is pressed, enabled, focused, selected and its window
1421     * has the focus.
1422     *
1423     * @see #PRESSED_STATE_SET
1424     * @see #ENABLED_STATE_SET
1425     * @see #SELECTED_STATE_SET
1426     * @see #FOCUSED_STATE_SET
1427     * @see #WINDOW_FOCUSED_STATE_SET
1428     */
1429    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1430
1431    /**
1432     * The order here is very important to {@link #getDrawableState()}
1433     */
1434    private static final int[][] VIEW_STATE_SETS;
1435
1436    static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1437    static final int VIEW_STATE_SELECTED = 1 << 1;
1438    static final int VIEW_STATE_FOCUSED = 1 << 2;
1439    static final int VIEW_STATE_ENABLED = 1 << 3;
1440    static final int VIEW_STATE_PRESSED = 1 << 4;
1441    static final int VIEW_STATE_ACTIVATED = 1 << 5;
1442    static final int VIEW_STATE_ACCELERATED = 1 << 6;
1443    static final int VIEW_STATE_HOVERED = 1 << 7;
1444    static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1445    static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
1446
1447    static final int[] VIEW_STATE_IDS = new int[] {
1448        R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
1449        R.attr.state_selected,          VIEW_STATE_SELECTED,
1450        R.attr.state_focused,           VIEW_STATE_FOCUSED,
1451        R.attr.state_enabled,           VIEW_STATE_ENABLED,
1452        R.attr.state_pressed,           VIEW_STATE_PRESSED,
1453        R.attr.state_activated,         VIEW_STATE_ACTIVATED,
1454        R.attr.state_accelerated,       VIEW_STATE_ACCELERATED,
1455        R.attr.state_hovered,           VIEW_STATE_HOVERED,
1456        R.attr.state_drag_can_accept,   VIEW_STATE_DRAG_CAN_ACCEPT,
1457        R.attr.state_drag_hovered,      VIEW_STATE_DRAG_HOVERED
1458    };
1459
1460    static {
1461        if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1462            throw new IllegalStateException(
1463                    "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1464        }
1465        int[] orderedIds = new int[VIEW_STATE_IDS.length];
1466        for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
1467            int viewState = R.styleable.ViewDrawableStates[i];
1468            for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
1469                if (VIEW_STATE_IDS[j] == viewState) {
1470                    orderedIds[i * 2] = viewState;
1471                    orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
1472                }
1473            }
1474        }
1475        final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1476        VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1477        for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
1478            int numBits = Integer.bitCount(i);
1479            int[] set = new int[numBits];
1480            int pos = 0;
1481            for (int j = 0; j < orderedIds.length; j += 2) {
1482                if ((i & orderedIds[j+1]) != 0) {
1483                    set[pos++] = orderedIds[j];
1484                }
1485            }
1486            VIEW_STATE_SETS[i] = set;
1487        }
1488
1489        EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1490        WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1491        SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1492        SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1493                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1494        FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1495        FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1496                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1497        FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1498                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1499        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1500                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1501                | VIEW_STATE_FOCUSED];
1502        ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1503        ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1504                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1505        ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1506                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1507        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1508                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1509                | VIEW_STATE_ENABLED];
1510        ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1511                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1512        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1513                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1514                | VIEW_STATE_ENABLED];
1515        ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1516                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1517                | VIEW_STATE_ENABLED];
1518        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1519                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1520                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1521
1522        PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1523        PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1524                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1525        PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1526                VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1527        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1528                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1529                | VIEW_STATE_PRESSED];
1530        PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1531                VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1532        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1533                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1534                | VIEW_STATE_PRESSED];
1535        PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1536                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1537                | VIEW_STATE_PRESSED];
1538        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1539                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1540                | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1541        PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1542                VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1543        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1544                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1545                | VIEW_STATE_PRESSED];
1546        PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1547                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1548                | VIEW_STATE_PRESSED];
1549        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1550                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1551                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1552        PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1553                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1554                | VIEW_STATE_PRESSED];
1555        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1556                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1557                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1558        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1559                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1560                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1561        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1562                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1563                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1564                | VIEW_STATE_PRESSED];
1565    }
1566
1567    /**
1568     * Accessibility event types that are dispatched for text population.
1569     */
1570    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1571            AccessibilityEvent.TYPE_VIEW_CLICKED
1572            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1573            | AccessibilityEvent.TYPE_VIEW_SELECTED
1574            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1575            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1576            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1577            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1578            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1579            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1580            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1581            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1582
1583    /**
1584     * Temporary Rect currently for use in setBackground().  This will probably
1585     * be extended in the future to hold our own class with more than just
1586     * a Rect. :)
1587     */
1588    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1589
1590    /**
1591     * Map used to store views' tags.
1592     */
1593    private SparseArray<Object> mKeyedTags;
1594
1595    /**
1596     * The next available accessibility id.
1597     */
1598    private static int sNextAccessibilityViewId;
1599
1600    /**
1601     * The animation currently associated with this view.
1602     * @hide
1603     */
1604    protected Animation mCurrentAnimation = null;
1605
1606    /**
1607     * Width as measured during measure pass.
1608     * {@hide}
1609     */
1610    @ViewDebug.ExportedProperty(category = "measurement")
1611    int mMeasuredWidth;
1612
1613    /**
1614     * Height as measured during measure pass.
1615     * {@hide}
1616     */
1617    @ViewDebug.ExportedProperty(category = "measurement")
1618    int mMeasuredHeight;
1619
1620    /**
1621     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1622     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1623     * its display list. This flag, used only when hw accelerated, allows us to clear the
1624     * flag while retaining this information until it's needed (at getDisplayList() time and
1625     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1626     *
1627     * {@hide}
1628     */
1629    boolean mRecreateDisplayList = false;
1630
1631    /**
1632     * The view's identifier.
1633     * {@hide}
1634     *
1635     * @see #setId(int)
1636     * @see #getId()
1637     */
1638    @ViewDebug.ExportedProperty(resolveId = true)
1639    int mID = NO_ID;
1640
1641    /**
1642     * The stable ID of this view for accessibility purposes.
1643     */
1644    int mAccessibilityViewId = NO_ID;
1645
1646    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1647
1648    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1649
1650    /**
1651     * The view's tag.
1652     * {@hide}
1653     *
1654     * @see #setTag(Object)
1655     * @see #getTag()
1656     */
1657    protected Object mTag = null;
1658
1659    // for mPrivateFlags:
1660    /** {@hide} */
1661    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1662    /** {@hide} */
1663    static final int PFLAG_FOCUSED                     = 0x00000002;
1664    /** {@hide} */
1665    static final int PFLAG_SELECTED                    = 0x00000004;
1666    /** {@hide} */
1667    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1668    /** {@hide} */
1669    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1670    /** {@hide} */
1671    static final int PFLAG_DRAWN                       = 0x00000020;
1672    /**
1673     * When this flag is set, this view is running an animation on behalf of its
1674     * children and should therefore not cancel invalidate requests, even if they
1675     * lie outside of this view's bounds.
1676     *
1677     * {@hide}
1678     */
1679    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1680    /** {@hide} */
1681    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1682    /** {@hide} */
1683    static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
1684    /** {@hide} */
1685    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1686    /** {@hide} */
1687    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1688    /** {@hide} */
1689    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1690    /** {@hide} */
1691    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1692    /** {@hide} */
1693    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1694
1695    private static final int PFLAG_PRESSED             = 0x00004000;
1696
1697    /** {@hide} */
1698    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1699    /**
1700     * Flag used to indicate that this view should be drawn once more (and only once
1701     * more) after its animation has completed.
1702     * {@hide}
1703     */
1704    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1705
1706    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1707
1708    /**
1709     * Indicates that the View returned true when onSetAlpha() was called and that
1710     * the alpha must be restored.
1711     * {@hide}
1712     */
1713    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1714
1715    /**
1716     * Set by {@link #setScrollContainer(boolean)}.
1717     */
1718    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1719
1720    /**
1721     * Set by {@link #setScrollContainer(boolean)}.
1722     */
1723    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1724
1725    /**
1726     * View flag indicating whether this view was invalidated (fully or partially.)
1727     *
1728     * @hide
1729     */
1730    static final int PFLAG_DIRTY                       = 0x00200000;
1731
1732    /**
1733     * View flag indicating whether this view was invalidated by an opaque
1734     * invalidate request.
1735     *
1736     * @hide
1737     */
1738    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1739
1740    /**
1741     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1742     *
1743     * @hide
1744     */
1745    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1746
1747    /**
1748     * Indicates whether the background is opaque.
1749     *
1750     * @hide
1751     */
1752    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1753
1754    /**
1755     * Indicates whether the scrollbars are opaque.
1756     *
1757     * @hide
1758     */
1759    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1760
1761    /**
1762     * Indicates whether the view is opaque.
1763     *
1764     * @hide
1765     */
1766    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1767
1768    /**
1769     * Indicates a prepressed state;
1770     * the short time between ACTION_DOWN and recognizing
1771     * a 'real' press. Prepressed is used to recognize quick taps
1772     * even when they are shorter than ViewConfiguration.getTapTimeout().
1773     *
1774     * @hide
1775     */
1776    private static final int PFLAG_PREPRESSED          = 0x02000000;
1777
1778    /**
1779     * Indicates whether the view is temporarily detached.
1780     *
1781     * @hide
1782     */
1783    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1784
1785    /**
1786     * Indicates that we should awaken scroll bars once attached
1787     *
1788     * @hide
1789     */
1790    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1791
1792    /**
1793     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1794     * @hide
1795     */
1796    private static final int PFLAG_HOVERED             = 0x10000000;
1797
1798    /**
1799     * no longer needed, should be reused
1800     */
1801    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1802
1803    /** {@hide} */
1804    static final int PFLAG_ACTIVATED                   = 0x40000000;
1805
1806    /**
1807     * Indicates that this view was specifically invalidated, not just dirtied because some
1808     * child view was invalidated. The flag is used to determine when we need to recreate
1809     * a view's display list (as opposed to just returning a reference to its existing
1810     * display list).
1811     *
1812     * @hide
1813     */
1814    static final int PFLAG_INVALIDATED                 = 0x80000000;
1815
1816    /**
1817     * Masks for mPrivateFlags2, as generated by dumpFlags():
1818     *
1819     * |-------|-------|-------|-------|
1820     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1821     *                                1  PFLAG2_DRAG_HOVERED
1822     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1823     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1824     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1825     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1826     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1827     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1828     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1829     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1830     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1831     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1832     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1833     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1834     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1835     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1836     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1837     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1838     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1839     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1840     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1841     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1842     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1843     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1844     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1845     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1846     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1847     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1848     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1849     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1850     *    1                              PFLAG2_PADDING_RESOLVED
1851     *   1                               PFLAG2_DRAWABLE_RESOLVED
1852     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1853     * |-------|-------|-------|-------|
1854     */
1855
1856    /**
1857     * Indicates that this view has reported that it can accept the current drag's content.
1858     * Cleared when the drag operation concludes.
1859     * @hide
1860     */
1861    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1862
1863    /**
1864     * Indicates that this view is currently directly under the drag location in a
1865     * drag-and-drop operation involving content that it can accept.  Cleared when
1866     * the drag exits the view, or when the drag operation concludes.
1867     * @hide
1868     */
1869    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1870
1871    /** @hide */
1872    @IntDef({
1873        LAYOUT_DIRECTION_LTR,
1874        LAYOUT_DIRECTION_RTL,
1875        LAYOUT_DIRECTION_INHERIT,
1876        LAYOUT_DIRECTION_LOCALE
1877    })
1878    @Retention(RetentionPolicy.SOURCE)
1879    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1880    public @interface LayoutDir {}
1881
1882    /** @hide */
1883    @IntDef({
1884        LAYOUT_DIRECTION_LTR,
1885        LAYOUT_DIRECTION_RTL
1886    })
1887    @Retention(RetentionPolicy.SOURCE)
1888    public @interface ResolvedLayoutDir {}
1889
1890    /**
1891     * Horizontal layout direction of this view is from Left to Right.
1892     * Use with {@link #setLayoutDirection}.
1893     */
1894    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1895
1896    /**
1897     * Horizontal layout direction of this view is from Right to Left.
1898     * Use with {@link #setLayoutDirection}.
1899     */
1900    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1901
1902    /**
1903     * Horizontal layout direction of this view is inherited from its parent.
1904     * Use with {@link #setLayoutDirection}.
1905     */
1906    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1907
1908    /**
1909     * Horizontal layout direction of this view is from deduced from the default language
1910     * script for the locale. Use with {@link #setLayoutDirection}.
1911     */
1912    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1913
1914    /**
1915     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1916     * @hide
1917     */
1918    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1919
1920    /**
1921     * Mask for use with private flags indicating bits used for horizontal layout direction.
1922     * @hide
1923     */
1924    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1925
1926    /**
1927     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1928     * right-to-left direction.
1929     * @hide
1930     */
1931    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1932
1933    /**
1934     * Indicates whether the view horizontal layout direction has been resolved.
1935     * @hide
1936     */
1937    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1938
1939    /**
1940     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1941     * @hide
1942     */
1943    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1944            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1945
1946    /*
1947     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1948     * flag value.
1949     * @hide
1950     */
1951    private static final int[] LAYOUT_DIRECTION_FLAGS = {
1952            LAYOUT_DIRECTION_LTR,
1953            LAYOUT_DIRECTION_RTL,
1954            LAYOUT_DIRECTION_INHERIT,
1955            LAYOUT_DIRECTION_LOCALE
1956    };
1957
1958    /**
1959     * Default horizontal layout direction.
1960     */
1961    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1962
1963    /**
1964     * Default horizontal layout direction.
1965     * @hide
1966     */
1967    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1968
1969    /**
1970     * Text direction is inherited thru {@link ViewGroup}
1971     */
1972    public static final int TEXT_DIRECTION_INHERIT = 0;
1973
1974    /**
1975     * Text direction is using "first strong algorithm". The first strong directional character
1976     * determines the paragraph direction. If there is no strong directional character, the
1977     * paragraph direction is the view's resolved layout direction.
1978     */
1979    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1980
1981    /**
1982     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1983     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1984     * If there are neither, the paragraph direction is the view's resolved layout direction.
1985     */
1986    public static final int TEXT_DIRECTION_ANY_RTL = 2;
1987
1988    /**
1989     * Text direction is forced to LTR.
1990     */
1991    public static final int TEXT_DIRECTION_LTR = 3;
1992
1993    /**
1994     * Text direction is forced to RTL.
1995     */
1996    public static final int TEXT_DIRECTION_RTL = 4;
1997
1998    /**
1999     * Text direction is coming from the system Locale.
2000     */
2001    public static final int TEXT_DIRECTION_LOCALE = 5;
2002
2003    /**
2004     * Default text direction is inherited
2005     */
2006    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2007
2008    /**
2009     * Default resolved text direction
2010     * @hide
2011     */
2012    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2013
2014    /**
2015     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2016     * @hide
2017     */
2018    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2019
2020    /**
2021     * Mask for use with private flags indicating bits used for text direction.
2022     * @hide
2023     */
2024    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2025            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2026
2027    /**
2028     * Array of text direction flags for mapping attribute "textDirection" to correct
2029     * flag value.
2030     * @hide
2031     */
2032    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2033            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2034            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2035            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2036            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2037            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2038            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2039    };
2040
2041    /**
2042     * Indicates whether the view text direction has been resolved.
2043     * @hide
2044     */
2045    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2046            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2047
2048    /**
2049     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2050     * @hide
2051     */
2052    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2053
2054    /**
2055     * Mask for use with private flags indicating bits used for resolved text direction.
2056     * @hide
2057     */
2058    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2059            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2060
2061    /**
2062     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2063     * @hide
2064     */
2065    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2066            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2067
2068    /** @hide */
2069    @IntDef({
2070        TEXT_ALIGNMENT_INHERIT,
2071        TEXT_ALIGNMENT_GRAVITY,
2072        TEXT_ALIGNMENT_CENTER,
2073        TEXT_ALIGNMENT_TEXT_START,
2074        TEXT_ALIGNMENT_TEXT_END,
2075        TEXT_ALIGNMENT_VIEW_START,
2076        TEXT_ALIGNMENT_VIEW_END
2077    })
2078    @Retention(RetentionPolicy.SOURCE)
2079    public @interface TextAlignment {}
2080
2081    /**
2082     * Default text alignment. The text alignment of this View is inherited from its parent.
2083     * Use with {@link #setTextAlignment(int)}
2084     */
2085    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2086
2087    /**
2088     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2089     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2090     *
2091     * Use with {@link #setTextAlignment(int)}
2092     */
2093    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2094
2095    /**
2096     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2097     *
2098     * Use with {@link #setTextAlignment(int)}
2099     */
2100    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2101
2102    /**
2103     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2104     *
2105     * Use with {@link #setTextAlignment(int)}
2106     */
2107    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2108
2109    /**
2110     * Center the paragraph, e.g. ALIGN_CENTER.
2111     *
2112     * Use with {@link #setTextAlignment(int)}
2113     */
2114    public static final int TEXT_ALIGNMENT_CENTER = 4;
2115
2116    /**
2117     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2118     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2119     *
2120     * Use with {@link #setTextAlignment(int)}
2121     */
2122    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2123
2124    /**
2125     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2126     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2127     *
2128     * Use with {@link #setTextAlignment(int)}
2129     */
2130    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2131
2132    /**
2133     * Default text alignment is inherited
2134     */
2135    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2136
2137    /**
2138     * Default resolved text alignment
2139     * @hide
2140     */
2141    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2142
2143    /**
2144      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2145      * @hide
2146      */
2147    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2148
2149    /**
2150      * Mask for use with private flags indicating bits used for text alignment.
2151      * @hide
2152      */
2153    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2154
2155    /**
2156     * Array of text direction flags for mapping attribute "textAlignment" to correct
2157     * flag value.
2158     * @hide
2159     */
2160    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2161            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2162            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2163            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2164            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2165            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2166            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2167            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2168    };
2169
2170    /**
2171     * Indicates whether the view text alignment has been resolved.
2172     * @hide
2173     */
2174    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2175
2176    /**
2177     * Bit shift to get the resolved text alignment.
2178     * @hide
2179     */
2180    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2181
2182    /**
2183     * Mask for use with private flags indicating bits used for text alignment.
2184     * @hide
2185     */
2186    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2187            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2188
2189    /**
2190     * Indicates whether if the view text alignment has been resolved to gravity
2191     */
2192    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2193            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2194
2195    // Accessiblity constants for mPrivateFlags2
2196
2197    /**
2198     * Shift for the bits in {@link #mPrivateFlags2} related to the
2199     * "importantForAccessibility" attribute.
2200     */
2201    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2202
2203    /**
2204     * Automatically determine whether a view is important for accessibility.
2205     */
2206    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2207
2208    /**
2209     * The view is important for accessibility.
2210     */
2211    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2212
2213    /**
2214     * The view is not important for accessibility.
2215     */
2216    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2217
2218    /**
2219     * The view is not important for accessibility, nor are any of its
2220     * descendant views.
2221     */
2222    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2223
2224    /**
2225     * The default whether the view is important for accessibility.
2226     */
2227    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2228
2229    /**
2230     * Mask for obtainig the bits which specify how to determine
2231     * whether a view is important for accessibility.
2232     */
2233    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2234        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2235        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2236        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2237
2238    /**
2239     * Shift for the bits in {@link #mPrivateFlags2} related to the
2240     * "accessibilityLiveRegion" attribute.
2241     */
2242    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2243
2244    /**
2245     * Live region mode specifying that accessibility services should not
2246     * automatically announce changes to this view. This is the default live
2247     * region mode for most views.
2248     * <p>
2249     * Use with {@link #setAccessibilityLiveRegion(int)}.
2250     */
2251    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2252
2253    /**
2254     * Live region mode specifying that accessibility services should announce
2255     * changes to this view.
2256     * <p>
2257     * Use with {@link #setAccessibilityLiveRegion(int)}.
2258     */
2259    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2260
2261    /**
2262     * Live region mode specifying that accessibility services should interrupt
2263     * ongoing speech to immediately announce changes to this view.
2264     * <p>
2265     * Use with {@link #setAccessibilityLiveRegion(int)}.
2266     */
2267    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2268
2269    /**
2270     * The default whether the view is important for accessibility.
2271     */
2272    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2273
2274    /**
2275     * Mask for obtaining the bits which specify a view's accessibility live
2276     * region mode.
2277     */
2278    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2279            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2280            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2281
2282    /**
2283     * Flag indicating whether a view has accessibility focus.
2284     */
2285    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2286
2287    /**
2288     * Flag whether the accessibility state of the subtree rooted at this view changed.
2289     */
2290    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2291
2292    /**
2293     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2294     * is used to check whether later changes to the view's transform should invalidate the
2295     * view to force the quickReject test to run again.
2296     */
2297    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2298
2299    /**
2300     * Flag indicating that start/end padding has been resolved into left/right padding
2301     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2302     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2303     * during measurement. In some special cases this is required such as when an adapter-based
2304     * view measures prospective children without attaching them to a window.
2305     */
2306    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2307
2308    /**
2309     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2310     */
2311    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2312
2313    /**
2314     * Indicates that the view is tracking some sort of transient state
2315     * that the app should not need to be aware of, but that the framework
2316     * should take special care to preserve.
2317     */
2318    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2319
2320    /**
2321     * Group of bits indicating that RTL properties resolution is done.
2322     */
2323    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2324            PFLAG2_TEXT_DIRECTION_RESOLVED |
2325            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2326            PFLAG2_PADDING_RESOLVED |
2327            PFLAG2_DRAWABLE_RESOLVED;
2328
2329    // There are a couple of flags left in mPrivateFlags2
2330
2331    /* End of masks for mPrivateFlags2 */
2332
2333    /**
2334     * Masks for mPrivateFlags3, as generated by dumpFlags():
2335     *
2336     * |-------|-------|-------|-------|
2337     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2338     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2339     *                               1   PFLAG3_IS_LAID_OUT
2340     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2341     *                             1     PFLAG3_CALLED_SUPER
2342     * |-------|-------|-------|-------|
2343     */
2344
2345    /**
2346     * Flag indicating that view has a transform animation set on it. This is used to track whether
2347     * an animation is cleared between successive frames, in order to tell the associated
2348     * DisplayList to clear its animation matrix.
2349     */
2350    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2351
2352    /**
2353     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2354     * animation is cleared between successive frames, in order to tell the associated
2355     * DisplayList to restore its alpha value.
2356     */
2357    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2358
2359    /**
2360     * Flag indicating that the view has been through at least one layout since it
2361     * was last attached to a window.
2362     */
2363    static final int PFLAG3_IS_LAID_OUT = 0x4;
2364
2365    /**
2366     * Flag indicating that a call to measure() was skipped and should be done
2367     * instead when layout() is invoked.
2368     */
2369    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2370
2371    /**
2372     * Flag indicating that an overridden method correctly  called down to
2373     * the superclass implementation as required by the API spec.
2374     */
2375    static final int PFLAG3_CALLED_SUPER = 0x10;
2376
2377    /**
2378     * Flag indicating that a view's outline has been specifically defined.
2379     */
2380    static final int PFLAG3_OUTLINE_DEFINED = 0x20;
2381
2382    /**
2383     * Flag indicating that we're in the process of applying window insets.
2384     */
2385    static final int PFLAG3_APPLYING_INSETS = 0x40;
2386
2387    /**
2388     * Flag indicating that we're in the process of fitting system windows using the old method.
2389     */
2390    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x80;
2391
2392    /**
2393     * Flag indicating that nested scrolling is enabled for this view.
2394     * The view will optionally cooperate with views up its parent chain to allow for
2395     * integrated nested scrolling along the same axis.
2396     */
2397    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x200;
2398
2399    /* End of masks for mPrivateFlags3 */
2400
2401    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2402
2403    /**
2404     * Always allow a user to over-scroll this view, provided it is a
2405     * view that can scroll.
2406     *
2407     * @see #getOverScrollMode()
2408     * @see #setOverScrollMode(int)
2409     */
2410    public static final int OVER_SCROLL_ALWAYS = 0;
2411
2412    /**
2413     * Allow a user to over-scroll this view only if the content is large
2414     * enough to meaningfully scroll, provided it is a view that can scroll.
2415     *
2416     * @see #getOverScrollMode()
2417     * @see #setOverScrollMode(int)
2418     */
2419    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2420
2421    /**
2422     * Never allow a user to over-scroll this view.
2423     *
2424     * @see #getOverScrollMode()
2425     * @see #setOverScrollMode(int)
2426     */
2427    public static final int OVER_SCROLL_NEVER = 2;
2428
2429    /**
2430     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2431     * requested the system UI (status bar) to be visible (the default).
2432     *
2433     * @see #setSystemUiVisibility(int)
2434     */
2435    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2436
2437    /**
2438     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2439     * system UI to enter an unobtrusive "low profile" mode.
2440     *
2441     * <p>This is for use in games, book readers, video players, or any other
2442     * "immersive" application where the usual system chrome is deemed too distracting.
2443     *
2444     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2445     *
2446     * @see #setSystemUiVisibility(int)
2447     */
2448    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2449
2450    /**
2451     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2452     * system navigation be temporarily hidden.
2453     *
2454     * <p>This is an even less obtrusive state than that called for by
2455     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2456     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2457     * those to disappear. This is useful (in conjunction with the
2458     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2459     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2460     * window flags) for displaying content using every last pixel on the display.
2461     *
2462     * <p>There is a limitation: because navigation controls are so important, the least user
2463     * interaction will cause them to reappear immediately.  When this happens, both
2464     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2465     * so that both elements reappear at the same time.
2466     *
2467     * @see #setSystemUiVisibility(int)
2468     */
2469    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2470
2471    /**
2472     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2473     * into the normal fullscreen mode so that its content can take over the screen
2474     * while still allowing the user to interact with the application.
2475     *
2476     * <p>This has the same visual effect as
2477     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2478     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2479     * meaning that non-critical screen decorations (such as the status bar) will be
2480     * hidden while the user is in the View's window, focusing the experience on
2481     * that content.  Unlike the window flag, if you are using ActionBar in
2482     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2483     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2484     * hide the action bar.
2485     *
2486     * <p>This approach to going fullscreen is best used over the window flag when
2487     * it is a transient state -- that is, the application does this at certain
2488     * points in its user interaction where it wants to allow the user to focus
2489     * on content, but not as a continuous state.  For situations where the application
2490     * would like to simply stay full screen the entire time (such as a game that
2491     * wants to take over the screen), the
2492     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2493     * is usually a better approach.  The state set here will be removed by the system
2494     * in various situations (such as the user moving to another application) like
2495     * the other system UI states.
2496     *
2497     * <p>When using this flag, the application should provide some easy facility
2498     * for the user to go out of it.  A common example would be in an e-book
2499     * reader, where tapping on the screen brings back whatever screen and UI
2500     * decorations that had been hidden while the user was immersed in reading
2501     * the book.
2502     *
2503     * @see #setSystemUiVisibility(int)
2504     */
2505    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2506
2507    /**
2508     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2509     * flags, we would like a stable view of the content insets given to
2510     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2511     * will always represent the worst case that the application can expect
2512     * as a continuous state.  In the stock Android UI this is the space for
2513     * the system bar, nav bar, and status bar, but not more transient elements
2514     * such as an input method.
2515     *
2516     * The stable layout your UI sees is based on the system UI modes you can
2517     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2518     * then you will get a stable layout for changes of the
2519     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2520     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2521     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2522     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2523     * with a stable layout.  (Note that you should avoid using
2524     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2525     *
2526     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2527     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2528     * then a hidden status bar will be considered a "stable" state for purposes
2529     * here.  This allows your UI to continually hide the status bar, while still
2530     * using the system UI flags to hide the action bar while still retaining
2531     * a stable layout.  Note that changing the window fullscreen flag will never
2532     * provide a stable layout for a clean transition.
2533     *
2534     * <p>If you are using ActionBar in
2535     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2536     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2537     * insets it adds to those given to the application.
2538     */
2539    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2540
2541    /**
2542     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2543     * to be layed out as if it has requested
2544     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2545     * allows it to avoid artifacts when switching in and out of that mode, at
2546     * the expense that some of its user interface may be covered by screen
2547     * decorations when they are shown.  You can perform layout of your inner
2548     * UI elements to account for the navigation system UI through the
2549     * {@link #fitSystemWindows(Rect)} method.
2550     */
2551    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2552
2553    /**
2554     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2555     * to be layed out as if it has requested
2556     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2557     * allows it to avoid artifacts when switching in and out of that mode, at
2558     * the expense that some of its user interface may be covered by screen
2559     * decorations when they are shown.  You can perform layout of your inner
2560     * UI elements to account for non-fullscreen system UI through the
2561     * {@link #fitSystemWindows(Rect)} method.
2562     */
2563    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2564
2565    /**
2566     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2567     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2568     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2569     * user interaction.
2570     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2571     * has an effect when used in combination with that flag.</p>
2572     */
2573    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2574
2575    /**
2576     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2577     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2578     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2579     * experience while also hiding the system bars.  If this flag is not set,
2580     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2581     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2582     * if the user swipes from the top of the screen.
2583     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2584     * system gestures, such as swiping from the top of the screen.  These transient system bars
2585     * will overlay app’s content, may have some degree of transparency, and will automatically
2586     * hide after a short timeout.
2587     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2588     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2589     * with one or both of those flags.</p>
2590     */
2591    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2592
2593    /**
2594     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2595     */
2596    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2597
2598    /**
2599     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2600     */
2601    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2602
2603    /**
2604     * @hide
2605     *
2606     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2607     * out of the public fields to keep the undefined bits out of the developer's way.
2608     *
2609     * Flag to make the status bar not expandable.  Unless you also
2610     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2611     */
2612    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2613
2614    /**
2615     * @hide
2616     *
2617     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2618     * out of the public fields to keep the undefined bits out of the developer's way.
2619     *
2620     * Flag to hide notification icons and scrolling ticker text.
2621     */
2622    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2623
2624    /**
2625     * @hide
2626     *
2627     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2628     * out of the public fields to keep the undefined bits out of the developer's way.
2629     *
2630     * Flag to disable incoming notification alerts.  This will not block
2631     * icons, but it will block sound, vibrating and other visual or aural notifications.
2632     */
2633    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2634
2635    /**
2636     * @hide
2637     *
2638     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2639     * out of the public fields to keep the undefined bits out of the developer's way.
2640     *
2641     * Flag to hide only the scrolling ticker.  Note that
2642     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2643     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2644     */
2645    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2646
2647    /**
2648     * @hide
2649     *
2650     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2651     * out of the public fields to keep the undefined bits out of the developer's way.
2652     *
2653     * Flag to hide the center system info area.
2654     */
2655    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2656
2657    /**
2658     * @hide
2659     *
2660     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2661     * out of the public fields to keep the undefined bits out of the developer's way.
2662     *
2663     * Flag to hide only the home button.  Don't use this
2664     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2665     */
2666    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2667
2668    /**
2669     * @hide
2670     *
2671     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2672     * out of the public fields to keep the undefined bits out of the developer's way.
2673     *
2674     * Flag to hide only the back button. Don't use this
2675     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2676     */
2677    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2678
2679    /**
2680     * @hide
2681     *
2682     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2683     * out of the public fields to keep the undefined bits out of the developer's way.
2684     *
2685     * Flag to hide only the clock.  You might use this if your activity has
2686     * its own clock making the status bar's clock redundant.
2687     */
2688    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2689
2690    /**
2691     * @hide
2692     *
2693     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2694     * out of the public fields to keep the undefined bits out of the developer's way.
2695     *
2696     * Flag to hide only the recent apps button. Don't use this
2697     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2698     */
2699    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2700
2701    /**
2702     * @hide
2703     *
2704     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2705     * out of the public fields to keep the undefined bits out of the developer's way.
2706     *
2707     * Flag to disable the global search gesture. Don't use this
2708     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2709     */
2710    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2711
2712    /**
2713     * @hide
2714     *
2715     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2716     * out of the public fields to keep the undefined bits out of the developer's way.
2717     *
2718     * Flag to specify that the status bar is displayed in transient mode.
2719     */
2720    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2721
2722    /**
2723     * @hide
2724     *
2725     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2726     * out of the public fields to keep the undefined bits out of the developer's way.
2727     *
2728     * Flag to specify that the navigation bar is displayed in transient mode.
2729     */
2730    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2731
2732    /**
2733     * @hide
2734     *
2735     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2736     * out of the public fields to keep the undefined bits out of the developer's way.
2737     *
2738     * Flag to specify that the hidden status bar would like to be shown.
2739     */
2740    public static final int STATUS_BAR_UNHIDE = 0x10000000;
2741
2742    /**
2743     * @hide
2744     *
2745     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2746     * out of the public fields to keep the undefined bits out of the developer's way.
2747     *
2748     * Flag to specify that the hidden navigation bar would like to be shown.
2749     */
2750    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2751
2752    /**
2753     * @hide
2754     *
2755     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2756     * out of the public fields to keep the undefined bits out of the developer's way.
2757     *
2758     * Flag to specify that the status bar is displayed in translucent mode.
2759     */
2760    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2761
2762    /**
2763     * @hide
2764     *
2765     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2766     * out of the public fields to keep the undefined bits out of the developer's way.
2767     *
2768     * Flag to specify that the navigation bar is displayed in translucent mode.
2769     */
2770    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2771
2772    /**
2773     * @hide
2774     */
2775    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
2776
2777    /**
2778     * These are the system UI flags that can be cleared by events outside
2779     * of an application.  Currently this is just the ability to tap on the
2780     * screen while hiding the navigation bar to have it return.
2781     * @hide
2782     */
2783    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2784            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2785            | SYSTEM_UI_FLAG_FULLSCREEN;
2786
2787    /**
2788     * Flags that can impact the layout in relation to system UI.
2789     */
2790    public static final int SYSTEM_UI_LAYOUT_FLAGS =
2791            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2792            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2793
2794    /** @hide */
2795    @IntDef(flag = true,
2796            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2797    @Retention(RetentionPolicy.SOURCE)
2798    public @interface FindViewFlags {}
2799
2800    /**
2801     * Find views that render the specified text.
2802     *
2803     * @see #findViewsWithText(ArrayList, CharSequence, int)
2804     */
2805    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2806
2807    /**
2808     * Find find views that contain the specified content description.
2809     *
2810     * @see #findViewsWithText(ArrayList, CharSequence, int)
2811     */
2812    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2813
2814    /**
2815     * Find views that contain {@link AccessibilityNodeProvider}. Such
2816     * a View is a root of virtual view hierarchy and may contain the searched
2817     * text. If this flag is set Views with providers are automatically
2818     * added and it is a responsibility of the client to call the APIs of
2819     * the provider to determine whether the virtual tree rooted at this View
2820     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2821     * representing the virtual views with this text.
2822     *
2823     * @see #findViewsWithText(ArrayList, CharSequence, int)
2824     *
2825     * @hide
2826     */
2827    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2828
2829    /**
2830     * The undefined cursor position.
2831     *
2832     * @hide
2833     */
2834    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2835
2836    /**
2837     * Indicates that the screen has changed state and is now off.
2838     *
2839     * @see #onScreenStateChanged(int)
2840     */
2841    public static final int SCREEN_STATE_OFF = 0x0;
2842
2843    /**
2844     * Indicates that the screen has changed state and is now on.
2845     *
2846     * @see #onScreenStateChanged(int)
2847     */
2848    public static final int SCREEN_STATE_ON = 0x1;
2849
2850    /**
2851     * Indicates no axis of view scrolling.
2852     */
2853    public static final int SCROLL_AXIS_NONE = 0;
2854
2855    /**
2856     * Indicates scrolling along the horizontal axis.
2857     */
2858    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
2859
2860    /**
2861     * Indicates scrolling along the vertical axis.
2862     */
2863    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
2864
2865    /**
2866     * Controls the over-scroll mode for this view.
2867     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2868     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2869     * and {@link #OVER_SCROLL_NEVER}.
2870     */
2871    private int mOverScrollMode;
2872
2873    /**
2874     * The parent this view is attached to.
2875     * {@hide}
2876     *
2877     * @see #getParent()
2878     */
2879    protected ViewParent mParent;
2880
2881    /**
2882     * {@hide}
2883     */
2884    AttachInfo mAttachInfo;
2885
2886    /**
2887     * {@hide}
2888     */
2889    @ViewDebug.ExportedProperty(flagMapping = {
2890        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2891                name = "FORCE_LAYOUT"),
2892        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2893                name = "LAYOUT_REQUIRED"),
2894        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2895            name = "DRAWING_CACHE_INVALID", outputIf = false),
2896        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2897        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2898        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2899        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2900    })
2901    int mPrivateFlags;
2902    int mPrivateFlags2;
2903    int mPrivateFlags3;
2904
2905    /**
2906     * This view's request for the visibility of the status bar.
2907     * @hide
2908     */
2909    @ViewDebug.ExportedProperty(flagMapping = {
2910        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2911                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2912                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2913        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2914                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2915                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2916        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2917                                equals = SYSTEM_UI_FLAG_VISIBLE,
2918                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2919    })
2920    int mSystemUiVisibility;
2921
2922    /**
2923     * Reference count for transient state.
2924     * @see #setHasTransientState(boolean)
2925     */
2926    int mTransientStateCount = 0;
2927
2928    /**
2929     * Count of how many windows this view has been attached to.
2930     */
2931    int mWindowAttachCount;
2932
2933    /**
2934     * The layout parameters associated with this view and used by the parent
2935     * {@link android.view.ViewGroup} to determine how this view should be
2936     * laid out.
2937     * {@hide}
2938     */
2939    protected ViewGroup.LayoutParams mLayoutParams;
2940
2941    /**
2942     * The view flags hold various views states.
2943     * {@hide}
2944     */
2945    @ViewDebug.ExportedProperty
2946    int mViewFlags;
2947
2948    static class TransformationInfo {
2949        /**
2950         * The transform matrix for the View. This transform is calculated internally
2951         * based on the translation, rotation, and scale properties.
2952         *
2953         * Do *not* use this variable directly; instead call getMatrix(), which will
2954         * load the value from the View's RenderNode.
2955         */
2956        private final Matrix mMatrix = new Matrix();
2957
2958        /**
2959         * The inverse transform matrix for the View. This transform is calculated
2960         * internally based on the translation, rotation, and scale properties.
2961         *
2962         * Do *not* use this variable directly; instead call getInverseMatrix(),
2963         * which will load the value from the View's RenderNode.
2964         */
2965        private Matrix mInverseMatrix;
2966
2967        /**
2968         * The opacity of the View. This is a value from 0 to 1, where 0 means
2969         * completely transparent and 1 means completely opaque.
2970         */
2971        @ViewDebug.ExportedProperty
2972        float mAlpha = 1f;
2973
2974        /**
2975         * The opacity of the view as manipulated by the Fade transition. This is a hidden
2976         * property only used by transitions, which is composited with the other alpha
2977         * values to calculate the final visual alpha value.
2978         */
2979        float mTransitionAlpha = 1f;
2980    }
2981
2982    TransformationInfo mTransformationInfo;
2983
2984    /**
2985     * Current clip bounds. to which all drawing of this view are constrained.
2986     */
2987    Rect mClipBounds = null;
2988
2989    private boolean mLastIsOpaque;
2990
2991    /**
2992     * The distance in pixels from the left edge of this view's parent
2993     * to the left edge of this view.
2994     * {@hide}
2995     */
2996    @ViewDebug.ExportedProperty(category = "layout")
2997    protected int mLeft;
2998    /**
2999     * The distance in pixels from the left edge of this view's parent
3000     * to the right edge of this view.
3001     * {@hide}
3002     */
3003    @ViewDebug.ExportedProperty(category = "layout")
3004    protected int mRight;
3005    /**
3006     * The distance in pixels from the top edge of this view's parent
3007     * to the top edge of this view.
3008     * {@hide}
3009     */
3010    @ViewDebug.ExportedProperty(category = "layout")
3011    protected int mTop;
3012    /**
3013     * The distance in pixels from the top edge of this view's parent
3014     * to the bottom edge of this view.
3015     * {@hide}
3016     */
3017    @ViewDebug.ExportedProperty(category = "layout")
3018    protected int mBottom;
3019
3020    /**
3021     * The offset, in pixels, by which the content of this view is scrolled
3022     * horizontally.
3023     * {@hide}
3024     */
3025    @ViewDebug.ExportedProperty(category = "scrolling")
3026    protected int mScrollX;
3027    /**
3028     * The offset, in pixels, by which the content of this view is scrolled
3029     * vertically.
3030     * {@hide}
3031     */
3032    @ViewDebug.ExportedProperty(category = "scrolling")
3033    protected int mScrollY;
3034
3035    /**
3036     * The left padding in pixels, that is the distance in pixels between the
3037     * left edge of this view and the left edge of its content.
3038     * {@hide}
3039     */
3040    @ViewDebug.ExportedProperty(category = "padding")
3041    protected int mPaddingLeft = 0;
3042    /**
3043     * The right padding in pixels, that is the distance in pixels between the
3044     * right edge of this view and the right edge of its content.
3045     * {@hide}
3046     */
3047    @ViewDebug.ExportedProperty(category = "padding")
3048    protected int mPaddingRight = 0;
3049    /**
3050     * The top padding in pixels, that is the distance in pixels between the
3051     * top edge of this view and the top edge of its content.
3052     * {@hide}
3053     */
3054    @ViewDebug.ExportedProperty(category = "padding")
3055    protected int mPaddingTop;
3056    /**
3057     * The bottom padding in pixels, that is the distance in pixels between the
3058     * bottom edge of this view and the bottom edge of its content.
3059     * {@hide}
3060     */
3061    @ViewDebug.ExportedProperty(category = "padding")
3062    protected int mPaddingBottom;
3063
3064    /**
3065     * The layout insets in pixels, that is the distance in pixels between the
3066     * visible edges of this view its bounds.
3067     */
3068    private Insets mLayoutInsets;
3069
3070    /**
3071     * Briefly describes the view and is primarily used for accessibility support.
3072     */
3073    private CharSequence mContentDescription;
3074
3075    /**
3076     * Specifies the id of a view for which this view serves as a label for
3077     * accessibility purposes.
3078     */
3079    private int mLabelForId = View.NO_ID;
3080
3081    /**
3082     * Predicate for matching labeled view id with its label for
3083     * accessibility purposes.
3084     */
3085    private MatchLabelForPredicate mMatchLabelForPredicate;
3086
3087    /**
3088     * Predicate for matching a view by its id.
3089     */
3090    private MatchIdPredicate mMatchIdPredicate;
3091
3092    /**
3093     * Cache the paddingRight set by the user to append to the scrollbar's size.
3094     *
3095     * @hide
3096     */
3097    @ViewDebug.ExportedProperty(category = "padding")
3098    protected int mUserPaddingRight;
3099
3100    /**
3101     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3102     *
3103     * @hide
3104     */
3105    @ViewDebug.ExportedProperty(category = "padding")
3106    protected int mUserPaddingBottom;
3107
3108    /**
3109     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3110     *
3111     * @hide
3112     */
3113    @ViewDebug.ExportedProperty(category = "padding")
3114    protected int mUserPaddingLeft;
3115
3116    /**
3117     * Cache the paddingStart set by the user to append to the scrollbar's size.
3118     *
3119     */
3120    @ViewDebug.ExportedProperty(category = "padding")
3121    int mUserPaddingStart;
3122
3123    /**
3124     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3125     *
3126     */
3127    @ViewDebug.ExportedProperty(category = "padding")
3128    int mUserPaddingEnd;
3129
3130    /**
3131     * Cache initial left padding.
3132     *
3133     * @hide
3134     */
3135    int mUserPaddingLeftInitial;
3136
3137    /**
3138     * Cache initial right padding.
3139     *
3140     * @hide
3141     */
3142    int mUserPaddingRightInitial;
3143
3144    /**
3145     * Default undefined padding
3146     */
3147    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3148
3149    /**
3150     * Cache if a left padding has been defined
3151     */
3152    private boolean mLeftPaddingDefined = false;
3153
3154    /**
3155     * Cache if a right padding has been defined
3156     */
3157    private boolean mRightPaddingDefined = false;
3158
3159    /**
3160     * @hide
3161     */
3162    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3163    /**
3164     * @hide
3165     */
3166    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3167
3168    private LongSparseLongArray mMeasureCache;
3169
3170    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3171    private Drawable mBackground;
3172
3173    /**
3174     * Display list used for backgrounds.
3175     * <p>
3176     * When non-null and valid, this is expected to contain an up-to-date copy
3177     * of the background drawable. It is cleared on temporary detach and reset
3178     * on cleanup.
3179     */
3180    private RenderNode mBackgroundDisplayList;
3181
3182    private int mBackgroundResource;
3183    private boolean mBackgroundSizeChanged;
3184
3185    static class ListenerInfo {
3186        /**
3187         * Listener used to dispatch focus change events.
3188         * This field should be made private, so it is hidden from the SDK.
3189         * {@hide}
3190         */
3191        protected OnFocusChangeListener mOnFocusChangeListener;
3192
3193        /**
3194         * Listeners for layout change events.
3195         */
3196        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3197
3198        /**
3199         * Listeners for attach events.
3200         */
3201        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3202
3203        /**
3204         * Listener used to dispatch click events.
3205         * This field should be made private, so it is hidden from the SDK.
3206         * {@hide}
3207         */
3208        public OnClickListener mOnClickListener;
3209
3210        /**
3211         * Listener used to dispatch long click events.
3212         * This field should be made private, so it is hidden from the SDK.
3213         * {@hide}
3214         */
3215        protected OnLongClickListener mOnLongClickListener;
3216
3217        /**
3218         * Listener used to build the context menu.
3219         * This field should be made private, so it is hidden from the SDK.
3220         * {@hide}
3221         */
3222        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3223
3224        private OnKeyListener mOnKeyListener;
3225
3226        private OnTouchListener mOnTouchListener;
3227
3228        private OnHoverListener mOnHoverListener;
3229
3230        private OnGenericMotionListener mOnGenericMotionListener;
3231
3232        private OnDragListener mOnDragListener;
3233
3234        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3235
3236        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3237    }
3238
3239    ListenerInfo mListenerInfo;
3240
3241    /**
3242     * The application environment this view lives in.
3243     * This field should be made private, so it is hidden from the SDK.
3244     * {@hide}
3245     */
3246    protected Context mContext;
3247
3248    private final Resources mResources;
3249
3250    private ScrollabilityCache mScrollCache;
3251
3252    private int[] mDrawableState = null;
3253
3254    /**
3255     * Stores the outline of the view, passed down to the DisplayList level for
3256     * defining shadow shape.
3257     */
3258    private Outline mOutline;
3259
3260    /**
3261     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3262     * the user may specify which view to go to next.
3263     */
3264    private int mNextFocusLeftId = View.NO_ID;
3265
3266    /**
3267     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3268     * the user may specify which view to go to next.
3269     */
3270    private int mNextFocusRightId = View.NO_ID;
3271
3272    /**
3273     * When this view has focus and the next focus is {@link #FOCUS_UP},
3274     * the user may specify which view to go to next.
3275     */
3276    private int mNextFocusUpId = View.NO_ID;
3277
3278    /**
3279     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3280     * the user may specify which view to go to next.
3281     */
3282    private int mNextFocusDownId = View.NO_ID;
3283
3284    /**
3285     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3286     * the user may specify which view to go to next.
3287     */
3288    int mNextFocusForwardId = View.NO_ID;
3289
3290    private CheckForLongPress mPendingCheckForLongPress;
3291    private CheckForTap mPendingCheckForTap = null;
3292    private PerformClick mPerformClick;
3293    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3294
3295    private UnsetPressedState mUnsetPressedState;
3296
3297    /**
3298     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3299     * up event while a long press is invoked as soon as the long press duration is reached, so
3300     * a long press could be performed before the tap is checked, in which case the tap's action
3301     * should not be invoked.
3302     */
3303    private boolean mHasPerformedLongPress;
3304
3305    /**
3306     * The minimum height of the view. We'll try our best to have the height
3307     * of this view to at least this amount.
3308     */
3309    @ViewDebug.ExportedProperty(category = "measurement")
3310    private int mMinHeight;
3311
3312    /**
3313     * The minimum width of the view. We'll try our best to have the width
3314     * of this view to at least this amount.
3315     */
3316    @ViewDebug.ExportedProperty(category = "measurement")
3317    private int mMinWidth;
3318
3319    /**
3320     * The delegate to handle touch events that are physically in this view
3321     * but should be handled by another view.
3322     */
3323    private TouchDelegate mTouchDelegate = null;
3324
3325    /**
3326     * Solid color to use as a background when creating the drawing cache. Enables
3327     * the cache to use 16 bit bitmaps instead of 32 bit.
3328     */
3329    private int mDrawingCacheBackgroundColor = 0;
3330
3331    /**
3332     * Special tree observer used when mAttachInfo is null.
3333     */
3334    private ViewTreeObserver mFloatingTreeObserver;
3335
3336    /**
3337     * Cache the touch slop from the context that created the view.
3338     */
3339    private int mTouchSlop;
3340
3341    /**
3342     * Object that handles automatic animation of view properties.
3343     */
3344    private ViewPropertyAnimator mAnimator = null;
3345
3346    /**
3347     * Flag indicating that a drag can cross window boundaries.  When
3348     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3349     * with this flag set, all visible applications will be able to participate
3350     * in the drag operation and receive the dragged content.
3351     *
3352     * @hide
3353     */
3354    public static final int DRAG_FLAG_GLOBAL = 1;
3355
3356    /**
3357     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3358     */
3359    private float mVerticalScrollFactor;
3360
3361    /**
3362     * Position of the vertical scroll bar.
3363     */
3364    private int mVerticalScrollbarPosition;
3365
3366    /**
3367     * Position the scroll bar at the default position as determined by the system.
3368     */
3369    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3370
3371    /**
3372     * Position the scroll bar along the left edge.
3373     */
3374    public static final int SCROLLBAR_POSITION_LEFT = 1;
3375
3376    /**
3377     * Position the scroll bar along the right edge.
3378     */
3379    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3380
3381    /**
3382     * Indicates that the view does not have a layer.
3383     *
3384     * @see #getLayerType()
3385     * @see #setLayerType(int, android.graphics.Paint)
3386     * @see #LAYER_TYPE_SOFTWARE
3387     * @see #LAYER_TYPE_HARDWARE
3388     */
3389    public static final int LAYER_TYPE_NONE = 0;
3390
3391    /**
3392     * <p>Indicates that the view has a software layer. A software layer is backed
3393     * by a bitmap and causes the view to be rendered using Android's software
3394     * rendering pipeline, even if hardware acceleration is enabled.</p>
3395     *
3396     * <p>Software layers have various usages:</p>
3397     * <p>When the application is not using hardware acceleration, a software layer
3398     * is useful to apply a specific color filter and/or blending mode and/or
3399     * translucency to a view and all its children.</p>
3400     * <p>When the application is using hardware acceleration, a software layer
3401     * is useful to render drawing primitives not supported by the hardware
3402     * accelerated pipeline. It can also be used to cache a complex view tree
3403     * into a texture and reduce the complexity of drawing operations. For instance,
3404     * when animating a complex view tree with a translation, a software layer can
3405     * be used to render the view tree only once.</p>
3406     * <p>Software layers should be avoided when the affected view tree updates
3407     * often. Every update will require to re-render the software layer, which can
3408     * potentially be slow (particularly when hardware acceleration is turned on
3409     * since the layer will have to be uploaded into a hardware texture after every
3410     * update.)</p>
3411     *
3412     * @see #getLayerType()
3413     * @see #setLayerType(int, android.graphics.Paint)
3414     * @see #LAYER_TYPE_NONE
3415     * @see #LAYER_TYPE_HARDWARE
3416     */
3417    public static final int LAYER_TYPE_SOFTWARE = 1;
3418
3419    /**
3420     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3421     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3422     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3423     * rendering pipeline, but only if hardware acceleration is turned on for the
3424     * view hierarchy. When hardware acceleration is turned off, hardware layers
3425     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3426     *
3427     * <p>A hardware layer is useful to apply a specific color filter and/or
3428     * blending mode and/or translucency to a view and all its children.</p>
3429     * <p>A hardware layer can be used to cache a complex view tree into a
3430     * texture and reduce the complexity of drawing operations. For instance,
3431     * when animating a complex view tree with a translation, a hardware layer can
3432     * be used to render the view tree only once.</p>
3433     * <p>A hardware layer can also be used to increase the rendering quality when
3434     * rotation transformations are applied on a view. It can also be used to
3435     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3436     *
3437     * @see #getLayerType()
3438     * @see #setLayerType(int, android.graphics.Paint)
3439     * @see #LAYER_TYPE_NONE
3440     * @see #LAYER_TYPE_SOFTWARE
3441     */
3442    public static final int LAYER_TYPE_HARDWARE = 2;
3443
3444    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3445            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3446            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3447            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3448    })
3449    int mLayerType = LAYER_TYPE_NONE;
3450    Paint mLayerPaint;
3451    Rect mLocalDirtyRect;
3452    private HardwareLayer mHardwareLayer;
3453
3454    /**
3455     * Set to true when drawing cache is enabled and cannot be created.
3456     *
3457     * @hide
3458     */
3459    public boolean mCachingFailed;
3460    private Bitmap mDrawingCache;
3461    private Bitmap mUnscaledDrawingCache;
3462
3463    /**
3464     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3465     * <p>
3466     * When non-null and valid, this is expected to contain an up-to-date copy
3467     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3468     * cleanup.
3469     */
3470    final RenderNode mRenderNode;
3471
3472    /**
3473     * Set to true when the view is sending hover accessibility events because it
3474     * is the innermost hovered view.
3475     */
3476    private boolean mSendingHoverAccessibilityEvents;
3477
3478    /**
3479     * Delegate for injecting accessibility functionality.
3480     */
3481    AccessibilityDelegate mAccessibilityDelegate;
3482
3483    /**
3484     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3485     * and add/remove objects to/from the overlay directly through the Overlay methods.
3486     */
3487    ViewOverlay mOverlay;
3488
3489    /**
3490     * The currently active parent view for receiving delegated nested scrolling events.
3491     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3492     * by {@link #stopNestedScroll()} at the same point where we clear
3493     * requestDisallowInterceptTouchEvent.
3494     */
3495    private ViewParent mNestedScrollingParent;
3496
3497    /**
3498     * Consistency verifier for debugging purposes.
3499     * @hide
3500     */
3501    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3502            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3503                    new InputEventConsistencyVerifier(this, 0) : null;
3504
3505    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3506
3507    private int[] mTempNestedScrollConsumed;
3508
3509    /**
3510     * Simple constructor to use when creating a view from code.
3511     *
3512     * @param context The Context the view is running in, through which it can
3513     *        access the current theme, resources, etc.
3514     */
3515    public View(Context context) {
3516        mContext = context;
3517        mResources = context != null ? context.getResources() : null;
3518        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3519        // Set some flags defaults
3520        mPrivateFlags2 =
3521                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3522                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3523                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3524                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3525                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3526                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3527        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3528        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3529        mUserPaddingStart = UNDEFINED_PADDING;
3530        mUserPaddingEnd = UNDEFINED_PADDING;
3531        mRenderNode = RenderNode.create(getClass().getName());
3532
3533        if (!sCompatibilityDone && context != null) {
3534            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3535
3536            // Older apps may need this compatibility hack for measurement.
3537            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3538
3539            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3540            // of whether a layout was requested on that View.
3541            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3542
3543            // Older apps may need this to ignore the clip bounds
3544            sIgnoreClipBoundsForChildren = targetSdkVersion < L;
3545
3546            sCompatibilityDone = true;
3547        }
3548    }
3549
3550    /**
3551     * Constructor that is called when inflating a view from XML. This is called
3552     * when a view is being constructed from an XML file, supplying attributes
3553     * that were specified in the XML file. This version uses a default style of
3554     * 0, so the only attribute values applied are those in the Context's Theme
3555     * and the given AttributeSet.
3556     *
3557     * <p>
3558     * The method onFinishInflate() will be called after all children have been
3559     * added.
3560     *
3561     * @param context The Context the view is running in, through which it can
3562     *        access the current theme, resources, etc.
3563     * @param attrs The attributes of the XML tag that is inflating the view.
3564     * @see #View(Context, AttributeSet, int)
3565     */
3566    public View(Context context, AttributeSet attrs) {
3567        this(context, attrs, 0);
3568    }
3569
3570    /**
3571     * Perform inflation from XML and apply a class-specific base style from a
3572     * theme attribute. This constructor of View allows subclasses to use their
3573     * own base style when they are inflating. For example, a Button class's
3574     * constructor would call this version of the super class constructor and
3575     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3576     * allows the theme's button style to modify all of the base view attributes
3577     * (in particular its background) as well as the Button class's attributes.
3578     *
3579     * @param context The Context the view is running in, through which it can
3580     *        access the current theme, resources, etc.
3581     * @param attrs The attributes of the XML tag that is inflating the view.
3582     * @param defStyleAttr An attribute in the current theme that contains a
3583     *        reference to a style resource that supplies default values for
3584     *        the view. Can be 0 to not look for defaults.
3585     * @see #View(Context, AttributeSet)
3586     */
3587    public View(Context context, AttributeSet attrs, int defStyleAttr) {
3588        this(context, attrs, defStyleAttr, 0);
3589    }
3590
3591    /**
3592     * Perform inflation from XML and apply a class-specific base style from a
3593     * theme attribute or style resource. This constructor of View allows
3594     * subclasses to use their own base style when they are inflating.
3595     * <p>
3596     * When determining the final value of a particular attribute, there are
3597     * four inputs that come into play:
3598     * <ol>
3599     * <li>Any attribute values in the given AttributeSet.
3600     * <li>The style resource specified in the AttributeSet (named "style").
3601     * <li>The default style specified by <var>defStyleAttr</var>.
3602     * <li>The default style specified by <var>defStyleRes</var>.
3603     * <li>The base values in this theme.
3604     * </ol>
3605     * <p>
3606     * Each of these inputs is considered in-order, with the first listed taking
3607     * precedence over the following ones. In other words, if in the
3608     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3609     * , then the button's text will <em>always</em> be black, regardless of
3610     * what is specified in any of the styles.
3611     *
3612     * @param context The Context the view is running in, through which it can
3613     *        access the current theme, resources, etc.
3614     * @param attrs The attributes of the XML tag that is inflating the view.
3615     * @param defStyleAttr An attribute in the current theme that contains a
3616     *        reference to a style resource that supplies default values for
3617     *        the view. Can be 0 to not look for defaults.
3618     * @param defStyleRes A resource identifier of a style resource that
3619     *        supplies default values for the view, used only if
3620     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3621     *        to not look for defaults.
3622     * @see #View(Context, AttributeSet, int)
3623     */
3624    public View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3625        this(context);
3626
3627        final TypedArray a = context.obtainStyledAttributes(
3628                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3629
3630        Drawable background = null;
3631
3632        int leftPadding = -1;
3633        int topPadding = -1;
3634        int rightPadding = -1;
3635        int bottomPadding = -1;
3636        int startPadding = UNDEFINED_PADDING;
3637        int endPadding = UNDEFINED_PADDING;
3638
3639        int padding = -1;
3640
3641        int viewFlagValues = 0;
3642        int viewFlagMasks = 0;
3643
3644        boolean setScrollContainer = false;
3645
3646        int x = 0;
3647        int y = 0;
3648
3649        float tx = 0;
3650        float ty = 0;
3651        float tz = 0;
3652        float rotation = 0;
3653        float rotationX = 0;
3654        float rotationY = 0;
3655        float sx = 1f;
3656        float sy = 1f;
3657        boolean transformSet = false;
3658
3659        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3660        int overScrollMode = mOverScrollMode;
3661        boolean initializeScrollbars = false;
3662
3663        boolean startPaddingDefined = false;
3664        boolean endPaddingDefined = false;
3665        boolean leftPaddingDefined = false;
3666        boolean rightPaddingDefined = false;
3667
3668        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3669
3670        final int N = a.getIndexCount();
3671        for (int i = 0; i < N; i++) {
3672            int attr = a.getIndex(i);
3673            switch (attr) {
3674                case com.android.internal.R.styleable.View_background:
3675                    background = a.getDrawable(attr);
3676                    break;
3677                case com.android.internal.R.styleable.View_padding:
3678                    padding = a.getDimensionPixelSize(attr, -1);
3679                    mUserPaddingLeftInitial = padding;
3680                    mUserPaddingRightInitial = padding;
3681                    leftPaddingDefined = true;
3682                    rightPaddingDefined = true;
3683                    break;
3684                 case com.android.internal.R.styleable.View_paddingLeft:
3685                    leftPadding = a.getDimensionPixelSize(attr, -1);
3686                    mUserPaddingLeftInitial = leftPadding;
3687                    leftPaddingDefined = true;
3688                    break;
3689                case com.android.internal.R.styleable.View_paddingTop:
3690                    topPadding = a.getDimensionPixelSize(attr, -1);
3691                    break;
3692                case com.android.internal.R.styleable.View_paddingRight:
3693                    rightPadding = a.getDimensionPixelSize(attr, -1);
3694                    mUserPaddingRightInitial = rightPadding;
3695                    rightPaddingDefined = true;
3696                    break;
3697                case com.android.internal.R.styleable.View_paddingBottom:
3698                    bottomPadding = a.getDimensionPixelSize(attr, -1);
3699                    break;
3700                case com.android.internal.R.styleable.View_paddingStart:
3701                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3702                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3703                    break;
3704                case com.android.internal.R.styleable.View_paddingEnd:
3705                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3706                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3707                    break;
3708                case com.android.internal.R.styleable.View_scrollX:
3709                    x = a.getDimensionPixelOffset(attr, 0);
3710                    break;
3711                case com.android.internal.R.styleable.View_scrollY:
3712                    y = a.getDimensionPixelOffset(attr, 0);
3713                    break;
3714                case com.android.internal.R.styleable.View_alpha:
3715                    setAlpha(a.getFloat(attr, 1f));
3716                    break;
3717                case com.android.internal.R.styleable.View_transformPivotX:
3718                    setPivotX(a.getDimensionPixelOffset(attr, 0));
3719                    break;
3720                case com.android.internal.R.styleable.View_transformPivotY:
3721                    setPivotY(a.getDimensionPixelOffset(attr, 0));
3722                    break;
3723                case com.android.internal.R.styleable.View_translationX:
3724                    tx = a.getDimensionPixelOffset(attr, 0);
3725                    transformSet = true;
3726                    break;
3727                case com.android.internal.R.styleable.View_translationY:
3728                    ty = a.getDimensionPixelOffset(attr, 0);
3729                    transformSet = true;
3730                    break;
3731                case com.android.internal.R.styleable.View_translationZ:
3732                    tz = a.getDimensionPixelOffset(attr, 0);
3733                    transformSet = true;
3734                    break;
3735                case com.android.internal.R.styleable.View_rotation:
3736                    rotation = a.getFloat(attr, 0);
3737                    transformSet = true;
3738                    break;
3739                case com.android.internal.R.styleable.View_rotationX:
3740                    rotationX = a.getFloat(attr, 0);
3741                    transformSet = true;
3742                    break;
3743                case com.android.internal.R.styleable.View_rotationY:
3744                    rotationY = a.getFloat(attr, 0);
3745                    transformSet = true;
3746                    break;
3747                case com.android.internal.R.styleable.View_scaleX:
3748                    sx = a.getFloat(attr, 1f);
3749                    transformSet = true;
3750                    break;
3751                case com.android.internal.R.styleable.View_scaleY:
3752                    sy = a.getFloat(attr, 1f);
3753                    transformSet = true;
3754                    break;
3755                case com.android.internal.R.styleable.View_id:
3756                    mID = a.getResourceId(attr, NO_ID);
3757                    break;
3758                case com.android.internal.R.styleable.View_tag:
3759                    mTag = a.getText(attr);
3760                    break;
3761                case com.android.internal.R.styleable.View_fitsSystemWindows:
3762                    if (a.getBoolean(attr, false)) {
3763                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
3764                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3765                    }
3766                    break;
3767                case com.android.internal.R.styleable.View_focusable:
3768                    if (a.getBoolean(attr, false)) {
3769                        viewFlagValues |= FOCUSABLE;
3770                        viewFlagMasks |= FOCUSABLE_MASK;
3771                    }
3772                    break;
3773                case com.android.internal.R.styleable.View_focusableInTouchMode:
3774                    if (a.getBoolean(attr, false)) {
3775                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3776                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3777                    }
3778                    break;
3779                case com.android.internal.R.styleable.View_clickable:
3780                    if (a.getBoolean(attr, false)) {
3781                        viewFlagValues |= CLICKABLE;
3782                        viewFlagMasks |= CLICKABLE;
3783                    }
3784                    break;
3785                case com.android.internal.R.styleable.View_longClickable:
3786                    if (a.getBoolean(attr, false)) {
3787                        viewFlagValues |= LONG_CLICKABLE;
3788                        viewFlagMasks |= LONG_CLICKABLE;
3789                    }
3790                    break;
3791                case com.android.internal.R.styleable.View_saveEnabled:
3792                    if (!a.getBoolean(attr, true)) {
3793                        viewFlagValues |= SAVE_DISABLED;
3794                        viewFlagMasks |= SAVE_DISABLED_MASK;
3795                    }
3796                    break;
3797                case com.android.internal.R.styleable.View_duplicateParentState:
3798                    if (a.getBoolean(attr, false)) {
3799                        viewFlagValues |= DUPLICATE_PARENT_STATE;
3800                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
3801                    }
3802                    break;
3803                case com.android.internal.R.styleable.View_visibility:
3804                    final int visibility = a.getInt(attr, 0);
3805                    if (visibility != 0) {
3806                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
3807                        viewFlagMasks |= VISIBILITY_MASK;
3808                    }
3809                    break;
3810                case com.android.internal.R.styleable.View_layoutDirection:
3811                    // Clear any layout direction flags (included resolved bits) already set
3812                    mPrivateFlags2 &=
3813                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3814                    // Set the layout direction flags depending on the value of the attribute
3815                    final int layoutDirection = a.getInt(attr, -1);
3816                    final int value = (layoutDirection != -1) ?
3817                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3818                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3819                    break;
3820                case com.android.internal.R.styleable.View_drawingCacheQuality:
3821                    final int cacheQuality = a.getInt(attr, 0);
3822                    if (cacheQuality != 0) {
3823                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3824                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3825                    }
3826                    break;
3827                case com.android.internal.R.styleable.View_contentDescription:
3828                    setContentDescription(a.getString(attr));
3829                    break;
3830                case com.android.internal.R.styleable.View_labelFor:
3831                    setLabelFor(a.getResourceId(attr, NO_ID));
3832                    break;
3833                case com.android.internal.R.styleable.View_soundEffectsEnabled:
3834                    if (!a.getBoolean(attr, true)) {
3835                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3836                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3837                    }
3838                    break;
3839                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3840                    if (!a.getBoolean(attr, true)) {
3841                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3842                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3843                    }
3844                    break;
3845                case R.styleable.View_scrollbars:
3846                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3847                    if (scrollbars != SCROLLBARS_NONE) {
3848                        viewFlagValues |= scrollbars;
3849                        viewFlagMasks |= SCROLLBARS_MASK;
3850                        initializeScrollbars = true;
3851                    }
3852                    break;
3853                //noinspection deprecation
3854                case R.styleable.View_fadingEdge:
3855                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3856                        // Ignore the attribute starting with ICS
3857                        break;
3858                    }
3859                    // With builds < ICS, fall through and apply fading edges
3860                case R.styleable.View_requiresFadingEdge:
3861                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3862                    if (fadingEdge != FADING_EDGE_NONE) {
3863                        viewFlagValues |= fadingEdge;
3864                        viewFlagMasks |= FADING_EDGE_MASK;
3865                        initializeFadingEdge(a);
3866                    }
3867                    break;
3868                case R.styleable.View_scrollbarStyle:
3869                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3870                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3871                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3872                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3873                    }
3874                    break;
3875                case R.styleable.View_isScrollContainer:
3876                    setScrollContainer = true;
3877                    if (a.getBoolean(attr, false)) {
3878                        setScrollContainer(true);
3879                    }
3880                    break;
3881                case com.android.internal.R.styleable.View_keepScreenOn:
3882                    if (a.getBoolean(attr, false)) {
3883                        viewFlagValues |= KEEP_SCREEN_ON;
3884                        viewFlagMasks |= KEEP_SCREEN_ON;
3885                    }
3886                    break;
3887                case R.styleable.View_filterTouchesWhenObscured:
3888                    if (a.getBoolean(attr, false)) {
3889                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3890                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3891                    }
3892                    break;
3893                case R.styleable.View_nextFocusLeft:
3894                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3895                    break;
3896                case R.styleable.View_nextFocusRight:
3897                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3898                    break;
3899                case R.styleable.View_nextFocusUp:
3900                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3901                    break;
3902                case R.styleable.View_nextFocusDown:
3903                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3904                    break;
3905                case R.styleable.View_nextFocusForward:
3906                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3907                    break;
3908                case R.styleable.View_minWidth:
3909                    mMinWidth = a.getDimensionPixelSize(attr, 0);
3910                    break;
3911                case R.styleable.View_minHeight:
3912                    mMinHeight = a.getDimensionPixelSize(attr, 0);
3913                    break;
3914                case R.styleable.View_onClick:
3915                    if (context.isRestricted()) {
3916                        throw new IllegalStateException("The android:onClick attribute cannot "
3917                                + "be used within a restricted context");
3918                    }
3919
3920                    final String handlerName = a.getString(attr);
3921                    if (handlerName != null) {
3922                        setOnClickListener(new OnClickListener() {
3923                            private Method mHandler;
3924
3925                            public void onClick(View v) {
3926                                if (mHandler == null) {
3927                                    try {
3928                                        mHandler = getContext().getClass().getMethod(handlerName,
3929                                                View.class);
3930                                    } catch (NoSuchMethodException e) {
3931                                        int id = getId();
3932                                        String idText = id == NO_ID ? "" : " with id '"
3933                                                + getContext().getResources().getResourceEntryName(
3934                                                    id) + "'";
3935                                        throw new IllegalStateException("Could not find a method " +
3936                                                handlerName + "(View) in the activity "
3937                                                + getContext().getClass() + " for onClick handler"
3938                                                + " on view " + View.this.getClass() + idText, e);
3939                                    }
3940                                }
3941
3942                                try {
3943                                    mHandler.invoke(getContext(), View.this);
3944                                } catch (IllegalAccessException e) {
3945                                    throw new IllegalStateException("Could not execute non "
3946                                            + "public method of the activity", e);
3947                                } catch (InvocationTargetException e) {
3948                                    throw new IllegalStateException("Could not execute "
3949                                            + "method of the activity", e);
3950                                }
3951                            }
3952                        });
3953                    }
3954                    break;
3955                case R.styleable.View_overScrollMode:
3956                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3957                    break;
3958                case R.styleable.View_verticalScrollbarPosition:
3959                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3960                    break;
3961                case R.styleable.View_layerType:
3962                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3963                    break;
3964                case R.styleable.View_textDirection:
3965                    // Clear any text direction flag already set
3966                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
3967                    // Set the text direction flags depending on the value of the attribute
3968                    final int textDirection = a.getInt(attr, -1);
3969                    if (textDirection != -1) {
3970                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
3971                    }
3972                    break;
3973                case R.styleable.View_textAlignment:
3974                    // Clear any text alignment flag already set
3975                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
3976                    // Set the text alignment flag depending on the value of the attribute
3977                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
3978                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
3979                    break;
3980                case R.styleable.View_importantForAccessibility:
3981                    setImportantForAccessibility(a.getInt(attr,
3982                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
3983                    break;
3984                case R.styleable.View_accessibilityLiveRegion:
3985                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
3986                    break;
3987                case R.styleable.View_sharedElementName:
3988                    setSharedElementName(a.getString(attr));
3989                    break;
3990                case R.styleable.View_nestedScrollingEnabled:
3991                    setNestedScrollingEnabled(a.getBoolean(attr, false));
3992                    break;
3993            }
3994        }
3995
3996        setOverScrollMode(overScrollMode);
3997
3998        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
3999        // the resolved layout direction). Those cached values will be used later during padding
4000        // resolution.
4001        mUserPaddingStart = startPadding;
4002        mUserPaddingEnd = endPadding;
4003
4004        if (background != null) {
4005            setBackground(background);
4006        }
4007
4008        // setBackground above will record that padding is currently provided by the background.
4009        // If we have padding specified via xml, record that here instead and use it.
4010        mLeftPaddingDefined = leftPaddingDefined;
4011        mRightPaddingDefined = rightPaddingDefined;
4012
4013        if (padding >= 0) {
4014            leftPadding = padding;
4015            topPadding = padding;
4016            rightPadding = padding;
4017            bottomPadding = padding;
4018            mUserPaddingLeftInitial = padding;
4019            mUserPaddingRightInitial = padding;
4020        }
4021
4022        if (isRtlCompatibilityMode()) {
4023            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4024            // left / right padding are used if defined (meaning here nothing to do). If they are not
4025            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4026            // start / end and resolve them as left / right (layout direction is not taken into account).
4027            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4028            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4029            // defined.
4030            if (!mLeftPaddingDefined && startPaddingDefined) {
4031                leftPadding = startPadding;
4032            }
4033            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4034            if (!mRightPaddingDefined && endPaddingDefined) {
4035                rightPadding = endPadding;
4036            }
4037            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4038        } else {
4039            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4040            // values defined. Otherwise, left /right values are used.
4041            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4042            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4043            // defined.
4044            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4045
4046            if (mLeftPaddingDefined && !hasRelativePadding) {
4047                mUserPaddingLeftInitial = leftPadding;
4048            }
4049            if (mRightPaddingDefined && !hasRelativePadding) {
4050                mUserPaddingRightInitial = rightPadding;
4051            }
4052        }
4053
4054        internalSetPadding(
4055                mUserPaddingLeftInitial,
4056                topPadding >= 0 ? topPadding : mPaddingTop,
4057                mUserPaddingRightInitial,
4058                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4059
4060        if (viewFlagMasks != 0) {
4061            setFlags(viewFlagValues, viewFlagMasks);
4062        }
4063
4064        if (initializeScrollbars) {
4065            initializeScrollbars(a);
4066        }
4067
4068        a.recycle();
4069
4070        // Needs to be called after mViewFlags is set
4071        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4072            recomputePadding();
4073        }
4074
4075        if (x != 0 || y != 0) {
4076            scrollTo(x, y);
4077        }
4078
4079        if (transformSet) {
4080            setTranslationX(tx);
4081            setTranslationY(ty);
4082            setTranslationZ(tz);
4083            setRotation(rotation);
4084            setRotationX(rotationX);
4085            setRotationY(rotationY);
4086            setScaleX(sx);
4087            setScaleY(sy);
4088        }
4089
4090        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4091            setScrollContainer(true);
4092        }
4093
4094        computeOpaqueFlags();
4095    }
4096
4097    /**
4098     * Non-public constructor for use in testing
4099     */
4100    View() {
4101        mResources = null;
4102        mRenderNode = RenderNode.create(getClass().getName());
4103    }
4104
4105    public String toString() {
4106        StringBuilder out = new StringBuilder(128);
4107        out.append(getClass().getName());
4108        out.append('{');
4109        out.append(Integer.toHexString(System.identityHashCode(this)));
4110        out.append(' ');
4111        switch (mViewFlags&VISIBILITY_MASK) {
4112            case VISIBLE: out.append('V'); break;
4113            case INVISIBLE: out.append('I'); break;
4114            case GONE: out.append('G'); break;
4115            default: out.append('.'); break;
4116        }
4117        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4118        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4119        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4120        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4121        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4122        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4123        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4124        out.append(' ');
4125        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4126        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4127        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4128        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4129            out.append('p');
4130        } else {
4131            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4132        }
4133        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4134        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4135        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4136        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4137        out.append(' ');
4138        out.append(mLeft);
4139        out.append(',');
4140        out.append(mTop);
4141        out.append('-');
4142        out.append(mRight);
4143        out.append(',');
4144        out.append(mBottom);
4145        final int id = getId();
4146        if (id != NO_ID) {
4147            out.append(" #");
4148            out.append(Integer.toHexString(id));
4149            final Resources r = mResources;
4150            if (Resources.resourceHasPackage(id) && r != null) {
4151                try {
4152                    String pkgname;
4153                    switch (id&0xff000000) {
4154                        case 0x7f000000:
4155                            pkgname="app";
4156                            break;
4157                        case 0x01000000:
4158                            pkgname="android";
4159                            break;
4160                        default:
4161                            pkgname = r.getResourcePackageName(id);
4162                            break;
4163                    }
4164                    String typename = r.getResourceTypeName(id);
4165                    String entryname = r.getResourceEntryName(id);
4166                    out.append(" ");
4167                    out.append(pkgname);
4168                    out.append(":");
4169                    out.append(typename);
4170                    out.append("/");
4171                    out.append(entryname);
4172                } catch (Resources.NotFoundException e) {
4173                }
4174            }
4175        }
4176        out.append("}");
4177        return out.toString();
4178    }
4179
4180    /**
4181     * <p>
4182     * Initializes the fading edges from a given set of styled attributes. This
4183     * method should be called by subclasses that need fading edges and when an
4184     * instance of these subclasses is created programmatically rather than
4185     * being inflated from XML. This method is automatically called when the XML
4186     * is inflated.
4187     * </p>
4188     *
4189     * @param a the styled attributes set to initialize the fading edges from
4190     */
4191    protected void initializeFadingEdge(TypedArray a) {
4192        initScrollCache();
4193
4194        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4195                R.styleable.View_fadingEdgeLength,
4196                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4197    }
4198
4199    /**
4200     * Returns the size of the vertical faded edges used to indicate that more
4201     * content in this view is visible.
4202     *
4203     * @return The size in pixels of the vertical faded edge or 0 if vertical
4204     *         faded edges are not enabled for this view.
4205     * @attr ref android.R.styleable#View_fadingEdgeLength
4206     */
4207    public int getVerticalFadingEdgeLength() {
4208        if (isVerticalFadingEdgeEnabled()) {
4209            ScrollabilityCache cache = mScrollCache;
4210            if (cache != null) {
4211                return cache.fadingEdgeLength;
4212            }
4213        }
4214        return 0;
4215    }
4216
4217    /**
4218     * Set the size of the faded edge used to indicate that more content in this
4219     * view is available.  Will not change whether the fading edge is enabled; use
4220     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4221     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4222     * for the vertical or horizontal fading edges.
4223     *
4224     * @param length The size in pixels of the faded edge used to indicate that more
4225     *        content in this view is visible.
4226     */
4227    public void setFadingEdgeLength(int length) {
4228        initScrollCache();
4229        mScrollCache.fadingEdgeLength = length;
4230    }
4231
4232    /**
4233     * Returns the size of the horizontal faded edges used to indicate that more
4234     * content in this view is visible.
4235     *
4236     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4237     *         faded edges are not enabled for this view.
4238     * @attr ref android.R.styleable#View_fadingEdgeLength
4239     */
4240    public int getHorizontalFadingEdgeLength() {
4241        if (isHorizontalFadingEdgeEnabled()) {
4242            ScrollabilityCache cache = mScrollCache;
4243            if (cache != null) {
4244                return cache.fadingEdgeLength;
4245            }
4246        }
4247        return 0;
4248    }
4249
4250    /**
4251     * Returns the width of the vertical scrollbar.
4252     *
4253     * @return The width in pixels of the vertical scrollbar or 0 if there
4254     *         is no vertical scrollbar.
4255     */
4256    public int getVerticalScrollbarWidth() {
4257        ScrollabilityCache cache = mScrollCache;
4258        if (cache != null) {
4259            ScrollBarDrawable scrollBar = cache.scrollBar;
4260            if (scrollBar != null) {
4261                int size = scrollBar.getSize(true);
4262                if (size <= 0) {
4263                    size = cache.scrollBarSize;
4264                }
4265                return size;
4266            }
4267            return 0;
4268        }
4269        return 0;
4270    }
4271
4272    /**
4273     * Returns the height of the horizontal scrollbar.
4274     *
4275     * @return The height in pixels of the horizontal scrollbar or 0 if
4276     *         there is no horizontal scrollbar.
4277     */
4278    protected int getHorizontalScrollbarHeight() {
4279        ScrollabilityCache cache = mScrollCache;
4280        if (cache != null) {
4281            ScrollBarDrawable scrollBar = cache.scrollBar;
4282            if (scrollBar != null) {
4283                int size = scrollBar.getSize(false);
4284                if (size <= 0) {
4285                    size = cache.scrollBarSize;
4286                }
4287                return size;
4288            }
4289            return 0;
4290        }
4291        return 0;
4292    }
4293
4294    /**
4295     * <p>
4296     * Initializes the scrollbars from a given set of styled attributes. This
4297     * method should be called by subclasses that need scrollbars and when an
4298     * instance of these subclasses is created programmatically rather than
4299     * being inflated from XML. This method is automatically called when the XML
4300     * is inflated.
4301     * </p>
4302     *
4303     * @param a the styled attributes set to initialize the scrollbars from
4304     */
4305    protected void initializeScrollbars(TypedArray a) {
4306        initScrollCache();
4307
4308        final ScrollabilityCache scrollabilityCache = mScrollCache;
4309
4310        if (scrollabilityCache.scrollBar == null) {
4311            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4312        }
4313
4314        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4315
4316        if (!fadeScrollbars) {
4317            scrollabilityCache.state = ScrollabilityCache.ON;
4318        }
4319        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4320
4321
4322        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4323                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4324                        .getScrollBarFadeDuration());
4325        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4326                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4327                ViewConfiguration.getScrollDefaultDelay());
4328
4329
4330        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4331                com.android.internal.R.styleable.View_scrollbarSize,
4332                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4333
4334        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4335        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4336
4337        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4338        if (thumb != null) {
4339            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4340        }
4341
4342        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4343                false);
4344        if (alwaysDraw) {
4345            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4346        }
4347
4348        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4349        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4350
4351        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4352        if (thumb != null) {
4353            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4354        }
4355
4356        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4357                false);
4358        if (alwaysDraw) {
4359            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4360        }
4361
4362        // Apply layout direction to the new Drawables if needed
4363        final int layoutDirection = getLayoutDirection();
4364        if (track != null) {
4365            track.setLayoutDirection(layoutDirection);
4366        }
4367        if (thumb != null) {
4368            thumb.setLayoutDirection(layoutDirection);
4369        }
4370
4371        // Re-apply user/background padding so that scrollbar(s) get added
4372        resolvePadding();
4373    }
4374
4375    /**
4376     * <p>
4377     * Initalizes the scrollability cache if necessary.
4378     * </p>
4379     */
4380    private void initScrollCache() {
4381        if (mScrollCache == null) {
4382            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4383        }
4384    }
4385
4386    private ScrollabilityCache getScrollCache() {
4387        initScrollCache();
4388        return mScrollCache;
4389    }
4390
4391    /**
4392     * Set the position of the vertical scroll bar. Should be one of
4393     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4394     * {@link #SCROLLBAR_POSITION_RIGHT}.
4395     *
4396     * @param position Where the vertical scroll bar should be positioned.
4397     */
4398    public void setVerticalScrollbarPosition(int position) {
4399        if (mVerticalScrollbarPosition != position) {
4400            mVerticalScrollbarPosition = position;
4401            computeOpaqueFlags();
4402            resolvePadding();
4403        }
4404    }
4405
4406    /**
4407     * @return The position where the vertical scroll bar will show, if applicable.
4408     * @see #setVerticalScrollbarPosition(int)
4409     */
4410    public int getVerticalScrollbarPosition() {
4411        return mVerticalScrollbarPosition;
4412    }
4413
4414    ListenerInfo getListenerInfo() {
4415        if (mListenerInfo != null) {
4416            return mListenerInfo;
4417        }
4418        mListenerInfo = new ListenerInfo();
4419        return mListenerInfo;
4420    }
4421
4422    /**
4423     * Register a callback to be invoked when focus of this view changed.
4424     *
4425     * @param l The callback that will run.
4426     */
4427    public void setOnFocusChangeListener(OnFocusChangeListener l) {
4428        getListenerInfo().mOnFocusChangeListener = l;
4429    }
4430
4431    /**
4432     * Add a listener that will be called when the bounds of the view change due to
4433     * layout processing.
4434     *
4435     * @param listener The listener that will be called when layout bounds change.
4436     */
4437    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4438        ListenerInfo li = getListenerInfo();
4439        if (li.mOnLayoutChangeListeners == null) {
4440            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4441        }
4442        if (!li.mOnLayoutChangeListeners.contains(listener)) {
4443            li.mOnLayoutChangeListeners.add(listener);
4444        }
4445    }
4446
4447    /**
4448     * Remove a listener for layout changes.
4449     *
4450     * @param listener The listener for layout bounds change.
4451     */
4452    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4453        ListenerInfo li = mListenerInfo;
4454        if (li == null || li.mOnLayoutChangeListeners == null) {
4455            return;
4456        }
4457        li.mOnLayoutChangeListeners.remove(listener);
4458    }
4459
4460    /**
4461     * Add a listener for attach state changes.
4462     *
4463     * This listener will be called whenever this view is attached or detached
4464     * from a window. Remove the listener using
4465     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4466     *
4467     * @param listener Listener to attach
4468     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4469     */
4470    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4471        ListenerInfo li = getListenerInfo();
4472        if (li.mOnAttachStateChangeListeners == null) {
4473            li.mOnAttachStateChangeListeners
4474                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4475        }
4476        li.mOnAttachStateChangeListeners.add(listener);
4477    }
4478
4479    /**
4480     * Remove a listener for attach state changes. The listener will receive no further
4481     * notification of window attach/detach events.
4482     *
4483     * @param listener Listener to remove
4484     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4485     */
4486    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4487        ListenerInfo li = mListenerInfo;
4488        if (li == null || li.mOnAttachStateChangeListeners == null) {
4489            return;
4490        }
4491        li.mOnAttachStateChangeListeners.remove(listener);
4492    }
4493
4494    /**
4495     * Returns the focus-change callback registered for this view.
4496     *
4497     * @return The callback, or null if one is not registered.
4498     */
4499    public OnFocusChangeListener getOnFocusChangeListener() {
4500        ListenerInfo li = mListenerInfo;
4501        return li != null ? li.mOnFocusChangeListener : null;
4502    }
4503
4504    /**
4505     * Register a callback to be invoked when this view is clicked. If this view is not
4506     * clickable, it becomes clickable.
4507     *
4508     * @param l The callback that will run
4509     *
4510     * @see #setClickable(boolean)
4511     */
4512    public void setOnClickListener(OnClickListener l) {
4513        if (!isClickable()) {
4514            setClickable(true);
4515        }
4516        getListenerInfo().mOnClickListener = l;
4517    }
4518
4519    /**
4520     * Return whether this view has an attached OnClickListener.  Returns
4521     * true if there is a listener, false if there is none.
4522     */
4523    public boolean hasOnClickListeners() {
4524        ListenerInfo li = mListenerInfo;
4525        return (li != null && li.mOnClickListener != null);
4526    }
4527
4528    /**
4529     * Register a callback to be invoked when this view is clicked and held. If this view is not
4530     * long clickable, it becomes long clickable.
4531     *
4532     * @param l The callback that will run
4533     *
4534     * @see #setLongClickable(boolean)
4535     */
4536    public void setOnLongClickListener(OnLongClickListener l) {
4537        if (!isLongClickable()) {
4538            setLongClickable(true);
4539        }
4540        getListenerInfo().mOnLongClickListener = l;
4541    }
4542
4543    /**
4544     * Register a callback to be invoked when the context menu for this view is
4545     * being built. If this view is not long clickable, it becomes long clickable.
4546     *
4547     * @param l The callback that will run
4548     *
4549     */
4550    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4551        if (!isLongClickable()) {
4552            setLongClickable(true);
4553        }
4554        getListenerInfo().mOnCreateContextMenuListener = l;
4555    }
4556
4557    /**
4558     * Call this view's OnClickListener, if it is defined.  Performs all normal
4559     * actions associated with clicking: reporting accessibility event, playing
4560     * a sound, etc.
4561     *
4562     * @return True there was an assigned OnClickListener that was called, false
4563     *         otherwise is returned.
4564     */
4565    public boolean performClick() {
4566        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4567
4568        ListenerInfo li = mListenerInfo;
4569        if (li != null && li.mOnClickListener != null) {
4570            playSoundEffect(SoundEffectConstants.CLICK);
4571            li.mOnClickListener.onClick(this);
4572            return true;
4573        }
4574
4575        return false;
4576    }
4577
4578    /**
4579     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
4580     * this only calls the listener, and does not do any associated clicking
4581     * actions like reporting an accessibility event.
4582     *
4583     * @return True there was an assigned OnClickListener that was called, false
4584     *         otherwise is returned.
4585     */
4586    public boolean callOnClick() {
4587        ListenerInfo li = mListenerInfo;
4588        if (li != null && li.mOnClickListener != null) {
4589            li.mOnClickListener.onClick(this);
4590            return true;
4591        }
4592        return false;
4593    }
4594
4595    /**
4596     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4597     * OnLongClickListener did not consume the event.
4598     *
4599     * @return True if one of the above receivers consumed the event, false otherwise.
4600     */
4601    public boolean performLongClick() {
4602        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4603
4604        boolean handled = false;
4605        ListenerInfo li = mListenerInfo;
4606        if (li != null && li.mOnLongClickListener != null) {
4607            handled = li.mOnLongClickListener.onLongClick(View.this);
4608        }
4609        if (!handled) {
4610            handled = showContextMenu();
4611        }
4612        if (handled) {
4613            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4614        }
4615        return handled;
4616    }
4617
4618    /**
4619     * Performs button-related actions during a touch down event.
4620     *
4621     * @param event The event.
4622     * @return True if the down was consumed.
4623     *
4624     * @hide
4625     */
4626    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4627        if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4628            if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4629                return true;
4630            }
4631        }
4632        return false;
4633    }
4634
4635    /**
4636     * Bring up the context menu for this view.
4637     *
4638     * @return Whether a context menu was displayed.
4639     */
4640    public boolean showContextMenu() {
4641        return getParent().showContextMenuForChild(this);
4642    }
4643
4644    /**
4645     * Bring up the context menu for this view, referring to the item under the specified point.
4646     *
4647     * @param x The referenced x coordinate.
4648     * @param y The referenced y coordinate.
4649     * @param metaState The keyboard modifiers that were pressed.
4650     * @return Whether a context menu was displayed.
4651     *
4652     * @hide
4653     */
4654    public boolean showContextMenu(float x, float y, int metaState) {
4655        return showContextMenu();
4656    }
4657
4658    /**
4659     * Start an action mode.
4660     *
4661     * @param callback Callback that will control the lifecycle of the action mode
4662     * @return The new action mode if it is started, null otherwise
4663     *
4664     * @see ActionMode
4665     */
4666    public ActionMode startActionMode(ActionMode.Callback callback) {
4667        ViewParent parent = getParent();
4668        if (parent == null) return null;
4669        return parent.startActionModeForChild(this, callback);
4670    }
4671
4672    /**
4673     * Register a callback to be invoked when a hardware key is pressed in this view.
4674     * Key presses in software input methods will generally not trigger the methods of
4675     * this listener.
4676     * @param l the key listener to attach to this view
4677     */
4678    public void setOnKeyListener(OnKeyListener l) {
4679        getListenerInfo().mOnKeyListener = l;
4680    }
4681
4682    /**
4683     * Register a callback to be invoked when a touch event is sent to this view.
4684     * @param l the touch listener to attach to this view
4685     */
4686    public void setOnTouchListener(OnTouchListener l) {
4687        getListenerInfo().mOnTouchListener = l;
4688    }
4689
4690    /**
4691     * Register a callback to be invoked when a generic motion event is sent to this view.
4692     * @param l the generic motion listener to attach to this view
4693     */
4694    public void setOnGenericMotionListener(OnGenericMotionListener l) {
4695        getListenerInfo().mOnGenericMotionListener = l;
4696    }
4697
4698    /**
4699     * Register a callback to be invoked when a hover event is sent to this view.
4700     * @param l the hover listener to attach to this view
4701     */
4702    public void setOnHoverListener(OnHoverListener l) {
4703        getListenerInfo().mOnHoverListener = l;
4704    }
4705
4706    /**
4707     * Register a drag event listener callback object for this View. The parameter is
4708     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4709     * View, the system calls the
4710     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4711     * @param l An implementation of {@link android.view.View.OnDragListener}.
4712     */
4713    public void setOnDragListener(OnDragListener l) {
4714        getListenerInfo().mOnDragListener = l;
4715    }
4716
4717    /**
4718     * Give this view focus. This will cause
4719     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
4720     *
4721     * Note: this does not check whether this {@link View} should get focus, it just
4722     * gives it focus no matter what.  It should only be called internally by framework
4723     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4724     *
4725     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4726     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
4727     *        focus moved when requestFocus() is called. It may not always
4728     *        apply, in which case use the default View.FOCUS_DOWN.
4729     * @param previouslyFocusedRect The rectangle of the view that had focus
4730     *        prior in this View's coordinate system.
4731     */
4732    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
4733        if (DBG) {
4734            System.out.println(this + " requestFocus()");
4735        }
4736
4737        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4738            mPrivateFlags |= PFLAG_FOCUSED;
4739
4740            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
4741
4742            if (mParent != null) {
4743                mParent.requestChildFocus(this, this);
4744            }
4745
4746            if (mAttachInfo != null) {
4747                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
4748            }
4749
4750            manageFocusHotspot(true, oldFocus);
4751            onFocusChanged(true, direction, previouslyFocusedRect);
4752            refreshDrawableState();
4753        }
4754    }
4755
4756    /**
4757     * Forwards focus information to the background drawable, if necessary. When
4758     * the view is gaining focus, <code>v</code> is the previous focus holder.
4759     * When the view is losing focus, <code>v</code> is the next focus holder.
4760     *
4761     * @param focused whether this view is focused
4762     * @param v previous or the next focus holder, or null if none
4763     */
4764    private void manageFocusHotspot(boolean focused, View v) {
4765        if (mBackground != null && mBackground.supportsHotspots()) {
4766            final Rect r = new Rect();
4767            if (!focused && v != null) {
4768                v.getBoundsOnScreen(r);
4769                final int[] location = new int[2];
4770                getLocationOnScreen(location);
4771                r.offset(-location[0], -location[1]);
4772            } else {
4773                r.set(0, 0, mRight - mLeft, mBottom - mTop);
4774            }
4775
4776            final float x = r.exactCenterX();
4777            final float y = r.exactCenterY();
4778            mBackground.setHotspot(R.attr.state_focused, x, y);
4779
4780            if (!focused) {
4781                mBackground.removeHotspot(R.attr.state_focused);
4782            }
4783        }
4784    }
4785
4786    /**
4787     * Request that a rectangle of this view be visible on the screen,
4788     * scrolling if necessary just enough.
4789     *
4790     * <p>A View should call this if it maintains some notion of which part
4791     * of its content is interesting.  For example, a text editing view
4792     * should call this when its cursor moves.
4793     *
4794     * @param rectangle The rectangle.
4795     * @return Whether any parent scrolled.
4796     */
4797    public boolean requestRectangleOnScreen(Rect rectangle) {
4798        return requestRectangleOnScreen(rectangle, false);
4799    }
4800
4801    /**
4802     * Request that a rectangle of this view be visible on the screen,
4803     * scrolling if necessary just enough.
4804     *
4805     * <p>A View should call this if it maintains some notion of which part
4806     * of its content is interesting.  For example, a text editing view
4807     * should call this when its cursor moves.
4808     *
4809     * <p>When <code>immediate</code> is set to true, scrolling will not be
4810     * animated.
4811     *
4812     * @param rectangle The rectangle.
4813     * @param immediate True to forbid animated scrolling, false otherwise
4814     * @return Whether any parent scrolled.
4815     */
4816    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
4817        if (mParent == null) {
4818            return false;
4819        }
4820
4821        View child = this;
4822
4823        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
4824        position.set(rectangle);
4825
4826        ViewParent parent = mParent;
4827        boolean scrolled = false;
4828        while (parent != null) {
4829            rectangle.set((int) position.left, (int) position.top,
4830                    (int) position.right, (int) position.bottom);
4831
4832            scrolled |= parent.requestChildRectangleOnScreen(child,
4833                    rectangle, immediate);
4834
4835            if (!child.hasIdentityMatrix()) {
4836                child.getMatrix().mapRect(position);
4837            }
4838
4839            position.offset(child.mLeft, child.mTop);
4840
4841            if (!(parent instanceof View)) {
4842                break;
4843            }
4844
4845            View parentView = (View) parent;
4846
4847            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
4848
4849            child = parentView;
4850            parent = child.getParent();
4851        }
4852
4853        return scrolled;
4854    }
4855
4856    /**
4857     * Called when this view wants to give up focus. If focus is cleared
4858     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
4859     * <p>
4860     * <strong>Note:</strong> When a View clears focus the framework is trying
4861     * to give focus to the first focusable View from the top. Hence, if this
4862     * View is the first from the top that can take focus, then all callbacks
4863     * related to clearing focus will be invoked after wich the framework will
4864     * give focus to this view.
4865     * </p>
4866     */
4867    public void clearFocus() {
4868        if (DBG) {
4869            System.out.println(this + " clearFocus()");
4870        }
4871
4872        clearFocusInternal(null, true, true);
4873    }
4874
4875    /**
4876     * Clears focus from the view, optionally propagating the change up through
4877     * the parent hierarchy and requesting that the root view place new focus.
4878     *
4879     * @param propagate whether to propagate the change up through the parent
4880     *            hierarchy
4881     * @param refocus when propagate is true, specifies whether to request the
4882     *            root view place new focus
4883     */
4884    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
4885        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4886            mPrivateFlags &= ~PFLAG_FOCUSED;
4887
4888            if (propagate && mParent != null) {
4889                mParent.clearChildFocus(this);
4890            }
4891
4892            onFocusChanged(false, 0, null);
4893
4894            manageFocusHotspot(false, focused);
4895            refreshDrawableState();
4896
4897            if (propagate && (!refocus || !rootViewRequestFocus())) {
4898                notifyGlobalFocusCleared(this);
4899            }
4900        }
4901    }
4902
4903    void notifyGlobalFocusCleared(View oldFocus) {
4904        if (oldFocus != null && mAttachInfo != null) {
4905            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
4906        }
4907    }
4908
4909    boolean rootViewRequestFocus() {
4910        final View root = getRootView();
4911        return root != null && root.requestFocus();
4912    }
4913
4914    /**
4915     * Called internally by the view system when a new view is getting focus.
4916     * This is what clears the old focus.
4917     * <p>
4918     * <b>NOTE:</b> The parent view's focused child must be updated manually
4919     * after calling this method. Otherwise, the view hierarchy may be left in
4920     * an inconstent state.
4921     */
4922    void unFocus(View focused) {
4923        if (DBG) {
4924            System.out.println(this + " unFocus()");
4925        }
4926
4927        clearFocusInternal(focused, false, false);
4928    }
4929
4930    /**
4931     * Returns true if this view has focus iteself, or is the ancestor of the
4932     * view that has focus.
4933     *
4934     * @return True if this view has or contains focus, false otherwise.
4935     */
4936    @ViewDebug.ExportedProperty(category = "focus")
4937    public boolean hasFocus() {
4938        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
4939    }
4940
4941    /**
4942     * Returns true if this view is focusable or if it contains a reachable View
4943     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
4944     * is a View whose parents do not block descendants focus.
4945     *
4946     * Only {@link #VISIBLE} views are considered focusable.
4947     *
4948     * @return True if the view is focusable or if the view contains a focusable
4949     *         View, false otherwise.
4950     *
4951     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
4952     */
4953    public boolean hasFocusable() {
4954        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
4955    }
4956
4957    /**
4958     * Called by the view system when the focus state of this view changes.
4959     * When the focus change event is caused by directional navigation, direction
4960     * and previouslyFocusedRect provide insight into where the focus is coming from.
4961     * When overriding, be sure to call up through to the super class so that
4962     * the standard focus handling will occur.
4963     *
4964     * @param gainFocus True if the View has focus; false otherwise.
4965     * @param direction The direction focus has moved when requestFocus()
4966     *                  is called to give this view focus. Values are
4967     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
4968     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
4969     *                  It may not always apply, in which case use the default.
4970     * @param previouslyFocusedRect The rectangle, in this view's coordinate
4971     *        system, of the previously focused view.  If applicable, this will be
4972     *        passed in as finer grained information about where the focus is coming
4973     *        from (in addition to direction).  Will be <code>null</code> otherwise.
4974     */
4975    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
4976            @Nullable Rect previouslyFocusedRect) {
4977        if (gainFocus) {
4978            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
4979        } else {
4980            notifyViewAccessibilityStateChangedIfNeeded(
4981                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
4982        }
4983
4984        InputMethodManager imm = InputMethodManager.peekInstance();
4985        if (!gainFocus) {
4986            if (isPressed()) {
4987                setPressed(false);
4988            }
4989            if (imm != null && mAttachInfo != null
4990                    && mAttachInfo.mHasWindowFocus) {
4991                imm.focusOut(this);
4992            }
4993            onFocusLost();
4994        } else if (imm != null && mAttachInfo != null
4995                && mAttachInfo.mHasWindowFocus) {
4996            imm.focusIn(this);
4997        }
4998
4999        invalidate(true);
5000        ListenerInfo li = mListenerInfo;
5001        if (li != null && li.mOnFocusChangeListener != null) {
5002            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5003        }
5004
5005        if (mAttachInfo != null) {
5006            mAttachInfo.mKeyDispatchState.reset(this);
5007        }
5008    }
5009
5010    /**
5011     * Sends an accessibility event of the given type. If accessibility is
5012     * not enabled this method has no effect. The default implementation calls
5013     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5014     * to populate information about the event source (this View), then calls
5015     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5016     * populate the text content of the event source including its descendants,
5017     * and last calls
5018     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5019     * on its parent to resuest sending of the event to interested parties.
5020     * <p>
5021     * If an {@link AccessibilityDelegate} has been specified via calling
5022     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5023     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5024     * responsible for handling this call.
5025     * </p>
5026     *
5027     * @param eventType The type of the event to send, as defined by several types from
5028     * {@link android.view.accessibility.AccessibilityEvent}, such as
5029     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5030     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5031     *
5032     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5033     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5034     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5035     * @see AccessibilityDelegate
5036     */
5037    public void sendAccessibilityEvent(int eventType) {
5038        if (mAccessibilityDelegate != null) {
5039            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5040        } else {
5041            sendAccessibilityEventInternal(eventType);
5042        }
5043    }
5044
5045    /**
5046     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5047     * {@link AccessibilityEvent} to make an announcement which is related to some
5048     * sort of a context change for which none of the events representing UI transitions
5049     * is a good fit. For example, announcing a new page in a book. If accessibility
5050     * is not enabled this method does nothing.
5051     *
5052     * @param text The announcement text.
5053     */
5054    public void announceForAccessibility(CharSequence text) {
5055        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5056            AccessibilityEvent event = AccessibilityEvent.obtain(
5057                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5058            onInitializeAccessibilityEvent(event);
5059            event.getText().add(text);
5060            event.setContentDescription(null);
5061            mParent.requestSendAccessibilityEvent(this, event);
5062        }
5063    }
5064
5065    /**
5066     * @see #sendAccessibilityEvent(int)
5067     *
5068     * Note: Called from the default {@link AccessibilityDelegate}.
5069     */
5070    void sendAccessibilityEventInternal(int eventType) {
5071        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5072            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5073        }
5074    }
5075
5076    /**
5077     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5078     * takes as an argument an empty {@link AccessibilityEvent} and does not
5079     * perform a check whether accessibility is enabled.
5080     * <p>
5081     * If an {@link AccessibilityDelegate} has been specified via calling
5082     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5083     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5084     * is responsible for handling this call.
5085     * </p>
5086     *
5087     * @param event The event to send.
5088     *
5089     * @see #sendAccessibilityEvent(int)
5090     */
5091    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5092        if (mAccessibilityDelegate != null) {
5093            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5094        } else {
5095            sendAccessibilityEventUncheckedInternal(event);
5096        }
5097    }
5098
5099    /**
5100     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5101     *
5102     * Note: Called from the default {@link AccessibilityDelegate}.
5103     */
5104    void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5105        if (!isShown()) {
5106            return;
5107        }
5108        onInitializeAccessibilityEvent(event);
5109        // Only a subset of accessibility events populates text content.
5110        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5111            dispatchPopulateAccessibilityEvent(event);
5112        }
5113        // In the beginning we called #isShown(), so we know that getParent() is not null.
5114        getParent().requestSendAccessibilityEvent(this, event);
5115    }
5116
5117    /**
5118     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5119     * to its children for adding their text content to the event. Note that the
5120     * event text is populated in a separate dispatch path since we add to the
5121     * event not only the text of the source but also the text of all its descendants.
5122     * A typical implementation will call
5123     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5124     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5125     * on each child. Override this method if custom population of the event text
5126     * content is required.
5127     * <p>
5128     * If an {@link AccessibilityDelegate} has been specified via calling
5129     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5130     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5131     * is responsible for handling this call.
5132     * </p>
5133     * <p>
5134     * <em>Note:</em> Accessibility events of certain types are not dispatched for
5135     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5136     * </p>
5137     *
5138     * @param event The event.
5139     *
5140     * @return True if the event population was completed.
5141     */
5142    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5143        if (mAccessibilityDelegate != null) {
5144            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5145        } else {
5146            return dispatchPopulateAccessibilityEventInternal(event);
5147        }
5148    }
5149
5150    /**
5151     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5152     *
5153     * Note: Called from the default {@link AccessibilityDelegate}.
5154     */
5155    boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5156        onPopulateAccessibilityEvent(event);
5157        return false;
5158    }
5159
5160    /**
5161     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5162     * giving a chance to this View to populate the accessibility event with its
5163     * text content. While this method is free to modify event
5164     * attributes other than text content, doing so should normally be performed in
5165     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5166     * <p>
5167     * Example: Adding formatted date string to an accessibility event in addition
5168     *          to the text added by the super implementation:
5169     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5170     *     super.onPopulateAccessibilityEvent(event);
5171     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5172     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5173     *         mCurrentDate.getTimeInMillis(), flags);
5174     *     event.getText().add(selectedDateUtterance);
5175     * }</pre>
5176     * <p>
5177     * If an {@link AccessibilityDelegate} has been specified via calling
5178     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5179     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5180     * is responsible for handling this call.
5181     * </p>
5182     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5183     * information to the event, in case the default implementation has basic information to add.
5184     * </p>
5185     *
5186     * @param event The accessibility event which to populate.
5187     *
5188     * @see #sendAccessibilityEvent(int)
5189     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5190     */
5191    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5192        if (mAccessibilityDelegate != null) {
5193            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5194        } else {
5195            onPopulateAccessibilityEventInternal(event);
5196        }
5197    }
5198
5199    /**
5200     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5201     *
5202     * Note: Called from the default {@link AccessibilityDelegate}.
5203     */
5204    void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5205    }
5206
5207    /**
5208     * Initializes an {@link AccessibilityEvent} with information about
5209     * this View which is the event source. In other words, the source of
5210     * an accessibility event is the view whose state change triggered firing
5211     * the event.
5212     * <p>
5213     * Example: Setting the password property of an event in addition
5214     *          to properties set by the super implementation:
5215     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5216     *     super.onInitializeAccessibilityEvent(event);
5217     *     event.setPassword(true);
5218     * }</pre>
5219     * <p>
5220     * If an {@link AccessibilityDelegate} has been specified via calling
5221     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5222     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5223     * is responsible for handling this call.
5224     * </p>
5225     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5226     * information to the event, in case the default implementation has basic information to add.
5227     * </p>
5228     * @param event The event to initialize.
5229     *
5230     * @see #sendAccessibilityEvent(int)
5231     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5232     */
5233    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5234        if (mAccessibilityDelegate != null) {
5235            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5236        } else {
5237            onInitializeAccessibilityEventInternal(event);
5238        }
5239    }
5240
5241    /**
5242     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5243     *
5244     * Note: Called from the default {@link AccessibilityDelegate}.
5245     */
5246    void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5247        event.setSource(this);
5248        event.setClassName(View.class.getName());
5249        event.setPackageName(getContext().getPackageName());
5250        event.setEnabled(isEnabled());
5251        event.setContentDescription(mContentDescription);
5252
5253        switch (event.getEventType()) {
5254            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5255                ArrayList<View> focusablesTempList = (mAttachInfo != null)
5256                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5257                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5258                event.setItemCount(focusablesTempList.size());
5259                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5260                if (mAttachInfo != null) {
5261                    focusablesTempList.clear();
5262                }
5263            } break;
5264            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5265                CharSequence text = getIterableTextForAccessibility();
5266                if (text != null && text.length() > 0) {
5267                    event.setFromIndex(getAccessibilitySelectionStart());
5268                    event.setToIndex(getAccessibilitySelectionEnd());
5269                    event.setItemCount(text.length());
5270                }
5271            } break;
5272        }
5273    }
5274
5275    /**
5276     * Returns an {@link AccessibilityNodeInfo} representing this view from the
5277     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
5278     * This method is responsible for obtaining an accessibility node info from a
5279     * pool of reusable instances and calling
5280     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
5281     * initialize the former.
5282     * <p>
5283     * Note: The client is responsible for recycling the obtained instance by calling
5284     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
5285     * </p>
5286     *
5287     * @return A populated {@link AccessibilityNodeInfo}.
5288     *
5289     * @see AccessibilityNodeInfo
5290     */
5291    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
5292        if (mAccessibilityDelegate != null) {
5293            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
5294        } else {
5295            return createAccessibilityNodeInfoInternal();
5296        }
5297    }
5298
5299    /**
5300     * @see #createAccessibilityNodeInfo()
5301     */
5302    AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
5303        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5304        if (provider != null) {
5305            return provider.createAccessibilityNodeInfo(View.NO_ID);
5306        } else {
5307            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
5308            onInitializeAccessibilityNodeInfo(info);
5309            return info;
5310        }
5311    }
5312
5313    /**
5314     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
5315     * The base implementation sets:
5316     * <ul>
5317     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
5318     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
5319     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
5320     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
5321     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
5322     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
5323     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
5324     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
5325     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
5326     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
5327     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
5328     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
5329     * </ul>
5330     * <p>
5331     * Subclasses should override this method, call the super implementation,
5332     * and set additional attributes.
5333     * </p>
5334     * <p>
5335     * If an {@link AccessibilityDelegate} has been specified via calling
5336     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5337     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
5338     * is responsible for handling this call.
5339     * </p>
5340     *
5341     * @param info The instance to initialize.
5342     */
5343    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
5344        if (mAccessibilityDelegate != null) {
5345            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
5346        } else {
5347            onInitializeAccessibilityNodeInfoInternal(info);
5348        }
5349    }
5350
5351    /**
5352     * Gets the location of this view in screen coordintates.
5353     *
5354     * @param outRect The output location
5355     */
5356    void getBoundsOnScreen(Rect outRect) {
5357        if (mAttachInfo == null) {
5358            return;
5359        }
5360
5361        RectF position = mAttachInfo.mTmpTransformRect;
5362        position.set(0, 0, mRight - mLeft, mBottom - mTop);
5363
5364        if (!hasIdentityMatrix()) {
5365            getMatrix().mapRect(position);
5366        }
5367
5368        position.offset(mLeft, mTop);
5369
5370        ViewParent parent = mParent;
5371        while (parent instanceof View) {
5372            View parentView = (View) parent;
5373
5374            position.offset(-parentView.mScrollX, -parentView.mScrollY);
5375
5376            if (!parentView.hasIdentityMatrix()) {
5377                parentView.getMatrix().mapRect(position);
5378            }
5379
5380            position.offset(parentView.mLeft, parentView.mTop);
5381
5382            parent = parentView.mParent;
5383        }
5384
5385        if (parent instanceof ViewRootImpl) {
5386            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
5387            position.offset(0, -viewRootImpl.mCurScrollY);
5388        }
5389
5390        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
5391
5392        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
5393                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
5394    }
5395
5396    /**
5397     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
5398     *
5399     * Note: Called from the default {@link AccessibilityDelegate}.
5400     */
5401    void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
5402        Rect bounds = mAttachInfo.mTmpInvalRect;
5403
5404        getDrawingRect(bounds);
5405        info.setBoundsInParent(bounds);
5406
5407        getBoundsOnScreen(bounds);
5408        info.setBoundsInScreen(bounds);
5409
5410        ViewParent parent = getParentForAccessibility();
5411        if (parent instanceof View) {
5412            info.setParent((View) parent);
5413        }
5414
5415        if (mID != View.NO_ID) {
5416            View rootView = getRootView();
5417            if (rootView == null) {
5418                rootView = this;
5419            }
5420            View label = rootView.findLabelForView(this, mID);
5421            if (label != null) {
5422                info.setLabeledBy(label);
5423            }
5424
5425            if ((mAttachInfo.mAccessibilityFetchFlags
5426                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
5427                    && Resources.resourceHasPackage(mID)) {
5428                try {
5429                    String viewId = getResources().getResourceName(mID);
5430                    info.setViewIdResourceName(viewId);
5431                } catch (Resources.NotFoundException nfe) {
5432                    /* ignore */
5433                }
5434            }
5435        }
5436
5437        if (mLabelForId != View.NO_ID) {
5438            View rootView = getRootView();
5439            if (rootView == null) {
5440                rootView = this;
5441            }
5442            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
5443            if (labeled != null) {
5444                info.setLabelFor(labeled);
5445            }
5446        }
5447
5448        info.setVisibleToUser(isVisibleToUser());
5449
5450        info.setPackageName(mContext.getPackageName());
5451        info.setClassName(View.class.getName());
5452        info.setContentDescription(getContentDescription());
5453
5454        info.setEnabled(isEnabled());
5455        info.setClickable(isClickable());
5456        info.setFocusable(isFocusable());
5457        info.setFocused(isFocused());
5458        info.setAccessibilityFocused(isAccessibilityFocused());
5459        info.setSelected(isSelected());
5460        info.setLongClickable(isLongClickable());
5461        info.setLiveRegion(getAccessibilityLiveRegion());
5462
5463        // TODO: These make sense only if we are in an AdapterView but all
5464        // views can be selected. Maybe from accessibility perspective
5465        // we should report as selectable view in an AdapterView.
5466        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
5467        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
5468
5469        if (isFocusable()) {
5470            if (isFocused()) {
5471                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
5472            } else {
5473                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
5474            }
5475        }
5476
5477        if (!isAccessibilityFocused()) {
5478            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
5479        } else {
5480            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
5481        }
5482
5483        if (isClickable() && isEnabled()) {
5484            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
5485        }
5486
5487        if (isLongClickable() && isEnabled()) {
5488            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
5489        }
5490
5491        CharSequence text = getIterableTextForAccessibility();
5492        if (text != null && text.length() > 0) {
5493            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
5494
5495            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
5496            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
5497            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
5498            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
5499                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
5500                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
5501        }
5502    }
5503
5504    private View findLabelForView(View view, int labeledId) {
5505        if (mMatchLabelForPredicate == null) {
5506            mMatchLabelForPredicate = new MatchLabelForPredicate();
5507        }
5508        mMatchLabelForPredicate.mLabeledId = labeledId;
5509        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
5510    }
5511
5512    /**
5513     * Computes whether this view is visible to the user. Such a view is
5514     * attached, visible, all its predecessors are visible, it is not clipped
5515     * entirely by its predecessors, and has an alpha greater than zero.
5516     *
5517     * @return Whether the view is visible on the screen.
5518     *
5519     * @hide
5520     */
5521    protected boolean isVisibleToUser() {
5522        return isVisibleToUser(null);
5523    }
5524
5525    /**
5526     * Computes whether the given portion of this view is visible to the user.
5527     * Such a view is attached, visible, all its predecessors are visible,
5528     * has an alpha greater than zero, and the specified portion is not
5529     * clipped entirely by its predecessors.
5530     *
5531     * @param boundInView the portion of the view to test; coordinates should be relative; may be
5532     *                    <code>null</code>, and the entire view will be tested in this case.
5533     *                    When <code>true</code> is returned by the function, the actual visible
5534     *                    region will be stored in this parameter; that is, if boundInView is fully
5535     *                    contained within the view, no modification will be made, otherwise regions
5536     *                    outside of the visible area of the view will be clipped.
5537     *
5538     * @return Whether the specified portion of the view is visible on the screen.
5539     *
5540     * @hide
5541     */
5542    protected boolean isVisibleToUser(Rect boundInView) {
5543        if (mAttachInfo != null) {
5544            // Attached to invisible window means this view is not visible.
5545            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
5546                return false;
5547            }
5548            // An invisible predecessor or one with alpha zero means
5549            // that this view is not visible to the user.
5550            Object current = this;
5551            while (current instanceof View) {
5552                View view = (View) current;
5553                // We have attach info so this view is attached and there is no
5554                // need to check whether we reach to ViewRootImpl on the way up.
5555                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
5556                        view.getVisibility() != VISIBLE) {
5557                    return false;
5558                }
5559                current = view.mParent;
5560            }
5561            // Check if the view is entirely covered by its predecessors.
5562            Rect visibleRect = mAttachInfo.mTmpInvalRect;
5563            Point offset = mAttachInfo.mPoint;
5564            if (!getGlobalVisibleRect(visibleRect, offset)) {
5565                return false;
5566            }
5567            // Check if the visible portion intersects the rectangle of interest.
5568            if (boundInView != null) {
5569                visibleRect.offset(-offset.x, -offset.y);
5570                return boundInView.intersect(visibleRect);
5571            }
5572            return true;
5573        }
5574        return false;
5575    }
5576
5577    /**
5578     * Returns the delegate for implementing accessibility support via
5579     * composition. For more details see {@link AccessibilityDelegate}.
5580     *
5581     * @return The delegate, or null if none set.
5582     *
5583     * @hide
5584     */
5585    public AccessibilityDelegate getAccessibilityDelegate() {
5586        return mAccessibilityDelegate;
5587    }
5588
5589    /**
5590     * Sets a delegate for implementing accessibility support via composition as
5591     * opposed to inheritance. The delegate's primary use is for implementing
5592     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
5593     *
5594     * @param delegate The delegate instance.
5595     *
5596     * @see AccessibilityDelegate
5597     */
5598    public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
5599        mAccessibilityDelegate = delegate;
5600    }
5601
5602    /**
5603     * Gets the provider for managing a virtual view hierarchy rooted at this View
5604     * and reported to {@link android.accessibilityservice.AccessibilityService}s
5605     * that explore the window content.
5606     * <p>
5607     * If this method returns an instance, this instance is responsible for managing
5608     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
5609     * View including the one representing the View itself. Similarly the returned
5610     * instance is responsible for performing accessibility actions on any virtual
5611     * view or the root view itself.
5612     * </p>
5613     * <p>
5614     * If an {@link AccessibilityDelegate} has been specified via calling
5615     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5616     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
5617     * is responsible for handling this call.
5618     * </p>
5619     *
5620     * @return The provider.
5621     *
5622     * @see AccessibilityNodeProvider
5623     */
5624    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
5625        if (mAccessibilityDelegate != null) {
5626            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
5627        } else {
5628            return null;
5629        }
5630    }
5631
5632    /**
5633     * Gets the unique identifier of this view on the screen for accessibility purposes.
5634     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
5635     *
5636     * @return The view accessibility id.
5637     *
5638     * @hide
5639     */
5640    public int getAccessibilityViewId() {
5641        if (mAccessibilityViewId == NO_ID) {
5642            mAccessibilityViewId = sNextAccessibilityViewId++;
5643        }
5644        return mAccessibilityViewId;
5645    }
5646
5647    /**
5648     * Gets the unique identifier of the window in which this View reseides.
5649     *
5650     * @return The window accessibility id.
5651     *
5652     * @hide
5653     */
5654    public int getAccessibilityWindowId() {
5655        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
5656                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
5657    }
5658
5659    /**
5660     * Gets the {@link View} description. It briefly describes the view and is
5661     * primarily used for accessibility support. Set this property to enable
5662     * better accessibility support for your application. This is especially
5663     * true for views that do not have textual representation (For example,
5664     * ImageButton).
5665     *
5666     * @return The content description.
5667     *
5668     * @attr ref android.R.styleable#View_contentDescription
5669     */
5670    @ViewDebug.ExportedProperty(category = "accessibility")
5671    public CharSequence getContentDescription() {
5672        return mContentDescription;
5673    }
5674
5675    /**
5676     * Sets the {@link View} description. It briefly describes the view and is
5677     * primarily used for accessibility support. Set this property to enable
5678     * better accessibility support for your application. This is especially
5679     * true for views that do not have textual representation (For example,
5680     * ImageButton).
5681     *
5682     * @param contentDescription The content description.
5683     *
5684     * @attr ref android.R.styleable#View_contentDescription
5685     */
5686    @RemotableViewMethod
5687    public void setContentDescription(CharSequence contentDescription) {
5688        if (mContentDescription == null) {
5689            if (contentDescription == null) {
5690                return;
5691            }
5692        } else if (mContentDescription.equals(contentDescription)) {
5693            return;
5694        }
5695        mContentDescription = contentDescription;
5696        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
5697        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
5698            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
5699            notifySubtreeAccessibilityStateChangedIfNeeded();
5700        } else {
5701            notifyViewAccessibilityStateChangedIfNeeded(
5702                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
5703        }
5704    }
5705
5706    /**
5707     * Gets the id of a view for which this view serves as a label for
5708     * accessibility purposes.
5709     *
5710     * @return The labeled view id.
5711     */
5712    @ViewDebug.ExportedProperty(category = "accessibility")
5713    public int getLabelFor() {
5714        return mLabelForId;
5715    }
5716
5717    /**
5718     * Sets the id of a view for which this view serves as a label for
5719     * accessibility purposes.
5720     *
5721     * @param id The labeled view id.
5722     */
5723    @RemotableViewMethod
5724    public void setLabelFor(int id) {
5725        mLabelForId = id;
5726        if (mLabelForId != View.NO_ID
5727                && mID == View.NO_ID) {
5728            mID = generateViewId();
5729        }
5730    }
5731
5732    /**
5733     * Invoked whenever this view loses focus, either by losing window focus or by losing
5734     * focus within its window. This method can be used to clear any state tied to the
5735     * focus. For instance, if a button is held pressed with the trackball and the window
5736     * loses focus, this method can be used to cancel the press.
5737     *
5738     * Subclasses of View overriding this method should always call super.onFocusLost().
5739     *
5740     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
5741     * @see #onWindowFocusChanged(boolean)
5742     *
5743     * @hide pending API council approval
5744     */
5745    protected void onFocusLost() {
5746        resetPressedState();
5747    }
5748
5749    private void resetPressedState() {
5750        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
5751            return;
5752        }
5753
5754        if (isPressed()) {
5755            setPressed(false);
5756
5757            if (!mHasPerformedLongPress) {
5758                removeLongPressCallback();
5759            }
5760        }
5761    }
5762
5763    /**
5764     * Returns true if this view has focus
5765     *
5766     * @return True if this view has focus, false otherwise.
5767     */
5768    @ViewDebug.ExportedProperty(category = "focus")
5769    public boolean isFocused() {
5770        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5771    }
5772
5773    /**
5774     * Find the view in the hierarchy rooted at this view that currently has
5775     * focus.
5776     *
5777     * @return The view that currently has focus, or null if no focused view can
5778     *         be found.
5779     */
5780    public View findFocus() {
5781        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
5782    }
5783
5784    /**
5785     * Indicates whether this view is one of the set of scrollable containers in
5786     * its window.
5787     *
5788     * @return whether this view is one of the set of scrollable containers in
5789     * its window
5790     *
5791     * @attr ref android.R.styleable#View_isScrollContainer
5792     */
5793    public boolean isScrollContainer() {
5794        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
5795    }
5796
5797    /**
5798     * Change whether this view is one of the set of scrollable containers in
5799     * its window.  This will be used to determine whether the window can
5800     * resize or must pan when a soft input area is open -- scrollable
5801     * containers allow the window to use resize mode since the container
5802     * will appropriately shrink.
5803     *
5804     * @attr ref android.R.styleable#View_isScrollContainer
5805     */
5806    public void setScrollContainer(boolean isScrollContainer) {
5807        if (isScrollContainer) {
5808            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
5809                mAttachInfo.mScrollContainers.add(this);
5810                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
5811            }
5812            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
5813        } else {
5814            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
5815                mAttachInfo.mScrollContainers.remove(this);
5816            }
5817            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
5818        }
5819    }
5820
5821    /**
5822     * Returns the quality of the drawing cache.
5823     *
5824     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5825     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5826     *
5827     * @see #setDrawingCacheQuality(int)
5828     * @see #setDrawingCacheEnabled(boolean)
5829     * @see #isDrawingCacheEnabled()
5830     *
5831     * @attr ref android.R.styleable#View_drawingCacheQuality
5832     */
5833    @DrawingCacheQuality
5834    public int getDrawingCacheQuality() {
5835        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
5836    }
5837
5838    /**
5839     * Set the drawing cache quality of this view. This value is used only when the
5840     * drawing cache is enabled
5841     *
5842     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5843     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5844     *
5845     * @see #getDrawingCacheQuality()
5846     * @see #setDrawingCacheEnabled(boolean)
5847     * @see #isDrawingCacheEnabled()
5848     *
5849     * @attr ref android.R.styleable#View_drawingCacheQuality
5850     */
5851    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
5852        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
5853    }
5854
5855    /**
5856     * Returns whether the screen should remain on, corresponding to the current
5857     * value of {@link #KEEP_SCREEN_ON}.
5858     *
5859     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
5860     *
5861     * @see #setKeepScreenOn(boolean)
5862     *
5863     * @attr ref android.R.styleable#View_keepScreenOn
5864     */
5865    public boolean getKeepScreenOn() {
5866        return (mViewFlags & KEEP_SCREEN_ON) != 0;
5867    }
5868
5869    /**
5870     * Controls whether the screen should remain on, modifying the
5871     * value of {@link #KEEP_SCREEN_ON}.
5872     *
5873     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
5874     *
5875     * @see #getKeepScreenOn()
5876     *
5877     * @attr ref android.R.styleable#View_keepScreenOn
5878     */
5879    public void setKeepScreenOn(boolean keepScreenOn) {
5880        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
5881    }
5882
5883    /**
5884     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5885     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5886     *
5887     * @attr ref android.R.styleable#View_nextFocusLeft
5888     */
5889    public int getNextFocusLeftId() {
5890        return mNextFocusLeftId;
5891    }
5892
5893    /**
5894     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5895     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
5896     * decide automatically.
5897     *
5898     * @attr ref android.R.styleable#View_nextFocusLeft
5899     */
5900    public void setNextFocusLeftId(int nextFocusLeftId) {
5901        mNextFocusLeftId = nextFocusLeftId;
5902    }
5903
5904    /**
5905     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5906     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5907     *
5908     * @attr ref android.R.styleable#View_nextFocusRight
5909     */
5910    public int getNextFocusRightId() {
5911        return mNextFocusRightId;
5912    }
5913
5914    /**
5915     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5916     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
5917     * decide automatically.
5918     *
5919     * @attr ref android.R.styleable#View_nextFocusRight
5920     */
5921    public void setNextFocusRightId(int nextFocusRightId) {
5922        mNextFocusRightId = nextFocusRightId;
5923    }
5924
5925    /**
5926     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5927     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5928     *
5929     * @attr ref android.R.styleable#View_nextFocusUp
5930     */
5931    public int getNextFocusUpId() {
5932        return mNextFocusUpId;
5933    }
5934
5935    /**
5936     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5937     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
5938     * decide automatically.
5939     *
5940     * @attr ref android.R.styleable#View_nextFocusUp
5941     */
5942    public void setNextFocusUpId(int nextFocusUpId) {
5943        mNextFocusUpId = nextFocusUpId;
5944    }
5945
5946    /**
5947     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5948     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5949     *
5950     * @attr ref android.R.styleable#View_nextFocusDown
5951     */
5952    public int getNextFocusDownId() {
5953        return mNextFocusDownId;
5954    }
5955
5956    /**
5957     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5958     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
5959     * decide automatically.
5960     *
5961     * @attr ref android.R.styleable#View_nextFocusDown
5962     */
5963    public void setNextFocusDownId(int nextFocusDownId) {
5964        mNextFocusDownId = nextFocusDownId;
5965    }
5966
5967    /**
5968     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5969     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5970     *
5971     * @attr ref android.R.styleable#View_nextFocusForward
5972     */
5973    public int getNextFocusForwardId() {
5974        return mNextFocusForwardId;
5975    }
5976
5977    /**
5978     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5979     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
5980     * decide automatically.
5981     *
5982     * @attr ref android.R.styleable#View_nextFocusForward
5983     */
5984    public void setNextFocusForwardId(int nextFocusForwardId) {
5985        mNextFocusForwardId = nextFocusForwardId;
5986    }
5987
5988    /**
5989     * Returns the visibility of this view and all of its ancestors
5990     *
5991     * @return True if this view and all of its ancestors are {@link #VISIBLE}
5992     */
5993    public boolean isShown() {
5994        View current = this;
5995        //noinspection ConstantConditions
5996        do {
5997            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
5998                return false;
5999            }
6000            ViewParent parent = current.mParent;
6001            if (parent == null) {
6002                return false; // We are not attached to the view root
6003            }
6004            if (!(parent instanceof View)) {
6005                return true;
6006            }
6007            current = (View) parent;
6008        } while (current != null);
6009
6010        return false;
6011    }
6012
6013    /**
6014     * Called by the view hierarchy when the content insets for a window have
6015     * changed, to allow it to adjust its content to fit within those windows.
6016     * The content insets tell you the space that the status bar, input method,
6017     * and other system windows infringe on the application's window.
6018     *
6019     * <p>You do not normally need to deal with this function, since the default
6020     * window decoration given to applications takes care of applying it to the
6021     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
6022     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
6023     * and your content can be placed under those system elements.  You can then
6024     * use this method within your view hierarchy if you have parts of your UI
6025     * which you would like to ensure are not being covered.
6026     *
6027     * <p>The default implementation of this method simply applies the content
6028     * insets to the view's padding, consuming that content (modifying the
6029     * insets to be 0), and returning true.  This behavior is off by default, but can
6030     * be enabled through {@link #setFitsSystemWindows(boolean)}.
6031     *
6032     * <p>This function's traversal down the hierarchy is depth-first.  The same content
6033     * insets object is propagated down the hierarchy, so any changes made to it will
6034     * be seen by all following views (including potentially ones above in
6035     * the hierarchy since this is a depth-first traversal).  The first view
6036     * that returns true will abort the entire traversal.
6037     *
6038     * <p>The default implementation works well for a situation where it is
6039     * used with a container that covers the entire window, allowing it to
6040     * apply the appropriate insets to its content on all edges.  If you need
6041     * a more complicated layout (such as two different views fitting system
6042     * windows, one on the top of the window, and one on the bottom),
6043     * you can override the method and handle the insets however you would like.
6044     * Note that the insets provided by the framework are always relative to the
6045     * far edges of the window, not accounting for the location of the called view
6046     * within that window.  (In fact when this method is called you do not yet know
6047     * where the layout will place the view, as it is done before layout happens.)
6048     *
6049     * <p>Note: unlike many View methods, there is no dispatch phase to this
6050     * call.  If you are overriding it in a ViewGroup and want to allow the
6051     * call to continue to your children, you must be sure to call the super
6052     * implementation.
6053     *
6054     * <p>Here is a sample layout that makes use of fitting system windows
6055     * to have controls for a video view placed inside of the window decorations
6056     * that it hides and shows.  This can be used with code like the second
6057     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
6058     *
6059     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
6060     *
6061     * @param insets Current content insets of the window.  Prior to
6062     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
6063     * the insets or else you and Android will be unhappy.
6064     *
6065     * @return {@code true} if this view applied the insets and it should not
6066     * continue propagating further down the hierarchy, {@code false} otherwise.
6067     * @see #getFitsSystemWindows()
6068     * @see #setFitsSystemWindows(boolean)
6069     * @see #setSystemUiVisibility(int)
6070     *
6071     * @deprecated As of API XX use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
6072     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
6073     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
6074     * to implement handling their own insets.
6075     */
6076    protected boolean fitSystemWindows(Rect insets) {
6077        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
6078            // If we're not in the process of dispatching the newer apply insets call,
6079            // that means we're not in the compatibility path. Dispatch into the newer
6080            // apply insets path and take things from there.
6081            try {
6082                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
6083                return !dispatchApplyWindowInsets(new WindowInsets(insets)).hasInsets();
6084            } finally {
6085                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
6086            }
6087        } else {
6088            // We're being called from the newer apply insets path.
6089            // Perform the standard fallback behavior.
6090            return fitSystemWindowsInt(insets);
6091        }
6092    }
6093
6094    private boolean fitSystemWindowsInt(Rect insets) {
6095        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
6096            mUserPaddingStart = UNDEFINED_PADDING;
6097            mUserPaddingEnd = UNDEFINED_PADDING;
6098            Rect localInsets = sThreadLocal.get();
6099            if (localInsets == null) {
6100                localInsets = new Rect();
6101                sThreadLocal.set(localInsets);
6102            }
6103            boolean res = computeFitSystemWindows(insets, localInsets);
6104            mUserPaddingLeftInitial = localInsets.left;
6105            mUserPaddingRightInitial = localInsets.right;
6106            internalSetPadding(localInsets.left, localInsets.top,
6107                    localInsets.right, localInsets.bottom);
6108            return res;
6109        }
6110        return false;
6111    }
6112
6113    /**
6114     * Called when the view should apply {@link WindowInsets} according to its internal policy.
6115     *
6116     * <p>This method should be overridden by views that wish to apply a policy different from or
6117     * in addition to the default behavior. Clients that wish to force a view subtree
6118     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
6119     *
6120     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
6121     * it will be called during dispatch instead of this method. The listener may optionally
6122     * call this method from its own implementation if it wishes to apply the view's default
6123     * insets policy in addition to its own.</p>
6124     *
6125     * <p>Implementations of this method should either return the insets parameter unchanged
6126     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
6127     * that this view applied itself. This allows new inset types added in future platform
6128     * versions to pass through existing implementations unchanged without being erroneously
6129     * consumed.</p>
6130     *
6131     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
6132     * property is set then the view will consume the system window insets and apply them
6133     * as padding for the view.</p>
6134     *
6135     * @param insets Insets to apply
6136     * @return The supplied insets with any applied insets consumed
6137     */
6138    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
6139        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
6140            // We weren't called from within a direct call to fitSystemWindows,
6141            // call into it as a fallback in case we're in a class that overrides it
6142            // and has logic to perform.
6143            if (fitSystemWindows(insets.getSystemWindowInsets())) {
6144                return insets.cloneWithSystemWindowInsetsConsumed();
6145            }
6146        } else {
6147            // We were called from within a direct call to fitSystemWindows.
6148            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
6149                return insets.cloneWithSystemWindowInsetsConsumed();
6150            }
6151        }
6152        return insets;
6153    }
6154
6155    /**
6156     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
6157     * window insets to this view. The listener's
6158     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
6159     * method will be called instead of the view's
6160     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
6161     *
6162     * @param listener Listener to set
6163     *
6164     * @see #onApplyWindowInsets(WindowInsets)
6165     */
6166    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
6167        getListenerInfo().mOnApplyWindowInsetsListener = listener;
6168    }
6169
6170    /**
6171     * Request to apply the given window insets to this view or another view in its subtree.
6172     *
6173     * <p>This method should be called by clients wishing to apply insets corresponding to areas
6174     * obscured by window decorations or overlays. This can include the status and navigation bars,
6175     * action bars, input methods and more. New inset categories may be added in the future.
6176     * The method returns the insets provided minus any that were applied by this view or its
6177     * children.</p>
6178     *
6179     * <p>Clients wishing to provide custom behavior should override the
6180     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
6181     * {@link OnApplyWindowInsetsListener} via the
6182     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
6183     * method.</p>
6184     *
6185     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
6186     * </p>
6187     *
6188     * @param insets Insets to apply
6189     * @return The provided insets minus the insets that were consumed
6190     */
6191    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
6192        try {
6193            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
6194            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
6195                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
6196            } else {
6197                return onApplyWindowInsets(insets);
6198            }
6199        } finally {
6200            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
6201        }
6202    }
6203
6204    /**
6205     * @hide Compute the insets that should be consumed by this view and the ones
6206     * that should propagate to those under it.
6207     */
6208    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
6209        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6210                || mAttachInfo == null
6211                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
6212                        && !mAttachInfo.mOverscanRequested)) {
6213            outLocalInsets.set(inoutInsets);
6214            inoutInsets.set(0, 0, 0, 0);
6215            return true;
6216        } else {
6217            // The application wants to take care of fitting system window for
6218            // the content...  however we still need to take care of any overscan here.
6219            final Rect overscan = mAttachInfo.mOverscanInsets;
6220            outLocalInsets.set(overscan);
6221            inoutInsets.left -= overscan.left;
6222            inoutInsets.top -= overscan.top;
6223            inoutInsets.right -= overscan.right;
6224            inoutInsets.bottom -= overscan.bottom;
6225            return false;
6226        }
6227    }
6228
6229    /**
6230     * Sets whether or not this view should account for system screen decorations
6231     * such as the status bar and inset its content; that is, controlling whether
6232     * the default implementation of {@link #fitSystemWindows(Rect)} will be
6233     * executed.  See that method for more details.
6234     *
6235     * <p>Note that if you are providing your own implementation of
6236     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
6237     * flag to true -- your implementation will be overriding the default
6238     * implementation that checks this flag.
6239     *
6240     * @param fitSystemWindows If true, then the default implementation of
6241     * {@link #fitSystemWindows(Rect)} will be executed.
6242     *
6243     * @attr ref android.R.styleable#View_fitsSystemWindows
6244     * @see #getFitsSystemWindows()
6245     * @see #fitSystemWindows(Rect)
6246     * @see #setSystemUiVisibility(int)
6247     */
6248    public void setFitsSystemWindows(boolean fitSystemWindows) {
6249        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
6250    }
6251
6252    /**
6253     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
6254     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
6255     * will be executed.
6256     *
6257     * @return {@code true} if the default implementation of
6258     * {@link #fitSystemWindows(Rect)} will be executed.
6259     *
6260     * @attr ref android.R.styleable#View_fitsSystemWindows
6261     * @see #setFitsSystemWindows(boolean)
6262     * @see #fitSystemWindows(Rect)
6263     * @see #setSystemUiVisibility(int)
6264     */
6265    public boolean getFitsSystemWindows() {
6266        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
6267    }
6268
6269    /** @hide */
6270    public boolean fitsSystemWindows() {
6271        return getFitsSystemWindows();
6272    }
6273
6274    /**
6275     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
6276     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
6277     */
6278    public void requestFitSystemWindows() {
6279        if (mParent != null) {
6280            mParent.requestFitSystemWindows();
6281        }
6282    }
6283
6284    /**
6285     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
6286     */
6287    public void requestApplyInsets() {
6288        requestFitSystemWindows();
6289    }
6290
6291    /**
6292     * For use by PhoneWindow to make its own system window fitting optional.
6293     * @hide
6294     */
6295    public void makeOptionalFitsSystemWindows() {
6296        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
6297    }
6298
6299    /**
6300     * Returns the visibility status for this view.
6301     *
6302     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6303     * @attr ref android.R.styleable#View_visibility
6304     */
6305    @ViewDebug.ExportedProperty(mapping = {
6306        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
6307        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
6308        @ViewDebug.IntToString(from = GONE,      to = "GONE")
6309    })
6310    @Visibility
6311    public int getVisibility() {
6312        return mViewFlags & VISIBILITY_MASK;
6313    }
6314
6315    /**
6316     * Set the enabled state of this view.
6317     *
6318     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6319     * @attr ref android.R.styleable#View_visibility
6320     */
6321    @RemotableViewMethod
6322    public void setVisibility(@Visibility int visibility) {
6323        setFlags(visibility, VISIBILITY_MASK);
6324        if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
6325    }
6326
6327    /**
6328     * Returns the enabled status for this view. The interpretation of the
6329     * enabled state varies by subclass.
6330     *
6331     * @return True if this view is enabled, false otherwise.
6332     */
6333    @ViewDebug.ExportedProperty
6334    public boolean isEnabled() {
6335        return (mViewFlags & ENABLED_MASK) == ENABLED;
6336    }
6337
6338    /**
6339     * Set the enabled state of this view. The interpretation of the enabled
6340     * state varies by subclass.
6341     *
6342     * @param enabled True if this view is enabled, false otherwise.
6343     */
6344    @RemotableViewMethod
6345    public void setEnabled(boolean enabled) {
6346        if (enabled == isEnabled()) return;
6347
6348        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
6349
6350        /*
6351         * The View most likely has to change its appearance, so refresh
6352         * the drawable state.
6353         */
6354        refreshDrawableState();
6355
6356        // Invalidate too, since the default behavior for views is to be
6357        // be drawn at 50% alpha rather than to change the drawable.
6358        invalidate(true);
6359
6360        if (!enabled) {
6361            cancelPendingInputEvents();
6362        }
6363    }
6364
6365    /**
6366     * Set whether this view can receive the focus.
6367     *
6368     * Setting this to false will also ensure that this view is not focusable
6369     * in touch mode.
6370     *
6371     * @param focusable If true, this view can receive the focus.
6372     *
6373     * @see #setFocusableInTouchMode(boolean)
6374     * @attr ref android.R.styleable#View_focusable
6375     */
6376    public void setFocusable(boolean focusable) {
6377        if (!focusable) {
6378            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
6379        }
6380        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
6381    }
6382
6383    /**
6384     * Set whether this view can receive focus while in touch mode.
6385     *
6386     * Setting this to true will also ensure that this view is focusable.
6387     *
6388     * @param focusableInTouchMode If true, this view can receive the focus while
6389     *   in touch mode.
6390     *
6391     * @see #setFocusable(boolean)
6392     * @attr ref android.R.styleable#View_focusableInTouchMode
6393     */
6394    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
6395        // Focusable in touch mode should always be set before the focusable flag
6396        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
6397        // which, in touch mode, will not successfully request focus on this view
6398        // because the focusable in touch mode flag is not set
6399        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
6400        if (focusableInTouchMode) {
6401            setFlags(FOCUSABLE, FOCUSABLE_MASK);
6402        }
6403    }
6404
6405    /**
6406     * Set whether this view should have sound effects enabled for events such as
6407     * clicking and touching.
6408     *
6409     * <p>You may wish to disable sound effects for a view if you already play sounds,
6410     * for instance, a dial key that plays dtmf tones.
6411     *
6412     * @param soundEffectsEnabled whether sound effects are enabled for this view.
6413     * @see #isSoundEffectsEnabled()
6414     * @see #playSoundEffect(int)
6415     * @attr ref android.R.styleable#View_soundEffectsEnabled
6416     */
6417    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
6418        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
6419    }
6420
6421    /**
6422     * @return whether this view should have sound effects enabled for events such as
6423     *     clicking and touching.
6424     *
6425     * @see #setSoundEffectsEnabled(boolean)
6426     * @see #playSoundEffect(int)
6427     * @attr ref android.R.styleable#View_soundEffectsEnabled
6428     */
6429    @ViewDebug.ExportedProperty
6430    public boolean isSoundEffectsEnabled() {
6431        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
6432    }
6433
6434    /**
6435     * Set whether this view should have haptic feedback for events such as
6436     * long presses.
6437     *
6438     * <p>You may wish to disable haptic feedback if your view already controls
6439     * its own haptic feedback.
6440     *
6441     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
6442     * @see #isHapticFeedbackEnabled()
6443     * @see #performHapticFeedback(int)
6444     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6445     */
6446    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
6447        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
6448    }
6449
6450    /**
6451     * @return whether this view should have haptic feedback enabled for events
6452     * long presses.
6453     *
6454     * @see #setHapticFeedbackEnabled(boolean)
6455     * @see #performHapticFeedback(int)
6456     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6457     */
6458    @ViewDebug.ExportedProperty
6459    public boolean isHapticFeedbackEnabled() {
6460        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
6461    }
6462
6463    /**
6464     * Returns the layout direction for this view.
6465     *
6466     * @return One of {@link #LAYOUT_DIRECTION_LTR},
6467     *   {@link #LAYOUT_DIRECTION_RTL},
6468     *   {@link #LAYOUT_DIRECTION_INHERIT} or
6469     *   {@link #LAYOUT_DIRECTION_LOCALE}.
6470     *
6471     * @attr ref android.R.styleable#View_layoutDirection
6472     *
6473     * @hide
6474     */
6475    @ViewDebug.ExportedProperty(category = "layout", mapping = {
6476        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
6477        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
6478        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
6479        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
6480    })
6481    @LayoutDir
6482    public int getRawLayoutDirection() {
6483        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
6484    }
6485
6486    /**
6487     * Set the layout direction for this view. This will propagate a reset of layout direction
6488     * resolution to the view's children and resolve layout direction for this view.
6489     *
6490     * @param layoutDirection the layout direction to set. Should be one of:
6491     *
6492     * {@link #LAYOUT_DIRECTION_LTR},
6493     * {@link #LAYOUT_DIRECTION_RTL},
6494     * {@link #LAYOUT_DIRECTION_INHERIT},
6495     * {@link #LAYOUT_DIRECTION_LOCALE}.
6496     *
6497     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
6498     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
6499     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
6500     *
6501     * @attr ref android.R.styleable#View_layoutDirection
6502     */
6503    @RemotableViewMethod
6504    public void setLayoutDirection(@LayoutDir int layoutDirection) {
6505        if (getRawLayoutDirection() != layoutDirection) {
6506            // Reset the current layout direction and the resolved one
6507            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
6508            resetRtlProperties();
6509            // Set the new layout direction (filtered)
6510            mPrivateFlags2 |=
6511                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
6512            // We need to resolve all RTL properties as they all depend on layout direction
6513            resolveRtlPropertiesIfNeeded();
6514            requestLayout();
6515            invalidate(true);
6516        }
6517    }
6518
6519    /**
6520     * Returns the resolved layout direction for this view.
6521     *
6522     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
6523     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
6524     *
6525     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
6526     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
6527     *
6528     * @attr ref android.R.styleable#View_layoutDirection
6529     */
6530    @ViewDebug.ExportedProperty(category = "layout", mapping = {
6531        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
6532        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
6533    })
6534    @ResolvedLayoutDir
6535    public int getLayoutDirection() {
6536        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
6537        if (targetSdkVersion < JELLY_BEAN_MR1) {
6538            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
6539            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
6540        }
6541        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
6542                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
6543    }
6544
6545    /**
6546     * Indicates whether or not this view's layout is right-to-left. This is resolved from
6547     * layout attribute and/or the inherited value from the parent
6548     *
6549     * @return true if the layout is right-to-left.
6550     *
6551     * @hide
6552     */
6553    @ViewDebug.ExportedProperty(category = "layout")
6554    public boolean isLayoutRtl() {
6555        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
6556    }
6557
6558    /**
6559     * Indicates whether the view is currently tracking transient state that the
6560     * app should not need to concern itself with saving and restoring, but that
6561     * the framework should take special note to preserve when possible.
6562     *
6563     * <p>A view with transient state cannot be trivially rebound from an external
6564     * data source, such as an adapter binding item views in a list. This may be
6565     * because the view is performing an animation, tracking user selection
6566     * of content, or similar.</p>
6567     *
6568     * @return true if the view has transient state
6569     */
6570    @ViewDebug.ExportedProperty(category = "layout")
6571    public boolean hasTransientState() {
6572        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
6573    }
6574
6575    /**
6576     * Set whether this view is currently tracking transient state that the
6577     * framework should attempt to preserve when possible. This flag is reference counted,
6578     * so every call to setHasTransientState(true) should be paired with a later call
6579     * to setHasTransientState(false).
6580     *
6581     * <p>A view with transient state cannot be trivially rebound from an external
6582     * data source, such as an adapter binding item views in a list. This may be
6583     * because the view is performing an animation, tracking user selection
6584     * of content, or similar.</p>
6585     *
6586     * @param hasTransientState true if this view has transient state
6587     */
6588    public void setHasTransientState(boolean hasTransientState) {
6589        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
6590                mTransientStateCount - 1;
6591        if (mTransientStateCount < 0) {
6592            mTransientStateCount = 0;
6593            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
6594                    "unmatched pair of setHasTransientState calls");
6595        } else if ((hasTransientState && mTransientStateCount == 1) ||
6596                (!hasTransientState && mTransientStateCount == 0)) {
6597            // update flag if we've just incremented up from 0 or decremented down to 0
6598            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
6599                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
6600            if (mParent != null) {
6601                try {
6602                    mParent.childHasTransientStateChanged(this, hasTransientState);
6603                } catch (AbstractMethodError e) {
6604                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
6605                            " does not fully implement ViewParent", e);
6606                }
6607            }
6608        }
6609    }
6610
6611    /**
6612     * Returns true if this view is currently attached to a window.
6613     */
6614    public boolean isAttachedToWindow() {
6615        return mAttachInfo != null;
6616    }
6617
6618    /**
6619     * Returns true if this view has been through at least one layout since it
6620     * was last attached to or detached from a window.
6621     */
6622    public boolean isLaidOut() {
6623        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
6624    }
6625
6626    /**
6627     * If this view doesn't do any drawing on its own, set this flag to
6628     * allow further optimizations. By default, this flag is not set on
6629     * View, but could be set on some View subclasses such as ViewGroup.
6630     *
6631     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
6632     * you should clear this flag.
6633     *
6634     * @param willNotDraw whether or not this View draw on its own
6635     */
6636    public void setWillNotDraw(boolean willNotDraw) {
6637        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
6638    }
6639
6640    /**
6641     * Returns whether or not this View draws on its own.
6642     *
6643     * @return true if this view has nothing to draw, false otherwise
6644     */
6645    @ViewDebug.ExportedProperty(category = "drawing")
6646    public boolean willNotDraw() {
6647        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
6648    }
6649
6650    /**
6651     * When a View's drawing cache is enabled, drawing is redirected to an
6652     * offscreen bitmap. Some views, like an ImageView, must be able to
6653     * bypass this mechanism if they already draw a single bitmap, to avoid
6654     * unnecessary usage of the memory.
6655     *
6656     * @param willNotCacheDrawing true if this view does not cache its
6657     *        drawing, false otherwise
6658     */
6659    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
6660        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
6661    }
6662
6663    /**
6664     * Returns whether or not this View can cache its drawing or not.
6665     *
6666     * @return true if this view does not cache its drawing, false otherwise
6667     */
6668    @ViewDebug.ExportedProperty(category = "drawing")
6669    public boolean willNotCacheDrawing() {
6670        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
6671    }
6672
6673    /**
6674     * Indicates whether this view reacts to click events or not.
6675     *
6676     * @return true if the view is clickable, false otherwise
6677     *
6678     * @see #setClickable(boolean)
6679     * @attr ref android.R.styleable#View_clickable
6680     */
6681    @ViewDebug.ExportedProperty
6682    public boolean isClickable() {
6683        return (mViewFlags & CLICKABLE) == CLICKABLE;
6684    }
6685
6686    /**
6687     * Enables or disables click events for this view. When a view
6688     * is clickable it will change its state to "pressed" on every click.
6689     * Subclasses should set the view clickable to visually react to
6690     * user's clicks.
6691     *
6692     * @param clickable true to make the view clickable, false otherwise
6693     *
6694     * @see #isClickable()
6695     * @attr ref android.R.styleable#View_clickable
6696     */
6697    public void setClickable(boolean clickable) {
6698        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
6699    }
6700
6701    /**
6702     * Indicates whether this view reacts to long click events or not.
6703     *
6704     * @return true if the view is long clickable, false otherwise
6705     *
6706     * @see #setLongClickable(boolean)
6707     * @attr ref android.R.styleable#View_longClickable
6708     */
6709    public boolean isLongClickable() {
6710        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
6711    }
6712
6713    /**
6714     * Enables or disables long click events for this view. When a view is long
6715     * clickable it reacts to the user holding down the button for a longer
6716     * duration than a tap. This event can either launch the listener or a
6717     * context menu.
6718     *
6719     * @param longClickable true to make the view long clickable, false otherwise
6720     * @see #isLongClickable()
6721     * @attr ref android.R.styleable#View_longClickable
6722     */
6723    public void setLongClickable(boolean longClickable) {
6724        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
6725    }
6726
6727    /**
6728     * Sets the pressed state for this view.
6729     *
6730     * @see #isClickable()
6731     * @see #setClickable(boolean)
6732     *
6733     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
6734     *        the View's internal state from a previously set "pressed" state.
6735     */
6736    public void setPressed(boolean pressed) {
6737        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
6738
6739        if (pressed) {
6740            mPrivateFlags |= PFLAG_PRESSED;
6741        } else {
6742            mPrivateFlags &= ~PFLAG_PRESSED;
6743        }
6744
6745        if (needsRefresh) {
6746            refreshDrawableState();
6747        }
6748        dispatchSetPressed(pressed);
6749    }
6750
6751    /**
6752     * Dispatch setPressed to all of this View's children.
6753     *
6754     * @see #setPressed(boolean)
6755     *
6756     * @param pressed The new pressed state
6757     */
6758    protected void dispatchSetPressed(boolean pressed) {
6759    }
6760
6761    /**
6762     * Indicates whether the view is currently in pressed state. Unless
6763     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
6764     * the pressed state.
6765     *
6766     * @see #setPressed(boolean)
6767     * @see #isClickable()
6768     * @see #setClickable(boolean)
6769     *
6770     * @return true if the view is currently pressed, false otherwise
6771     */
6772    public boolean isPressed() {
6773        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
6774    }
6775
6776    /**
6777     * Indicates whether this view will save its state (that is,
6778     * whether its {@link #onSaveInstanceState} method will be called).
6779     *
6780     * @return Returns true if the view state saving is enabled, else false.
6781     *
6782     * @see #setSaveEnabled(boolean)
6783     * @attr ref android.R.styleable#View_saveEnabled
6784     */
6785    public boolean isSaveEnabled() {
6786        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
6787    }
6788
6789    /**
6790     * Controls whether the saving of this view's state is
6791     * enabled (that is, whether its {@link #onSaveInstanceState} method
6792     * will be called).  Note that even if freezing is enabled, the
6793     * view still must have an id assigned to it (via {@link #setId(int)})
6794     * for its state to be saved.  This flag can only disable the
6795     * saving of this view; any child views may still have their state saved.
6796     *
6797     * @param enabled Set to false to <em>disable</em> state saving, or true
6798     * (the default) to allow it.
6799     *
6800     * @see #isSaveEnabled()
6801     * @see #setId(int)
6802     * @see #onSaveInstanceState()
6803     * @attr ref android.R.styleable#View_saveEnabled
6804     */
6805    public void setSaveEnabled(boolean enabled) {
6806        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
6807    }
6808
6809    /**
6810     * Gets whether the framework should discard touches when the view's
6811     * window is obscured by another visible window.
6812     * Refer to the {@link View} security documentation for more details.
6813     *
6814     * @return True if touch filtering is enabled.
6815     *
6816     * @see #setFilterTouchesWhenObscured(boolean)
6817     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
6818     */
6819    @ViewDebug.ExportedProperty
6820    public boolean getFilterTouchesWhenObscured() {
6821        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
6822    }
6823
6824    /**
6825     * Sets whether the framework should discard touches when the view's
6826     * window is obscured by another visible window.
6827     * Refer to the {@link View} security documentation for more details.
6828     *
6829     * @param enabled True if touch filtering should be enabled.
6830     *
6831     * @see #getFilterTouchesWhenObscured
6832     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
6833     */
6834    public void setFilterTouchesWhenObscured(boolean enabled) {
6835        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
6836                FILTER_TOUCHES_WHEN_OBSCURED);
6837    }
6838
6839    /**
6840     * Indicates whether the entire hierarchy under this view will save its
6841     * state when a state saving traversal occurs from its parent.  The default
6842     * is true; if false, these views will not be saved unless
6843     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
6844     *
6845     * @return Returns true if the view state saving from parent is enabled, else false.
6846     *
6847     * @see #setSaveFromParentEnabled(boolean)
6848     */
6849    public boolean isSaveFromParentEnabled() {
6850        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
6851    }
6852
6853    /**
6854     * Controls whether the entire hierarchy under this view will save its
6855     * state when a state saving traversal occurs from its parent.  The default
6856     * is true; if false, these views will not be saved unless
6857     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
6858     *
6859     * @param enabled Set to false to <em>disable</em> state saving, or true
6860     * (the default) to allow it.
6861     *
6862     * @see #isSaveFromParentEnabled()
6863     * @see #setId(int)
6864     * @see #onSaveInstanceState()
6865     */
6866    public void setSaveFromParentEnabled(boolean enabled) {
6867        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
6868    }
6869
6870
6871    /**
6872     * Returns whether this View is able to take focus.
6873     *
6874     * @return True if this view can take focus, or false otherwise.
6875     * @attr ref android.R.styleable#View_focusable
6876     */
6877    @ViewDebug.ExportedProperty(category = "focus")
6878    public final boolean isFocusable() {
6879        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
6880    }
6881
6882    /**
6883     * When a view is focusable, it may not want to take focus when in touch mode.
6884     * For example, a button would like focus when the user is navigating via a D-pad
6885     * so that the user can click on it, but once the user starts touching the screen,
6886     * the button shouldn't take focus
6887     * @return Whether the view is focusable in touch mode.
6888     * @attr ref android.R.styleable#View_focusableInTouchMode
6889     */
6890    @ViewDebug.ExportedProperty
6891    public final boolean isFocusableInTouchMode() {
6892        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
6893    }
6894
6895    /**
6896     * Find the nearest view in the specified direction that can take focus.
6897     * This does not actually give focus to that view.
6898     *
6899     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6900     *
6901     * @return The nearest focusable in the specified direction, or null if none
6902     *         can be found.
6903     */
6904    public View focusSearch(@FocusRealDirection int direction) {
6905        if (mParent != null) {
6906            return mParent.focusSearch(this, direction);
6907        } else {
6908            return null;
6909        }
6910    }
6911
6912    /**
6913     * This method is the last chance for the focused view and its ancestors to
6914     * respond to an arrow key. This is called when the focused view did not
6915     * consume the key internally, nor could the view system find a new view in
6916     * the requested direction to give focus to.
6917     *
6918     * @param focused The currently focused view.
6919     * @param direction The direction focus wants to move. One of FOCUS_UP,
6920     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
6921     * @return True if the this view consumed this unhandled move.
6922     */
6923    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
6924        return false;
6925    }
6926
6927    /**
6928     * If a user manually specified the next view id for a particular direction,
6929     * use the root to look up the view.
6930     * @param root The root view of the hierarchy containing this view.
6931     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
6932     * or FOCUS_BACKWARD.
6933     * @return The user specified next view, or null if there is none.
6934     */
6935    View findUserSetNextFocus(View root, @FocusDirection int direction) {
6936        switch (direction) {
6937            case FOCUS_LEFT:
6938                if (mNextFocusLeftId == View.NO_ID) return null;
6939                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
6940            case FOCUS_RIGHT:
6941                if (mNextFocusRightId == View.NO_ID) return null;
6942                return findViewInsideOutShouldExist(root, mNextFocusRightId);
6943            case FOCUS_UP:
6944                if (mNextFocusUpId == View.NO_ID) return null;
6945                return findViewInsideOutShouldExist(root, mNextFocusUpId);
6946            case FOCUS_DOWN:
6947                if (mNextFocusDownId == View.NO_ID) return null;
6948                return findViewInsideOutShouldExist(root, mNextFocusDownId);
6949            case FOCUS_FORWARD:
6950                if (mNextFocusForwardId == View.NO_ID) return null;
6951                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
6952            case FOCUS_BACKWARD: {
6953                if (mID == View.NO_ID) return null;
6954                final int id = mID;
6955                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
6956                    @Override
6957                    public boolean apply(View t) {
6958                        return t.mNextFocusForwardId == id;
6959                    }
6960                });
6961            }
6962        }
6963        return null;
6964    }
6965
6966    private View findViewInsideOutShouldExist(View root, int id) {
6967        if (mMatchIdPredicate == null) {
6968            mMatchIdPredicate = new MatchIdPredicate();
6969        }
6970        mMatchIdPredicate.mId = id;
6971        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
6972        if (result == null) {
6973            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
6974        }
6975        return result;
6976    }
6977
6978    /**
6979     * Find and return all focusable views that are descendants of this view,
6980     * possibly including this view if it is focusable itself.
6981     *
6982     * @param direction The direction of the focus
6983     * @return A list of focusable views
6984     */
6985    public ArrayList<View> getFocusables(@FocusDirection int direction) {
6986        ArrayList<View> result = new ArrayList<View>(24);
6987        addFocusables(result, direction);
6988        return result;
6989    }
6990
6991    /**
6992     * Add any focusable views that are descendants of this view (possibly
6993     * including this view if it is focusable itself) to views.  If we are in touch mode,
6994     * only add views that are also focusable in touch mode.
6995     *
6996     * @param views Focusable views found so far
6997     * @param direction The direction of the focus
6998     */
6999    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
7000        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
7001    }
7002
7003    /**
7004     * Adds any focusable views that are descendants of this view (possibly
7005     * including this view if it is focusable itself) to views. This method
7006     * adds all focusable views regardless if we are in touch mode or
7007     * only views focusable in touch mode if we are in touch mode or
7008     * only views that can take accessibility focus if accessibility is enabeld
7009     * depending on the focusable mode paramater.
7010     *
7011     * @param views Focusable views found so far or null if all we are interested is
7012     *        the number of focusables.
7013     * @param direction The direction of the focus.
7014     * @param focusableMode The type of focusables to be added.
7015     *
7016     * @see #FOCUSABLES_ALL
7017     * @see #FOCUSABLES_TOUCH_MODE
7018     */
7019    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
7020            @FocusableMode int focusableMode) {
7021        if (views == null) {
7022            return;
7023        }
7024        if (!isFocusable()) {
7025            return;
7026        }
7027        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
7028                && isInTouchMode() && !isFocusableInTouchMode()) {
7029            return;
7030        }
7031        views.add(this);
7032    }
7033
7034    /**
7035     * Finds the Views that contain given text. The containment is case insensitive.
7036     * The search is performed by either the text that the View renders or the content
7037     * description that describes the view for accessibility purposes and the view does
7038     * not render or both. Clients can specify how the search is to be performed via
7039     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
7040     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
7041     *
7042     * @param outViews The output list of matching Views.
7043     * @param searched The text to match against.
7044     *
7045     * @see #FIND_VIEWS_WITH_TEXT
7046     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
7047     * @see #setContentDescription(CharSequence)
7048     */
7049    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
7050            @FindViewFlags int flags) {
7051        if (getAccessibilityNodeProvider() != null) {
7052            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
7053                outViews.add(this);
7054            }
7055        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
7056                && (searched != null && searched.length() > 0)
7057                && (mContentDescription != null && mContentDescription.length() > 0)) {
7058            String searchedLowerCase = searched.toString().toLowerCase();
7059            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
7060            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
7061                outViews.add(this);
7062            }
7063        }
7064    }
7065
7066    /**
7067     * Find and return all touchable views that are descendants of this view,
7068     * possibly including this view if it is touchable itself.
7069     *
7070     * @return A list of touchable views
7071     */
7072    public ArrayList<View> getTouchables() {
7073        ArrayList<View> result = new ArrayList<View>();
7074        addTouchables(result);
7075        return result;
7076    }
7077
7078    /**
7079     * Add any touchable views that are descendants of this view (possibly
7080     * including this view if it is touchable itself) to views.
7081     *
7082     * @param views Touchable views found so far
7083     */
7084    public void addTouchables(ArrayList<View> views) {
7085        final int viewFlags = mViewFlags;
7086
7087        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
7088                && (viewFlags & ENABLED_MASK) == ENABLED) {
7089            views.add(this);
7090        }
7091    }
7092
7093    /**
7094     * Returns whether this View is accessibility focused.
7095     *
7096     * @return True if this View is accessibility focused.
7097     */
7098    public boolean isAccessibilityFocused() {
7099        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
7100    }
7101
7102    /**
7103     * Call this to try to give accessibility focus to this view.
7104     *
7105     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
7106     * returns false or the view is no visible or the view already has accessibility
7107     * focus.
7108     *
7109     * See also {@link #focusSearch(int)}, which is what you call to say that you
7110     * have focus, and you want your parent to look for the next one.
7111     *
7112     * @return Whether this view actually took accessibility focus.
7113     *
7114     * @hide
7115     */
7116    public boolean requestAccessibilityFocus() {
7117        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
7118        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
7119            return false;
7120        }
7121        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7122            return false;
7123        }
7124        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
7125            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
7126            ViewRootImpl viewRootImpl = getViewRootImpl();
7127            if (viewRootImpl != null) {
7128                viewRootImpl.setAccessibilityFocus(this, null);
7129            }
7130            invalidate();
7131            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
7132            return true;
7133        }
7134        return false;
7135    }
7136
7137    /**
7138     * Call this to try to clear accessibility focus of this view.
7139     *
7140     * See also {@link #focusSearch(int)}, which is what you call to say that you
7141     * have focus, and you want your parent to look for the next one.
7142     *
7143     * @hide
7144     */
7145    public void clearAccessibilityFocus() {
7146        clearAccessibilityFocusNoCallbacks();
7147        // Clear the global reference of accessibility focus if this
7148        // view or any of its descendants had accessibility focus.
7149        ViewRootImpl viewRootImpl = getViewRootImpl();
7150        if (viewRootImpl != null) {
7151            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
7152            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
7153                viewRootImpl.setAccessibilityFocus(null, null);
7154            }
7155        }
7156    }
7157
7158    private void sendAccessibilityHoverEvent(int eventType) {
7159        // Since we are not delivering to a client accessibility events from not
7160        // important views (unless the clinet request that) we need to fire the
7161        // event from the deepest view exposed to the client. As a consequence if
7162        // the user crosses a not exposed view the client will see enter and exit
7163        // of the exposed predecessor followed by and enter and exit of that same
7164        // predecessor when entering and exiting the not exposed descendant. This
7165        // is fine since the client has a clear idea which view is hovered at the
7166        // price of a couple more events being sent. This is a simple and
7167        // working solution.
7168        View source = this;
7169        while (true) {
7170            if (source.includeForAccessibility()) {
7171                source.sendAccessibilityEvent(eventType);
7172                return;
7173            }
7174            ViewParent parent = source.getParent();
7175            if (parent instanceof View) {
7176                source = (View) parent;
7177            } else {
7178                return;
7179            }
7180        }
7181    }
7182
7183    /**
7184     * Clears accessibility focus without calling any callback methods
7185     * normally invoked in {@link #clearAccessibilityFocus()}. This method
7186     * is used for clearing accessibility focus when giving this focus to
7187     * another view.
7188     */
7189    void clearAccessibilityFocusNoCallbacks() {
7190        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
7191            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
7192            invalidate();
7193            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
7194        }
7195    }
7196
7197    /**
7198     * Call this to try to give focus to a specific view or to one of its
7199     * descendants.
7200     *
7201     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7202     * false), or if it is focusable and it is not focusable in touch mode
7203     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7204     *
7205     * See also {@link #focusSearch(int)}, which is what you call to say that you
7206     * have focus, and you want your parent to look for the next one.
7207     *
7208     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
7209     * {@link #FOCUS_DOWN} and <code>null</code>.
7210     *
7211     * @return Whether this view or one of its descendants actually took focus.
7212     */
7213    public final boolean requestFocus() {
7214        return requestFocus(View.FOCUS_DOWN);
7215    }
7216
7217    /**
7218     * Call this to try to give focus to a specific view or to one of its
7219     * descendants and give it a hint about what direction focus is heading.
7220     *
7221     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7222     * false), or if it is focusable and it is not focusable in touch mode
7223     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7224     *
7225     * See also {@link #focusSearch(int)}, which is what you call to say that you
7226     * have focus, and you want your parent to look for the next one.
7227     *
7228     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
7229     * <code>null</code> set for the previously focused rectangle.
7230     *
7231     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7232     * @return Whether this view or one of its descendants actually took focus.
7233     */
7234    public final boolean requestFocus(int direction) {
7235        return requestFocus(direction, null);
7236    }
7237
7238    /**
7239     * Call this to try to give focus to a specific view or to one of its descendants
7240     * and give it hints about the direction and a specific rectangle that the focus
7241     * is coming from.  The rectangle can help give larger views a finer grained hint
7242     * about where focus is coming from, and therefore, where to show selection, or
7243     * forward focus change internally.
7244     *
7245     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7246     * false), or if it is focusable and it is not focusable in touch mode
7247     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7248     *
7249     * A View will not take focus if it is not visible.
7250     *
7251     * A View will not take focus if one of its parents has
7252     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
7253     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
7254     *
7255     * See also {@link #focusSearch(int)}, which is what you call to say that you
7256     * have focus, and you want your parent to look for the next one.
7257     *
7258     * You may wish to override this method if your custom {@link View} has an internal
7259     * {@link View} that it wishes to forward the request to.
7260     *
7261     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7262     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
7263     *        to give a finer grained hint about where focus is coming from.  May be null
7264     *        if there is no hint.
7265     * @return Whether this view or one of its descendants actually took focus.
7266     */
7267    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
7268        return requestFocusNoSearch(direction, previouslyFocusedRect);
7269    }
7270
7271    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
7272        // need to be focusable
7273        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
7274                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7275            return false;
7276        }
7277
7278        // need to be focusable in touch mode if in touch mode
7279        if (isInTouchMode() &&
7280            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
7281               return false;
7282        }
7283
7284        // need to not have any parents blocking us
7285        if (hasAncestorThatBlocksDescendantFocus()) {
7286            return false;
7287        }
7288
7289        handleFocusGainInternal(direction, previouslyFocusedRect);
7290        return true;
7291    }
7292
7293    /**
7294     * Call this to try to give focus to a specific view or to one of its descendants. This is a
7295     * special variant of {@link #requestFocus() } that will allow views that are not focuable in
7296     * touch mode to request focus when they are touched.
7297     *
7298     * @return Whether this view or one of its descendants actually took focus.
7299     *
7300     * @see #isInTouchMode()
7301     *
7302     */
7303    public final boolean requestFocusFromTouch() {
7304        // Leave touch mode if we need to
7305        if (isInTouchMode()) {
7306            ViewRootImpl viewRoot = getViewRootImpl();
7307            if (viewRoot != null) {
7308                viewRoot.ensureTouchMode(false);
7309            }
7310        }
7311        return requestFocus(View.FOCUS_DOWN);
7312    }
7313
7314    /**
7315     * @return Whether any ancestor of this view blocks descendant focus.
7316     */
7317    private boolean hasAncestorThatBlocksDescendantFocus() {
7318        ViewParent ancestor = mParent;
7319        while (ancestor instanceof ViewGroup) {
7320            final ViewGroup vgAncestor = (ViewGroup) ancestor;
7321            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
7322                return true;
7323            } else {
7324                ancestor = vgAncestor.getParent();
7325            }
7326        }
7327        return false;
7328    }
7329
7330    /**
7331     * Gets the mode for determining whether this View is important for accessibility
7332     * which is if it fires accessibility events and if it is reported to
7333     * accessibility services that query the screen.
7334     *
7335     * @return The mode for determining whether a View is important for accessibility.
7336     *
7337     * @attr ref android.R.styleable#View_importantForAccessibility
7338     *
7339     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7340     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7341     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7342     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7343     */
7344    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
7345            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
7346            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
7347            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
7348            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
7349                    to = "noHideDescendants")
7350        })
7351    public int getImportantForAccessibility() {
7352        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7353                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7354    }
7355
7356    /**
7357     * Sets the live region mode for this view. This indicates to accessibility
7358     * services whether they should automatically notify the user about changes
7359     * to the view's content description or text, or to the content descriptions
7360     * or text of the view's children (where applicable).
7361     * <p>
7362     * For example, in a login screen with a TextView that displays an "incorrect
7363     * password" notification, that view should be marked as a live region with
7364     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7365     * <p>
7366     * To disable change notifications for this view, use
7367     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
7368     * mode for most views.
7369     * <p>
7370     * To indicate that the user should be notified of changes, use
7371     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7372     * <p>
7373     * If the view's changes should interrupt ongoing speech and notify the user
7374     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
7375     *
7376     * @param mode The live region mode for this view, one of:
7377     *        <ul>
7378     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
7379     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
7380     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
7381     *        </ul>
7382     * @attr ref android.R.styleable#View_accessibilityLiveRegion
7383     */
7384    public void setAccessibilityLiveRegion(int mode) {
7385        if (mode != getAccessibilityLiveRegion()) {
7386            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7387            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
7388                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7389            notifyViewAccessibilityStateChangedIfNeeded(
7390                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7391        }
7392    }
7393
7394    /**
7395     * Gets the live region mode for this View.
7396     *
7397     * @return The live region mode for the view.
7398     *
7399     * @attr ref android.R.styleable#View_accessibilityLiveRegion
7400     *
7401     * @see #setAccessibilityLiveRegion(int)
7402     */
7403    public int getAccessibilityLiveRegion() {
7404        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
7405                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
7406    }
7407
7408    /**
7409     * Sets how to determine whether this view is important for accessibility
7410     * which is if it fires accessibility events and if it is reported to
7411     * accessibility services that query the screen.
7412     *
7413     * @param mode How to determine whether this view is important for accessibility.
7414     *
7415     * @attr ref android.R.styleable#View_importantForAccessibility
7416     *
7417     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7418     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7419     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7420     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7421     */
7422    public void setImportantForAccessibility(int mode) {
7423        final int oldMode = getImportantForAccessibility();
7424        if (mode != oldMode) {
7425            // If we're moving between AUTO and another state, we might not need
7426            // to send a subtree changed notification. We'll store the computed
7427            // importance, since we'll need to check it later to make sure.
7428            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
7429                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
7430            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
7431            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7432            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
7433                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7434            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
7435                notifySubtreeAccessibilityStateChangedIfNeeded();
7436            } else {
7437                notifyViewAccessibilityStateChangedIfNeeded(
7438                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7439            }
7440        }
7441    }
7442
7443    /**
7444     * Computes whether this view should be exposed for accessibility. In
7445     * general, views that are interactive or provide information are exposed
7446     * while views that serve only as containers are hidden.
7447     * <p>
7448     * If an ancestor of this view has importance
7449     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
7450     * returns <code>false</code>.
7451     * <p>
7452     * Otherwise, the value is computed according to the view's
7453     * {@link #getImportantForAccessibility()} value:
7454     * <ol>
7455     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
7456     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
7457     * </code>
7458     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
7459     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
7460     * view satisfies any of the following:
7461     * <ul>
7462     * <li>Is actionable, e.g. {@link #isClickable()},
7463     * {@link #isLongClickable()}, or {@link #isFocusable()}
7464     * <li>Has an {@link AccessibilityDelegate}
7465     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
7466     * {@link OnKeyListener}, etc.
7467     * <li>Is an accessibility live region, e.g.
7468     * {@link #getAccessibilityLiveRegion()} is not
7469     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
7470     * </ul>
7471     * </ol>
7472     *
7473     * @return Whether the view is exposed for accessibility.
7474     * @see #setImportantForAccessibility(int)
7475     * @see #getImportantForAccessibility()
7476     */
7477    public boolean isImportantForAccessibility() {
7478        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7479                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7480        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
7481                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7482            return false;
7483        }
7484
7485        // Check parent mode to ensure we're not hidden.
7486        ViewParent parent = mParent;
7487        while (parent instanceof View) {
7488            if (((View) parent).getImportantForAccessibility()
7489                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7490                return false;
7491            }
7492            parent = parent.getParent();
7493        }
7494
7495        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
7496                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
7497                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
7498    }
7499
7500    /**
7501     * Gets the parent for accessibility purposes. Note that the parent for
7502     * accessibility is not necessary the immediate parent. It is the first
7503     * predecessor that is important for accessibility.
7504     *
7505     * @return The parent for accessibility purposes.
7506     */
7507    public ViewParent getParentForAccessibility() {
7508        if (mParent instanceof View) {
7509            View parentView = (View) mParent;
7510            if (parentView.includeForAccessibility()) {
7511                return mParent;
7512            } else {
7513                return mParent.getParentForAccessibility();
7514            }
7515        }
7516        return null;
7517    }
7518
7519    /**
7520     * Adds the children of a given View for accessibility. Since some Views are
7521     * not important for accessibility the children for accessibility are not
7522     * necessarily direct children of the view, rather they are the first level of
7523     * descendants important for accessibility.
7524     *
7525     * @param children The list of children for accessibility.
7526     */
7527    public void addChildrenForAccessibility(ArrayList<View> children) {
7528
7529    }
7530
7531    /**
7532     * Whether to regard this view for accessibility. A view is regarded for
7533     * accessibility if it is important for accessibility or the querying
7534     * accessibility service has explicitly requested that view not
7535     * important for accessibility are regarded.
7536     *
7537     * @return Whether to regard the view for accessibility.
7538     *
7539     * @hide
7540     */
7541    public boolean includeForAccessibility() {
7542        if (mAttachInfo != null) {
7543            return (mAttachInfo.mAccessibilityFetchFlags
7544                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
7545                    || isImportantForAccessibility();
7546        }
7547        return false;
7548    }
7549
7550    /**
7551     * Returns whether the View is considered actionable from
7552     * accessibility perspective. Such view are important for
7553     * accessibility.
7554     *
7555     * @return True if the view is actionable for accessibility.
7556     *
7557     * @hide
7558     */
7559    public boolean isActionableForAccessibility() {
7560        return (isClickable() || isLongClickable() || isFocusable());
7561    }
7562
7563    /**
7564     * Returns whether the View has registered callbacks which makes it
7565     * important for accessibility.
7566     *
7567     * @return True if the view is actionable for accessibility.
7568     */
7569    private boolean hasListenersForAccessibility() {
7570        ListenerInfo info = getListenerInfo();
7571        return mTouchDelegate != null || info.mOnKeyListener != null
7572                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
7573                || info.mOnHoverListener != null || info.mOnDragListener != null;
7574    }
7575
7576    /**
7577     * Notifies that the accessibility state of this view changed. The change
7578     * is local to this view and does not represent structural changes such
7579     * as children and parent. For example, the view became focusable. The
7580     * notification is at at most once every
7581     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7582     * to avoid unnecessary load to the system. Also once a view has a pending
7583     * notification this method is a NOP until the notification has been sent.
7584     *
7585     * @hide
7586     */
7587    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
7588        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
7589            return;
7590        }
7591        if (mSendViewStateChangedAccessibilityEvent == null) {
7592            mSendViewStateChangedAccessibilityEvent =
7593                    new SendViewStateChangedAccessibilityEvent();
7594        }
7595        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
7596    }
7597
7598    /**
7599     * Notifies that the accessibility state of this view changed. The change
7600     * is *not* local to this view and does represent structural changes such
7601     * as children and parent. For example, the view size changed. The
7602     * notification is at at most once every
7603     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7604     * to avoid unnecessary load to the system. Also once a view has a pending
7605     * notifucation this method is a NOP until the notification has been sent.
7606     *
7607     * @hide
7608     */
7609    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
7610        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
7611            return;
7612        }
7613        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
7614            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
7615            if (mParent != null) {
7616                try {
7617                    mParent.notifySubtreeAccessibilityStateChanged(
7618                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
7619                } catch (AbstractMethodError e) {
7620                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7621                            " does not fully implement ViewParent", e);
7622                }
7623            }
7624        }
7625    }
7626
7627    /**
7628     * Reset the flag indicating the accessibility state of the subtree rooted
7629     * at this view changed.
7630     */
7631    void resetSubtreeAccessibilityStateChanged() {
7632        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
7633    }
7634
7635    /**
7636     * Performs the specified accessibility action on the view. For
7637     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
7638     * <p>
7639     * If an {@link AccessibilityDelegate} has been specified via calling
7640     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7641     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
7642     * is responsible for handling this call.
7643     * </p>
7644     *
7645     * @param action The action to perform.
7646     * @param arguments Optional action arguments.
7647     * @return Whether the action was performed.
7648     */
7649    public boolean performAccessibilityAction(int action, Bundle arguments) {
7650      if (mAccessibilityDelegate != null) {
7651          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
7652      } else {
7653          return performAccessibilityActionInternal(action, arguments);
7654      }
7655    }
7656
7657   /**
7658    * @see #performAccessibilityAction(int, Bundle)
7659    *
7660    * Note: Called from the default {@link AccessibilityDelegate}.
7661    */
7662    boolean performAccessibilityActionInternal(int action, Bundle arguments) {
7663        switch (action) {
7664            case AccessibilityNodeInfo.ACTION_CLICK: {
7665                if (isClickable()) {
7666                    performClick();
7667                    return true;
7668                }
7669            } break;
7670            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
7671                if (isLongClickable()) {
7672                    performLongClick();
7673                    return true;
7674                }
7675            } break;
7676            case AccessibilityNodeInfo.ACTION_FOCUS: {
7677                if (!hasFocus()) {
7678                    // Get out of touch mode since accessibility
7679                    // wants to move focus around.
7680                    getViewRootImpl().ensureTouchMode(false);
7681                    return requestFocus();
7682                }
7683            } break;
7684            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
7685                if (hasFocus()) {
7686                    clearFocus();
7687                    return !isFocused();
7688                }
7689            } break;
7690            case AccessibilityNodeInfo.ACTION_SELECT: {
7691                if (!isSelected()) {
7692                    setSelected(true);
7693                    return isSelected();
7694                }
7695            } break;
7696            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
7697                if (isSelected()) {
7698                    setSelected(false);
7699                    return !isSelected();
7700                }
7701            } break;
7702            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
7703                if (!isAccessibilityFocused()) {
7704                    return requestAccessibilityFocus();
7705                }
7706            } break;
7707            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
7708                if (isAccessibilityFocused()) {
7709                    clearAccessibilityFocus();
7710                    return true;
7711                }
7712            } break;
7713            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
7714                if (arguments != null) {
7715                    final int granularity = arguments.getInt(
7716                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
7717                    final boolean extendSelection = arguments.getBoolean(
7718                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
7719                    return traverseAtGranularity(granularity, true, extendSelection);
7720                }
7721            } break;
7722            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
7723                if (arguments != null) {
7724                    final int granularity = arguments.getInt(
7725                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
7726                    final boolean extendSelection = arguments.getBoolean(
7727                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
7728                    return traverseAtGranularity(granularity, false, extendSelection);
7729                }
7730            } break;
7731            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
7732                CharSequence text = getIterableTextForAccessibility();
7733                if (text == null) {
7734                    return false;
7735                }
7736                final int start = (arguments != null) ? arguments.getInt(
7737                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
7738                final int end = (arguments != null) ? arguments.getInt(
7739                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
7740                // Only cursor position can be specified (selection length == 0)
7741                if ((getAccessibilitySelectionStart() != start
7742                        || getAccessibilitySelectionEnd() != end)
7743                        && (start == end)) {
7744                    setAccessibilitySelection(start, end);
7745                    notifyViewAccessibilityStateChangedIfNeeded(
7746                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7747                    return true;
7748                }
7749            } break;
7750        }
7751        return false;
7752    }
7753
7754    private boolean traverseAtGranularity(int granularity, boolean forward,
7755            boolean extendSelection) {
7756        CharSequence text = getIterableTextForAccessibility();
7757        if (text == null || text.length() == 0) {
7758            return false;
7759        }
7760        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
7761        if (iterator == null) {
7762            return false;
7763        }
7764        int current = getAccessibilitySelectionEnd();
7765        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
7766            current = forward ? 0 : text.length();
7767        }
7768        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
7769        if (range == null) {
7770            return false;
7771        }
7772        final int segmentStart = range[0];
7773        final int segmentEnd = range[1];
7774        int selectionStart;
7775        int selectionEnd;
7776        if (extendSelection && isAccessibilitySelectionExtendable()) {
7777            selectionStart = getAccessibilitySelectionStart();
7778            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
7779                selectionStart = forward ? segmentStart : segmentEnd;
7780            }
7781            selectionEnd = forward ? segmentEnd : segmentStart;
7782        } else {
7783            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
7784        }
7785        setAccessibilitySelection(selectionStart, selectionEnd);
7786        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
7787                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
7788        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
7789        return true;
7790    }
7791
7792    /**
7793     * Gets the text reported for accessibility purposes.
7794     *
7795     * @return The accessibility text.
7796     *
7797     * @hide
7798     */
7799    public CharSequence getIterableTextForAccessibility() {
7800        return getContentDescription();
7801    }
7802
7803    /**
7804     * Gets whether accessibility selection can be extended.
7805     *
7806     * @return If selection is extensible.
7807     *
7808     * @hide
7809     */
7810    public boolean isAccessibilitySelectionExtendable() {
7811        return false;
7812    }
7813
7814    /**
7815     * @hide
7816     */
7817    public int getAccessibilitySelectionStart() {
7818        return mAccessibilityCursorPosition;
7819    }
7820
7821    /**
7822     * @hide
7823     */
7824    public int getAccessibilitySelectionEnd() {
7825        return getAccessibilitySelectionStart();
7826    }
7827
7828    /**
7829     * @hide
7830     */
7831    public void setAccessibilitySelection(int start, int end) {
7832        if (start ==  end && end == mAccessibilityCursorPosition) {
7833            return;
7834        }
7835        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
7836            mAccessibilityCursorPosition = start;
7837        } else {
7838            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
7839        }
7840        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
7841    }
7842
7843    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
7844            int fromIndex, int toIndex) {
7845        if (mParent == null) {
7846            return;
7847        }
7848        AccessibilityEvent event = AccessibilityEvent.obtain(
7849                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
7850        onInitializeAccessibilityEvent(event);
7851        onPopulateAccessibilityEvent(event);
7852        event.setFromIndex(fromIndex);
7853        event.setToIndex(toIndex);
7854        event.setAction(action);
7855        event.setMovementGranularity(granularity);
7856        mParent.requestSendAccessibilityEvent(this, event);
7857    }
7858
7859    /**
7860     * @hide
7861     */
7862    public TextSegmentIterator getIteratorForGranularity(int granularity) {
7863        switch (granularity) {
7864            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
7865                CharSequence text = getIterableTextForAccessibility();
7866                if (text != null && text.length() > 0) {
7867                    CharacterTextSegmentIterator iterator =
7868                        CharacterTextSegmentIterator.getInstance(
7869                                mContext.getResources().getConfiguration().locale);
7870                    iterator.initialize(text.toString());
7871                    return iterator;
7872                }
7873            } break;
7874            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
7875                CharSequence text = getIterableTextForAccessibility();
7876                if (text != null && text.length() > 0) {
7877                    WordTextSegmentIterator iterator =
7878                        WordTextSegmentIterator.getInstance(
7879                                mContext.getResources().getConfiguration().locale);
7880                    iterator.initialize(text.toString());
7881                    return iterator;
7882                }
7883            } break;
7884            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
7885                CharSequence text = getIterableTextForAccessibility();
7886                if (text != null && text.length() > 0) {
7887                    ParagraphTextSegmentIterator iterator =
7888                        ParagraphTextSegmentIterator.getInstance();
7889                    iterator.initialize(text.toString());
7890                    return iterator;
7891                }
7892            } break;
7893        }
7894        return null;
7895    }
7896
7897    /**
7898     * @hide
7899     */
7900    public void dispatchStartTemporaryDetach() {
7901        onStartTemporaryDetach();
7902    }
7903
7904    /**
7905     * This is called when a container is going to temporarily detach a child, with
7906     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
7907     * It will either be followed by {@link #onFinishTemporaryDetach()} or
7908     * {@link #onDetachedFromWindow()} when the container is done.
7909     */
7910    public void onStartTemporaryDetach() {
7911        removeUnsetPressCallback();
7912        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
7913    }
7914
7915    /**
7916     * @hide
7917     */
7918    public void dispatchFinishTemporaryDetach() {
7919        onFinishTemporaryDetach();
7920    }
7921
7922    /**
7923     * Called after {@link #onStartTemporaryDetach} when the container is done
7924     * changing the view.
7925     */
7926    public void onFinishTemporaryDetach() {
7927    }
7928
7929    /**
7930     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
7931     * for this view's window.  Returns null if the view is not currently attached
7932     * to the window.  Normally you will not need to use this directly, but
7933     * just use the standard high-level event callbacks like
7934     * {@link #onKeyDown(int, KeyEvent)}.
7935     */
7936    public KeyEvent.DispatcherState getKeyDispatcherState() {
7937        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
7938    }
7939
7940    /**
7941     * Dispatch a key event before it is processed by any input method
7942     * associated with the view hierarchy.  This can be used to intercept
7943     * key events in special situations before the IME consumes them; a
7944     * typical example would be handling the BACK key to update the application's
7945     * UI instead of allowing the IME to see it and close itself.
7946     *
7947     * @param event The key event to be dispatched.
7948     * @return True if the event was handled, false otherwise.
7949     */
7950    public boolean dispatchKeyEventPreIme(KeyEvent event) {
7951        return onKeyPreIme(event.getKeyCode(), event);
7952    }
7953
7954    /**
7955     * Dispatch a key event to the next view on the focus path. This path runs
7956     * from the top of the view tree down to the currently focused view. If this
7957     * view has focus, it will dispatch to itself. Otherwise it will dispatch
7958     * the next node down the focus path. This method also fires any key
7959     * listeners.
7960     *
7961     * @param event The key event to be dispatched.
7962     * @return True if the event was handled, false otherwise.
7963     */
7964    public boolean dispatchKeyEvent(KeyEvent event) {
7965        if (mInputEventConsistencyVerifier != null) {
7966            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
7967        }
7968
7969        // Give any attached key listener a first crack at the event.
7970        //noinspection SimplifiableIfStatement
7971        ListenerInfo li = mListenerInfo;
7972        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
7973                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
7974            return true;
7975        }
7976
7977        if (event.dispatch(this, mAttachInfo != null
7978                ? mAttachInfo.mKeyDispatchState : null, this)) {
7979            return true;
7980        }
7981
7982        if (mInputEventConsistencyVerifier != null) {
7983            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7984        }
7985        return false;
7986    }
7987
7988    /**
7989     * Dispatches a key shortcut event.
7990     *
7991     * @param event The key event to be dispatched.
7992     * @return True if the event was handled by the view, false otherwise.
7993     */
7994    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7995        return onKeyShortcut(event.getKeyCode(), event);
7996    }
7997
7998    /**
7999     * Pass the touch screen motion event down to the target view, or this
8000     * view if it is the target.
8001     *
8002     * @param event The motion event to be dispatched.
8003     * @return True if the event was handled by the view, false otherwise.
8004     */
8005    public boolean dispatchTouchEvent(MotionEvent event) {
8006        boolean result = false;
8007
8008        if (mInputEventConsistencyVerifier != null) {
8009            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
8010        }
8011
8012        final int actionMasked = event.getActionMasked();
8013        if (actionMasked == MotionEvent.ACTION_DOWN) {
8014            // Defensive cleanup for new gesture
8015            stopNestedScroll();
8016        }
8017
8018        if (onFilterTouchEventForSecurity(event)) {
8019            //noinspection SimplifiableIfStatement
8020            ListenerInfo li = mListenerInfo;
8021            if (li != null && li.mOnTouchListener != null
8022                    && (mViewFlags & ENABLED_MASK) == ENABLED
8023                    && li.mOnTouchListener.onTouch(this, event)) {
8024                result = true;
8025            }
8026
8027            if (!result && onTouchEvent(event)) {
8028                result = true;
8029            }
8030        }
8031
8032        if (!result && mInputEventConsistencyVerifier != null) {
8033            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8034        }
8035
8036        // Clean up after nested scrolls if this is the end of a gesture;
8037        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
8038        // of the gesture.
8039        if (actionMasked == MotionEvent.ACTION_UP ||
8040                actionMasked == MotionEvent.ACTION_CANCEL ||
8041                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
8042            stopNestedScroll();
8043        }
8044
8045        return result;
8046    }
8047
8048    /**
8049     * Filter the touch event to apply security policies.
8050     *
8051     * @param event The motion event to be filtered.
8052     * @return True if the event should be dispatched, false if the event should be dropped.
8053     *
8054     * @see #getFilterTouchesWhenObscured
8055     */
8056    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
8057        //noinspection RedundantIfStatement
8058        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
8059                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
8060            // Window is obscured, drop this touch.
8061            return false;
8062        }
8063        return true;
8064    }
8065
8066    /**
8067     * Pass a trackball motion event down to the focused view.
8068     *
8069     * @param event The motion event to be dispatched.
8070     * @return True if the event was handled by the view, false otherwise.
8071     */
8072    public boolean dispatchTrackballEvent(MotionEvent event) {
8073        if (mInputEventConsistencyVerifier != null) {
8074            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
8075        }
8076
8077        return onTrackballEvent(event);
8078    }
8079
8080    /**
8081     * Dispatch a generic motion event.
8082     * <p>
8083     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8084     * are delivered to the view under the pointer.  All other generic motion events are
8085     * delivered to the focused view.  Hover events are handled specially and are delivered
8086     * to {@link #onHoverEvent(MotionEvent)}.
8087     * </p>
8088     *
8089     * @param event The motion event to be dispatched.
8090     * @return True if the event was handled by the view, false otherwise.
8091     */
8092    public boolean dispatchGenericMotionEvent(MotionEvent event) {
8093        if (mInputEventConsistencyVerifier != null) {
8094            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
8095        }
8096
8097        final int source = event.getSource();
8098        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
8099            final int action = event.getAction();
8100            if (action == MotionEvent.ACTION_HOVER_ENTER
8101                    || action == MotionEvent.ACTION_HOVER_MOVE
8102                    || action == MotionEvent.ACTION_HOVER_EXIT) {
8103                if (dispatchHoverEvent(event)) {
8104                    return true;
8105                }
8106            } else if (dispatchGenericPointerEvent(event)) {
8107                return true;
8108            }
8109        } else if (dispatchGenericFocusedEvent(event)) {
8110            return true;
8111        }
8112
8113        if (dispatchGenericMotionEventInternal(event)) {
8114            return true;
8115        }
8116
8117        if (mInputEventConsistencyVerifier != null) {
8118            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8119        }
8120        return false;
8121    }
8122
8123    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
8124        //noinspection SimplifiableIfStatement
8125        ListenerInfo li = mListenerInfo;
8126        if (li != null && li.mOnGenericMotionListener != null
8127                && (mViewFlags & ENABLED_MASK) == ENABLED
8128                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
8129            return true;
8130        }
8131
8132        if (onGenericMotionEvent(event)) {
8133            return true;
8134        }
8135
8136        if (mInputEventConsistencyVerifier != null) {
8137            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8138        }
8139        return false;
8140    }
8141
8142    /**
8143     * Dispatch a hover event.
8144     * <p>
8145     * Do not call this method directly.
8146     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8147     * </p>
8148     *
8149     * @param event The motion event to be dispatched.
8150     * @return True if the event was handled by the view, false otherwise.
8151     */
8152    protected boolean dispatchHoverEvent(MotionEvent event) {
8153        ListenerInfo li = mListenerInfo;
8154        //noinspection SimplifiableIfStatement
8155        if (li != null && li.mOnHoverListener != null
8156                && (mViewFlags & ENABLED_MASK) == ENABLED
8157                && li.mOnHoverListener.onHover(this, event)) {
8158            return true;
8159        }
8160
8161        return onHoverEvent(event);
8162    }
8163
8164    /**
8165     * Returns true if the view has a child to which it has recently sent
8166     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
8167     * it does not have a hovered child, then it must be the innermost hovered view.
8168     * @hide
8169     */
8170    protected boolean hasHoveredChild() {
8171        return false;
8172    }
8173
8174    /**
8175     * Dispatch a generic motion event to the view under the first pointer.
8176     * <p>
8177     * Do not call this method directly.
8178     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8179     * </p>
8180     *
8181     * @param event The motion event to be dispatched.
8182     * @return True if the event was handled by the view, false otherwise.
8183     */
8184    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
8185        return false;
8186    }
8187
8188    /**
8189     * Dispatch a generic motion event to the currently focused view.
8190     * <p>
8191     * Do not call this method directly.
8192     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8193     * </p>
8194     *
8195     * @param event The motion event to be dispatched.
8196     * @return True if the event was handled by the view, false otherwise.
8197     */
8198    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
8199        return false;
8200    }
8201
8202    /**
8203     * Dispatch a pointer event.
8204     * <p>
8205     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
8206     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
8207     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
8208     * and should not be expected to handle other pointing device features.
8209     * </p>
8210     *
8211     * @param event The motion event to be dispatched.
8212     * @return True if the event was handled by the view, false otherwise.
8213     * @hide
8214     */
8215    public final boolean dispatchPointerEvent(MotionEvent event) {
8216        if (event.isTouchEvent()) {
8217            return dispatchTouchEvent(event);
8218        } else {
8219            return dispatchGenericMotionEvent(event);
8220        }
8221    }
8222
8223    /**
8224     * Called when the window containing this view gains or loses window focus.
8225     * ViewGroups should override to route to their children.
8226     *
8227     * @param hasFocus True if the window containing this view now has focus,
8228     *        false otherwise.
8229     */
8230    public void dispatchWindowFocusChanged(boolean hasFocus) {
8231        onWindowFocusChanged(hasFocus);
8232    }
8233
8234    /**
8235     * Called when the window containing this view gains or loses focus.  Note
8236     * that this is separate from view focus: to receive key events, both
8237     * your view and its window must have focus.  If a window is displayed
8238     * on top of yours that takes input focus, then your own window will lose
8239     * focus but the view focus will remain unchanged.
8240     *
8241     * @param hasWindowFocus True if the window containing this view now has
8242     *        focus, false otherwise.
8243     */
8244    public void onWindowFocusChanged(boolean hasWindowFocus) {
8245        InputMethodManager imm = InputMethodManager.peekInstance();
8246        if (!hasWindowFocus) {
8247            if (isPressed()) {
8248                setPressed(false);
8249            }
8250            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8251                imm.focusOut(this);
8252            }
8253            removeLongPressCallback();
8254            removeTapCallback();
8255            onFocusLost();
8256        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8257            imm.focusIn(this);
8258        }
8259        refreshDrawableState();
8260    }
8261
8262    /**
8263     * Returns true if this view is in a window that currently has window focus.
8264     * Note that this is not the same as the view itself having focus.
8265     *
8266     * @return True if this view is in a window that currently has window focus.
8267     */
8268    public boolean hasWindowFocus() {
8269        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
8270    }
8271
8272    /**
8273     * Dispatch a view visibility change down the view hierarchy.
8274     * ViewGroups should override to route to their children.
8275     * @param changedView The view whose visibility changed. Could be 'this' or
8276     * an ancestor view.
8277     * @param visibility The new visibility of changedView: {@link #VISIBLE},
8278     * {@link #INVISIBLE} or {@link #GONE}.
8279     */
8280    protected void dispatchVisibilityChanged(@NonNull View changedView,
8281            @Visibility int visibility) {
8282        onVisibilityChanged(changedView, visibility);
8283    }
8284
8285    /**
8286     * Called when the visibility of the view or an ancestor of the view is changed.
8287     * @param changedView The view whose visibility changed. Could be 'this' or
8288     * an ancestor view.
8289     * @param visibility The new visibility of changedView: {@link #VISIBLE},
8290     * {@link #INVISIBLE} or {@link #GONE}.
8291     */
8292    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
8293        if (visibility == VISIBLE) {
8294            if (mAttachInfo != null) {
8295                initialAwakenScrollBars();
8296            } else {
8297                mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
8298            }
8299        }
8300    }
8301
8302    /**
8303     * Dispatch a hint about whether this view is displayed. For instance, when
8304     * a View moves out of the screen, it might receives a display hint indicating
8305     * the view is not displayed. Applications should not <em>rely</em> on this hint
8306     * as there is no guarantee that they will receive one.
8307     *
8308     * @param hint A hint about whether or not this view is displayed:
8309     * {@link #VISIBLE} or {@link #INVISIBLE}.
8310     */
8311    public void dispatchDisplayHint(@Visibility int hint) {
8312        onDisplayHint(hint);
8313    }
8314
8315    /**
8316     * Gives this view a hint about whether is displayed or not. For instance, when
8317     * a View moves out of the screen, it might receives a display hint indicating
8318     * the view is not displayed. Applications should not <em>rely</em> on this hint
8319     * as there is no guarantee that they will receive one.
8320     *
8321     * @param hint A hint about whether or not this view is displayed:
8322     * {@link #VISIBLE} or {@link #INVISIBLE}.
8323     */
8324    protected void onDisplayHint(@Visibility int hint) {
8325    }
8326
8327    /**
8328     * Dispatch a window visibility change down the view hierarchy.
8329     * ViewGroups should override to route to their children.
8330     *
8331     * @param visibility The new visibility of the window.
8332     *
8333     * @see #onWindowVisibilityChanged(int)
8334     */
8335    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
8336        onWindowVisibilityChanged(visibility);
8337    }
8338
8339    /**
8340     * Called when the window containing has change its visibility
8341     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
8342     * that this tells you whether or not your window is being made visible
8343     * to the window manager; this does <em>not</em> tell you whether or not
8344     * your window is obscured by other windows on the screen, even if it
8345     * is itself visible.
8346     *
8347     * @param visibility The new visibility of the window.
8348     */
8349    protected void onWindowVisibilityChanged(@Visibility int visibility) {
8350        if (visibility == VISIBLE) {
8351            initialAwakenScrollBars();
8352        }
8353    }
8354
8355    /**
8356     * Returns the current visibility of the window this view is attached to
8357     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
8358     *
8359     * @return Returns the current visibility of the view's window.
8360     */
8361    @Visibility
8362    public int getWindowVisibility() {
8363        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
8364    }
8365
8366    /**
8367     * Retrieve the overall visible display size in which the window this view is
8368     * attached to has been positioned in.  This takes into account screen
8369     * decorations above the window, for both cases where the window itself
8370     * is being position inside of them or the window is being placed under
8371     * then and covered insets are used for the window to position its content
8372     * inside.  In effect, this tells you the available area where content can
8373     * be placed and remain visible to users.
8374     *
8375     * <p>This function requires an IPC back to the window manager to retrieve
8376     * the requested information, so should not be used in performance critical
8377     * code like drawing.
8378     *
8379     * @param outRect Filled in with the visible display frame.  If the view
8380     * is not attached to a window, this is simply the raw display size.
8381     */
8382    public void getWindowVisibleDisplayFrame(Rect outRect) {
8383        if (mAttachInfo != null) {
8384            try {
8385                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
8386            } catch (RemoteException e) {
8387                return;
8388            }
8389            // XXX This is really broken, and probably all needs to be done
8390            // in the window manager, and we need to know more about whether
8391            // we want the area behind or in front of the IME.
8392            final Rect insets = mAttachInfo.mVisibleInsets;
8393            outRect.left += insets.left;
8394            outRect.top += insets.top;
8395            outRect.right -= insets.right;
8396            outRect.bottom -= insets.bottom;
8397            return;
8398        }
8399        // The view is not attached to a display so we don't have a context.
8400        // Make a best guess about the display size.
8401        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
8402        d.getRectSize(outRect);
8403    }
8404
8405    /**
8406     * Dispatch a notification about a resource configuration change down
8407     * the view hierarchy.
8408     * ViewGroups should override to route to their children.
8409     *
8410     * @param newConfig The new resource configuration.
8411     *
8412     * @see #onConfigurationChanged(android.content.res.Configuration)
8413     */
8414    public void dispatchConfigurationChanged(Configuration newConfig) {
8415        onConfigurationChanged(newConfig);
8416    }
8417
8418    /**
8419     * Called when the current configuration of the resources being used
8420     * by the application have changed.  You can use this to decide when
8421     * to reload resources that can changed based on orientation and other
8422     * configuration characterstics.  You only need to use this if you are
8423     * not relying on the normal {@link android.app.Activity} mechanism of
8424     * recreating the activity instance upon a configuration change.
8425     *
8426     * @param newConfig The new resource configuration.
8427     */
8428    protected void onConfigurationChanged(Configuration newConfig) {
8429    }
8430
8431    /**
8432     * Private function to aggregate all per-view attributes in to the view
8433     * root.
8434     */
8435    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8436        performCollectViewAttributes(attachInfo, visibility);
8437    }
8438
8439    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8440        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
8441            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
8442                attachInfo.mKeepScreenOn = true;
8443            }
8444            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
8445            ListenerInfo li = mListenerInfo;
8446            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
8447                attachInfo.mHasSystemUiListeners = true;
8448            }
8449        }
8450    }
8451
8452    void needGlobalAttributesUpdate(boolean force) {
8453        final AttachInfo ai = mAttachInfo;
8454        if (ai != null && !ai.mRecomputeGlobalAttributes) {
8455            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
8456                    || ai.mHasSystemUiListeners) {
8457                ai.mRecomputeGlobalAttributes = true;
8458            }
8459        }
8460    }
8461
8462    /**
8463     * Returns whether the device is currently in touch mode.  Touch mode is entered
8464     * once the user begins interacting with the device by touch, and affects various
8465     * things like whether focus is always visible to the user.
8466     *
8467     * @return Whether the device is in touch mode.
8468     */
8469    @ViewDebug.ExportedProperty
8470    public boolean isInTouchMode() {
8471        if (mAttachInfo != null) {
8472            return mAttachInfo.mInTouchMode;
8473        } else {
8474            return ViewRootImpl.isInTouchMode();
8475        }
8476    }
8477
8478    /**
8479     * Returns the context the view is running in, through which it can
8480     * access the current theme, resources, etc.
8481     *
8482     * @return The view's Context.
8483     */
8484    @ViewDebug.CapturedViewProperty
8485    public final Context getContext() {
8486        return mContext;
8487    }
8488
8489    /**
8490     * Handle a key event before it is processed by any input method
8491     * associated with the view hierarchy.  This can be used to intercept
8492     * key events in special situations before the IME consumes them; a
8493     * typical example would be handling the BACK key to update the application's
8494     * UI instead of allowing the IME to see it and close itself.
8495     *
8496     * @param keyCode The value in event.getKeyCode().
8497     * @param event Description of the key event.
8498     * @return If you handled the event, return true. If you want to allow the
8499     *         event to be handled by the next receiver, return false.
8500     */
8501    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
8502        return false;
8503    }
8504
8505    /**
8506     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
8507     * KeyEvent.Callback.onKeyDown()}: perform press of the view
8508     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
8509     * is released, if the view is enabled and clickable.
8510     *
8511     * <p>Key presses in software keyboards will generally NOT trigger this listener,
8512     * although some may elect to do so in some situations. Do not rely on this to
8513     * catch software key presses.
8514     *
8515     * @param keyCode A key code that represents the button pressed, from
8516     *                {@link android.view.KeyEvent}.
8517     * @param event   The KeyEvent object that defines the button action.
8518     */
8519    public boolean onKeyDown(int keyCode, KeyEvent event) {
8520        boolean result = false;
8521
8522        if (KeyEvent.isConfirmKey(keyCode)) {
8523            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8524                return true;
8525            }
8526            // Long clickable items don't necessarily have to be clickable
8527            if (((mViewFlags & CLICKABLE) == CLICKABLE ||
8528                    (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
8529                    (event.getRepeatCount() == 0)) {
8530                setPressed(true);
8531                checkForLongClick(0);
8532                return true;
8533            }
8534        }
8535        return result;
8536    }
8537
8538    /**
8539     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
8540     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
8541     * the event).
8542     * <p>Key presses in software keyboards will generally NOT trigger this listener,
8543     * although some may elect to do so in some situations. Do not rely on this to
8544     * catch software key presses.
8545     */
8546    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
8547        return false;
8548    }
8549
8550    /**
8551     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
8552     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
8553     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
8554     * {@link KeyEvent#KEYCODE_ENTER} is released.
8555     * <p>Key presses in software keyboards will generally NOT trigger this listener,
8556     * although some may elect to do so in some situations. Do not rely on this to
8557     * catch software key presses.
8558     *
8559     * @param keyCode A key code that represents the button pressed, from
8560     *                {@link android.view.KeyEvent}.
8561     * @param event   The KeyEvent object that defines the button action.
8562     */
8563    public boolean onKeyUp(int keyCode, KeyEvent event) {
8564        if (KeyEvent.isConfirmKey(keyCode)) {
8565            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8566                return true;
8567            }
8568            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
8569                setPressed(false);
8570
8571                if (!mHasPerformedLongPress) {
8572                    // This is a tap, so remove the longpress check
8573                    removeLongPressCallback();
8574                    return performClick();
8575                }
8576            }
8577        }
8578        return false;
8579    }
8580
8581    /**
8582     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
8583     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
8584     * the event).
8585     * <p>Key presses in software keyboards will generally NOT trigger this listener,
8586     * although some may elect to do so in some situations. Do not rely on this to
8587     * catch software key presses.
8588     *
8589     * @param keyCode     A key code that represents the button pressed, from
8590     *                    {@link android.view.KeyEvent}.
8591     * @param repeatCount The number of times the action was made.
8592     * @param event       The KeyEvent object that defines the button action.
8593     */
8594    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
8595        return false;
8596    }
8597
8598    /**
8599     * Called on the focused view when a key shortcut event is not handled.
8600     * Override this method to implement local key shortcuts for the View.
8601     * Key shortcuts can also be implemented by setting the
8602     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
8603     *
8604     * @param keyCode The value in event.getKeyCode().
8605     * @param event Description of the key event.
8606     * @return If you handled the event, return true. If you want to allow the
8607     *         event to be handled by the next receiver, return false.
8608     */
8609    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
8610        return false;
8611    }
8612
8613    /**
8614     * Check whether the called view is a text editor, in which case it
8615     * would make sense to automatically display a soft input window for
8616     * it.  Subclasses should override this if they implement
8617     * {@link #onCreateInputConnection(EditorInfo)} to return true if
8618     * a call on that method would return a non-null InputConnection, and
8619     * they are really a first-class editor that the user would normally
8620     * start typing on when the go into a window containing your view.
8621     *
8622     * <p>The default implementation always returns false.  This does
8623     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
8624     * will not be called or the user can not otherwise perform edits on your
8625     * view; it is just a hint to the system that this is not the primary
8626     * purpose of this view.
8627     *
8628     * @return Returns true if this view is a text editor, else false.
8629     */
8630    public boolean onCheckIsTextEditor() {
8631        return false;
8632    }
8633
8634    /**
8635     * Create a new InputConnection for an InputMethod to interact
8636     * with the view.  The default implementation returns null, since it doesn't
8637     * support input methods.  You can override this to implement such support.
8638     * This is only needed for views that take focus and text input.
8639     *
8640     * <p>When implementing this, you probably also want to implement
8641     * {@link #onCheckIsTextEditor()} to indicate you will return a
8642     * non-null InputConnection.</p>
8643     *
8644     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
8645     * object correctly and in its entirety, so that the connected IME can rely
8646     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
8647     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
8648     * must be filled in with the correct cursor position for IMEs to work correctly
8649     * with your application.</p>
8650     *
8651     * @param outAttrs Fill in with attribute information about the connection.
8652     */
8653    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
8654        return null;
8655    }
8656
8657    /**
8658     * Called by the {@link android.view.inputmethod.InputMethodManager}
8659     * when a view who is not the current
8660     * input connection target is trying to make a call on the manager.  The
8661     * default implementation returns false; you can override this to return
8662     * true for certain views if you are performing InputConnection proxying
8663     * to them.
8664     * @param view The View that is making the InputMethodManager call.
8665     * @return Return true to allow the call, false to reject.
8666     */
8667    public boolean checkInputConnectionProxy(View view) {
8668        return false;
8669    }
8670
8671    /**
8672     * Show the context menu for this view. It is not safe to hold on to the
8673     * menu after returning from this method.
8674     *
8675     * You should normally not overload this method. Overload
8676     * {@link #onCreateContextMenu(ContextMenu)} or define an
8677     * {@link OnCreateContextMenuListener} to add items to the context menu.
8678     *
8679     * @param menu The context menu to populate
8680     */
8681    public void createContextMenu(ContextMenu menu) {
8682        ContextMenuInfo menuInfo = getContextMenuInfo();
8683
8684        // Sets the current menu info so all items added to menu will have
8685        // my extra info set.
8686        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
8687
8688        onCreateContextMenu(menu);
8689        ListenerInfo li = mListenerInfo;
8690        if (li != null && li.mOnCreateContextMenuListener != null) {
8691            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
8692        }
8693
8694        // Clear the extra information so subsequent items that aren't mine don't
8695        // have my extra info.
8696        ((MenuBuilder)menu).setCurrentMenuInfo(null);
8697
8698        if (mParent != null) {
8699            mParent.createContextMenu(menu);
8700        }
8701    }
8702
8703    /**
8704     * Views should implement this if they have extra information to associate
8705     * with the context menu. The return result is supplied as a parameter to
8706     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
8707     * callback.
8708     *
8709     * @return Extra information about the item for which the context menu
8710     *         should be shown. This information will vary across different
8711     *         subclasses of View.
8712     */
8713    protected ContextMenuInfo getContextMenuInfo() {
8714        return null;
8715    }
8716
8717    /**
8718     * Views should implement this if the view itself is going to add items to
8719     * the context menu.
8720     *
8721     * @param menu the context menu to populate
8722     */
8723    protected void onCreateContextMenu(ContextMenu menu) {
8724    }
8725
8726    /**
8727     * Implement this method to handle trackball motion events.  The
8728     * <em>relative</em> movement of the trackball since the last event
8729     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
8730     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
8731     * that a movement of 1 corresponds to the user pressing one DPAD key (so
8732     * they will often be fractional values, representing the more fine-grained
8733     * movement information available from a trackball).
8734     *
8735     * @param event The motion event.
8736     * @return True if the event was handled, false otherwise.
8737     */
8738    public boolean onTrackballEvent(MotionEvent event) {
8739        return false;
8740    }
8741
8742    /**
8743     * Implement this method to handle generic motion events.
8744     * <p>
8745     * Generic motion events describe joystick movements, mouse hovers, track pad
8746     * touches, scroll wheel movements and other input events.  The
8747     * {@link MotionEvent#getSource() source} of the motion event specifies
8748     * the class of input that was received.  Implementations of this method
8749     * must examine the bits in the source before processing the event.
8750     * The following code example shows how this is done.
8751     * </p><p>
8752     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8753     * are delivered to the view under the pointer.  All other generic motion events are
8754     * delivered to the focused view.
8755     * </p>
8756     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
8757     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
8758     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
8759     *             // process the joystick movement...
8760     *             return true;
8761     *         }
8762     *     }
8763     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
8764     *         switch (event.getAction()) {
8765     *             case MotionEvent.ACTION_HOVER_MOVE:
8766     *                 // process the mouse hover movement...
8767     *                 return true;
8768     *             case MotionEvent.ACTION_SCROLL:
8769     *                 // process the scroll wheel movement...
8770     *                 return true;
8771     *         }
8772     *     }
8773     *     return super.onGenericMotionEvent(event);
8774     * }</pre>
8775     *
8776     * @param event The generic motion event being processed.
8777     * @return True if the event was handled, false otherwise.
8778     */
8779    public boolean onGenericMotionEvent(MotionEvent event) {
8780        return false;
8781    }
8782
8783    /**
8784     * Implement this method to handle hover events.
8785     * <p>
8786     * This method is called whenever a pointer is hovering into, over, or out of the
8787     * bounds of a view and the view is not currently being touched.
8788     * Hover events are represented as pointer events with action
8789     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
8790     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
8791     * </p>
8792     * <ul>
8793     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
8794     * when the pointer enters the bounds of the view.</li>
8795     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
8796     * when the pointer has already entered the bounds of the view and has moved.</li>
8797     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
8798     * when the pointer has exited the bounds of the view or when the pointer is
8799     * about to go down due to a button click, tap, or similar user action that
8800     * causes the view to be touched.</li>
8801     * </ul>
8802     * <p>
8803     * The view should implement this method to return true to indicate that it is
8804     * handling the hover event, such as by changing its drawable state.
8805     * </p><p>
8806     * The default implementation calls {@link #setHovered} to update the hovered state
8807     * of the view when a hover enter or hover exit event is received, if the view
8808     * is enabled and is clickable.  The default implementation also sends hover
8809     * accessibility events.
8810     * </p>
8811     *
8812     * @param event The motion event that describes the hover.
8813     * @return True if the view handled the hover event.
8814     *
8815     * @see #isHovered
8816     * @see #setHovered
8817     * @see #onHoverChanged
8818     */
8819    public boolean onHoverEvent(MotionEvent event) {
8820        // The root view may receive hover (or touch) events that are outside the bounds of
8821        // the window.  This code ensures that we only send accessibility events for
8822        // hovers that are actually within the bounds of the root view.
8823        final int action = event.getActionMasked();
8824        if (!mSendingHoverAccessibilityEvents) {
8825            if ((action == MotionEvent.ACTION_HOVER_ENTER
8826                    || action == MotionEvent.ACTION_HOVER_MOVE)
8827                    && !hasHoveredChild()
8828                    && pointInView(event.getX(), event.getY())) {
8829                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
8830                mSendingHoverAccessibilityEvents = true;
8831            }
8832        } else {
8833            if (action == MotionEvent.ACTION_HOVER_EXIT
8834                    || (action == MotionEvent.ACTION_MOVE
8835                            && !pointInView(event.getX(), event.getY()))) {
8836                mSendingHoverAccessibilityEvents = false;
8837                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
8838            }
8839        }
8840
8841        if (isHoverable()) {
8842            switch (action) {
8843                case MotionEvent.ACTION_HOVER_ENTER:
8844                    setHovered(true);
8845                    break;
8846                case MotionEvent.ACTION_HOVER_EXIT:
8847                    setHovered(false);
8848                    break;
8849            }
8850
8851            // Dispatch the event to onGenericMotionEvent before returning true.
8852            // This is to provide compatibility with existing applications that
8853            // handled HOVER_MOVE events in onGenericMotionEvent and that would
8854            // break because of the new default handling for hoverable views
8855            // in onHoverEvent.
8856            // Note that onGenericMotionEvent will be called by default when
8857            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
8858            dispatchGenericMotionEventInternal(event);
8859            // The event was already handled by calling setHovered(), so always
8860            // return true.
8861            return true;
8862        }
8863
8864        return false;
8865    }
8866
8867    /**
8868     * Returns true if the view should handle {@link #onHoverEvent}
8869     * by calling {@link #setHovered} to change its hovered state.
8870     *
8871     * @return True if the view is hoverable.
8872     */
8873    private boolean isHoverable() {
8874        final int viewFlags = mViewFlags;
8875        if ((viewFlags & ENABLED_MASK) == DISABLED) {
8876            return false;
8877        }
8878
8879        return (viewFlags & CLICKABLE) == CLICKABLE
8880                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8881    }
8882
8883    /**
8884     * Returns true if the view is currently hovered.
8885     *
8886     * @return True if the view is currently hovered.
8887     *
8888     * @see #setHovered
8889     * @see #onHoverChanged
8890     */
8891    @ViewDebug.ExportedProperty
8892    public boolean isHovered() {
8893        return (mPrivateFlags & PFLAG_HOVERED) != 0;
8894    }
8895
8896    /**
8897     * Sets whether the view is currently hovered.
8898     * <p>
8899     * Calling this method also changes the drawable state of the view.  This
8900     * enables the view to react to hover by using different drawable resources
8901     * to change its appearance.
8902     * </p><p>
8903     * The {@link #onHoverChanged} method is called when the hovered state changes.
8904     * </p>
8905     *
8906     * @param hovered True if the view is hovered.
8907     *
8908     * @see #isHovered
8909     * @see #onHoverChanged
8910     */
8911    public void setHovered(boolean hovered) {
8912        if (hovered) {
8913            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
8914                mPrivateFlags |= PFLAG_HOVERED;
8915                refreshDrawableState();
8916                onHoverChanged(true);
8917            }
8918        } else {
8919            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
8920                mPrivateFlags &= ~PFLAG_HOVERED;
8921                refreshDrawableState();
8922                onHoverChanged(false);
8923            }
8924        }
8925    }
8926
8927    /**
8928     * Implement this method to handle hover state changes.
8929     * <p>
8930     * This method is called whenever the hover state changes as a result of a
8931     * call to {@link #setHovered}.
8932     * </p>
8933     *
8934     * @param hovered The current hover state, as returned by {@link #isHovered}.
8935     *
8936     * @see #isHovered
8937     * @see #setHovered
8938     */
8939    public void onHoverChanged(boolean hovered) {
8940    }
8941
8942    /**
8943     * Implement this method to handle touch screen motion events.
8944     * <p>
8945     * If this method is used to detect click actions, it is recommended that
8946     * the actions be performed by implementing and calling
8947     * {@link #performClick()}. This will ensure consistent system behavior,
8948     * including:
8949     * <ul>
8950     * <li>obeying click sound preferences
8951     * <li>dispatching OnClickListener calls
8952     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
8953     * accessibility features are enabled
8954     * </ul>
8955     *
8956     * @param event The motion event.
8957     * @return True if the event was handled, false otherwise.
8958     */
8959    public boolean onTouchEvent(MotionEvent event) {
8960        final float x = event.getX();
8961        final float y = event.getY();
8962        final int viewFlags = mViewFlags;
8963
8964        if ((viewFlags & ENABLED_MASK) == DISABLED) {
8965            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
8966                clearHotspot(R.attr.state_pressed);
8967                setPressed(false);
8968            }
8969            // A disabled view that is clickable still consumes the touch
8970            // events, it just doesn't respond to them.
8971            return (((viewFlags & CLICKABLE) == CLICKABLE ||
8972                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
8973        }
8974
8975        if (mTouchDelegate != null) {
8976            if (mTouchDelegate.onTouchEvent(event)) {
8977                return true;
8978            }
8979        }
8980
8981        if (((viewFlags & CLICKABLE) == CLICKABLE ||
8982                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
8983            switch (event.getAction()) {
8984                case MotionEvent.ACTION_UP:
8985                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
8986                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
8987                        // take focus if we don't have it already and we should in
8988                        // touch mode.
8989                        boolean focusTaken = false;
8990                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
8991                            focusTaken = requestFocus();
8992                        }
8993
8994                        if (prepressed) {
8995                            // The button is being released before we actually
8996                            // showed it as pressed.  Make it show the pressed
8997                            // state now (before scheduling the click) to ensure
8998                            // the user sees it.
8999                            setHotspot(R.attr.state_pressed, x, y);
9000                            setPressed(true);
9001                       }
9002
9003                        if (!mHasPerformedLongPress) {
9004                            // This is a tap, so remove the longpress check
9005                            removeLongPressCallback();
9006
9007                            // Only perform take click actions if we were in the pressed state
9008                            if (!focusTaken) {
9009                                // Use a Runnable and post this rather than calling
9010                                // performClick directly. This lets other visual state
9011                                // of the view update before click actions start.
9012                                if (mPerformClick == null) {
9013                                    mPerformClick = new PerformClick();
9014                                }
9015                                if (!post(mPerformClick)) {
9016                                    performClick();
9017                                }
9018                            }
9019                        }
9020
9021                        if (mUnsetPressedState == null) {
9022                            mUnsetPressedState = new UnsetPressedState();
9023                        }
9024
9025                        if (prepressed) {
9026                            postDelayed(mUnsetPressedState,
9027                                    ViewConfiguration.getPressedStateDuration());
9028                        } else if (!post(mUnsetPressedState)) {
9029                            // If the post failed, unpress right now
9030                            mUnsetPressedState.run();
9031                        }
9032
9033                        removeTapCallback();
9034                    } else {
9035                        clearHotspot(R.attr.state_pressed);
9036                    }
9037                    break;
9038
9039                case MotionEvent.ACTION_DOWN:
9040                    mHasPerformedLongPress = false;
9041
9042                    if (performButtonActionOnTouchDown(event)) {
9043                        break;
9044                    }
9045
9046                    // Walk up the hierarchy to determine if we're inside a scrolling container.
9047                    boolean isInScrollingContainer = isInScrollingContainer();
9048
9049                    // For views inside a scrolling container, delay the pressed feedback for
9050                    // a short period in case this is a scroll.
9051                    if (isInScrollingContainer) {
9052                        mPrivateFlags |= PFLAG_PREPRESSED;
9053                        if (mPendingCheckForTap == null) {
9054                            mPendingCheckForTap = new CheckForTap();
9055                        }
9056                        mPendingCheckForTap.x = event.getX();
9057                        mPendingCheckForTap.y = event.getY();
9058                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
9059                    } else {
9060                        // Not inside a scrolling container, so show the feedback right away
9061                        setHotspot(R.attr.state_pressed, x, y);
9062                        setPressed(true);
9063                        checkForLongClick(0);
9064                    }
9065                    break;
9066
9067                case MotionEvent.ACTION_CANCEL:
9068                    clearHotspot(R.attr.state_pressed);
9069                    setPressed(false);
9070                    removeTapCallback();
9071                    removeLongPressCallback();
9072                    break;
9073
9074                case MotionEvent.ACTION_MOVE:
9075                    setHotspot(R.attr.state_pressed, x, y);
9076
9077                    // Be lenient about moving outside of buttons
9078                    if (!pointInView(x, y, mTouchSlop)) {
9079                        // Outside button
9080                        removeTapCallback();
9081                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
9082                            // Remove any future long press/tap checks
9083                            removeLongPressCallback();
9084
9085                            setPressed(false);
9086                        }
9087                    }
9088                    break;
9089            }
9090
9091            return true;
9092        }
9093
9094        return false;
9095    }
9096
9097    private void setHotspot(int id, float x, float y) {
9098        final Drawable bg = mBackground;
9099        if (bg != null && bg.supportsHotspots()) {
9100            bg.setHotspot(id, x, y);
9101        }
9102    }
9103
9104    private void clearHotspot(int id) {
9105        final Drawable bg = mBackground;
9106        if (bg != null && bg.supportsHotspots()) {
9107            bg.removeHotspot(id);
9108        }
9109    }
9110
9111    /**
9112     * @hide
9113     */
9114    public boolean isInScrollingContainer() {
9115        ViewParent p = getParent();
9116        while (p != null && p instanceof ViewGroup) {
9117            if (((ViewGroup) p).shouldDelayChildPressedState()) {
9118                return true;
9119            }
9120            p = p.getParent();
9121        }
9122        return false;
9123    }
9124
9125    /**
9126     * Remove the longpress detection timer.
9127     */
9128    private void removeLongPressCallback() {
9129        if (mPendingCheckForLongPress != null) {
9130          removeCallbacks(mPendingCheckForLongPress);
9131        }
9132    }
9133
9134    /**
9135     * Remove the pending click action
9136     */
9137    private void removePerformClickCallback() {
9138        if (mPerformClick != null) {
9139            removeCallbacks(mPerformClick);
9140        }
9141    }
9142
9143    /**
9144     * Remove the prepress detection timer.
9145     */
9146    private void removeUnsetPressCallback() {
9147        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
9148            clearHotspot(R.attr.state_pressed);
9149            setPressed(false);
9150            removeCallbacks(mUnsetPressedState);
9151        }
9152    }
9153
9154    /**
9155     * Remove the tap detection timer.
9156     */
9157    private void removeTapCallback() {
9158        if (mPendingCheckForTap != null) {
9159            mPrivateFlags &= ~PFLAG_PREPRESSED;
9160            removeCallbacks(mPendingCheckForTap);
9161        }
9162    }
9163
9164    /**
9165     * Cancels a pending long press.  Your subclass can use this if you
9166     * want the context menu to come up if the user presses and holds
9167     * at the same place, but you don't want it to come up if they press
9168     * and then move around enough to cause scrolling.
9169     */
9170    public void cancelLongPress() {
9171        removeLongPressCallback();
9172
9173        /*
9174         * The prepressed state handled by the tap callback is a display
9175         * construct, but the tap callback will post a long press callback
9176         * less its own timeout. Remove it here.
9177         */
9178        removeTapCallback();
9179    }
9180
9181    /**
9182     * Remove the pending callback for sending a
9183     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
9184     */
9185    private void removeSendViewScrolledAccessibilityEventCallback() {
9186        if (mSendViewScrolledAccessibilityEvent != null) {
9187            removeCallbacks(mSendViewScrolledAccessibilityEvent);
9188            mSendViewScrolledAccessibilityEvent.mIsPending = false;
9189        }
9190    }
9191
9192    /**
9193     * Sets the TouchDelegate for this View.
9194     */
9195    public void setTouchDelegate(TouchDelegate delegate) {
9196        mTouchDelegate = delegate;
9197    }
9198
9199    /**
9200     * Gets the TouchDelegate for this View.
9201     */
9202    public TouchDelegate getTouchDelegate() {
9203        return mTouchDelegate;
9204    }
9205
9206    /**
9207     * Set flags controlling behavior of this view.
9208     *
9209     * @param flags Constant indicating the value which should be set
9210     * @param mask Constant indicating the bit range that should be changed
9211     */
9212    void setFlags(int flags, int mask) {
9213        final boolean accessibilityEnabled =
9214                AccessibilityManager.getInstance(mContext).isEnabled();
9215        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
9216
9217        int old = mViewFlags;
9218        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
9219
9220        int changed = mViewFlags ^ old;
9221        if (changed == 0) {
9222            return;
9223        }
9224        int privateFlags = mPrivateFlags;
9225
9226        /* Check if the FOCUSABLE bit has changed */
9227        if (((changed & FOCUSABLE_MASK) != 0) &&
9228                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
9229            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
9230                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
9231                /* Give up focus if we are no longer focusable */
9232                clearFocus();
9233            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
9234                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
9235                /*
9236                 * Tell the view system that we are now available to take focus
9237                 * if no one else already has it.
9238                 */
9239                if (mParent != null) mParent.focusableViewAvailable(this);
9240            }
9241        }
9242
9243        final int newVisibility = flags & VISIBILITY_MASK;
9244        if (newVisibility == VISIBLE) {
9245            if ((changed & VISIBILITY_MASK) != 0) {
9246                /*
9247                 * If this view is becoming visible, invalidate it in case it changed while
9248                 * it was not visible. Marking it drawn ensures that the invalidation will
9249                 * go through.
9250                 */
9251                mPrivateFlags |= PFLAG_DRAWN;
9252                invalidate(true);
9253
9254                needGlobalAttributesUpdate(true);
9255
9256                // a view becoming visible is worth notifying the parent
9257                // about in case nothing has focus.  even if this specific view
9258                // isn't focusable, it may contain something that is, so let
9259                // the root view try to give this focus if nothing else does.
9260                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
9261                    mParent.focusableViewAvailable(this);
9262                }
9263            }
9264        }
9265
9266        /* Check if the GONE bit has changed */
9267        if ((changed & GONE) != 0) {
9268            needGlobalAttributesUpdate(false);
9269            requestLayout();
9270
9271            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
9272                if (hasFocus()) clearFocus();
9273                clearAccessibilityFocus();
9274                destroyDrawingCache();
9275                if (mParent instanceof View) {
9276                    // GONE views noop invalidation, so invalidate the parent
9277                    ((View) mParent).invalidate(true);
9278                }
9279                // Mark the view drawn to ensure that it gets invalidated properly the next
9280                // time it is visible and gets invalidated
9281                mPrivateFlags |= PFLAG_DRAWN;
9282            }
9283            if (mAttachInfo != null) {
9284                mAttachInfo.mViewVisibilityChanged = true;
9285            }
9286        }
9287
9288        /* Check if the VISIBLE bit has changed */
9289        if ((changed & INVISIBLE) != 0) {
9290            needGlobalAttributesUpdate(false);
9291            /*
9292             * If this view is becoming invisible, set the DRAWN flag so that
9293             * the next invalidate() will not be skipped.
9294             */
9295            mPrivateFlags |= PFLAG_DRAWN;
9296
9297            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
9298                // root view becoming invisible shouldn't clear focus and accessibility focus
9299                if (getRootView() != this) {
9300                    if (hasFocus()) clearFocus();
9301                    clearAccessibilityFocus();
9302                }
9303            }
9304            if (mAttachInfo != null) {
9305                mAttachInfo.mViewVisibilityChanged = true;
9306            }
9307        }
9308
9309        if ((changed & VISIBILITY_MASK) != 0) {
9310            // If the view is invisible, cleanup its display list to free up resources
9311            if (newVisibility != VISIBLE && mAttachInfo != null) {
9312                cleanupDraw();
9313            }
9314
9315            if (mParent instanceof ViewGroup) {
9316                ((ViewGroup) mParent).onChildVisibilityChanged(this,
9317                        (changed & VISIBILITY_MASK), newVisibility);
9318                ((View) mParent).invalidate(true);
9319            } else if (mParent != null) {
9320                mParent.invalidateChild(this, null);
9321            }
9322            dispatchVisibilityChanged(this, newVisibility);
9323
9324            notifySubtreeAccessibilityStateChangedIfNeeded();
9325        }
9326
9327        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
9328            destroyDrawingCache();
9329        }
9330
9331        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
9332            destroyDrawingCache();
9333            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9334            invalidateParentCaches();
9335        }
9336
9337        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
9338            destroyDrawingCache();
9339            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9340        }
9341
9342        if ((changed & DRAW_MASK) != 0) {
9343            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
9344                if (mBackground != null) {
9345                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9346                    mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
9347                } else {
9348                    mPrivateFlags |= PFLAG_SKIP_DRAW;
9349                }
9350            } else {
9351                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9352            }
9353            requestLayout();
9354            invalidate(true);
9355        }
9356
9357        if ((changed & KEEP_SCREEN_ON) != 0) {
9358            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
9359                mParent.recomputeViewAttributes(this);
9360            }
9361        }
9362
9363        if (accessibilityEnabled) {
9364            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
9365                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
9366                if (oldIncludeForAccessibility != includeForAccessibility()) {
9367                    notifySubtreeAccessibilityStateChangedIfNeeded();
9368                } else {
9369                    notifyViewAccessibilityStateChangedIfNeeded(
9370                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9371                }
9372            } else if ((changed & ENABLED_MASK) != 0) {
9373                notifyViewAccessibilityStateChangedIfNeeded(
9374                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9375            }
9376        }
9377    }
9378
9379    /**
9380     * Change the view's z order in the tree, so it's on top of other sibling
9381     * views. This ordering change may affect layout, if the parent container
9382     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
9383     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
9384     * method should be followed by calls to {@link #requestLayout()} and
9385     * {@link View#invalidate()} on the view's parent to force the parent to redraw
9386     * with the new child ordering.
9387     *
9388     * @see ViewGroup#bringChildToFront(View)
9389     */
9390    public void bringToFront() {
9391        if (mParent != null) {
9392            mParent.bringChildToFront(this);
9393        }
9394    }
9395
9396    /**
9397     * This is called in response to an internal scroll in this view (i.e., the
9398     * view scrolled its own contents). This is typically as a result of
9399     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
9400     * called.
9401     *
9402     * @param l Current horizontal scroll origin.
9403     * @param t Current vertical scroll origin.
9404     * @param oldl Previous horizontal scroll origin.
9405     * @param oldt Previous vertical scroll origin.
9406     */
9407    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
9408        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9409            postSendViewScrolledAccessibilityEventCallback();
9410        }
9411
9412        mBackgroundSizeChanged = true;
9413
9414        final AttachInfo ai = mAttachInfo;
9415        if (ai != null) {
9416            ai.mViewScrollChanged = true;
9417        }
9418    }
9419
9420    /**
9421     * Interface definition for a callback to be invoked when the layout bounds of a view
9422     * changes due to layout processing.
9423     */
9424    public interface OnLayoutChangeListener {
9425        /**
9426         * Called when the layout bounds of a view changes due to layout processing.
9427         *
9428         * @param v The view whose bounds have changed.
9429         * @param left The new value of the view's left property.
9430         * @param top The new value of the view's top property.
9431         * @param right The new value of the view's right property.
9432         * @param bottom The new value of the view's bottom property.
9433         * @param oldLeft The previous value of the view's left property.
9434         * @param oldTop The previous value of the view's top property.
9435         * @param oldRight The previous value of the view's right property.
9436         * @param oldBottom The previous value of the view's bottom property.
9437         */
9438        void onLayoutChange(View v, int left, int top, int right, int bottom,
9439            int oldLeft, int oldTop, int oldRight, int oldBottom);
9440    }
9441
9442    /**
9443     * This is called during layout when the size of this view has changed. If
9444     * you were just added to the view hierarchy, you're called with the old
9445     * values of 0.
9446     *
9447     * @param w Current width of this view.
9448     * @param h Current height of this view.
9449     * @param oldw Old width of this view.
9450     * @param oldh Old height of this view.
9451     */
9452    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
9453    }
9454
9455    /**
9456     * Called by draw to draw the child views. This may be overridden
9457     * by derived classes to gain control just before its children are drawn
9458     * (but after its own view has been drawn).
9459     * @param canvas the canvas on which to draw the view
9460     */
9461    protected void dispatchDraw(Canvas canvas) {
9462
9463    }
9464
9465    /**
9466     * Gets the parent of this view. Note that the parent is a
9467     * ViewParent and not necessarily a View.
9468     *
9469     * @return Parent of this view.
9470     */
9471    public final ViewParent getParent() {
9472        return mParent;
9473    }
9474
9475    /**
9476     * Set the horizontal scrolled position of your view. This will cause a call to
9477     * {@link #onScrollChanged(int, int, int, int)} and the view will be
9478     * invalidated.
9479     * @param value the x position to scroll to
9480     */
9481    public void setScrollX(int value) {
9482        scrollTo(value, mScrollY);
9483    }
9484
9485    /**
9486     * Set the vertical scrolled position of your view. This will cause a call to
9487     * {@link #onScrollChanged(int, int, int, int)} and the view will be
9488     * invalidated.
9489     * @param value the y position to scroll to
9490     */
9491    public void setScrollY(int value) {
9492        scrollTo(mScrollX, value);
9493    }
9494
9495    /**
9496     * Return the scrolled left position of this view. This is the left edge of
9497     * the displayed part of your view. You do not need to draw any pixels
9498     * farther left, since those are outside of the frame of your view on
9499     * screen.
9500     *
9501     * @return The left edge of the displayed part of your view, in pixels.
9502     */
9503    public final int getScrollX() {
9504        return mScrollX;
9505    }
9506
9507    /**
9508     * Return the scrolled top position of this view. This is the top edge of
9509     * the displayed part of your view. You do not need to draw any pixels above
9510     * it, since those are outside of the frame of your view on screen.
9511     *
9512     * @return The top edge of the displayed part of your view, in pixels.
9513     */
9514    public final int getScrollY() {
9515        return mScrollY;
9516    }
9517
9518    /**
9519     * Return the width of the your view.
9520     *
9521     * @return The width of your view, in pixels.
9522     */
9523    @ViewDebug.ExportedProperty(category = "layout")
9524    public final int getWidth() {
9525        return mRight - mLeft;
9526    }
9527
9528    /**
9529     * Return the height of your view.
9530     *
9531     * @return The height of your view, in pixels.
9532     */
9533    @ViewDebug.ExportedProperty(category = "layout")
9534    public final int getHeight() {
9535        return mBottom - mTop;
9536    }
9537
9538    /**
9539     * Return the visible drawing bounds of your view. Fills in the output
9540     * rectangle with the values from getScrollX(), getScrollY(),
9541     * getWidth(), and getHeight(). These bounds do not account for any
9542     * transformation properties currently set on the view, such as
9543     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
9544     *
9545     * @param outRect The (scrolled) drawing bounds of the view.
9546     */
9547    public void getDrawingRect(Rect outRect) {
9548        outRect.left = mScrollX;
9549        outRect.top = mScrollY;
9550        outRect.right = mScrollX + (mRight - mLeft);
9551        outRect.bottom = mScrollY + (mBottom - mTop);
9552    }
9553
9554    /**
9555     * Like {@link #getMeasuredWidthAndState()}, but only returns the
9556     * raw width component (that is the result is masked by
9557     * {@link #MEASURED_SIZE_MASK}).
9558     *
9559     * @return The raw measured width of this view.
9560     */
9561    public final int getMeasuredWidth() {
9562        return mMeasuredWidth & MEASURED_SIZE_MASK;
9563    }
9564
9565    /**
9566     * Return the full width measurement information for this view as computed
9567     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
9568     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
9569     * This should be used during measurement and layout calculations only. Use
9570     * {@link #getWidth()} to see how wide a view is after layout.
9571     *
9572     * @return The measured width of this view as a bit mask.
9573     */
9574    public final int getMeasuredWidthAndState() {
9575        return mMeasuredWidth;
9576    }
9577
9578    /**
9579     * Like {@link #getMeasuredHeightAndState()}, but only returns the
9580     * raw width component (that is the result is masked by
9581     * {@link #MEASURED_SIZE_MASK}).
9582     *
9583     * @return The raw measured height of this view.
9584     */
9585    public final int getMeasuredHeight() {
9586        return mMeasuredHeight & MEASURED_SIZE_MASK;
9587    }
9588
9589    /**
9590     * Return the full height measurement information for this view as computed
9591     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
9592     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
9593     * This should be used during measurement and layout calculations only. Use
9594     * {@link #getHeight()} to see how wide a view is after layout.
9595     *
9596     * @return The measured width of this view as a bit mask.
9597     */
9598    public final int getMeasuredHeightAndState() {
9599        return mMeasuredHeight;
9600    }
9601
9602    /**
9603     * Return only the state bits of {@link #getMeasuredWidthAndState()}
9604     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
9605     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
9606     * and the height component is at the shifted bits
9607     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
9608     */
9609    public final int getMeasuredState() {
9610        return (mMeasuredWidth&MEASURED_STATE_MASK)
9611                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
9612                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
9613    }
9614
9615    /**
9616     * The transform matrix of this view, which is calculated based on the current
9617     * roation, scale, and pivot properties.
9618     *
9619     * @see #getRotation()
9620     * @see #getScaleX()
9621     * @see #getScaleY()
9622     * @see #getPivotX()
9623     * @see #getPivotY()
9624     * @return The current transform matrix for the view
9625     */
9626    public Matrix getMatrix() {
9627        ensureTransformationInfo();
9628        final Matrix matrix = mTransformationInfo.mMatrix;
9629        mRenderNode.getMatrix(matrix);
9630        return matrix;
9631    }
9632
9633    /**
9634     * Returns true if the transform matrix is the identity matrix.
9635     * Recomputes the matrix if necessary.
9636     *
9637     * @return True if the transform matrix is the identity matrix, false otherwise.
9638     */
9639    final boolean hasIdentityMatrix() {
9640        return mRenderNode.hasIdentityMatrix();
9641    }
9642
9643    void ensureTransformationInfo() {
9644        if (mTransformationInfo == null) {
9645            mTransformationInfo = new TransformationInfo();
9646        }
9647    }
9648
9649   /**
9650     * Utility method to retrieve the inverse of the current mMatrix property.
9651     * We cache the matrix to avoid recalculating it when transform properties
9652     * have not changed.
9653     *
9654     * @return The inverse of the current matrix of this view.
9655     */
9656    final Matrix getInverseMatrix() {
9657        ensureTransformationInfo();
9658        if (mTransformationInfo.mInverseMatrix == null) {
9659            mTransformationInfo.mInverseMatrix = new Matrix();
9660        }
9661        final Matrix matrix = mTransformationInfo.mInverseMatrix;
9662        mRenderNode.getInverseMatrix(matrix);
9663        return matrix;
9664    }
9665
9666    /**
9667     * Gets the distance along the Z axis from the camera to this view.
9668     *
9669     * @see #setCameraDistance(float)
9670     *
9671     * @return The distance along the Z axis.
9672     */
9673    public float getCameraDistance() {
9674        final float dpi = mResources.getDisplayMetrics().densityDpi;
9675        return -(mRenderNode.getCameraDistance() * dpi);
9676    }
9677
9678    /**
9679     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
9680     * views are drawn) from the camera to this view. The camera's distance
9681     * affects 3D transformations, for instance rotations around the X and Y
9682     * axis. If the rotationX or rotationY properties are changed and this view is
9683     * large (more than half the size of the screen), it is recommended to always
9684     * use a camera distance that's greater than the height (X axis rotation) or
9685     * the width (Y axis rotation) of this view.</p>
9686     *
9687     * <p>The distance of the camera from the view plane can have an affect on the
9688     * perspective distortion of the view when it is rotated around the x or y axis.
9689     * For example, a large distance will result in a large viewing angle, and there
9690     * will not be much perspective distortion of the view as it rotates. A short
9691     * distance may cause much more perspective distortion upon rotation, and can
9692     * also result in some drawing artifacts if the rotated view ends up partially
9693     * behind the camera (which is why the recommendation is to use a distance at
9694     * least as far as the size of the view, if the view is to be rotated.)</p>
9695     *
9696     * <p>The distance is expressed in "depth pixels." The default distance depends
9697     * on the screen density. For instance, on a medium density display, the
9698     * default distance is 1280. On a high density display, the default distance
9699     * is 1920.</p>
9700     *
9701     * <p>If you want to specify a distance that leads to visually consistent
9702     * results across various densities, use the following formula:</p>
9703     * <pre>
9704     * float scale = context.getResources().getDisplayMetrics().density;
9705     * view.setCameraDistance(distance * scale);
9706     * </pre>
9707     *
9708     * <p>The density scale factor of a high density display is 1.5,
9709     * and 1920 = 1280 * 1.5.</p>
9710     *
9711     * @param distance The distance in "depth pixels", if negative the opposite
9712     *        value is used
9713     *
9714     * @see #setRotationX(float)
9715     * @see #setRotationY(float)
9716     */
9717    public void setCameraDistance(float distance) {
9718        final float dpi = mResources.getDisplayMetrics().densityDpi;
9719
9720        invalidateViewProperty(true, false);
9721        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
9722        invalidateViewProperty(false, false);
9723
9724        invalidateParentIfNeededAndWasQuickRejected();
9725    }
9726
9727    /**
9728     * The degrees that the view is rotated around the pivot point.
9729     *
9730     * @see #setRotation(float)
9731     * @see #getPivotX()
9732     * @see #getPivotY()
9733     *
9734     * @return The degrees of rotation.
9735     */
9736    @ViewDebug.ExportedProperty(category = "drawing")
9737    public float getRotation() {
9738        return mRenderNode.getRotation();
9739    }
9740
9741    /**
9742     * Sets the degrees that the view is rotated around the pivot point. Increasing values
9743     * result in clockwise rotation.
9744     *
9745     * @param rotation The degrees of rotation.
9746     *
9747     * @see #getRotation()
9748     * @see #getPivotX()
9749     * @see #getPivotY()
9750     * @see #setRotationX(float)
9751     * @see #setRotationY(float)
9752     *
9753     * @attr ref android.R.styleable#View_rotation
9754     */
9755    public void setRotation(float rotation) {
9756        if (rotation != getRotation()) {
9757            // Double-invalidation is necessary to capture view's old and new areas
9758            invalidateViewProperty(true, false);
9759            mRenderNode.setRotation(rotation);
9760            invalidateViewProperty(false, true);
9761
9762            invalidateParentIfNeededAndWasQuickRejected();
9763        }
9764    }
9765
9766    /**
9767     * The degrees that the view is rotated around the vertical axis through the pivot point.
9768     *
9769     * @see #getPivotX()
9770     * @see #getPivotY()
9771     * @see #setRotationY(float)
9772     *
9773     * @return The degrees of Y rotation.
9774     */
9775    @ViewDebug.ExportedProperty(category = "drawing")
9776    public float getRotationY() {
9777        return mRenderNode.getRotationY();
9778    }
9779
9780    /**
9781     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
9782     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
9783     * down the y axis.
9784     *
9785     * When rotating large views, it is recommended to adjust the camera distance
9786     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
9787     *
9788     * @param rotationY The degrees of Y rotation.
9789     *
9790     * @see #getRotationY()
9791     * @see #getPivotX()
9792     * @see #getPivotY()
9793     * @see #setRotation(float)
9794     * @see #setRotationX(float)
9795     * @see #setCameraDistance(float)
9796     *
9797     * @attr ref android.R.styleable#View_rotationY
9798     */
9799    public void setRotationY(float rotationY) {
9800        if (rotationY != getRotationY()) {
9801            invalidateViewProperty(true, false);
9802            mRenderNode.setRotationY(rotationY);
9803            invalidateViewProperty(false, true);
9804
9805            invalidateParentIfNeededAndWasQuickRejected();
9806        }
9807    }
9808
9809    /**
9810     * The degrees that the view is rotated around the horizontal axis through the pivot point.
9811     *
9812     * @see #getPivotX()
9813     * @see #getPivotY()
9814     * @see #setRotationX(float)
9815     *
9816     * @return The degrees of X rotation.
9817     */
9818    @ViewDebug.ExportedProperty(category = "drawing")
9819    public float getRotationX() {
9820        return mRenderNode.getRotationX();
9821    }
9822
9823    /**
9824     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
9825     * Increasing values result in clockwise rotation from the viewpoint of looking down the
9826     * x axis.
9827     *
9828     * When rotating large views, it is recommended to adjust the camera distance
9829     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
9830     *
9831     * @param rotationX The degrees of X rotation.
9832     *
9833     * @see #getRotationX()
9834     * @see #getPivotX()
9835     * @see #getPivotY()
9836     * @see #setRotation(float)
9837     * @see #setRotationY(float)
9838     * @see #setCameraDistance(float)
9839     *
9840     * @attr ref android.R.styleable#View_rotationX
9841     */
9842    public void setRotationX(float rotationX) {
9843        if (rotationX != getRotationX()) {
9844            invalidateViewProperty(true, false);
9845            mRenderNode.setRotationX(rotationX);
9846            invalidateViewProperty(false, true);
9847
9848            invalidateParentIfNeededAndWasQuickRejected();
9849        }
9850    }
9851
9852    /**
9853     * The amount that the view is scaled in x around the pivot point, as a proportion of
9854     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
9855     *
9856     * <p>By default, this is 1.0f.
9857     *
9858     * @see #getPivotX()
9859     * @see #getPivotY()
9860     * @return The scaling factor.
9861     */
9862    @ViewDebug.ExportedProperty(category = "drawing")
9863    public float getScaleX() {
9864        return mRenderNode.getScaleX();
9865    }
9866
9867    /**
9868     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
9869     * the view's unscaled width. A value of 1 means that no scaling is applied.
9870     *
9871     * @param scaleX The scaling factor.
9872     * @see #getPivotX()
9873     * @see #getPivotY()
9874     *
9875     * @attr ref android.R.styleable#View_scaleX
9876     */
9877    public void setScaleX(float scaleX) {
9878        if (scaleX != getScaleX()) {
9879            invalidateViewProperty(true, false);
9880            mRenderNode.setScaleX(scaleX);
9881            invalidateViewProperty(false, true);
9882
9883            invalidateParentIfNeededAndWasQuickRejected();
9884        }
9885    }
9886
9887    /**
9888     * The amount that the view is scaled in y around the pivot point, as a proportion of
9889     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
9890     *
9891     * <p>By default, this is 1.0f.
9892     *
9893     * @see #getPivotX()
9894     * @see #getPivotY()
9895     * @return The scaling factor.
9896     */
9897    @ViewDebug.ExportedProperty(category = "drawing")
9898    public float getScaleY() {
9899        return mRenderNode.getScaleY();
9900    }
9901
9902    /**
9903     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
9904     * the view's unscaled width. A value of 1 means that no scaling is applied.
9905     *
9906     * @param scaleY The scaling factor.
9907     * @see #getPivotX()
9908     * @see #getPivotY()
9909     *
9910     * @attr ref android.R.styleable#View_scaleY
9911     */
9912    public void setScaleY(float scaleY) {
9913        if (scaleY != getScaleY()) {
9914            invalidateViewProperty(true, false);
9915            mRenderNode.setScaleY(scaleY);
9916            invalidateViewProperty(false, true);
9917
9918            invalidateParentIfNeededAndWasQuickRejected();
9919        }
9920    }
9921
9922    /**
9923     * The x location of the point around which the view is {@link #setRotation(float) rotated}
9924     * and {@link #setScaleX(float) scaled}.
9925     *
9926     * @see #getRotation()
9927     * @see #getScaleX()
9928     * @see #getScaleY()
9929     * @see #getPivotY()
9930     * @return The x location of the pivot point.
9931     *
9932     * @attr ref android.R.styleable#View_transformPivotX
9933     */
9934    @ViewDebug.ExportedProperty(category = "drawing")
9935    public float getPivotX() {
9936        return mRenderNode.getPivotX();
9937    }
9938
9939    /**
9940     * Sets the x location of the point around which the view is
9941     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
9942     * By default, the pivot point is centered on the object.
9943     * Setting this property disables this behavior and causes the view to use only the
9944     * explicitly set pivotX and pivotY values.
9945     *
9946     * @param pivotX The x location of the pivot point.
9947     * @see #getRotation()
9948     * @see #getScaleX()
9949     * @see #getScaleY()
9950     * @see #getPivotY()
9951     *
9952     * @attr ref android.R.styleable#View_transformPivotX
9953     */
9954    public void setPivotX(float pivotX) {
9955        if (mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
9956            invalidateViewProperty(true, false);
9957            mRenderNode.setPivotX(pivotX);
9958            invalidateViewProperty(false, true);
9959
9960            invalidateParentIfNeededAndWasQuickRejected();
9961        }
9962    }
9963
9964    /**
9965     * The y location of the point around which the view is {@link #setRotation(float) rotated}
9966     * and {@link #setScaleY(float) scaled}.
9967     *
9968     * @see #getRotation()
9969     * @see #getScaleX()
9970     * @see #getScaleY()
9971     * @see #getPivotY()
9972     * @return The y location of the pivot point.
9973     *
9974     * @attr ref android.R.styleable#View_transformPivotY
9975     */
9976    @ViewDebug.ExportedProperty(category = "drawing")
9977    public float getPivotY() {
9978        return mRenderNode.getPivotY();
9979    }
9980
9981    /**
9982     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
9983     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
9984     * Setting this property disables this behavior and causes the view to use only the
9985     * explicitly set pivotX and pivotY values.
9986     *
9987     * @param pivotY The y location of the pivot point.
9988     * @see #getRotation()
9989     * @see #getScaleX()
9990     * @see #getScaleY()
9991     * @see #getPivotY()
9992     *
9993     * @attr ref android.R.styleable#View_transformPivotY
9994     */
9995    public void setPivotY(float pivotY) {
9996        if (mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
9997            invalidateViewProperty(true, false);
9998            mRenderNode.setPivotY(pivotY);
9999            invalidateViewProperty(false, true);
10000
10001            invalidateParentIfNeededAndWasQuickRejected();
10002        }
10003    }
10004
10005    /**
10006     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
10007     * completely transparent and 1 means the view is completely opaque.
10008     *
10009     * <p>By default this is 1.0f.
10010     * @return The opacity of the view.
10011     */
10012    @ViewDebug.ExportedProperty(category = "drawing")
10013    public float getAlpha() {
10014        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
10015    }
10016
10017    /**
10018     * Returns whether this View has content which overlaps.
10019     *
10020     * <p>This function, intended to be overridden by specific View types, is an optimization when
10021     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
10022     * an offscreen buffer and then composited into place, which can be expensive. If the view has
10023     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
10024     * directly. An example of overlapping rendering is a TextView with a background image, such as
10025     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
10026     * ImageView with only the foreground image. The default implementation returns true; subclasses
10027     * should override if they have cases which can be optimized.</p>
10028     *
10029     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
10030     * necessitates that a View return true if it uses the methods internally without passing the
10031     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
10032     *
10033     * @return true if the content in this view might overlap, false otherwise.
10034     */
10035    public boolean hasOverlappingRendering() {
10036        return true;
10037    }
10038
10039    /**
10040     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
10041     * completely transparent and 1 means the view is completely opaque.</p>
10042     *
10043     * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
10044     * performance implications, especially for large views. It is best to use the alpha property
10045     * sparingly and transiently, as in the case of fading animations.</p>
10046     *
10047     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
10048     * strongly recommended for performance reasons to either override
10049     * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
10050     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
10051     *
10052     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
10053     * responsible for applying the opacity itself.</p>
10054     *
10055     * <p>Note that if the view is backed by a
10056     * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
10057     * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
10058     * 1.0 will supercede the alpha of the layer paint.</p>
10059     *
10060     * @param alpha The opacity of the view.
10061     *
10062     * @see #hasOverlappingRendering()
10063     * @see #setLayerType(int, android.graphics.Paint)
10064     *
10065     * @attr ref android.R.styleable#View_alpha
10066     */
10067    public void setAlpha(float alpha) {
10068        ensureTransformationInfo();
10069        if (mTransformationInfo.mAlpha != alpha) {
10070            mTransformationInfo.mAlpha = alpha;
10071            if (onSetAlpha((int) (alpha * 255))) {
10072                mPrivateFlags |= PFLAG_ALPHA_SET;
10073                // subclass is handling alpha - don't optimize rendering cache invalidation
10074                invalidateParentCaches();
10075                invalidate(true);
10076            } else {
10077                mPrivateFlags &= ~PFLAG_ALPHA_SET;
10078                invalidateViewProperty(true, false);
10079                mRenderNode.setAlpha(getFinalAlpha());
10080            }
10081        }
10082    }
10083
10084    /**
10085     * Faster version of setAlpha() which performs the same steps except there are
10086     * no calls to invalidate(). The caller of this function should perform proper invalidation
10087     * on the parent and this object. The return value indicates whether the subclass handles
10088     * alpha (the return value for onSetAlpha()).
10089     *
10090     * @param alpha The new value for the alpha property
10091     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
10092     *         the new value for the alpha property is different from the old value
10093     */
10094    boolean setAlphaNoInvalidation(float alpha) {
10095        ensureTransformationInfo();
10096        if (mTransformationInfo.mAlpha != alpha) {
10097            mTransformationInfo.mAlpha = alpha;
10098            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
10099            if (subclassHandlesAlpha) {
10100                mPrivateFlags |= PFLAG_ALPHA_SET;
10101                return true;
10102            } else {
10103                mPrivateFlags &= ~PFLAG_ALPHA_SET;
10104                mRenderNode.setAlpha(getFinalAlpha());
10105            }
10106        }
10107        return false;
10108    }
10109
10110    /**
10111     * This property is hidden and intended only for use by the Fade transition, which
10112     * animates it to produce a visual translucency that does not side-effect (or get
10113     * affected by) the real alpha property. This value is composited with the other
10114     * alpha value (and the AlphaAnimation value, when that is present) to produce
10115     * a final visual translucency result, which is what is passed into the DisplayList.
10116     *
10117     * @hide
10118     */
10119    public void setTransitionAlpha(float alpha) {
10120        ensureTransformationInfo();
10121        if (mTransformationInfo.mTransitionAlpha != alpha) {
10122            mTransformationInfo.mTransitionAlpha = alpha;
10123            mPrivateFlags &= ~PFLAG_ALPHA_SET;
10124            invalidateViewProperty(true, false);
10125            mRenderNode.setAlpha(getFinalAlpha());
10126        }
10127    }
10128
10129    /**
10130     * Calculates the visual alpha of this view, which is a combination of the actual
10131     * alpha value and the transitionAlpha value (if set).
10132     */
10133    private float getFinalAlpha() {
10134        if (mTransformationInfo != null) {
10135            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
10136        }
10137        return 1;
10138    }
10139
10140    /**
10141     * This property is hidden and intended only for use by the Fade transition, which
10142     * animates it to produce a visual translucency that does not side-effect (or get
10143     * affected by) the real alpha property. This value is composited with the other
10144     * alpha value (and the AlphaAnimation value, when that is present) to produce
10145     * a final visual translucency result, which is what is passed into the DisplayList.
10146     *
10147     * @hide
10148     */
10149    public float getTransitionAlpha() {
10150        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
10151    }
10152
10153    /**
10154     * Top position of this view relative to its parent.
10155     *
10156     * @return The top of this view, in pixels.
10157     */
10158    @ViewDebug.CapturedViewProperty
10159    public final int getTop() {
10160        return mTop;
10161    }
10162
10163    /**
10164     * Sets the top position of this view relative to its parent. This method is meant to be called
10165     * by the layout system and should not generally be called otherwise, because the property
10166     * may be changed at any time by the layout.
10167     *
10168     * @param top The top of this view, in pixels.
10169     */
10170    public final void setTop(int top) {
10171        if (top != mTop) {
10172            final boolean matrixIsIdentity = hasIdentityMatrix();
10173            if (matrixIsIdentity) {
10174                if (mAttachInfo != null) {
10175                    int minTop;
10176                    int yLoc;
10177                    if (top < mTop) {
10178                        minTop = top;
10179                        yLoc = top - mTop;
10180                    } else {
10181                        minTop = mTop;
10182                        yLoc = 0;
10183                    }
10184                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
10185                }
10186            } else {
10187                // Double-invalidation is necessary to capture view's old and new areas
10188                invalidate(true);
10189            }
10190
10191            int width = mRight - mLeft;
10192            int oldHeight = mBottom - mTop;
10193
10194            mTop = top;
10195            mRenderNode.setTop(mTop);
10196
10197            sizeChange(width, mBottom - mTop, width, oldHeight);
10198
10199            if (!matrixIsIdentity) {
10200                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10201                invalidate(true);
10202            }
10203            mBackgroundSizeChanged = true;
10204            invalidateParentIfNeeded();
10205            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10206                // View was rejected last time it was drawn by its parent; this may have changed
10207                invalidateParentIfNeeded();
10208            }
10209        }
10210    }
10211
10212    /**
10213     * Bottom position of this view relative to its parent.
10214     *
10215     * @return The bottom of this view, in pixels.
10216     */
10217    @ViewDebug.CapturedViewProperty
10218    public final int getBottom() {
10219        return mBottom;
10220    }
10221
10222    /**
10223     * True if this view has changed since the last time being drawn.
10224     *
10225     * @return The dirty state of this view.
10226     */
10227    public boolean isDirty() {
10228        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
10229    }
10230
10231    /**
10232     * Sets the bottom position of this view relative to its parent. This method is meant to be
10233     * called by the layout system and should not generally be called otherwise, because the
10234     * property may be changed at any time by the layout.
10235     *
10236     * @param bottom The bottom of this view, in pixels.
10237     */
10238    public final void setBottom(int bottom) {
10239        if (bottom != mBottom) {
10240            final boolean matrixIsIdentity = hasIdentityMatrix();
10241            if (matrixIsIdentity) {
10242                if (mAttachInfo != null) {
10243                    int maxBottom;
10244                    if (bottom < mBottom) {
10245                        maxBottom = mBottom;
10246                    } else {
10247                        maxBottom = bottom;
10248                    }
10249                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
10250                }
10251            } else {
10252                // Double-invalidation is necessary to capture view's old and new areas
10253                invalidate(true);
10254            }
10255
10256            int width = mRight - mLeft;
10257            int oldHeight = mBottom - mTop;
10258
10259            mBottom = bottom;
10260            mRenderNode.setBottom(mBottom);
10261
10262            sizeChange(width, mBottom - mTop, width, oldHeight);
10263
10264            if (!matrixIsIdentity) {
10265                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10266                invalidate(true);
10267            }
10268            mBackgroundSizeChanged = true;
10269            invalidateParentIfNeeded();
10270            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10271                // View was rejected last time it was drawn by its parent; this may have changed
10272                invalidateParentIfNeeded();
10273            }
10274        }
10275    }
10276
10277    /**
10278     * Left position of this view relative to its parent.
10279     *
10280     * @return The left edge of this view, in pixels.
10281     */
10282    @ViewDebug.CapturedViewProperty
10283    public final int getLeft() {
10284        return mLeft;
10285    }
10286
10287    /**
10288     * Sets the left position of this view relative to its parent. This method is meant to be called
10289     * by the layout system and should not generally be called otherwise, because the property
10290     * may be changed at any time by the layout.
10291     *
10292     * @param left The left of this view, in pixels.
10293     */
10294    public final void setLeft(int left) {
10295        if (left != mLeft) {
10296            final boolean matrixIsIdentity = hasIdentityMatrix();
10297            if (matrixIsIdentity) {
10298                if (mAttachInfo != null) {
10299                    int minLeft;
10300                    int xLoc;
10301                    if (left < mLeft) {
10302                        minLeft = left;
10303                        xLoc = left - mLeft;
10304                    } else {
10305                        minLeft = mLeft;
10306                        xLoc = 0;
10307                    }
10308                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
10309                }
10310            } else {
10311                // Double-invalidation is necessary to capture view's old and new areas
10312                invalidate(true);
10313            }
10314
10315            int oldWidth = mRight - mLeft;
10316            int height = mBottom - mTop;
10317
10318            mLeft = left;
10319            mRenderNode.setLeft(left);
10320
10321            sizeChange(mRight - mLeft, height, oldWidth, height);
10322
10323            if (!matrixIsIdentity) {
10324                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10325                invalidate(true);
10326            }
10327            mBackgroundSizeChanged = true;
10328            invalidateParentIfNeeded();
10329            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10330                // View was rejected last time it was drawn by its parent; this may have changed
10331                invalidateParentIfNeeded();
10332            }
10333        }
10334    }
10335
10336    /**
10337     * Right position of this view relative to its parent.
10338     *
10339     * @return The right edge of this view, in pixels.
10340     */
10341    @ViewDebug.CapturedViewProperty
10342    public final int getRight() {
10343        return mRight;
10344    }
10345
10346    /**
10347     * Sets the right position of this view relative to its parent. This method is meant to be called
10348     * by the layout system and should not generally be called otherwise, because the property
10349     * may be changed at any time by the layout.
10350     *
10351     * @param right The right of this view, in pixels.
10352     */
10353    public final void setRight(int right) {
10354        if (right != mRight) {
10355            final boolean matrixIsIdentity = hasIdentityMatrix();
10356            if (matrixIsIdentity) {
10357                if (mAttachInfo != null) {
10358                    int maxRight;
10359                    if (right < mRight) {
10360                        maxRight = mRight;
10361                    } else {
10362                        maxRight = right;
10363                    }
10364                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
10365                }
10366            } else {
10367                // Double-invalidation is necessary to capture view's old and new areas
10368                invalidate(true);
10369            }
10370
10371            int oldWidth = mRight - mLeft;
10372            int height = mBottom - mTop;
10373
10374            mRight = right;
10375            mRenderNode.setRight(mRight);
10376
10377            sizeChange(mRight - mLeft, height, oldWidth, height);
10378
10379            if (!matrixIsIdentity) {
10380                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10381                invalidate(true);
10382            }
10383            mBackgroundSizeChanged = true;
10384            invalidateParentIfNeeded();
10385            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10386                // View was rejected last time it was drawn by its parent; this may have changed
10387                invalidateParentIfNeeded();
10388            }
10389        }
10390    }
10391
10392    /**
10393     * The visual x position of this view, in pixels. This is equivalent to the
10394     * {@link #setTranslationX(float) translationX} property plus the current
10395     * {@link #getLeft() left} property.
10396     *
10397     * @return The visual x position of this view, in pixels.
10398     */
10399    @ViewDebug.ExportedProperty(category = "drawing")
10400    public float getX() {
10401        return mLeft + getTranslationX();
10402    }
10403
10404    /**
10405     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
10406     * {@link #setTranslationX(float) translationX} property to be the difference between
10407     * the x value passed in and the current {@link #getLeft() left} property.
10408     *
10409     * @param x The visual x position of this view, in pixels.
10410     */
10411    public void setX(float x) {
10412        setTranslationX(x - mLeft);
10413    }
10414
10415    /**
10416     * The visual y position of this view, in pixels. This is equivalent to the
10417     * {@link #setTranslationY(float) translationY} property plus the current
10418     * {@link #getTop() top} property.
10419     *
10420     * @return The visual y position of this view, in pixels.
10421     */
10422    @ViewDebug.ExportedProperty(category = "drawing")
10423    public float getY() {
10424        return mTop + getTranslationY();
10425    }
10426
10427    /**
10428     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
10429     * {@link #setTranslationY(float) translationY} property to be the difference between
10430     * the y value passed in and the current {@link #getTop() top} property.
10431     *
10432     * @param y The visual y position of this view, in pixels.
10433     */
10434    public void setY(float y) {
10435        setTranslationY(y - mTop);
10436    }
10437
10438
10439    /**
10440     * The horizontal location of this view relative to its {@link #getLeft() left} position.
10441     * This position is post-layout, in addition to wherever the object's
10442     * layout placed it.
10443     *
10444     * @return The horizontal position of this view relative to its left position, in pixels.
10445     */
10446    @ViewDebug.ExportedProperty(category = "drawing")
10447    public float getTranslationX() {
10448        return mRenderNode.getTranslationX();
10449    }
10450
10451    /**
10452     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
10453     * This effectively positions the object post-layout, in addition to wherever the object's
10454     * layout placed it.
10455     *
10456     * @param translationX The horizontal position of this view relative to its left position,
10457     * in pixels.
10458     *
10459     * @attr ref android.R.styleable#View_translationX
10460     */
10461    public void setTranslationX(float translationX) {
10462        if (translationX != getTranslationX()) {
10463            invalidateViewProperty(true, false);
10464            mRenderNode.setTranslationX(translationX);
10465            invalidateViewProperty(false, true);
10466
10467            invalidateParentIfNeededAndWasQuickRejected();
10468        }
10469    }
10470
10471    /**
10472     * The vertical location of this view relative to its {@link #getTop() top} position.
10473     * This position is post-layout, in addition to wherever the object's
10474     * layout placed it.
10475     *
10476     * @return The vertical position of this view relative to its top position,
10477     * in pixels.
10478     */
10479    @ViewDebug.ExportedProperty(category = "drawing")
10480    public float getTranslationY() {
10481        return mRenderNode.getTranslationY();
10482    }
10483
10484    /**
10485     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
10486     * This effectively positions the object post-layout, in addition to wherever the object's
10487     * layout placed it.
10488     *
10489     * @param translationY The vertical position of this view relative to its top position,
10490     * in pixels.
10491     *
10492     * @attr ref android.R.styleable#View_translationY
10493     */
10494    public void setTranslationY(float translationY) {
10495        if (translationY != getTranslationY()) {
10496            invalidateViewProperty(true, false);
10497            mRenderNode.setTranslationY(translationY);
10498            invalidateViewProperty(false, true);
10499
10500            invalidateParentIfNeededAndWasQuickRejected();
10501        }
10502    }
10503
10504    /**
10505     * The depth location of this view relative to its parent.
10506     *
10507     * @return The depth of this view relative to its parent.
10508     */
10509    @ViewDebug.ExportedProperty(category = "drawing")
10510    public float getTranslationZ() {
10511        return mRenderNode.getTranslationZ();
10512    }
10513
10514    /**
10515     * Sets the depth location of this view relative to its parent.
10516     *
10517     * @attr ref android.R.styleable#View_translationZ
10518     */
10519    public void setTranslationZ(float translationZ) {
10520        if (translationZ != getTranslationZ()) {
10521            invalidateViewProperty(true, false);
10522            mRenderNode.setTranslationZ(translationZ);
10523            invalidateViewProperty(false, true);
10524
10525            invalidateParentIfNeededAndWasQuickRejected();
10526        }
10527    }
10528
10529    /**
10530     * Returns a ValueAnimator which can animate a clipping circle.
10531     * <p>
10532     * The View will be clipped to the animating circle.
10533     * <p>
10534     * Any shadow cast by the View will respect the circular clip from this animator.
10535     *
10536     * @param centerX The x coordinate of the center of the animating circle.
10537     * @param centerY The y coordinate of the center of the animating circle.
10538     * @param startRadius The starting radius of the animating circle.
10539     * @param endRadius The ending radius of the animating circle.
10540     */
10541    public final ValueAnimator createRevealAnimator(int centerX,  int centerY,
10542            float startRadius, float endRadius) {
10543        return RevealAnimator.ofRevealCircle(this, centerX, centerY,
10544                startRadius, endRadius, false);
10545    }
10546
10547    /**
10548     * Returns a ValueAnimator which can animate a clearing circle.
10549     * <p>
10550     * The View is prevented from drawing within the circle, so the content
10551     * behind the View shows through.
10552     *
10553     * @param centerX The x coordinate of the center of the animating circle.
10554     * @param centerY The y coordinate of the center of the animating circle.
10555     * @param startRadius The starting radius of the animating circle.
10556     * @param endRadius The ending radius of the animating circle.
10557     *
10558     * @hide
10559     */
10560    public final ValueAnimator createClearCircleAnimator(int centerX,  int centerY,
10561            float startRadius, float endRadius) {
10562        return RevealAnimator.ofRevealCircle(this, centerX, centerY,
10563                startRadius, endRadius, true);
10564    }
10565
10566    /**
10567     * Sets the outline of the view, which defines the shape of the shadow it
10568     * casts.
10569     * <p>
10570     * If the outline is not set or is null, shadows will be cast from the
10571     * bounds of the View.
10572     *
10573     * @param outline The new outline of the view.
10574     *         Must be {@link android.graphics.Outline#isValid() valid.}
10575     */
10576    public void setOutline(@Nullable Outline outline) {
10577        if (outline != null && !outline.isValid()) {
10578            throw new IllegalArgumentException("Outline must not be invalid");
10579        }
10580
10581        mPrivateFlags3 |= PFLAG3_OUTLINE_DEFINED;
10582
10583        if (outline == null) {
10584            mOutline = null;
10585        } else {
10586            // always copy the path since caller may reuse
10587            if (mOutline == null) {
10588                mOutline = new Outline(outline);
10589            }
10590        }
10591        mRenderNode.setOutline(mOutline);
10592    }
10593
10594    // TODO: remove
10595    public final boolean getClipToOutline() { return false; }
10596    public void setClipToOutline(boolean clipToOutline) {}
10597
10598    private void queryOutlineFromBackgroundIfUndefined() {
10599        if ((mPrivateFlags3 & PFLAG3_OUTLINE_DEFINED) == 0) {
10600            // Outline not currently defined, query from background
10601            if (mOutline == null) {
10602                mOutline = new Outline();
10603            } else {
10604                //invalidate outline, to ensure background calculates it
10605                mOutline.set(null);
10606            }
10607            if (mBackground.getOutline(mOutline)) {
10608                if (!mOutline.isValid()) {
10609                    throw new IllegalStateException("Background drawable failed to build outline");
10610                }
10611                mRenderNode.setOutline(mOutline);
10612            } else {
10613                mRenderNode.setOutline(null);
10614            }
10615        }
10616    }
10617
10618    /**
10619     * Private API to be used for reveal animation
10620     *
10621     * @hide
10622     */
10623    public void setRevealClip(boolean shouldClip, boolean inverseClip,
10624            float x, float y, float radius) {
10625        mRenderNode.setRevealClip(shouldClip, inverseClip, x, y, radius);
10626        // TODO: Handle this invalidate in a better way, or purely in native.
10627        invalidate();
10628    }
10629
10630    /**
10631     * Hit rectangle in parent's coordinates
10632     *
10633     * @param outRect The hit rectangle of the view.
10634     */
10635    public void getHitRect(Rect outRect) {
10636        if (hasIdentityMatrix() || mAttachInfo == null) {
10637            outRect.set(mLeft, mTop, mRight, mBottom);
10638        } else {
10639            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
10640            tmpRect.set(0, 0, getWidth(), getHeight());
10641            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
10642            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
10643                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
10644        }
10645    }
10646
10647    /**
10648     * Determines whether the given point, in local coordinates is inside the view.
10649     */
10650    /*package*/ final boolean pointInView(float localX, float localY) {
10651        return localX >= 0 && localX < (mRight - mLeft)
10652                && localY >= 0 && localY < (mBottom - mTop);
10653    }
10654
10655    /**
10656     * Utility method to determine whether the given point, in local coordinates,
10657     * is inside the view, where the area of the view is expanded by the slop factor.
10658     * This method is called while processing touch-move events to determine if the event
10659     * is still within the view.
10660     *
10661     * @hide
10662     */
10663    public boolean pointInView(float localX, float localY, float slop) {
10664        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
10665                localY < ((mBottom - mTop) + slop);
10666    }
10667
10668    /**
10669     * When a view has focus and the user navigates away from it, the next view is searched for
10670     * starting from the rectangle filled in by this method.
10671     *
10672     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
10673     * of the view.  However, if your view maintains some idea of internal selection,
10674     * such as a cursor, or a selected row or column, you should override this method and
10675     * fill in a more specific rectangle.
10676     *
10677     * @param r The rectangle to fill in, in this view's coordinates.
10678     */
10679    public void getFocusedRect(Rect r) {
10680        getDrawingRect(r);
10681    }
10682
10683    /**
10684     * If some part of this view is not clipped by any of its parents, then
10685     * return that area in r in global (root) coordinates. To convert r to local
10686     * coordinates (without taking possible View rotations into account), offset
10687     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
10688     * If the view is completely clipped or translated out, return false.
10689     *
10690     * @param r If true is returned, r holds the global coordinates of the
10691     *        visible portion of this view.
10692     * @param globalOffset If true is returned, globalOffset holds the dx,dy
10693     *        between this view and its root. globalOffet may be null.
10694     * @return true if r is non-empty (i.e. part of the view is visible at the
10695     *         root level.
10696     */
10697    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
10698        int width = mRight - mLeft;
10699        int height = mBottom - mTop;
10700        if (width > 0 && height > 0) {
10701            r.set(0, 0, width, height);
10702            if (globalOffset != null) {
10703                globalOffset.set(-mScrollX, -mScrollY);
10704            }
10705            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
10706        }
10707        return false;
10708    }
10709
10710    public final boolean getGlobalVisibleRect(Rect r) {
10711        return getGlobalVisibleRect(r, null);
10712    }
10713
10714    public final boolean getLocalVisibleRect(Rect r) {
10715        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
10716        if (getGlobalVisibleRect(r, offset)) {
10717            r.offset(-offset.x, -offset.y); // make r local
10718            return true;
10719        }
10720        return false;
10721    }
10722
10723    /**
10724     * Offset this view's vertical location by the specified number of pixels.
10725     *
10726     * @param offset the number of pixels to offset the view by
10727     */
10728    public void offsetTopAndBottom(int offset) {
10729        if (offset != 0) {
10730            final boolean matrixIsIdentity = hasIdentityMatrix();
10731            if (matrixIsIdentity) {
10732                if (isHardwareAccelerated()) {
10733                    invalidateViewProperty(false, false);
10734                } else {
10735                    final ViewParent p = mParent;
10736                    if (p != null && mAttachInfo != null) {
10737                        final Rect r = mAttachInfo.mTmpInvalRect;
10738                        int minTop;
10739                        int maxBottom;
10740                        int yLoc;
10741                        if (offset < 0) {
10742                            minTop = mTop + offset;
10743                            maxBottom = mBottom;
10744                            yLoc = offset;
10745                        } else {
10746                            minTop = mTop;
10747                            maxBottom = mBottom + offset;
10748                            yLoc = 0;
10749                        }
10750                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
10751                        p.invalidateChild(this, r);
10752                    }
10753                }
10754            } else {
10755                invalidateViewProperty(false, false);
10756            }
10757
10758            mTop += offset;
10759            mBottom += offset;
10760            mRenderNode.offsetTopAndBottom(offset);
10761            if (isHardwareAccelerated()) {
10762                invalidateViewProperty(false, false);
10763            } else {
10764                if (!matrixIsIdentity) {
10765                    invalidateViewProperty(false, true);
10766                }
10767                invalidateParentIfNeeded();
10768            }
10769        }
10770    }
10771
10772    /**
10773     * Offset this view's horizontal location by the specified amount of pixels.
10774     *
10775     * @param offset the number of pixels to offset the view by
10776     */
10777    public void offsetLeftAndRight(int offset) {
10778        if (offset != 0) {
10779            final boolean matrixIsIdentity = hasIdentityMatrix();
10780            if (matrixIsIdentity) {
10781                if (isHardwareAccelerated()) {
10782                    invalidateViewProperty(false, false);
10783                } else {
10784                    final ViewParent p = mParent;
10785                    if (p != null && mAttachInfo != null) {
10786                        final Rect r = mAttachInfo.mTmpInvalRect;
10787                        int minLeft;
10788                        int maxRight;
10789                        if (offset < 0) {
10790                            minLeft = mLeft + offset;
10791                            maxRight = mRight;
10792                        } else {
10793                            minLeft = mLeft;
10794                            maxRight = mRight + offset;
10795                        }
10796                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
10797                        p.invalidateChild(this, r);
10798                    }
10799                }
10800            } else {
10801                invalidateViewProperty(false, false);
10802            }
10803
10804            mLeft += offset;
10805            mRight += offset;
10806            mRenderNode.offsetLeftAndRight(offset);
10807            if (isHardwareAccelerated()) {
10808                invalidateViewProperty(false, false);
10809            } else {
10810                if (!matrixIsIdentity) {
10811                    invalidateViewProperty(false, true);
10812                }
10813                invalidateParentIfNeeded();
10814            }
10815        }
10816    }
10817
10818    /**
10819     * Get the LayoutParams associated with this view. All views should have
10820     * layout parameters. These supply parameters to the <i>parent</i> of this
10821     * view specifying how it should be arranged. There are many subclasses of
10822     * ViewGroup.LayoutParams, and these correspond to the different subclasses
10823     * of ViewGroup that are responsible for arranging their children.
10824     *
10825     * This method may return null if this View is not attached to a parent
10826     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
10827     * was not invoked successfully. When a View is attached to a parent
10828     * ViewGroup, this method must not return null.
10829     *
10830     * @return The LayoutParams associated with this view, or null if no
10831     *         parameters have been set yet
10832     */
10833    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
10834    public ViewGroup.LayoutParams getLayoutParams() {
10835        return mLayoutParams;
10836    }
10837
10838    /**
10839     * Set the layout parameters associated with this view. These supply
10840     * parameters to the <i>parent</i> of this view specifying how it should be
10841     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
10842     * correspond to the different subclasses of ViewGroup that are responsible
10843     * for arranging their children.
10844     *
10845     * @param params The layout parameters for this view, cannot be null
10846     */
10847    public void setLayoutParams(ViewGroup.LayoutParams params) {
10848        if (params == null) {
10849            throw new NullPointerException("Layout parameters cannot be null");
10850        }
10851        mLayoutParams = params;
10852        resolveLayoutParams();
10853        if (mParent instanceof ViewGroup) {
10854            ((ViewGroup) mParent).onSetLayoutParams(this, params);
10855        }
10856        requestLayout();
10857    }
10858
10859    /**
10860     * Resolve the layout parameters depending on the resolved layout direction
10861     *
10862     * @hide
10863     */
10864    public void resolveLayoutParams() {
10865        if (mLayoutParams != null) {
10866            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
10867        }
10868    }
10869
10870    /**
10871     * Set the scrolled position of your view. This will cause a call to
10872     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10873     * invalidated.
10874     * @param x the x position to scroll to
10875     * @param y the y position to scroll to
10876     */
10877    public void scrollTo(int x, int y) {
10878        if (mScrollX != x || mScrollY != y) {
10879            int oldX = mScrollX;
10880            int oldY = mScrollY;
10881            mScrollX = x;
10882            mScrollY = y;
10883            invalidateParentCaches();
10884            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
10885            if (!awakenScrollBars()) {
10886                postInvalidateOnAnimation();
10887            }
10888        }
10889    }
10890
10891    /**
10892     * Move the scrolled position of your view. This will cause a call to
10893     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10894     * invalidated.
10895     * @param x the amount of pixels to scroll by horizontally
10896     * @param y the amount of pixels to scroll by vertically
10897     */
10898    public void scrollBy(int x, int y) {
10899        scrollTo(mScrollX + x, mScrollY + y);
10900    }
10901
10902    /**
10903     * <p>Trigger the scrollbars to draw. When invoked this method starts an
10904     * animation to fade the scrollbars out after a default delay. If a subclass
10905     * provides animated scrolling, the start delay should equal the duration
10906     * of the scrolling animation.</p>
10907     *
10908     * <p>The animation starts only if at least one of the scrollbars is
10909     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
10910     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
10911     * this method returns true, and false otherwise. If the animation is
10912     * started, this method calls {@link #invalidate()}; in that case the
10913     * caller should not call {@link #invalidate()}.</p>
10914     *
10915     * <p>This method should be invoked every time a subclass directly updates
10916     * the scroll parameters.</p>
10917     *
10918     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
10919     * and {@link #scrollTo(int, int)}.</p>
10920     *
10921     * @return true if the animation is played, false otherwise
10922     *
10923     * @see #awakenScrollBars(int)
10924     * @see #scrollBy(int, int)
10925     * @see #scrollTo(int, int)
10926     * @see #isHorizontalScrollBarEnabled()
10927     * @see #isVerticalScrollBarEnabled()
10928     * @see #setHorizontalScrollBarEnabled(boolean)
10929     * @see #setVerticalScrollBarEnabled(boolean)
10930     */
10931    protected boolean awakenScrollBars() {
10932        return mScrollCache != null &&
10933                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
10934    }
10935
10936    /**
10937     * Trigger the scrollbars to draw.
10938     * This method differs from awakenScrollBars() only in its default duration.
10939     * initialAwakenScrollBars() will show the scroll bars for longer than
10940     * usual to give the user more of a chance to notice them.
10941     *
10942     * @return true if the animation is played, false otherwise.
10943     */
10944    private boolean initialAwakenScrollBars() {
10945        return mScrollCache != null &&
10946                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
10947    }
10948
10949    /**
10950     * <p>
10951     * Trigger the scrollbars to draw. When invoked this method starts an
10952     * animation to fade the scrollbars out after a fixed delay. If a subclass
10953     * provides animated scrolling, the start delay should equal the duration of
10954     * the scrolling animation.
10955     * </p>
10956     *
10957     * <p>
10958     * The animation starts only if at least one of the scrollbars is enabled,
10959     * as specified by {@link #isHorizontalScrollBarEnabled()} and
10960     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
10961     * this method returns true, and false otherwise. If the animation is
10962     * started, this method calls {@link #invalidate()}; in that case the caller
10963     * should not call {@link #invalidate()}.
10964     * </p>
10965     *
10966     * <p>
10967     * This method should be invoked everytime a subclass directly updates the
10968     * scroll parameters.
10969     * </p>
10970     *
10971     * @param startDelay the delay, in milliseconds, after which the animation
10972     *        should start; when the delay is 0, the animation starts
10973     *        immediately
10974     * @return true if the animation is played, false otherwise
10975     *
10976     * @see #scrollBy(int, int)
10977     * @see #scrollTo(int, int)
10978     * @see #isHorizontalScrollBarEnabled()
10979     * @see #isVerticalScrollBarEnabled()
10980     * @see #setHorizontalScrollBarEnabled(boolean)
10981     * @see #setVerticalScrollBarEnabled(boolean)
10982     */
10983    protected boolean awakenScrollBars(int startDelay) {
10984        return awakenScrollBars(startDelay, true);
10985    }
10986
10987    /**
10988     * <p>
10989     * Trigger the scrollbars to draw. When invoked this method starts an
10990     * animation to fade the scrollbars out after a fixed delay. If a subclass
10991     * provides animated scrolling, the start delay should equal the duration of
10992     * the scrolling animation.
10993     * </p>
10994     *
10995     * <p>
10996     * The animation starts only if at least one of the scrollbars is enabled,
10997     * as specified by {@link #isHorizontalScrollBarEnabled()} and
10998     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
10999     * this method returns true, and false otherwise. If the animation is
11000     * started, this method calls {@link #invalidate()} if the invalidate parameter
11001     * is set to true; in that case the caller
11002     * should not call {@link #invalidate()}.
11003     * </p>
11004     *
11005     * <p>
11006     * This method should be invoked everytime a subclass directly updates the
11007     * scroll parameters.
11008     * </p>
11009     *
11010     * @param startDelay the delay, in milliseconds, after which the animation
11011     *        should start; when the delay is 0, the animation starts
11012     *        immediately
11013     *
11014     * @param invalidate Wheter this method should call invalidate
11015     *
11016     * @return true if the animation is played, false otherwise
11017     *
11018     * @see #scrollBy(int, int)
11019     * @see #scrollTo(int, int)
11020     * @see #isHorizontalScrollBarEnabled()
11021     * @see #isVerticalScrollBarEnabled()
11022     * @see #setHorizontalScrollBarEnabled(boolean)
11023     * @see #setVerticalScrollBarEnabled(boolean)
11024     */
11025    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
11026        final ScrollabilityCache scrollCache = mScrollCache;
11027
11028        if (scrollCache == null || !scrollCache.fadeScrollBars) {
11029            return false;
11030        }
11031
11032        if (scrollCache.scrollBar == null) {
11033            scrollCache.scrollBar = new ScrollBarDrawable();
11034        }
11035
11036        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
11037
11038            if (invalidate) {
11039                // Invalidate to show the scrollbars
11040                postInvalidateOnAnimation();
11041            }
11042
11043            if (scrollCache.state == ScrollabilityCache.OFF) {
11044                // FIXME: this is copied from WindowManagerService.
11045                // We should get this value from the system when it
11046                // is possible to do so.
11047                final int KEY_REPEAT_FIRST_DELAY = 750;
11048                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
11049            }
11050
11051            // Tell mScrollCache when we should start fading. This may
11052            // extend the fade start time if one was already scheduled
11053            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
11054            scrollCache.fadeStartTime = fadeStartTime;
11055            scrollCache.state = ScrollabilityCache.ON;
11056
11057            // Schedule our fader to run, unscheduling any old ones first
11058            if (mAttachInfo != null) {
11059                mAttachInfo.mHandler.removeCallbacks(scrollCache);
11060                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
11061            }
11062
11063            return true;
11064        }
11065
11066        return false;
11067    }
11068
11069    /**
11070     * Do not invalidate views which are not visible and which are not running an animation. They
11071     * will not get drawn and they should not set dirty flags as if they will be drawn
11072     */
11073    private boolean skipInvalidate() {
11074        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
11075                (!(mParent instanceof ViewGroup) ||
11076                        !((ViewGroup) mParent).isViewTransitioning(this));
11077    }
11078
11079    /**
11080     * Mark the area defined by dirty as needing to be drawn. If the view is
11081     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11082     * point in the future.
11083     * <p>
11084     * This must be called from a UI thread. To call from a non-UI thread, call
11085     * {@link #postInvalidate()}.
11086     * <p>
11087     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
11088     * {@code dirty}.
11089     *
11090     * @param dirty the rectangle representing the bounds of the dirty region
11091     */
11092    public void invalidate(Rect dirty) {
11093        final int scrollX = mScrollX;
11094        final int scrollY = mScrollY;
11095        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
11096                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
11097    }
11098
11099    /**
11100     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
11101     * coordinates of the dirty rect are relative to the view. If the view is
11102     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11103     * point in the future.
11104     * <p>
11105     * This must be called from a UI thread. To call from a non-UI thread, call
11106     * {@link #postInvalidate()}.
11107     *
11108     * @param l the left position of the dirty region
11109     * @param t the top position of the dirty region
11110     * @param r the right position of the dirty region
11111     * @param b the bottom position of the dirty region
11112     */
11113    public void invalidate(int l, int t, int r, int b) {
11114        final int scrollX = mScrollX;
11115        final int scrollY = mScrollY;
11116        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
11117    }
11118
11119    /**
11120     * Invalidate the whole view. If the view is visible,
11121     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
11122     * the future.
11123     * <p>
11124     * This must be called from a UI thread. To call from a non-UI thread, call
11125     * {@link #postInvalidate()}.
11126     */
11127    public void invalidate() {
11128        invalidate(true);
11129    }
11130
11131    /**
11132     * This is where the invalidate() work actually happens. A full invalidate()
11133     * causes the drawing cache to be invalidated, but this function can be
11134     * called with invalidateCache set to false to skip that invalidation step
11135     * for cases that do not need it (for example, a component that remains at
11136     * the same dimensions with the same content).
11137     *
11138     * @param invalidateCache Whether the drawing cache for this view should be
11139     *            invalidated as well. This is usually true for a full
11140     *            invalidate, but may be set to false if the View's contents or
11141     *            dimensions have not changed.
11142     */
11143    void invalidate(boolean invalidateCache) {
11144        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
11145    }
11146
11147    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
11148            boolean fullInvalidate) {
11149        if (skipInvalidate()) {
11150            return;
11151        }
11152
11153        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
11154                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
11155                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
11156                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
11157            if (fullInvalidate) {
11158                mLastIsOpaque = isOpaque();
11159                mPrivateFlags &= ~PFLAG_DRAWN;
11160            }
11161
11162            mPrivateFlags |= PFLAG_DIRTY;
11163
11164            if (invalidateCache) {
11165                mPrivateFlags |= PFLAG_INVALIDATED;
11166                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11167            }
11168
11169            // Propagate the damage rectangle to the parent view.
11170            final AttachInfo ai = mAttachInfo;
11171            final ViewParent p = mParent;
11172            if (p != null && ai != null && l < r && t < b) {
11173                final Rect damage = ai.mTmpInvalRect;
11174                damage.set(l, t, r, b);
11175                p.invalidateChild(this, damage);
11176            }
11177
11178            // Damage the entire projection receiver, if necessary.
11179            if (mBackground != null && mBackground.isProjected()) {
11180                final View receiver = getProjectionReceiver();
11181                if (receiver != null) {
11182                    receiver.damageInParent();
11183                }
11184            }
11185
11186            // Damage the entire IsolatedZVolume recieving this view's shadow.
11187            if (isHardwareAccelerated() && getTranslationZ() != 0) {
11188                damageShadowReceiver();
11189            }
11190        }
11191    }
11192
11193    /**
11194     * @return this view's projection receiver, or {@code null} if none exists
11195     */
11196    private View getProjectionReceiver() {
11197        ViewParent p = getParent();
11198        while (p != null && p instanceof View) {
11199            final View v = (View) p;
11200            if (v.isProjectionReceiver()) {
11201                return v;
11202            }
11203            p = p.getParent();
11204        }
11205
11206        return null;
11207    }
11208
11209    /**
11210     * @return whether the view is a projection receiver
11211     */
11212    private boolean isProjectionReceiver() {
11213        return mBackground != null;
11214    }
11215
11216    /**
11217     * Damage area of the screen that can be covered by this View's shadow.
11218     *
11219     * This method will guarantee that any changes to shadows cast by a View
11220     * are damaged on the screen for future redraw.
11221     */
11222    private void damageShadowReceiver() {
11223        final AttachInfo ai = mAttachInfo;
11224        if (ai != null) {
11225            ViewParent p = getParent();
11226            if (p != null && p instanceof ViewGroup) {
11227                final ViewGroup vg = (ViewGroup) p;
11228                vg.damageInParent();
11229            }
11230        }
11231    }
11232
11233    /**
11234     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
11235     * set any flags or handle all of the cases handled by the default invalidation methods.
11236     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
11237     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
11238     * walk up the hierarchy, transforming the dirty rect as necessary.
11239     *
11240     * The method also handles normal invalidation logic if display list properties are not
11241     * being used in this view. The invalidateParent and forceRedraw flags are used by that
11242     * backup approach, to handle these cases used in the various property-setting methods.
11243     *
11244     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
11245     * are not being used in this view
11246     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
11247     * list properties are not being used in this view
11248     */
11249    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
11250        if (!isHardwareAccelerated()
11251                || !mRenderNode.isValid()
11252                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
11253            if (invalidateParent) {
11254                invalidateParentCaches();
11255            }
11256            if (forceRedraw) {
11257                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11258            }
11259            invalidate(false);
11260        } else {
11261            damageInParent();
11262        }
11263        if (isHardwareAccelerated() && invalidateParent && getTranslationZ() != 0) {
11264            damageShadowReceiver();
11265        }
11266    }
11267
11268    /**
11269     * Tells the parent view to damage this view's bounds.
11270     *
11271     * @hide
11272     */
11273    protected void damageInParent() {
11274        final AttachInfo ai = mAttachInfo;
11275        final ViewParent p = mParent;
11276        if (p != null && ai != null) {
11277            final Rect r = ai.mTmpInvalRect;
11278            r.set(0, 0, mRight - mLeft, mBottom - mTop);
11279            if (mParent instanceof ViewGroup) {
11280                ((ViewGroup) mParent).damageChild(this, r);
11281            } else {
11282                mParent.invalidateChild(this, r);
11283            }
11284        }
11285    }
11286
11287    /**
11288     * Utility method to transform a given Rect by the current matrix of this view.
11289     */
11290    void transformRect(final Rect rect) {
11291        if (!getMatrix().isIdentity()) {
11292            RectF boundingRect = mAttachInfo.mTmpTransformRect;
11293            boundingRect.set(rect);
11294            getMatrix().mapRect(boundingRect);
11295            rect.set((int) Math.floor(boundingRect.left),
11296                    (int) Math.floor(boundingRect.top),
11297                    (int) Math.ceil(boundingRect.right),
11298                    (int) Math.ceil(boundingRect.bottom));
11299        }
11300    }
11301
11302    /**
11303     * Used to indicate that the parent of this view should clear its caches. This functionality
11304     * is used to force the parent to rebuild its display list (when hardware-accelerated),
11305     * which is necessary when various parent-managed properties of the view change, such as
11306     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
11307     * clears the parent caches and does not causes an invalidate event.
11308     *
11309     * @hide
11310     */
11311    protected void invalidateParentCaches() {
11312        if (mParent instanceof View) {
11313            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
11314        }
11315    }
11316
11317    /**
11318     * Used to indicate that the parent of this view should be invalidated. This functionality
11319     * is used to force the parent to rebuild its display list (when hardware-accelerated),
11320     * which is necessary when various parent-managed properties of the view change, such as
11321     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
11322     * an invalidation event to the parent.
11323     *
11324     * @hide
11325     */
11326    protected void invalidateParentIfNeeded() {
11327        if (isHardwareAccelerated() && mParent instanceof View) {
11328            ((View) mParent).invalidate(true);
11329        }
11330    }
11331
11332    /**
11333     * @hide
11334     */
11335    protected void invalidateParentIfNeededAndWasQuickRejected() {
11336        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
11337            // View was rejected last time it was drawn by its parent; this may have changed
11338            invalidateParentIfNeeded();
11339        }
11340    }
11341
11342    /**
11343     * Indicates whether this View is opaque. An opaque View guarantees that it will
11344     * draw all the pixels overlapping its bounds using a fully opaque color.
11345     *
11346     * Subclasses of View should override this method whenever possible to indicate
11347     * whether an instance is opaque. Opaque Views are treated in a special way by
11348     * the View hierarchy, possibly allowing it to perform optimizations during
11349     * invalidate/draw passes.
11350     *
11351     * @return True if this View is guaranteed to be fully opaque, false otherwise.
11352     */
11353    @ViewDebug.ExportedProperty(category = "drawing")
11354    public boolean isOpaque() {
11355        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
11356                getFinalAlpha() >= 1.0f;
11357    }
11358
11359    /**
11360     * @hide
11361     */
11362    protected void computeOpaqueFlags() {
11363        // Opaque if:
11364        //   - Has a background
11365        //   - Background is opaque
11366        //   - Doesn't have scrollbars or scrollbars overlay
11367
11368        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
11369            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
11370        } else {
11371            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
11372        }
11373
11374        final int flags = mViewFlags;
11375        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
11376                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
11377                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
11378            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
11379        } else {
11380            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
11381        }
11382    }
11383
11384    /**
11385     * @hide
11386     */
11387    protected boolean hasOpaqueScrollbars() {
11388        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
11389    }
11390
11391    /**
11392     * @return A handler associated with the thread running the View. This
11393     * handler can be used to pump events in the UI events queue.
11394     */
11395    public Handler getHandler() {
11396        final AttachInfo attachInfo = mAttachInfo;
11397        if (attachInfo != null) {
11398            return attachInfo.mHandler;
11399        }
11400        return null;
11401    }
11402
11403    /**
11404     * Gets the view root associated with the View.
11405     * @return The view root, or null if none.
11406     * @hide
11407     */
11408    public ViewRootImpl getViewRootImpl() {
11409        if (mAttachInfo != null) {
11410            return mAttachInfo.mViewRootImpl;
11411        }
11412        return null;
11413    }
11414
11415    /**
11416     * @hide
11417     */
11418    public HardwareRenderer getHardwareRenderer() {
11419        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
11420    }
11421
11422    /**
11423     * <p>Causes the Runnable to be added to the message queue.
11424     * The runnable will be run on the user interface thread.</p>
11425     *
11426     * @param action The Runnable that will be executed.
11427     *
11428     * @return Returns true if the Runnable was successfully placed in to the
11429     *         message queue.  Returns false on failure, usually because the
11430     *         looper processing the message queue is exiting.
11431     *
11432     * @see #postDelayed
11433     * @see #removeCallbacks
11434     */
11435    public boolean post(Runnable action) {
11436        final AttachInfo attachInfo = mAttachInfo;
11437        if (attachInfo != null) {
11438            return attachInfo.mHandler.post(action);
11439        }
11440        // Assume that post will succeed later
11441        ViewRootImpl.getRunQueue().post(action);
11442        return true;
11443    }
11444
11445    /**
11446     * <p>Causes the Runnable to be added to the message queue, to be run
11447     * after the specified amount of time elapses.
11448     * The runnable will be run on the user interface thread.</p>
11449     *
11450     * @param action The Runnable that will be executed.
11451     * @param delayMillis The delay (in milliseconds) until the Runnable
11452     *        will be executed.
11453     *
11454     * @return true if the Runnable was successfully placed in to the
11455     *         message queue.  Returns false on failure, usually because the
11456     *         looper processing the message queue is exiting.  Note that a
11457     *         result of true does not mean the Runnable will be processed --
11458     *         if the looper is quit before the delivery time of the message
11459     *         occurs then the message will be dropped.
11460     *
11461     * @see #post
11462     * @see #removeCallbacks
11463     */
11464    public boolean postDelayed(Runnable action, long delayMillis) {
11465        final AttachInfo attachInfo = mAttachInfo;
11466        if (attachInfo != null) {
11467            return attachInfo.mHandler.postDelayed(action, delayMillis);
11468        }
11469        // Assume that post will succeed later
11470        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
11471        return true;
11472    }
11473
11474    /**
11475     * <p>Causes the Runnable to execute on the next animation time step.
11476     * The runnable will be run on the user interface thread.</p>
11477     *
11478     * @param action The Runnable that will be executed.
11479     *
11480     * @see #postOnAnimationDelayed
11481     * @see #removeCallbacks
11482     */
11483    public void postOnAnimation(Runnable action) {
11484        final AttachInfo attachInfo = mAttachInfo;
11485        if (attachInfo != null) {
11486            attachInfo.mViewRootImpl.mChoreographer.postCallback(
11487                    Choreographer.CALLBACK_ANIMATION, action, null);
11488        } else {
11489            // Assume that post will succeed later
11490            ViewRootImpl.getRunQueue().post(action);
11491        }
11492    }
11493
11494    /**
11495     * <p>Causes the Runnable to execute on the next animation time step,
11496     * after the specified amount of time elapses.
11497     * The runnable will be run on the user interface thread.</p>
11498     *
11499     * @param action The Runnable that will be executed.
11500     * @param delayMillis The delay (in milliseconds) until the Runnable
11501     *        will be executed.
11502     *
11503     * @see #postOnAnimation
11504     * @see #removeCallbacks
11505     */
11506    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
11507        final AttachInfo attachInfo = mAttachInfo;
11508        if (attachInfo != null) {
11509            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
11510                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
11511        } else {
11512            // Assume that post will succeed later
11513            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
11514        }
11515    }
11516
11517    /**
11518     * <p>Removes the specified Runnable from the message queue.</p>
11519     *
11520     * @param action The Runnable to remove from the message handling queue
11521     *
11522     * @return true if this view could ask the Handler to remove the Runnable,
11523     *         false otherwise. When the returned value is true, the Runnable
11524     *         may or may not have been actually removed from the message queue
11525     *         (for instance, if the Runnable was not in the queue already.)
11526     *
11527     * @see #post
11528     * @see #postDelayed
11529     * @see #postOnAnimation
11530     * @see #postOnAnimationDelayed
11531     */
11532    public boolean removeCallbacks(Runnable action) {
11533        if (action != null) {
11534            final AttachInfo attachInfo = mAttachInfo;
11535            if (attachInfo != null) {
11536                attachInfo.mHandler.removeCallbacks(action);
11537                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
11538                        Choreographer.CALLBACK_ANIMATION, action, null);
11539            }
11540            // Assume that post will succeed later
11541            ViewRootImpl.getRunQueue().removeCallbacks(action);
11542        }
11543        return true;
11544    }
11545
11546    /**
11547     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
11548     * Use this to invalidate the View from a non-UI thread.</p>
11549     *
11550     * <p>This method can be invoked from outside of the UI thread
11551     * only when this View is attached to a window.</p>
11552     *
11553     * @see #invalidate()
11554     * @see #postInvalidateDelayed(long)
11555     */
11556    public void postInvalidate() {
11557        postInvalidateDelayed(0);
11558    }
11559
11560    /**
11561     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
11562     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
11563     *
11564     * <p>This method can be invoked from outside of the UI thread
11565     * only when this View is attached to a window.</p>
11566     *
11567     * @param left The left coordinate of the rectangle to invalidate.
11568     * @param top The top coordinate of the rectangle to invalidate.
11569     * @param right The right coordinate of the rectangle to invalidate.
11570     * @param bottom The bottom coordinate of the rectangle to invalidate.
11571     *
11572     * @see #invalidate(int, int, int, int)
11573     * @see #invalidate(Rect)
11574     * @see #postInvalidateDelayed(long, int, int, int, int)
11575     */
11576    public void postInvalidate(int left, int top, int right, int bottom) {
11577        postInvalidateDelayed(0, left, top, right, bottom);
11578    }
11579
11580    /**
11581     * <p>Cause an invalidate to happen on a subsequent cycle through the event
11582     * loop. Waits for the specified amount of time.</p>
11583     *
11584     * <p>This method can be invoked from outside of the UI thread
11585     * only when this View is attached to a window.</p>
11586     *
11587     * @param delayMilliseconds the duration in milliseconds to delay the
11588     *         invalidation by
11589     *
11590     * @see #invalidate()
11591     * @see #postInvalidate()
11592     */
11593    public void postInvalidateDelayed(long delayMilliseconds) {
11594        // We try only with the AttachInfo because there's no point in invalidating
11595        // if we are not attached to our window
11596        final AttachInfo attachInfo = mAttachInfo;
11597        if (attachInfo != null) {
11598            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
11599        }
11600    }
11601
11602    /**
11603     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
11604     * through the event loop. Waits for the specified amount of time.</p>
11605     *
11606     * <p>This method can be invoked from outside of the UI thread
11607     * only when this View is attached to a window.</p>
11608     *
11609     * @param delayMilliseconds the duration in milliseconds to delay the
11610     *         invalidation by
11611     * @param left The left coordinate of the rectangle to invalidate.
11612     * @param top The top coordinate of the rectangle to invalidate.
11613     * @param right The right coordinate of the rectangle to invalidate.
11614     * @param bottom The bottom coordinate of the rectangle to invalidate.
11615     *
11616     * @see #invalidate(int, int, int, int)
11617     * @see #invalidate(Rect)
11618     * @see #postInvalidate(int, int, int, int)
11619     */
11620    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
11621            int right, int bottom) {
11622
11623        // We try only with the AttachInfo because there's no point in invalidating
11624        // if we are not attached to our window
11625        final AttachInfo attachInfo = mAttachInfo;
11626        if (attachInfo != null) {
11627            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
11628            info.target = this;
11629            info.left = left;
11630            info.top = top;
11631            info.right = right;
11632            info.bottom = bottom;
11633
11634            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
11635        }
11636    }
11637
11638    /**
11639     * <p>Cause an invalidate to happen on the next animation time step, typically the
11640     * next display frame.</p>
11641     *
11642     * <p>This method can be invoked from outside of the UI thread
11643     * only when this View is attached to a window.</p>
11644     *
11645     * @see #invalidate()
11646     */
11647    public void postInvalidateOnAnimation() {
11648        // We try only with the AttachInfo because there's no point in invalidating
11649        // if we are not attached to our window
11650        final AttachInfo attachInfo = mAttachInfo;
11651        if (attachInfo != null) {
11652            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
11653        }
11654    }
11655
11656    /**
11657     * <p>Cause an invalidate of the specified area to happen on the next animation
11658     * time step, typically the next display frame.</p>
11659     *
11660     * <p>This method can be invoked from outside of the UI thread
11661     * only when this View is attached to a window.</p>
11662     *
11663     * @param left The left coordinate of the rectangle to invalidate.
11664     * @param top The top coordinate of the rectangle to invalidate.
11665     * @param right The right coordinate of the rectangle to invalidate.
11666     * @param bottom The bottom coordinate of the rectangle to invalidate.
11667     *
11668     * @see #invalidate(int, int, int, int)
11669     * @see #invalidate(Rect)
11670     */
11671    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
11672        // We try only with the AttachInfo because there's no point in invalidating
11673        // if we are not attached to our window
11674        final AttachInfo attachInfo = mAttachInfo;
11675        if (attachInfo != null) {
11676            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
11677            info.target = this;
11678            info.left = left;
11679            info.top = top;
11680            info.right = right;
11681            info.bottom = bottom;
11682
11683            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
11684        }
11685    }
11686
11687    /**
11688     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
11689     * This event is sent at most once every
11690     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
11691     */
11692    private void postSendViewScrolledAccessibilityEventCallback() {
11693        if (mSendViewScrolledAccessibilityEvent == null) {
11694            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
11695        }
11696        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
11697            mSendViewScrolledAccessibilityEvent.mIsPending = true;
11698            postDelayed(mSendViewScrolledAccessibilityEvent,
11699                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
11700        }
11701    }
11702
11703    /**
11704     * Called by a parent to request that a child update its values for mScrollX
11705     * and mScrollY if necessary. This will typically be done if the child is
11706     * animating a scroll using a {@link android.widget.Scroller Scroller}
11707     * object.
11708     */
11709    public void computeScroll() {
11710    }
11711
11712    /**
11713     * <p>Indicate whether the horizontal edges are faded when the view is
11714     * scrolled horizontally.</p>
11715     *
11716     * @return true if the horizontal edges should are faded on scroll, false
11717     *         otherwise
11718     *
11719     * @see #setHorizontalFadingEdgeEnabled(boolean)
11720     *
11721     * @attr ref android.R.styleable#View_requiresFadingEdge
11722     */
11723    public boolean isHorizontalFadingEdgeEnabled() {
11724        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
11725    }
11726
11727    /**
11728     * <p>Define whether the horizontal edges should be faded when this view
11729     * is scrolled horizontally.</p>
11730     *
11731     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
11732     *                                    be faded when the view is scrolled
11733     *                                    horizontally
11734     *
11735     * @see #isHorizontalFadingEdgeEnabled()
11736     *
11737     * @attr ref android.R.styleable#View_requiresFadingEdge
11738     */
11739    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
11740        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
11741            if (horizontalFadingEdgeEnabled) {
11742                initScrollCache();
11743            }
11744
11745            mViewFlags ^= FADING_EDGE_HORIZONTAL;
11746        }
11747    }
11748
11749    /**
11750     * <p>Indicate whether the vertical edges are faded when the view is
11751     * scrolled horizontally.</p>
11752     *
11753     * @return true if the vertical edges should are faded on scroll, false
11754     *         otherwise
11755     *
11756     * @see #setVerticalFadingEdgeEnabled(boolean)
11757     *
11758     * @attr ref android.R.styleable#View_requiresFadingEdge
11759     */
11760    public boolean isVerticalFadingEdgeEnabled() {
11761        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
11762    }
11763
11764    /**
11765     * <p>Define whether the vertical edges should be faded when this view
11766     * is scrolled vertically.</p>
11767     *
11768     * @param verticalFadingEdgeEnabled true if the vertical edges should
11769     *                                  be faded when the view is scrolled
11770     *                                  vertically
11771     *
11772     * @see #isVerticalFadingEdgeEnabled()
11773     *
11774     * @attr ref android.R.styleable#View_requiresFadingEdge
11775     */
11776    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
11777        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
11778            if (verticalFadingEdgeEnabled) {
11779                initScrollCache();
11780            }
11781
11782            mViewFlags ^= FADING_EDGE_VERTICAL;
11783        }
11784    }
11785
11786    /**
11787     * Returns the strength, or intensity, of the top faded edge. The strength is
11788     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
11789     * returns 0.0 or 1.0 but no value in between.
11790     *
11791     * Subclasses should override this method to provide a smoother fade transition
11792     * when scrolling occurs.
11793     *
11794     * @return the intensity of the top fade as a float between 0.0f and 1.0f
11795     */
11796    protected float getTopFadingEdgeStrength() {
11797        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
11798    }
11799
11800    /**
11801     * Returns the strength, or intensity, of the bottom faded edge. The strength is
11802     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
11803     * returns 0.0 or 1.0 but no value in between.
11804     *
11805     * Subclasses should override this method to provide a smoother fade transition
11806     * when scrolling occurs.
11807     *
11808     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
11809     */
11810    protected float getBottomFadingEdgeStrength() {
11811        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
11812                computeVerticalScrollRange() ? 1.0f : 0.0f;
11813    }
11814
11815    /**
11816     * Returns the strength, or intensity, of the left faded edge. The strength is
11817     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
11818     * returns 0.0 or 1.0 but no value in between.
11819     *
11820     * Subclasses should override this method to provide a smoother fade transition
11821     * when scrolling occurs.
11822     *
11823     * @return the intensity of the left fade as a float between 0.0f and 1.0f
11824     */
11825    protected float getLeftFadingEdgeStrength() {
11826        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
11827    }
11828
11829    /**
11830     * Returns the strength, or intensity, of the right faded edge. The strength is
11831     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
11832     * returns 0.0 or 1.0 but no value in between.
11833     *
11834     * Subclasses should override this method to provide a smoother fade transition
11835     * when scrolling occurs.
11836     *
11837     * @return the intensity of the right fade as a float between 0.0f and 1.0f
11838     */
11839    protected float getRightFadingEdgeStrength() {
11840        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
11841                computeHorizontalScrollRange() ? 1.0f : 0.0f;
11842    }
11843
11844    /**
11845     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
11846     * scrollbar is not drawn by default.</p>
11847     *
11848     * @return true if the horizontal scrollbar should be painted, false
11849     *         otherwise
11850     *
11851     * @see #setHorizontalScrollBarEnabled(boolean)
11852     */
11853    public boolean isHorizontalScrollBarEnabled() {
11854        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
11855    }
11856
11857    /**
11858     * <p>Define whether the horizontal scrollbar should be drawn or not. The
11859     * scrollbar is not drawn by default.</p>
11860     *
11861     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
11862     *                                   be painted
11863     *
11864     * @see #isHorizontalScrollBarEnabled()
11865     */
11866    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
11867        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
11868            mViewFlags ^= SCROLLBARS_HORIZONTAL;
11869            computeOpaqueFlags();
11870            resolvePadding();
11871        }
11872    }
11873
11874    /**
11875     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
11876     * scrollbar is not drawn by default.</p>
11877     *
11878     * @return true if the vertical scrollbar should be painted, false
11879     *         otherwise
11880     *
11881     * @see #setVerticalScrollBarEnabled(boolean)
11882     */
11883    public boolean isVerticalScrollBarEnabled() {
11884        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
11885    }
11886
11887    /**
11888     * <p>Define whether the vertical scrollbar should be drawn or not. The
11889     * scrollbar is not drawn by default.</p>
11890     *
11891     * @param verticalScrollBarEnabled true if the vertical scrollbar should
11892     *                                 be painted
11893     *
11894     * @see #isVerticalScrollBarEnabled()
11895     */
11896    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
11897        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
11898            mViewFlags ^= SCROLLBARS_VERTICAL;
11899            computeOpaqueFlags();
11900            resolvePadding();
11901        }
11902    }
11903
11904    /**
11905     * @hide
11906     */
11907    protected void recomputePadding() {
11908        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
11909    }
11910
11911    /**
11912     * Define whether scrollbars will fade when the view is not scrolling.
11913     *
11914     * @param fadeScrollbars wheter to enable fading
11915     *
11916     * @attr ref android.R.styleable#View_fadeScrollbars
11917     */
11918    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
11919        initScrollCache();
11920        final ScrollabilityCache scrollabilityCache = mScrollCache;
11921        scrollabilityCache.fadeScrollBars = fadeScrollbars;
11922        if (fadeScrollbars) {
11923            scrollabilityCache.state = ScrollabilityCache.OFF;
11924        } else {
11925            scrollabilityCache.state = ScrollabilityCache.ON;
11926        }
11927    }
11928
11929    /**
11930     *
11931     * Returns true if scrollbars will fade when this view is not scrolling
11932     *
11933     * @return true if scrollbar fading is enabled
11934     *
11935     * @attr ref android.R.styleable#View_fadeScrollbars
11936     */
11937    public boolean isScrollbarFadingEnabled() {
11938        return mScrollCache != null && mScrollCache.fadeScrollBars;
11939    }
11940
11941    /**
11942     *
11943     * Returns the delay before scrollbars fade.
11944     *
11945     * @return the delay before scrollbars fade
11946     *
11947     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
11948     */
11949    public int getScrollBarDefaultDelayBeforeFade() {
11950        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
11951                mScrollCache.scrollBarDefaultDelayBeforeFade;
11952    }
11953
11954    /**
11955     * Define the delay before scrollbars fade.
11956     *
11957     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
11958     *
11959     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
11960     */
11961    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
11962        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
11963    }
11964
11965    /**
11966     *
11967     * Returns the scrollbar fade duration.
11968     *
11969     * @return the scrollbar fade duration
11970     *
11971     * @attr ref android.R.styleable#View_scrollbarFadeDuration
11972     */
11973    public int getScrollBarFadeDuration() {
11974        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
11975                mScrollCache.scrollBarFadeDuration;
11976    }
11977
11978    /**
11979     * Define the scrollbar fade duration.
11980     *
11981     * @param scrollBarFadeDuration - the scrollbar fade duration
11982     *
11983     * @attr ref android.R.styleable#View_scrollbarFadeDuration
11984     */
11985    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
11986        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
11987    }
11988
11989    /**
11990     *
11991     * Returns the scrollbar size.
11992     *
11993     * @return the scrollbar size
11994     *
11995     * @attr ref android.R.styleable#View_scrollbarSize
11996     */
11997    public int getScrollBarSize() {
11998        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
11999                mScrollCache.scrollBarSize;
12000    }
12001
12002    /**
12003     * Define the scrollbar size.
12004     *
12005     * @param scrollBarSize - the scrollbar size
12006     *
12007     * @attr ref android.R.styleable#View_scrollbarSize
12008     */
12009    public void setScrollBarSize(int scrollBarSize) {
12010        getScrollCache().scrollBarSize = scrollBarSize;
12011    }
12012
12013    /**
12014     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
12015     * inset. When inset, they add to the padding of the view. And the scrollbars
12016     * can be drawn inside the padding area or on the edge of the view. For example,
12017     * if a view has a background drawable and you want to draw the scrollbars
12018     * inside the padding specified by the drawable, you can use
12019     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
12020     * appear at the edge of the view, ignoring the padding, then you can use
12021     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
12022     * @param style the style of the scrollbars. Should be one of
12023     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
12024     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
12025     * @see #SCROLLBARS_INSIDE_OVERLAY
12026     * @see #SCROLLBARS_INSIDE_INSET
12027     * @see #SCROLLBARS_OUTSIDE_OVERLAY
12028     * @see #SCROLLBARS_OUTSIDE_INSET
12029     *
12030     * @attr ref android.R.styleable#View_scrollbarStyle
12031     */
12032    public void setScrollBarStyle(@ScrollBarStyle int style) {
12033        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
12034            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
12035            computeOpaqueFlags();
12036            resolvePadding();
12037        }
12038    }
12039
12040    /**
12041     * <p>Returns the current scrollbar style.</p>
12042     * @return the current scrollbar style
12043     * @see #SCROLLBARS_INSIDE_OVERLAY
12044     * @see #SCROLLBARS_INSIDE_INSET
12045     * @see #SCROLLBARS_OUTSIDE_OVERLAY
12046     * @see #SCROLLBARS_OUTSIDE_INSET
12047     *
12048     * @attr ref android.R.styleable#View_scrollbarStyle
12049     */
12050    @ViewDebug.ExportedProperty(mapping = {
12051            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
12052            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
12053            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
12054            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
12055    })
12056    @ScrollBarStyle
12057    public int getScrollBarStyle() {
12058        return mViewFlags & SCROLLBARS_STYLE_MASK;
12059    }
12060
12061    /**
12062     * <p>Compute the horizontal range that the horizontal scrollbar
12063     * represents.</p>
12064     *
12065     * <p>The range is expressed in arbitrary units that must be the same as the
12066     * units used by {@link #computeHorizontalScrollExtent()} and
12067     * {@link #computeHorizontalScrollOffset()}.</p>
12068     *
12069     * <p>The default range is the drawing width of this view.</p>
12070     *
12071     * @return the total horizontal range represented by the horizontal
12072     *         scrollbar
12073     *
12074     * @see #computeHorizontalScrollExtent()
12075     * @see #computeHorizontalScrollOffset()
12076     * @see android.widget.ScrollBarDrawable
12077     */
12078    protected int computeHorizontalScrollRange() {
12079        return getWidth();
12080    }
12081
12082    /**
12083     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
12084     * within the horizontal range. This value is used to compute the position
12085     * of the thumb within the scrollbar's track.</p>
12086     *
12087     * <p>The range is expressed in arbitrary units that must be the same as the
12088     * units used by {@link #computeHorizontalScrollRange()} and
12089     * {@link #computeHorizontalScrollExtent()}.</p>
12090     *
12091     * <p>The default offset is the scroll offset of this view.</p>
12092     *
12093     * @return the horizontal offset of the scrollbar's thumb
12094     *
12095     * @see #computeHorizontalScrollRange()
12096     * @see #computeHorizontalScrollExtent()
12097     * @see android.widget.ScrollBarDrawable
12098     */
12099    protected int computeHorizontalScrollOffset() {
12100        return mScrollX;
12101    }
12102
12103    /**
12104     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
12105     * within the horizontal range. This value is used to compute the length
12106     * of the thumb within the scrollbar's track.</p>
12107     *
12108     * <p>The range is expressed in arbitrary units that must be the same as the
12109     * units used by {@link #computeHorizontalScrollRange()} and
12110     * {@link #computeHorizontalScrollOffset()}.</p>
12111     *
12112     * <p>The default extent is the drawing width of this view.</p>
12113     *
12114     * @return the horizontal extent of the scrollbar's thumb
12115     *
12116     * @see #computeHorizontalScrollRange()
12117     * @see #computeHorizontalScrollOffset()
12118     * @see android.widget.ScrollBarDrawable
12119     */
12120    protected int computeHorizontalScrollExtent() {
12121        return getWidth();
12122    }
12123
12124    /**
12125     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
12126     *
12127     * <p>The range is expressed in arbitrary units that must be the same as the
12128     * units used by {@link #computeVerticalScrollExtent()} and
12129     * {@link #computeVerticalScrollOffset()}.</p>
12130     *
12131     * @return the total vertical range represented by the vertical scrollbar
12132     *
12133     * <p>The default range is the drawing height of this view.</p>
12134     *
12135     * @see #computeVerticalScrollExtent()
12136     * @see #computeVerticalScrollOffset()
12137     * @see android.widget.ScrollBarDrawable
12138     */
12139    protected int computeVerticalScrollRange() {
12140        return getHeight();
12141    }
12142
12143    /**
12144     * <p>Compute the vertical offset of the vertical scrollbar's thumb
12145     * within the horizontal range. This value is used to compute the position
12146     * of the thumb within the scrollbar's track.</p>
12147     *
12148     * <p>The range is expressed in arbitrary units that must be the same as the
12149     * units used by {@link #computeVerticalScrollRange()} and
12150     * {@link #computeVerticalScrollExtent()}.</p>
12151     *
12152     * <p>The default offset is the scroll offset of this view.</p>
12153     *
12154     * @return the vertical offset of the scrollbar's thumb
12155     *
12156     * @see #computeVerticalScrollRange()
12157     * @see #computeVerticalScrollExtent()
12158     * @see android.widget.ScrollBarDrawable
12159     */
12160    protected int computeVerticalScrollOffset() {
12161        return mScrollY;
12162    }
12163
12164    /**
12165     * <p>Compute the vertical extent of the vertical scrollbar's thumb
12166     * within the vertical range. This value is used to compute the length
12167     * of the thumb within the scrollbar's track.</p>
12168     *
12169     * <p>The range is expressed in arbitrary units that must be the same as the
12170     * units used by {@link #computeVerticalScrollRange()} and
12171     * {@link #computeVerticalScrollOffset()}.</p>
12172     *
12173     * <p>The default extent is the drawing height of this view.</p>
12174     *
12175     * @return the vertical extent of the scrollbar's thumb
12176     *
12177     * @see #computeVerticalScrollRange()
12178     * @see #computeVerticalScrollOffset()
12179     * @see android.widget.ScrollBarDrawable
12180     */
12181    protected int computeVerticalScrollExtent() {
12182        return getHeight();
12183    }
12184
12185    /**
12186     * Check if this view can be scrolled horizontally in a certain direction.
12187     *
12188     * @param direction Negative to check scrolling left, positive to check scrolling right.
12189     * @return true if this view can be scrolled in the specified direction, false otherwise.
12190     */
12191    public boolean canScrollHorizontally(int direction) {
12192        final int offset = computeHorizontalScrollOffset();
12193        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
12194        if (range == 0) return false;
12195        if (direction < 0) {
12196            return offset > 0;
12197        } else {
12198            return offset < range - 1;
12199        }
12200    }
12201
12202    /**
12203     * Check if this view can be scrolled vertically in a certain direction.
12204     *
12205     * @param direction Negative to check scrolling up, positive to check scrolling down.
12206     * @return true if this view can be scrolled in the specified direction, false otherwise.
12207     */
12208    public boolean canScrollVertically(int direction) {
12209        final int offset = computeVerticalScrollOffset();
12210        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
12211        if (range == 0) return false;
12212        if (direction < 0) {
12213            return offset > 0;
12214        } else {
12215            return offset < range - 1;
12216        }
12217    }
12218
12219    /**
12220     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
12221     * scrollbars are painted only if they have been awakened first.</p>
12222     *
12223     * @param canvas the canvas on which to draw the scrollbars
12224     *
12225     * @see #awakenScrollBars(int)
12226     */
12227    protected final void onDrawScrollBars(Canvas canvas) {
12228        // scrollbars are drawn only when the animation is running
12229        final ScrollabilityCache cache = mScrollCache;
12230        if (cache != null) {
12231
12232            int state = cache.state;
12233
12234            if (state == ScrollabilityCache.OFF) {
12235                return;
12236            }
12237
12238            boolean invalidate = false;
12239
12240            if (state == ScrollabilityCache.FADING) {
12241                // We're fading -- get our fade interpolation
12242                if (cache.interpolatorValues == null) {
12243                    cache.interpolatorValues = new float[1];
12244                }
12245
12246                float[] values = cache.interpolatorValues;
12247
12248                // Stops the animation if we're done
12249                if (cache.scrollBarInterpolator.timeToValues(values) ==
12250                        Interpolator.Result.FREEZE_END) {
12251                    cache.state = ScrollabilityCache.OFF;
12252                } else {
12253                    cache.scrollBar.setAlpha(Math.round(values[0]));
12254                }
12255
12256                // This will make the scroll bars inval themselves after
12257                // drawing. We only want this when we're fading so that
12258                // we prevent excessive redraws
12259                invalidate = true;
12260            } else {
12261                // We're just on -- but we may have been fading before so
12262                // reset alpha
12263                cache.scrollBar.setAlpha(255);
12264            }
12265
12266
12267            final int viewFlags = mViewFlags;
12268
12269            final boolean drawHorizontalScrollBar =
12270                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12271            final boolean drawVerticalScrollBar =
12272                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
12273                && !isVerticalScrollBarHidden();
12274
12275            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
12276                final int width = mRight - mLeft;
12277                final int height = mBottom - mTop;
12278
12279                final ScrollBarDrawable scrollBar = cache.scrollBar;
12280
12281                final int scrollX = mScrollX;
12282                final int scrollY = mScrollY;
12283                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
12284
12285                int left;
12286                int top;
12287                int right;
12288                int bottom;
12289
12290                if (drawHorizontalScrollBar) {
12291                    int size = scrollBar.getSize(false);
12292                    if (size <= 0) {
12293                        size = cache.scrollBarSize;
12294                    }
12295
12296                    scrollBar.setParameters(computeHorizontalScrollRange(),
12297                                            computeHorizontalScrollOffset(),
12298                                            computeHorizontalScrollExtent(), false);
12299                    final int verticalScrollBarGap = drawVerticalScrollBar ?
12300                            getVerticalScrollbarWidth() : 0;
12301                    top = scrollY + height - size - (mUserPaddingBottom & inside);
12302                    left = scrollX + (mPaddingLeft & inside);
12303                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
12304                    bottom = top + size;
12305                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
12306                    if (invalidate) {
12307                        invalidate(left, top, right, bottom);
12308                    }
12309                }
12310
12311                if (drawVerticalScrollBar) {
12312                    int size = scrollBar.getSize(true);
12313                    if (size <= 0) {
12314                        size = cache.scrollBarSize;
12315                    }
12316
12317                    scrollBar.setParameters(computeVerticalScrollRange(),
12318                                            computeVerticalScrollOffset(),
12319                                            computeVerticalScrollExtent(), true);
12320                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
12321                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
12322                        verticalScrollbarPosition = isLayoutRtl() ?
12323                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
12324                    }
12325                    switch (verticalScrollbarPosition) {
12326                        default:
12327                        case SCROLLBAR_POSITION_RIGHT:
12328                            left = scrollX + width - size - (mUserPaddingRight & inside);
12329                            break;
12330                        case SCROLLBAR_POSITION_LEFT:
12331                            left = scrollX + (mUserPaddingLeft & inside);
12332                            break;
12333                    }
12334                    top = scrollY + (mPaddingTop & inside);
12335                    right = left + size;
12336                    bottom = scrollY + height - (mUserPaddingBottom & inside);
12337                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
12338                    if (invalidate) {
12339                        invalidate(left, top, right, bottom);
12340                    }
12341                }
12342            }
12343        }
12344    }
12345
12346    /**
12347     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
12348     * FastScroller is visible.
12349     * @return whether to temporarily hide the vertical scrollbar
12350     * @hide
12351     */
12352    protected boolean isVerticalScrollBarHidden() {
12353        return false;
12354    }
12355
12356    /**
12357     * <p>Draw the horizontal scrollbar if
12358     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
12359     *
12360     * @param canvas the canvas on which to draw the scrollbar
12361     * @param scrollBar the scrollbar's drawable
12362     *
12363     * @see #isHorizontalScrollBarEnabled()
12364     * @see #computeHorizontalScrollRange()
12365     * @see #computeHorizontalScrollExtent()
12366     * @see #computeHorizontalScrollOffset()
12367     * @see android.widget.ScrollBarDrawable
12368     * @hide
12369     */
12370    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
12371            int l, int t, int r, int b) {
12372        scrollBar.setBounds(l, t, r, b);
12373        scrollBar.draw(canvas);
12374    }
12375
12376    /**
12377     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
12378     * returns true.</p>
12379     *
12380     * @param canvas the canvas on which to draw the scrollbar
12381     * @param scrollBar the scrollbar's drawable
12382     *
12383     * @see #isVerticalScrollBarEnabled()
12384     * @see #computeVerticalScrollRange()
12385     * @see #computeVerticalScrollExtent()
12386     * @see #computeVerticalScrollOffset()
12387     * @see android.widget.ScrollBarDrawable
12388     * @hide
12389     */
12390    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
12391            int l, int t, int r, int b) {
12392        scrollBar.setBounds(l, t, r, b);
12393        scrollBar.draw(canvas);
12394    }
12395
12396    /**
12397     * Implement this to do your drawing.
12398     *
12399     * @param canvas the canvas on which the background will be drawn
12400     */
12401    protected void onDraw(Canvas canvas) {
12402    }
12403
12404    /*
12405     * Caller is responsible for calling requestLayout if necessary.
12406     * (This allows addViewInLayout to not request a new layout.)
12407     */
12408    void assignParent(ViewParent parent) {
12409        if (mParent == null) {
12410            mParent = parent;
12411        } else if (parent == null) {
12412            mParent = null;
12413        } else {
12414            throw new RuntimeException("view " + this + " being added, but"
12415                    + " it already has a parent");
12416        }
12417    }
12418
12419    /**
12420     * This is called when the view is attached to a window.  At this point it
12421     * has a Surface and will start drawing.  Note that this function is
12422     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
12423     * however it may be called any time before the first onDraw -- including
12424     * before or after {@link #onMeasure(int, int)}.
12425     *
12426     * @see #onDetachedFromWindow()
12427     */
12428    protected void onAttachedToWindow() {
12429        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
12430            mParent.requestTransparentRegion(this);
12431        }
12432
12433        if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
12434            initialAwakenScrollBars();
12435            mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
12436        }
12437
12438        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
12439
12440        jumpDrawablesToCurrentState();
12441
12442        resetSubtreeAccessibilityStateChanged();
12443
12444        if (isFocused()) {
12445            InputMethodManager imm = InputMethodManager.peekInstance();
12446            imm.focusIn(this);
12447        }
12448    }
12449
12450    /**
12451     * Resolve all RTL related properties.
12452     *
12453     * @return true if resolution of RTL properties has been done
12454     *
12455     * @hide
12456     */
12457    public boolean resolveRtlPropertiesIfNeeded() {
12458        if (!needRtlPropertiesResolution()) return false;
12459
12460        // Order is important here: LayoutDirection MUST be resolved first
12461        if (!isLayoutDirectionResolved()) {
12462            resolveLayoutDirection();
12463            resolveLayoutParams();
12464        }
12465        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
12466        if (!isTextDirectionResolved()) {
12467            resolveTextDirection();
12468        }
12469        if (!isTextAlignmentResolved()) {
12470            resolveTextAlignment();
12471        }
12472        // Should resolve Drawables before Padding because we need the layout direction of the
12473        // Drawable to correctly resolve Padding.
12474        if (!isDrawablesResolved()) {
12475            resolveDrawables();
12476        }
12477        if (!isPaddingResolved()) {
12478            resolvePadding();
12479        }
12480        onRtlPropertiesChanged(getLayoutDirection());
12481        return true;
12482    }
12483
12484    /**
12485     * Reset resolution of all RTL related properties.
12486     *
12487     * @hide
12488     */
12489    public void resetRtlProperties() {
12490        resetResolvedLayoutDirection();
12491        resetResolvedTextDirection();
12492        resetResolvedTextAlignment();
12493        resetResolvedPadding();
12494        resetResolvedDrawables();
12495    }
12496
12497    /**
12498     * @see #onScreenStateChanged(int)
12499     */
12500    void dispatchScreenStateChanged(int screenState) {
12501        onScreenStateChanged(screenState);
12502    }
12503
12504    /**
12505     * This method is called whenever the state of the screen this view is
12506     * attached to changes. A state change will usually occurs when the screen
12507     * turns on or off (whether it happens automatically or the user does it
12508     * manually.)
12509     *
12510     * @param screenState The new state of the screen. Can be either
12511     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
12512     */
12513    public void onScreenStateChanged(int screenState) {
12514    }
12515
12516    /**
12517     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
12518     */
12519    private boolean hasRtlSupport() {
12520        return mContext.getApplicationInfo().hasRtlSupport();
12521    }
12522
12523    /**
12524     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
12525     * RTL not supported)
12526     */
12527    private boolean isRtlCompatibilityMode() {
12528        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
12529        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
12530    }
12531
12532    /**
12533     * @return true if RTL properties need resolution.
12534     *
12535     */
12536    private boolean needRtlPropertiesResolution() {
12537        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
12538    }
12539
12540    /**
12541     * Called when any RTL property (layout direction or text direction or text alignment) has
12542     * been changed.
12543     *
12544     * Subclasses need to override this method to take care of cached information that depends on the
12545     * resolved layout direction, or to inform child views that inherit their layout direction.
12546     *
12547     * The default implementation does nothing.
12548     *
12549     * @param layoutDirection the direction of the layout
12550     *
12551     * @see #LAYOUT_DIRECTION_LTR
12552     * @see #LAYOUT_DIRECTION_RTL
12553     */
12554    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
12555    }
12556
12557    /**
12558     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
12559     * that the parent directionality can and will be resolved before its children.
12560     *
12561     * @return true if resolution has been done, false otherwise.
12562     *
12563     * @hide
12564     */
12565    public boolean resolveLayoutDirection() {
12566        // Clear any previous layout direction resolution
12567        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
12568
12569        if (hasRtlSupport()) {
12570            // Set resolved depending on layout direction
12571            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
12572                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
12573                case LAYOUT_DIRECTION_INHERIT:
12574                    // We cannot resolve yet. LTR is by default and let the resolution happen again
12575                    // later to get the correct resolved value
12576                    if (!canResolveLayoutDirection()) return false;
12577
12578                    // Parent has not yet resolved, LTR is still the default
12579                    try {
12580                        if (!mParent.isLayoutDirectionResolved()) return false;
12581
12582                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
12583                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
12584                        }
12585                    } catch (AbstractMethodError e) {
12586                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
12587                                " does not fully implement ViewParent", e);
12588                    }
12589                    break;
12590                case LAYOUT_DIRECTION_RTL:
12591                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
12592                    break;
12593                case LAYOUT_DIRECTION_LOCALE:
12594                    if((LAYOUT_DIRECTION_RTL ==
12595                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
12596                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
12597                    }
12598                    break;
12599                default:
12600                    // Nothing to do, LTR by default
12601            }
12602        }
12603
12604        // Set to resolved
12605        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
12606        return true;
12607    }
12608
12609    /**
12610     * Check if layout direction resolution can be done.
12611     *
12612     * @return true if layout direction resolution can be done otherwise return false.
12613     */
12614    public boolean canResolveLayoutDirection() {
12615        switch (getRawLayoutDirection()) {
12616            case LAYOUT_DIRECTION_INHERIT:
12617                if (mParent != null) {
12618                    try {
12619                        return mParent.canResolveLayoutDirection();
12620                    } catch (AbstractMethodError e) {
12621                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
12622                                " does not fully implement ViewParent", e);
12623                    }
12624                }
12625                return false;
12626
12627            default:
12628                return true;
12629        }
12630    }
12631
12632    /**
12633     * Reset the resolved layout direction. Layout direction will be resolved during a call to
12634     * {@link #onMeasure(int, int)}.
12635     *
12636     * @hide
12637     */
12638    public void resetResolvedLayoutDirection() {
12639        // Reset the current resolved bits
12640        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
12641    }
12642
12643    /**
12644     * @return true if the layout direction is inherited.
12645     *
12646     * @hide
12647     */
12648    public boolean isLayoutDirectionInherited() {
12649        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
12650    }
12651
12652    /**
12653     * @return true if layout direction has been resolved.
12654     */
12655    public boolean isLayoutDirectionResolved() {
12656        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
12657    }
12658
12659    /**
12660     * Return if padding has been resolved
12661     *
12662     * @hide
12663     */
12664    boolean isPaddingResolved() {
12665        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
12666    }
12667
12668    /**
12669     * Resolves padding depending on layout direction, if applicable, and
12670     * recomputes internal padding values to adjust for scroll bars.
12671     *
12672     * @hide
12673     */
12674    public void resolvePadding() {
12675        final int resolvedLayoutDirection = getLayoutDirection();
12676
12677        if (!isRtlCompatibilityMode()) {
12678            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
12679            // If start / end padding are defined, they will be resolved (hence overriding) to
12680            // left / right or right / left depending on the resolved layout direction.
12681            // If start / end padding are not defined, use the left / right ones.
12682            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
12683                Rect padding = sThreadLocal.get();
12684                if (padding == null) {
12685                    padding = new Rect();
12686                    sThreadLocal.set(padding);
12687                }
12688                mBackground.getPadding(padding);
12689                if (!mLeftPaddingDefined) {
12690                    mUserPaddingLeftInitial = padding.left;
12691                }
12692                if (!mRightPaddingDefined) {
12693                    mUserPaddingRightInitial = padding.right;
12694                }
12695            }
12696            switch (resolvedLayoutDirection) {
12697                case LAYOUT_DIRECTION_RTL:
12698                    if (mUserPaddingStart != UNDEFINED_PADDING) {
12699                        mUserPaddingRight = mUserPaddingStart;
12700                    } else {
12701                        mUserPaddingRight = mUserPaddingRightInitial;
12702                    }
12703                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
12704                        mUserPaddingLeft = mUserPaddingEnd;
12705                    } else {
12706                        mUserPaddingLeft = mUserPaddingLeftInitial;
12707                    }
12708                    break;
12709                case LAYOUT_DIRECTION_LTR:
12710                default:
12711                    if (mUserPaddingStart != UNDEFINED_PADDING) {
12712                        mUserPaddingLeft = mUserPaddingStart;
12713                    } else {
12714                        mUserPaddingLeft = mUserPaddingLeftInitial;
12715                    }
12716                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
12717                        mUserPaddingRight = mUserPaddingEnd;
12718                    } else {
12719                        mUserPaddingRight = mUserPaddingRightInitial;
12720                    }
12721            }
12722
12723            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
12724        }
12725
12726        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
12727        onRtlPropertiesChanged(resolvedLayoutDirection);
12728
12729        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
12730    }
12731
12732    /**
12733     * Reset the resolved layout direction.
12734     *
12735     * @hide
12736     */
12737    public void resetResolvedPadding() {
12738        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
12739    }
12740
12741    /**
12742     * This is called when the view is detached from a window.  At this point it
12743     * no longer has a surface for drawing.
12744     *
12745     * @see #onAttachedToWindow()
12746     */
12747    protected void onDetachedFromWindow() {
12748    }
12749
12750    /**
12751     * This is a framework-internal mirror of onDetachedFromWindow() that's called
12752     * after onDetachedFromWindow().
12753     *
12754     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
12755     * The super method should be called at the end of the overriden method to ensure
12756     * subclasses are destroyed first
12757     *
12758     * @hide
12759     */
12760    protected void onDetachedFromWindowInternal() {
12761        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
12762        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
12763
12764        if (mBackground != null) {
12765            mBackground.clearHotspots();
12766        }
12767
12768        removeUnsetPressCallback();
12769        removeLongPressCallback();
12770        removePerformClickCallback();
12771        removeSendViewScrolledAccessibilityEventCallback();
12772        stopNestedScroll();
12773
12774        destroyDrawingCache();
12775        destroyLayer(false);
12776
12777        cleanupDraw();
12778
12779        mCurrentAnimation = null;
12780    }
12781
12782    private void cleanupDraw() {
12783        resetDisplayList();
12784        if (mAttachInfo != null) {
12785            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
12786        }
12787    }
12788
12789    /**
12790     * This method ensures the hardware renderer is in a valid state
12791     * before executing the specified action.
12792     *
12793     * This method will attempt to set a valid state even if the window
12794     * the renderer is attached to was destroyed.
12795     *
12796     * This method is not guaranteed to work. If the hardware renderer
12797     * does not exist or cannot be put in a valid state, this method
12798     * will not executed the specified action.
12799     *
12800     * The specified action is executed synchronously.
12801     *
12802     * @param action The action to execute after the renderer is in a valid state
12803     *
12804     * @return True if the specified Runnable was executed, false otherwise
12805     *
12806     * @hide
12807     */
12808    public boolean executeHardwareAction(Runnable action) {
12809        //noinspection SimplifiableIfStatement
12810        if (mAttachInfo != null && mAttachInfo.mHardwareRenderer != null) {
12811            return mAttachInfo.mHardwareRenderer.safelyRun(action);
12812        }
12813        return false;
12814    }
12815
12816    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
12817    }
12818
12819    /**
12820     * @return The number of times this view has been attached to a window
12821     */
12822    protected int getWindowAttachCount() {
12823        return mWindowAttachCount;
12824    }
12825
12826    /**
12827     * Retrieve a unique token identifying the window this view is attached to.
12828     * @return Return the window's token for use in
12829     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
12830     */
12831    public IBinder getWindowToken() {
12832        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
12833    }
12834
12835    /**
12836     * Retrieve the {@link WindowId} for the window this view is
12837     * currently attached to.
12838     */
12839    public WindowId getWindowId() {
12840        if (mAttachInfo == null) {
12841            return null;
12842        }
12843        if (mAttachInfo.mWindowId == null) {
12844            try {
12845                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
12846                        mAttachInfo.mWindowToken);
12847                mAttachInfo.mWindowId = new WindowId(
12848                        mAttachInfo.mIWindowId);
12849            } catch (RemoteException e) {
12850            }
12851        }
12852        return mAttachInfo.mWindowId;
12853    }
12854
12855    /**
12856     * Retrieve a unique token identifying the top-level "real" window of
12857     * the window that this view is attached to.  That is, this is like
12858     * {@link #getWindowToken}, except if the window this view in is a panel
12859     * window (attached to another containing window), then the token of
12860     * the containing window is returned instead.
12861     *
12862     * @return Returns the associated window token, either
12863     * {@link #getWindowToken()} or the containing window's token.
12864     */
12865    public IBinder getApplicationWindowToken() {
12866        AttachInfo ai = mAttachInfo;
12867        if (ai != null) {
12868            IBinder appWindowToken = ai.mPanelParentWindowToken;
12869            if (appWindowToken == null) {
12870                appWindowToken = ai.mWindowToken;
12871            }
12872            return appWindowToken;
12873        }
12874        return null;
12875    }
12876
12877    /**
12878     * Gets the logical display to which the view's window has been attached.
12879     *
12880     * @return The logical display, or null if the view is not currently attached to a window.
12881     */
12882    public Display getDisplay() {
12883        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
12884    }
12885
12886    /**
12887     * Retrieve private session object this view hierarchy is using to
12888     * communicate with the window manager.
12889     * @return the session object to communicate with the window manager
12890     */
12891    /*package*/ IWindowSession getWindowSession() {
12892        return mAttachInfo != null ? mAttachInfo.mSession : null;
12893    }
12894
12895    /**
12896     * @param info the {@link android.view.View.AttachInfo} to associated with
12897     *        this view
12898     */
12899    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
12900        //System.out.println("Attached! " + this);
12901        mAttachInfo = info;
12902        if (mOverlay != null) {
12903            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
12904        }
12905        mWindowAttachCount++;
12906        // We will need to evaluate the drawable state at least once.
12907        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
12908        if (mFloatingTreeObserver != null) {
12909            info.mTreeObserver.merge(mFloatingTreeObserver);
12910            mFloatingTreeObserver = null;
12911        }
12912        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
12913            mAttachInfo.mScrollContainers.add(this);
12914            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
12915        }
12916        performCollectViewAttributes(mAttachInfo, visibility);
12917        onAttachedToWindow();
12918
12919        ListenerInfo li = mListenerInfo;
12920        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
12921                li != null ? li.mOnAttachStateChangeListeners : null;
12922        if (listeners != null && listeners.size() > 0) {
12923            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
12924            // perform the dispatching. The iterator is a safe guard against listeners that
12925            // could mutate the list by calling the various add/remove methods. This prevents
12926            // the array from being modified while we iterate it.
12927            for (OnAttachStateChangeListener listener : listeners) {
12928                listener.onViewAttachedToWindow(this);
12929            }
12930        }
12931
12932        int vis = info.mWindowVisibility;
12933        if (vis != GONE) {
12934            onWindowVisibilityChanged(vis);
12935        }
12936        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
12937            // If nobody has evaluated the drawable state yet, then do it now.
12938            refreshDrawableState();
12939        }
12940        needGlobalAttributesUpdate(false);
12941    }
12942
12943    void dispatchDetachedFromWindow() {
12944        AttachInfo info = mAttachInfo;
12945        if (info != null) {
12946            int vis = info.mWindowVisibility;
12947            if (vis != GONE) {
12948                onWindowVisibilityChanged(GONE);
12949            }
12950        }
12951
12952        onDetachedFromWindow();
12953        onDetachedFromWindowInternal();
12954
12955        ListenerInfo li = mListenerInfo;
12956        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
12957                li != null ? li.mOnAttachStateChangeListeners : null;
12958        if (listeners != null && listeners.size() > 0) {
12959            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
12960            // perform the dispatching. The iterator is a safe guard against listeners that
12961            // could mutate the list by calling the various add/remove methods. This prevents
12962            // the array from being modified while we iterate it.
12963            for (OnAttachStateChangeListener listener : listeners) {
12964                listener.onViewDetachedFromWindow(this);
12965            }
12966        }
12967
12968        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
12969            mAttachInfo.mScrollContainers.remove(this);
12970            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
12971        }
12972
12973        mAttachInfo = null;
12974        if (mOverlay != null) {
12975            mOverlay.getOverlayView().dispatchDetachedFromWindow();
12976        }
12977    }
12978
12979    /**
12980     * Cancel any deferred high-level input events that were previously posted to the event queue.
12981     *
12982     * <p>Many views post high-level events such as click handlers to the event queue
12983     * to run deferred in order to preserve a desired user experience - clearing visible
12984     * pressed states before executing, etc. This method will abort any events of this nature
12985     * that are currently in flight.</p>
12986     *
12987     * <p>Custom views that generate their own high-level deferred input events should override
12988     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
12989     *
12990     * <p>This will also cancel pending input events for any child views.</p>
12991     *
12992     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
12993     * This will not impact newer events posted after this call that may occur as a result of
12994     * lower-level input events still waiting in the queue. If you are trying to prevent
12995     * double-submitted  events for the duration of some sort of asynchronous transaction
12996     * you should also take other steps to protect against unexpected double inputs e.g. calling
12997     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
12998     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
12999     */
13000    public final void cancelPendingInputEvents() {
13001        dispatchCancelPendingInputEvents();
13002    }
13003
13004    /**
13005     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
13006     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
13007     */
13008    void dispatchCancelPendingInputEvents() {
13009        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
13010        onCancelPendingInputEvents();
13011        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
13012            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
13013                    " did not call through to super.onCancelPendingInputEvents()");
13014        }
13015    }
13016
13017    /**
13018     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
13019     * a parent view.
13020     *
13021     * <p>This method is responsible for removing any pending high-level input events that were
13022     * posted to the event queue to run later. Custom view classes that post their own deferred
13023     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
13024     * {@link android.os.Handler} should override this method, call
13025     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
13026     * </p>
13027     */
13028    public void onCancelPendingInputEvents() {
13029        removePerformClickCallback();
13030        cancelLongPress();
13031        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
13032    }
13033
13034    /**
13035     * Store this view hierarchy's frozen state into the given container.
13036     *
13037     * @param container The SparseArray in which to save the view's state.
13038     *
13039     * @see #restoreHierarchyState(android.util.SparseArray)
13040     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13041     * @see #onSaveInstanceState()
13042     */
13043    public void saveHierarchyState(SparseArray<Parcelable> container) {
13044        dispatchSaveInstanceState(container);
13045    }
13046
13047    /**
13048     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
13049     * this view and its children. May be overridden to modify how freezing happens to a
13050     * view's children; for example, some views may want to not store state for their children.
13051     *
13052     * @param container The SparseArray in which to save the view's state.
13053     *
13054     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13055     * @see #saveHierarchyState(android.util.SparseArray)
13056     * @see #onSaveInstanceState()
13057     */
13058    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
13059        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
13060            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13061            Parcelable state = onSaveInstanceState();
13062            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13063                throw new IllegalStateException(
13064                        "Derived class did not call super.onSaveInstanceState()");
13065            }
13066            if (state != null) {
13067                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
13068                // + ": " + state);
13069                container.put(mID, state);
13070            }
13071        }
13072    }
13073
13074    /**
13075     * Hook allowing a view to generate a representation of its internal state
13076     * that can later be used to create a new instance with that same state.
13077     * This state should only contain information that is not persistent or can
13078     * not be reconstructed later. For example, you will never store your
13079     * current position on screen because that will be computed again when a
13080     * new instance of the view is placed in its view hierarchy.
13081     * <p>
13082     * Some examples of things you may store here: the current cursor position
13083     * in a text view (but usually not the text itself since that is stored in a
13084     * content provider or other persistent storage), the currently selected
13085     * item in a list view.
13086     *
13087     * @return Returns a Parcelable object containing the view's current dynamic
13088     *         state, or null if there is nothing interesting to save. The
13089     *         default implementation returns null.
13090     * @see #onRestoreInstanceState(android.os.Parcelable)
13091     * @see #saveHierarchyState(android.util.SparseArray)
13092     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13093     * @see #setSaveEnabled(boolean)
13094     */
13095    protected Parcelable onSaveInstanceState() {
13096        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13097        return BaseSavedState.EMPTY_STATE;
13098    }
13099
13100    /**
13101     * Restore this view hierarchy's frozen state from the given container.
13102     *
13103     * @param container The SparseArray which holds previously frozen states.
13104     *
13105     * @see #saveHierarchyState(android.util.SparseArray)
13106     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13107     * @see #onRestoreInstanceState(android.os.Parcelable)
13108     */
13109    public void restoreHierarchyState(SparseArray<Parcelable> container) {
13110        dispatchRestoreInstanceState(container);
13111    }
13112
13113    /**
13114     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
13115     * state for this view and its children. May be overridden to modify how restoring
13116     * happens to a view's children; for example, some views may want to not store state
13117     * for their children.
13118     *
13119     * @param container The SparseArray which holds previously saved state.
13120     *
13121     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13122     * @see #restoreHierarchyState(android.util.SparseArray)
13123     * @see #onRestoreInstanceState(android.os.Parcelable)
13124     */
13125    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
13126        if (mID != NO_ID) {
13127            Parcelable state = container.get(mID);
13128            if (state != null) {
13129                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
13130                // + ": " + state);
13131                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13132                onRestoreInstanceState(state);
13133                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13134                    throw new IllegalStateException(
13135                            "Derived class did not call super.onRestoreInstanceState()");
13136                }
13137            }
13138        }
13139    }
13140
13141    /**
13142     * Hook allowing a view to re-apply a representation of its internal state that had previously
13143     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
13144     * null state.
13145     *
13146     * @param state The frozen state that had previously been returned by
13147     *        {@link #onSaveInstanceState}.
13148     *
13149     * @see #onSaveInstanceState()
13150     * @see #restoreHierarchyState(android.util.SparseArray)
13151     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13152     */
13153    protected void onRestoreInstanceState(Parcelable state) {
13154        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13155        if (state != BaseSavedState.EMPTY_STATE && state != null) {
13156            throw new IllegalArgumentException("Wrong state class, expecting View State but "
13157                    + "received " + state.getClass().toString() + " instead. This usually happens "
13158                    + "when two views of different type have the same id in the same hierarchy. "
13159                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
13160                    + "other views do not use the same id.");
13161        }
13162    }
13163
13164    /**
13165     * <p>Return the time at which the drawing of the view hierarchy started.</p>
13166     *
13167     * @return the drawing start time in milliseconds
13168     */
13169    public long getDrawingTime() {
13170        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
13171    }
13172
13173    /**
13174     * <p>Enables or disables the duplication of the parent's state into this view. When
13175     * duplication is enabled, this view gets its drawable state from its parent rather
13176     * than from its own internal properties.</p>
13177     *
13178     * <p>Note: in the current implementation, setting this property to true after the
13179     * view was added to a ViewGroup might have no effect at all. This property should
13180     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
13181     *
13182     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
13183     * property is enabled, an exception will be thrown.</p>
13184     *
13185     * <p>Note: if the child view uses and updates additionnal states which are unknown to the
13186     * parent, these states should not be affected by this method.</p>
13187     *
13188     * @param enabled True to enable duplication of the parent's drawable state, false
13189     *                to disable it.
13190     *
13191     * @see #getDrawableState()
13192     * @see #isDuplicateParentStateEnabled()
13193     */
13194    public void setDuplicateParentStateEnabled(boolean enabled) {
13195        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
13196    }
13197
13198    /**
13199     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
13200     *
13201     * @return True if this view's drawable state is duplicated from the parent,
13202     *         false otherwise
13203     *
13204     * @see #getDrawableState()
13205     * @see #setDuplicateParentStateEnabled(boolean)
13206     */
13207    public boolean isDuplicateParentStateEnabled() {
13208        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
13209    }
13210
13211    /**
13212     * <p>Specifies the type of layer backing this view. The layer can be
13213     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13214     * {@link #LAYER_TYPE_HARDWARE}.</p>
13215     *
13216     * <p>A layer is associated with an optional {@link android.graphics.Paint}
13217     * instance that controls how the layer is composed on screen. The following
13218     * properties of the paint are taken into account when composing the layer:</p>
13219     * <ul>
13220     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13221     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13222     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13223     * </ul>
13224     *
13225     * <p>If this view has an alpha value set to < 1.0 by calling
13226     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superceded
13227     * by this view's alpha value.</p>
13228     *
13229     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
13230     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
13231     * for more information on when and how to use layers.</p>
13232     *
13233     * @param layerType The type of layer to use with this view, must be one of
13234     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13235     *        {@link #LAYER_TYPE_HARDWARE}
13236     * @param paint The paint used to compose the layer. This argument is optional
13237     *        and can be null. It is ignored when the layer type is
13238     *        {@link #LAYER_TYPE_NONE}
13239     *
13240     * @see #getLayerType()
13241     * @see #LAYER_TYPE_NONE
13242     * @see #LAYER_TYPE_SOFTWARE
13243     * @see #LAYER_TYPE_HARDWARE
13244     * @see #setAlpha(float)
13245     *
13246     * @attr ref android.R.styleable#View_layerType
13247     */
13248    public void setLayerType(int layerType, Paint paint) {
13249        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
13250            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
13251                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
13252        }
13253
13254        if (layerType == mLayerType) {
13255            setLayerPaint(paint);
13256            return;
13257        }
13258
13259        // Destroy any previous software drawing cache if needed
13260        switch (mLayerType) {
13261            case LAYER_TYPE_HARDWARE:
13262                destroyLayer(false);
13263                // fall through - non-accelerated views may use software layer mechanism instead
13264            case LAYER_TYPE_SOFTWARE:
13265                destroyDrawingCache();
13266                break;
13267            default:
13268                break;
13269        }
13270
13271        mLayerType = layerType;
13272        final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
13273        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
13274        mLocalDirtyRect = layerDisabled ? null : new Rect();
13275
13276        invalidateParentCaches();
13277        invalidate(true);
13278    }
13279
13280    /**
13281     * Updates the {@link Paint} object used with the current layer (used only if the current
13282     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
13283     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
13284     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
13285     * ensure that the view gets redrawn immediately.
13286     *
13287     * <p>A layer is associated with an optional {@link android.graphics.Paint}
13288     * instance that controls how the layer is composed on screen. The following
13289     * properties of the paint are taken into account when composing the layer:</p>
13290     * <ul>
13291     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13292     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13293     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13294     * </ul>
13295     *
13296     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
13297     * alpha value of the layer's paint is superceded by this view's alpha value.</p>
13298     *
13299     * @param paint The paint used to compose the layer. This argument is optional
13300     *        and can be null. It is ignored when the layer type is
13301     *        {@link #LAYER_TYPE_NONE}
13302     *
13303     * @see #setLayerType(int, android.graphics.Paint)
13304     */
13305    public void setLayerPaint(Paint paint) {
13306        int layerType = getLayerType();
13307        if (layerType != LAYER_TYPE_NONE) {
13308            mLayerPaint = paint == null ? new Paint() : paint;
13309            if (layerType == LAYER_TYPE_HARDWARE) {
13310                HardwareLayer layer = getHardwareLayer();
13311                if (layer != null) {
13312                    layer.setLayerPaint(mLayerPaint);
13313                }
13314                invalidateViewProperty(false, false);
13315            } else {
13316                invalidate();
13317            }
13318        }
13319    }
13320
13321    /**
13322     * Indicates whether this view has a static layer. A view with layer type
13323     * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
13324     * dynamic.
13325     */
13326    boolean hasStaticLayer() {
13327        return true;
13328    }
13329
13330    /**
13331     * Indicates what type of layer is currently associated with this view. By default
13332     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
13333     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
13334     * for more information on the different types of layers.
13335     *
13336     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13337     *         {@link #LAYER_TYPE_HARDWARE}
13338     *
13339     * @see #setLayerType(int, android.graphics.Paint)
13340     * @see #buildLayer()
13341     * @see #LAYER_TYPE_NONE
13342     * @see #LAYER_TYPE_SOFTWARE
13343     * @see #LAYER_TYPE_HARDWARE
13344     */
13345    public int getLayerType() {
13346        return mLayerType;
13347    }
13348
13349    /**
13350     * Forces this view's layer to be created and this view to be rendered
13351     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
13352     * invoking this method will have no effect.
13353     *
13354     * This method can for instance be used to render a view into its layer before
13355     * starting an animation. If this view is complex, rendering into the layer
13356     * before starting the animation will avoid skipping frames.
13357     *
13358     * @throws IllegalStateException If this view is not attached to a window
13359     *
13360     * @see #setLayerType(int, android.graphics.Paint)
13361     */
13362    public void buildLayer() {
13363        if (mLayerType == LAYER_TYPE_NONE) return;
13364
13365        final AttachInfo attachInfo = mAttachInfo;
13366        if (attachInfo == null) {
13367            throw new IllegalStateException("This view must be attached to a window first");
13368        }
13369
13370        switch (mLayerType) {
13371            case LAYER_TYPE_HARDWARE:
13372                getHardwareLayer();
13373                // TODO: We need a better way to handle this case
13374                // If views have registered pre-draw listeners they need
13375                // to be notified before we build the layer. Those listeners
13376                // may however rely on other events to happen first so we
13377                // cannot just invoke them here until they don't cancel the
13378                // current frame
13379                if (!attachInfo.mTreeObserver.hasOnPreDrawListeners()) {
13380                    attachInfo.mViewRootImpl.dispatchFlushHardwareLayerUpdates();
13381                }
13382                break;
13383            case LAYER_TYPE_SOFTWARE:
13384                buildDrawingCache(true);
13385                break;
13386        }
13387    }
13388
13389    /**
13390     * <p>Returns a hardware layer that can be used to draw this view again
13391     * without executing its draw method.</p>
13392     *
13393     * @return A HardwareLayer ready to render, or null if an error occurred.
13394     */
13395    HardwareLayer getHardwareLayer() {
13396        if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
13397                !mAttachInfo.mHardwareRenderer.isEnabled()) {
13398            return null;
13399        }
13400
13401        final int width = mRight - mLeft;
13402        final int height = mBottom - mTop;
13403
13404        if (width == 0 || height == 0) {
13405            return null;
13406        }
13407
13408        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
13409            if (mHardwareLayer == null) {
13410                mHardwareLayer = mAttachInfo.mHardwareRenderer.createDisplayListLayer(
13411                        width, height);
13412                mLocalDirtyRect.set(0, 0, width, height);
13413            } else if (mHardwareLayer.isValid()) {
13414                // This should not be necessary but applications that change
13415                // the parameters of their background drawable without calling
13416                // this.setBackground(Drawable) can leave the view in a bad state
13417                // (for instance isOpaque() returns true, but the background is
13418                // not opaque.)
13419                computeOpaqueFlags();
13420
13421                if (mHardwareLayer.prepare(width, height, isOpaque())) {
13422                    mLocalDirtyRect.set(0, 0, width, height);
13423                }
13424            }
13425
13426            // The layer is not valid if the underlying GPU resources cannot be allocated
13427            mHardwareLayer.flushChanges();
13428            if (!mHardwareLayer.isValid()) {
13429                return null;
13430            }
13431
13432            mHardwareLayer.setLayerPaint(mLayerPaint);
13433            RenderNode displayList = mHardwareLayer.startRecording();
13434            updateDisplayListIfDirty(displayList, true);
13435            mHardwareLayer.endRecording(mLocalDirtyRect);
13436            mLocalDirtyRect.setEmpty();
13437        }
13438
13439        return mHardwareLayer;
13440    }
13441
13442    /**
13443     * Destroys this View's hardware layer if possible.
13444     *
13445     * @return True if the layer was destroyed, false otherwise.
13446     *
13447     * @see #setLayerType(int, android.graphics.Paint)
13448     * @see #LAYER_TYPE_HARDWARE
13449     */
13450    boolean destroyLayer(boolean valid) {
13451        if (mHardwareLayer != null) {
13452            mHardwareLayer.destroy();
13453            mHardwareLayer = null;
13454
13455            invalidate(true);
13456            invalidateParentCaches();
13457            return true;
13458        }
13459        return false;
13460    }
13461
13462    /**
13463     * Destroys all hardware rendering resources. This method is invoked
13464     * when the system needs to reclaim resources. Upon execution of this
13465     * method, you should free any OpenGL resources created by the view.
13466     *
13467     * Note: you <strong>must</strong> call
13468     * <code>super.destroyHardwareResources()</code> when overriding
13469     * this method.
13470     *
13471     * @hide
13472     */
13473    protected void destroyHardwareResources() {
13474        resetDisplayList();
13475        destroyLayer(true);
13476    }
13477
13478    /**
13479     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
13480     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
13481     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
13482     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
13483     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
13484     * null.</p>
13485     *
13486     * <p>Enabling the drawing cache is similar to
13487     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
13488     * acceleration is turned off. When hardware acceleration is turned on, enabling the
13489     * drawing cache has no effect on rendering because the system uses a different mechanism
13490     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
13491     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
13492     * for information on how to enable software and hardware layers.</p>
13493     *
13494     * <p>This API can be used to manually generate
13495     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
13496     * {@link #getDrawingCache()}.</p>
13497     *
13498     * @param enabled true to enable the drawing cache, false otherwise
13499     *
13500     * @see #isDrawingCacheEnabled()
13501     * @see #getDrawingCache()
13502     * @see #buildDrawingCache()
13503     * @see #setLayerType(int, android.graphics.Paint)
13504     */
13505    public void setDrawingCacheEnabled(boolean enabled) {
13506        mCachingFailed = false;
13507        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
13508    }
13509
13510    /**
13511     * <p>Indicates whether the drawing cache is enabled for this view.</p>
13512     *
13513     * @return true if the drawing cache is enabled
13514     *
13515     * @see #setDrawingCacheEnabled(boolean)
13516     * @see #getDrawingCache()
13517     */
13518    @ViewDebug.ExportedProperty(category = "drawing")
13519    public boolean isDrawingCacheEnabled() {
13520        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
13521    }
13522
13523    /**
13524     * Debugging utility which recursively outputs the dirty state of a view and its
13525     * descendants.
13526     *
13527     * @hide
13528     */
13529    @SuppressWarnings({"UnusedDeclaration"})
13530    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
13531        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
13532                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
13533                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
13534                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
13535        if (clear) {
13536            mPrivateFlags &= clearMask;
13537        }
13538        if (this instanceof ViewGroup) {
13539            ViewGroup parent = (ViewGroup) this;
13540            final int count = parent.getChildCount();
13541            for (int i = 0; i < count; i++) {
13542                final View child = parent.getChildAt(i);
13543                child.outputDirtyFlags(indent + "  ", clear, clearMask);
13544            }
13545        }
13546    }
13547
13548    /**
13549     * This method is used by ViewGroup to cause its children to restore or recreate their
13550     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
13551     * to recreate its own display list, which would happen if it went through the normal
13552     * draw/dispatchDraw mechanisms.
13553     *
13554     * @hide
13555     */
13556    protected void dispatchGetDisplayList() {}
13557
13558    /**
13559     * A view that is not attached or hardware accelerated cannot create a display list.
13560     * This method checks these conditions and returns the appropriate result.
13561     *
13562     * @return true if view has the ability to create a display list, false otherwise.
13563     *
13564     * @hide
13565     */
13566    public boolean canHaveDisplayList() {
13567        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
13568    }
13569
13570    /**
13571     * Returns a DisplayList. If the incoming displayList is null, one will be created.
13572     * Otherwise, the same display list will be returned (after having been rendered into
13573     * along the way, depending on the invalidation state of the view).
13574     *
13575     * @param renderNode The previous version of this displayList, could be null.
13576     * @param isLayer Whether the requester of the display list is a layer. If so,
13577     * the view will avoid creating a layer inside the resulting display list.
13578     * @return A new or reused DisplayList object.
13579     */
13580    private void updateDisplayListIfDirty(@NonNull RenderNode renderNode, boolean isLayer) {
13581        if (renderNode == null) {
13582            throw new IllegalArgumentException("RenderNode must not be null");
13583        }
13584        if (!canHaveDisplayList()) {
13585            // can't populate RenderNode, don't try
13586            return;
13587        }
13588
13589        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
13590                || !renderNode.isValid()
13591                || (!isLayer && mRecreateDisplayList)) {
13592            // Don't need to recreate the display list, just need to tell our
13593            // children to restore/recreate theirs
13594            if (renderNode.isValid()
13595                    && !isLayer
13596                    && !mRecreateDisplayList) {
13597                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
13598                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13599                dispatchGetDisplayList();
13600
13601                return; // no work needed
13602            }
13603
13604            if (!isLayer) {
13605                // If we got here, we're recreating it. Mark it as such to ensure that
13606                // we copy in child display lists into ours in drawChild()
13607                mRecreateDisplayList = true;
13608            }
13609
13610            boolean caching = false;
13611            int width = mRight - mLeft;
13612            int height = mBottom - mTop;
13613            int layerType = getLayerType();
13614
13615            final HardwareCanvas canvas = renderNode.start(width, height);
13616
13617            try {
13618                if (!isLayer && layerType != LAYER_TYPE_NONE) {
13619                    if (layerType == LAYER_TYPE_HARDWARE) {
13620                        final HardwareLayer layer = getHardwareLayer();
13621                        if (layer != null && layer.isValid()) {
13622                            canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
13623                        } else {
13624                            canvas.saveLayer(0, 0, mRight - mLeft, mBottom - mTop, mLayerPaint,
13625                                    Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
13626                                            Canvas.CLIP_TO_LAYER_SAVE_FLAG);
13627                        }
13628                        caching = true;
13629                    } else {
13630                        buildDrawingCache(true);
13631                        Bitmap cache = getDrawingCache(true);
13632                        if (cache != null) {
13633                            canvas.drawBitmap(cache, 0, 0, mLayerPaint);
13634                            caching = true;
13635                        }
13636                    }
13637                } else {
13638
13639                    computeScroll();
13640
13641                    canvas.translate(-mScrollX, -mScrollY);
13642                    if (!isLayer) {
13643                        mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
13644                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13645                    }
13646
13647                    // Fast path for layouts with no backgrounds
13648                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13649                        dispatchDraw(canvas);
13650                        if (mOverlay != null && !mOverlay.isEmpty()) {
13651                            mOverlay.getOverlayView().draw(canvas);
13652                        }
13653                    } else {
13654                        draw(canvas);
13655                    }
13656                }
13657            } finally {
13658                renderNode.end(canvas);
13659                renderNode.setCaching(caching);
13660                if (isLayer) {
13661                    renderNode.setLeftTopRightBottom(0, 0, width, height);
13662                } else {
13663                    setDisplayListProperties(renderNode);
13664                }
13665            }
13666        } else if (!isLayer) {
13667            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
13668            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13669        }
13670    }
13671
13672    /**
13673     * Returns a RenderNode with View draw content recorded, which can be
13674     * used to draw this view again without executing its draw method.
13675     *
13676     * @return A RenderNode ready to replay, or null if caching is not enabled.
13677     *
13678     * @hide
13679     */
13680    public RenderNode getDisplayList() {
13681        updateDisplayListIfDirty(mRenderNode, false);
13682        return mRenderNode;
13683    }
13684
13685    private void resetDisplayList() {
13686        if (mRenderNode.isValid()) {
13687            mRenderNode.destroyDisplayListData();
13688        }
13689
13690        if (mBackgroundDisplayList != null && mBackgroundDisplayList.isValid()) {
13691            mBackgroundDisplayList.destroyDisplayListData();
13692        }
13693    }
13694
13695    /**
13696     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
13697     *
13698     * @return A non-scaled bitmap representing this view or null if cache is disabled.
13699     *
13700     * @see #getDrawingCache(boolean)
13701     */
13702    public Bitmap getDrawingCache() {
13703        return getDrawingCache(false);
13704    }
13705
13706    /**
13707     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
13708     * is null when caching is disabled. If caching is enabled and the cache is not ready,
13709     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
13710     * draw from the cache when the cache is enabled. To benefit from the cache, you must
13711     * request the drawing cache by calling this method and draw it on screen if the
13712     * returned bitmap is not null.</p>
13713     *
13714     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
13715     * this method will create a bitmap of the same size as this view. Because this bitmap
13716     * will be drawn scaled by the parent ViewGroup, the result on screen might show
13717     * scaling artifacts. To avoid such artifacts, you should call this method by setting
13718     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
13719     * size than the view. This implies that your application must be able to handle this
13720     * size.</p>
13721     *
13722     * @param autoScale Indicates whether the generated bitmap should be scaled based on
13723     *        the current density of the screen when the application is in compatibility
13724     *        mode.
13725     *
13726     * @return A bitmap representing this view or null if cache is disabled.
13727     *
13728     * @see #setDrawingCacheEnabled(boolean)
13729     * @see #isDrawingCacheEnabled()
13730     * @see #buildDrawingCache(boolean)
13731     * @see #destroyDrawingCache()
13732     */
13733    public Bitmap getDrawingCache(boolean autoScale) {
13734        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
13735            return null;
13736        }
13737        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
13738            buildDrawingCache(autoScale);
13739        }
13740        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
13741    }
13742
13743    /**
13744     * <p>Frees the resources used by the drawing cache. If you call
13745     * {@link #buildDrawingCache()} manually without calling
13746     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
13747     * should cleanup the cache with this method afterwards.</p>
13748     *
13749     * @see #setDrawingCacheEnabled(boolean)
13750     * @see #buildDrawingCache()
13751     * @see #getDrawingCache()
13752     */
13753    public void destroyDrawingCache() {
13754        if (mDrawingCache != null) {
13755            mDrawingCache.recycle();
13756            mDrawingCache = null;
13757        }
13758        if (mUnscaledDrawingCache != null) {
13759            mUnscaledDrawingCache.recycle();
13760            mUnscaledDrawingCache = null;
13761        }
13762    }
13763
13764    /**
13765     * Setting a solid background color for the drawing cache's bitmaps will improve
13766     * performance and memory usage. Note, though that this should only be used if this
13767     * view will always be drawn on top of a solid color.
13768     *
13769     * @param color The background color to use for the drawing cache's bitmap
13770     *
13771     * @see #setDrawingCacheEnabled(boolean)
13772     * @see #buildDrawingCache()
13773     * @see #getDrawingCache()
13774     */
13775    public void setDrawingCacheBackgroundColor(int color) {
13776        if (color != mDrawingCacheBackgroundColor) {
13777            mDrawingCacheBackgroundColor = color;
13778            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13779        }
13780    }
13781
13782    /**
13783     * @see #setDrawingCacheBackgroundColor(int)
13784     *
13785     * @return The background color to used for the drawing cache's bitmap
13786     */
13787    public int getDrawingCacheBackgroundColor() {
13788        return mDrawingCacheBackgroundColor;
13789    }
13790
13791    /**
13792     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
13793     *
13794     * @see #buildDrawingCache(boolean)
13795     */
13796    public void buildDrawingCache() {
13797        buildDrawingCache(false);
13798    }
13799
13800    /**
13801     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
13802     *
13803     * <p>If you call {@link #buildDrawingCache()} manually without calling
13804     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
13805     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
13806     *
13807     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
13808     * this method will create a bitmap of the same size as this view. Because this bitmap
13809     * will be drawn scaled by the parent ViewGroup, the result on screen might show
13810     * scaling artifacts. To avoid such artifacts, you should call this method by setting
13811     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
13812     * size than the view. This implies that your application must be able to handle this
13813     * size.</p>
13814     *
13815     * <p>You should avoid calling this method when hardware acceleration is enabled. If
13816     * you do not need the drawing cache bitmap, calling this method will increase memory
13817     * usage and cause the view to be rendered in software once, thus negatively impacting
13818     * performance.</p>
13819     *
13820     * @see #getDrawingCache()
13821     * @see #destroyDrawingCache()
13822     */
13823    public void buildDrawingCache(boolean autoScale) {
13824        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
13825                mDrawingCache == null : mUnscaledDrawingCache == null)) {
13826            mCachingFailed = false;
13827
13828            int width = mRight - mLeft;
13829            int height = mBottom - mTop;
13830
13831            final AttachInfo attachInfo = mAttachInfo;
13832            final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
13833
13834            if (autoScale && scalingRequired) {
13835                width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
13836                height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
13837            }
13838
13839            final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
13840            final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
13841            final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
13842
13843            final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
13844            final long drawingCacheSize =
13845                    ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
13846            if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
13847                if (width > 0 && height > 0) {
13848                    Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
13849                            + projectedBitmapSize + " bytes, only "
13850                            + drawingCacheSize + " available");
13851                }
13852                destroyDrawingCache();
13853                mCachingFailed = true;
13854                return;
13855            }
13856
13857            boolean clear = true;
13858            Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
13859
13860            if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
13861                Bitmap.Config quality;
13862                if (!opaque) {
13863                    // Never pick ARGB_4444 because it looks awful
13864                    // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
13865                    switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
13866                        case DRAWING_CACHE_QUALITY_AUTO:
13867                        case DRAWING_CACHE_QUALITY_LOW:
13868                        case DRAWING_CACHE_QUALITY_HIGH:
13869                        default:
13870                            quality = Bitmap.Config.ARGB_8888;
13871                            break;
13872                    }
13873                } else {
13874                    // Optimization for translucent windows
13875                    // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
13876                    quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
13877                }
13878
13879                // Try to cleanup memory
13880                if (bitmap != null) bitmap.recycle();
13881
13882                try {
13883                    bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
13884                            width, height, quality);
13885                    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
13886                    if (autoScale) {
13887                        mDrawingCache = bitmap;
13888                    } else {
13889                        mUnscaledDrawingCache = bitmap;
13890                    }
13891                    if (opaque && use32BitCache) bitmap.setHasAlpha(false);
13892                } catch (OutOfMemoryError e) {
13893                    // If there is not enough memory to create the bitmap cache, just
13894                    // ignore the issue as bitmap caches are not required to draw the
13895                    // view hierarchy
13896                    if (autoScale) {
13897                        mDrawingCache = null;
13898                    } else {
13899                        mUnscaledDrawingCache = null;
13900                    }
13901                    mCachingFailed = true;
13902                    return;
13903                }
13904
13905                clear = drawingCacheBackgroundColor != 0;
13906            }
13907
13908            Canvas canvas;
13909            if (attachInfo != null) {
13910                canvas = attachInfo.mCanvas;
13911                if (canvas == null) {
13912                    canvas = new Canvas();
13913                }
13914                canvas.setBitmap(bitmap);
13915                // Temporarily clobber the cached Canvas in case one of our children
13916                // is also using a drawing cache. Without this, the children would
13917                // steal the canvas by attaching their own bitmap to it and bad, bad
13918                // thing would happen (invisible views, corrupted drawings, etc.)
13919                attachInfo.mCanvas = null;
13920            } else {
13921                // This case should hopefully never or seldom happen
13922                canvas = new Canvas(bitmap);
13923            }
13924
13925            if (clear) {
13926                bitmap.eraseColor(drawingCacheBackgroundColor);
13927            }
13928
13929            computeScroll();
13930            final int restoreCount = canvas.save();
13931
13932            if (autoScale && scalingRequired) {
13933                final float scale = attachInfo.mApplicationScale;
13934                canvas.scale(scale, scale);
13935            }
13936
13937            canvas.translate(-mScrollX, -mScrollY);
13938
13939            mPrivateFlags |= PFLAG_DRAWN;
13940            if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
13941                    mLayerType != LAYER_TYPE_NONE) {
13942                mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
13943            }
13944
13945            // Fast path for layouts with no backgrounds
13946            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13947                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13948                dispatchDraw(canvas);
13949                if (mOverlay != null && !mOverlay.isEmpty()) {
13950                    mOverlay.getOverlayView().draw(canvas);
13951                }
13952            } else {
13953                draw(canvas);
13954            }
13955
13956            canvas.restoreToCount(restoreCount);
13957            canvas.setBitmap(null);
13958
13959            if (attachInfo != null) {
13960                // Restore the cached Canvas for our siblings
13961                attachInfo.mCanvas = canvas;
13962            }
13963        }
13964    }
13965
13966    /**
13967     * Create a snapshot of the view into a bitmap.  We should probably make
13968     * some form of this public, but should think about the API.
13969     */
13970    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
13971        int width = mRight - mLeft;
13972        int height = mBottom - mTop;
13973
13974        final AttachInfo attachInfo = mAttachInfo;
13975        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
13976        width = (int) ((width * scale) + 0.5f);
13977        height = (int) ((height * scale) + 0.5f);
13978
13979        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
13980                width > 0 ? width : 1, height > 0 ? height : 1, quality);
13981        if (bitmap == null) {
13982            throw new OutOfMemoryError();
13983        }
13984
13985        Resources resources = getResources();
13986        if (resources != null) {
13987            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
13988        }
13989
13990        Canvas canvas;
13991        if (attachInfo != null) {
13992            canvas = attachInfo.mCanvas;
13993            if (canvas == null) {
13994                canvas = new Canvas();
13995            }
13996            canvas.setBitmap(bitmap);
13997            // Temporarily clobber the cached Canvas in case one of our children
13998            // is also using a drawing cache. Without this, the children would
13999            // steal the canvas by attaching their own bitmap to it and bad, bad
14000            // things would happen (invisible views, corrupted drawings, etc.)
14001            attachInfo.mCanvas = null;
14002        } else {
14003            // This case should hopefully never or seldom happen
14004            canvas = new Canvas(bitmap);
14005        }
14006
14007        if ((backgroundColor & 0xff000000) != 0) {
14008            bitmap.eraseColor(backgroundColor);
14009        }
14010
14011        computeScroll();
14012        final int restoreCount = canvas.save();
14013        canvas.scale(scale, scale);
14014        canvas.translate(-mScrollX, -mScrollY);
14015
14016        // Temporarily remove the dirty mask
14017        int flags = mPrivateFlags;
14018        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14019
14020        // Fast path for layouts with no backgrounds
14021        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14022            dispatchDraw(canvas);
14023            if (mOverlay != null && !mOverlay.isEmpty()) {
14024                mOverlay.getOverlayView().draw(canvas);
14025            }
14026        } else {
14027            draw(canvas);
14028        }
14029
14030        mPrivateFlags = flags;
14031
14032        canvas.restoreToCount(restoreCount);
14033        canvas.setBitmap(null);
14034
14035        if (attachInfo != null) {
14036            // Restore the cached Canvas for our siblings
14037            attachInfo.mCanvas = canvas;
14038        }
14039
14040        return bitmap;
14041    }
14042
14043    /**
14044     * Indicates whether this View is currently in edit mode. A View is usually
14045     * in edit mode when displayed within a developer tool. For instance, if
14046     * this View is being drawn by a visual user interface builder, this method
14047     * should return true.
14048     *
14049     * Subclasses should check the return value of this method to provide
14050     * different behaviors if their normal behavior might interfere with the
14051     * host environment. For instance: the class spawns a thread in its
14052     * constructor, the drawing code relies on device-specific features, etc.
14053     *
14054     * This method is usually checked in the drawing code of custom widgets.
14055     *
14056     * @return True if this View is in edit mode, false otherwise.
14057     */
14058    public boolean isInEditMode() {
14059        return false;
14060    }
14061
14062    /**
14063     * If the View draws content inside its padding and enables fading edges,
14064     * it needs to support padding offsets. Padding offsets are added to the
14065     * fading edges to extend the length of the fade so that it covers pixels
14066     * drawn inside the padding.
14067     *
14068     * Subclasses of this class should override this method if they need
14069     * to draw content inside the padding.
14070     *
14071     * @return True if padding offset must be applied, false otherwise.
14072     *
14073     * @see #getLeftPaddingOffset()
14074     * @see #getRightPaddingOffset()
14075     * @see #getTopPaddingOffset()
14076     * @see #getBottomPaddingOffset()
14077     *
14078     * @since CURRENT
14079     */
14080    protected boolean isPaddingOffsetRequired() {
14081        return false;
14082    }
14083
14084    /**
14085     * Amount by which to extend the left fading region. Called only when
14086     * {@link #isPaddingOffsetRequired()} returns true.
14087     *
14088     * @return The left padding offset in pixels.
14089     *
14090     * @see #isPaddingOffsetRequired()
14091     *
14092     * @since CURRENT
14093     */
14094    protected int getLeftPaddingOffset() {
14095        return 0;
14096    }
14097
14098    /**
14099     * Amount by which to extend the right fading region. Called only when
14100     * {@link #isPaddingOffsetRequired()} returns true.
14101     *
14102     * @return The right padding offset in pixels.
14103     *
14104     * @see #isPaddingOffsetRequired()
14105     *
14106     * @since CURRENT
14107     */
14108    protected int getRightPaddingOffset() {
14109        return 0;
14110    }
14111
14112    /**
14113     * Amount by which to extend the top fading region. Called only when
14114     * {@link #isPaddingOffsetRequired()} returns true.
14115     *
14116     * @return The top padding offset in pixels.
14117     *
14118     * @see #isPaddingOffsetRequired()
14119     *
14120     * @since CURRENT
14121     */
14122    protected int getTopPaddingOffset() {
14123        return 0;
14124    }
14125
14126    /**
14127     * Amount by which to extend the bottom fading region. Called only when
14128     * {@link #isPaddingOffsetRequired()} returns true.
14129     *
14130     * @return The bottom padding offset in pixels.
14131     *
14132     * @see #isPaddingOffsetRequired()
14133     *
14134     * @since CURRENT
14135     */
14136    protected int getBottomPaddingOffset() {
14137        return 0;
14138    }
14139
14140    /**
14141     * @hide
14142     * @param offsetRequired
14143     */
14144    protected int getFadeTop(boolean offsetRequired) {
14145        int top = mPaddingTop;
14146        if (offsetRequired) top += getTopPaddingOffset();
14147        return top;
14148    }
14149
14150    /**
14151     * @hide
14152     * @param offsetRequired
14153     */
14154    protected int getFadeHeight(boolean offsetRequired) {
14155        int padding = mPaddingTop;
14156        if (offsetRequired) padding += getTopPaddingOffset();
14157        return mBottom - mTop - mPaddingBottom - padding;
14158    }
14159
14160    /**
14161     * <p>Indicates whether this view is attached to a hardware accelerated
14162     * window or not.</p>
14163     *
14164     * <p>Even if this method returns true, it does not mean that every call
14165     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
14166     * accelerated {@link android.graphics.Canvas}. For instance, if this view
14167     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
14168     * window is hardware accelerated,
14169     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
14170     * return false, and this method will return true.</p>
14171     *
14172     * @return True if the view is attached to a window and the window is
14173     *         hardware accelerated; false in any other case.
14174     */
14175    public boolean isHardwareAccelerated() {
14176        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14177    }
14178
14179    /**
14180     * Sets a rectangular area on this view to which the view will be clipped
14181     * when it is drawn. Setting the value to null will remove the clip bounds
14182     * and the view will draw normally, using its full bounds.
14183     *
14184     * @param clipBounds The rectangular area, in the local coordinates of
14185     * this view, to which future drawing operations will be clipped.
14186     */
14187    public void setClipBounds(Rect clipBounds) {
14188        if (clipBounds != null) {
14189            if (clipBounds.equals(mClipBounds)) {
14190                return;
14191            }
14192            if (mClipBounds == null) {
14193                invalidate();
14194                mClipBounds = new Rect(clipBounds);
14195            } else {
14196                invalidate(Math.min(mClipBounds.left, clipBounds.left),
14197                        Math.min(mClipBounds.top, clipBounds.top),
14198                        Math.max(mClipBounds.right, clipBounds.right),
14199                        Math.max(mClipBounds.bottom, clipBounds.bottom));
14200                mClipBounds.set(clipBounds);
14201            }
14202        } else {
14203            if (mClipBounds != null) {
14204                invalidate();
14205                mClipBounds = null;
14206            }
14207        }
14208    }
14209
14210    /**
14211     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
14212     *
14213     * @return A copy of the current clip bounds if clip bounds are set,
14214     * otherwise null.
14215     */
14216    public Rect getClipBounds() {
14217        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
14218    }
14219
14220    /**
14221     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
14222     * case of an active Animation being run on the view.
14223     */
14224    private boolean drawAnimation(ViewGroup parent, long drawingTime,
14225            Animation a, boolean scalingRequired) {
14226        Transformation invalidationTransform;
14227        final int flags = parent.mGroupFlags;
14228        final boolean initialized = a.isInitialized();
14229        if (!initialized) {
14230            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
14231            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
14232            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
14233            onAnimationStart();
14234        }
14235
14236        final Transformation t = parent.getChildTransformation();
14237        boolean more = a.getTransformation(drawingTime, t, 1f);
14238        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
14239            if (parent.mInvalidationTransformation == null) {
14240                parent.mInvalidationTransformation = new Transformation();
14241            }
14242            invalidationTransform = parent.mInvalidationTransformation;
14243            a.getTransformation(drawingTime, invalidationTransform, 1f);
14244        } else {
14245            invalidationTransform = t;
14246        }
14247
14248        if (more) {
14249            if (!a.willChangeBounds()) {
14250                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
14251                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
14252                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
14253                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
14254                    // The child need to draw an animation, potentially offscreen, so
14255                    // make sure we do not cancel invalidate requests
14256                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14257                    parent.invalidate(mLeft, mTop, mRight, mBottom);
14258                }
14259            } else {
14260                if (parent.mInvalidateRegion == null) {
14261                    parent.mInvalidateRegion = new RectF();
14262                }
14263                final RectF region = parent.mInvalidateRegion;
14264                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
14265                        invalidationTransform);
14266
14267                // The child need to draw an animation, potentially offscreen, so
14268                // make sure we do not cancel invalidate requests
14269                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14270
14271                final int left = mLeft + (int) region.left;
14272                final int top = mTop + (int) region.top;
14273                parent.invalidate(left, top, left + (int) (region.width() + .5f),
14274                        top + (int) (region.height() + .5f));
14275            }
14276        }
14277        return more;
14278    }
14279
14280    /**
14281     * This method is called by getDisplayList() when a display list is recorded for a View.
14282     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
14283     */
14284    void setDisplayListProperties(RenderNode renderNode) {
14285        if (renderNode != null) {
14286            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
14287            if (mParent instanceof ViewGroup) {
14288                renderNode.setClipToBounds(
14289                        (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
14290            }
14291            float alpha = 1;
14292            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
14293                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14294                ViewGroup parentVG = (ViewGroup) mParent;
14295                final Transformation t = parentVG.getChildTransformation();
14296                if (parentVG.getChildStaticTransformation(this, t)) {
14297                    final int transformType = t.getTransformationType();
14298                    if (transformType != Transformation.TYPE_IDENTITY) {
14299                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
14300                            alpha = t.getAlpha();
14301                        }
14302                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
14303                            renderNode.setStaticMatrix(t.getMatrix());
14304                        }
14305                    }
14306                }
14307            }
14308            if (mTransformationInfo != null) {
14309                alpha *= getFinalAlpha();
14310                if (alpha < 1) {
14311                    final int multipliedAlpha = (int) (255 * alpha);
14312                    if (onSetAlpha(multipliedAlpha)) {
14313                        alpha = 1;
14314                    }
14315                }
14316                renderNode.setAlpha(alpha);
14317            } else if (alpha < 1) {
14318                renderNode.setAlpha(alpha);
14319            }
14320        }
14321    }
14322
14323    /**
14324     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
14325     * This draw() method is an implementation detail and is not intended to be overridden or
14326     * to be called from anywhere else other than ViewGroup.drawChild().
14327     */
14328    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
14329        boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14330        boolean more = false;
14331        final boolean childHasIdentityMatrix = hasIdentityMatrix();
14332        final int flags = parent.mGroupFlags;
14333
14334        if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
14335            parent.getChildTransformation().clear();
14336            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14337        }
14338
14339        Transformation transformToApply = null;
14340        boolean concatMatrix = false;
14341
14342        boolean scalingRequired = false;
14343        boolean caching;
14344        int layerType = getLayerType();
14345
14346        final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
14347        if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
14348                (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
14349            caching = true;
14350            // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
14351            if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
14352        } else {
14353            caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
14354        }
14355
14356        final Animation a = getAnimation();
14357        if (a != null) {
14358            more = drawAnimation(parent, drawingTime, a, scalingRequired);
14359            concatMatrix = a.willChangeTransformationMatrix();
14360            if (concatMatrix) {
14361                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14362            }
14363            transformToApply = parent.getChildTransformation();
14364        } else {
14365            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
14366                // No longer animating: clear out old animation matrix
14367                mRenderNode.setAnimationMatrix(null);
14368                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14369            }
14370            if (!useDisplayListProperties &&
14371                    (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14372                final Transformation t = parent.getChildTransformation();
14373                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
14374                if (hasTransform) {
14375                    final int transformType = t.getTransformationType();
14376                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
14377                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
14378                }
14379            }
14380        }
14381
14382        concatMatrix |= !childHasIdentityMatrix;
14383
14384        // Sets the flag as early as possible to allow draw() implementations
14385        // to call invalidate() successfully when doing animations
14386        mPrivateFlags |= PFLAG_DRAWN;
14387
14388        if (!concatMatrix &&
14389                (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
14390                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
14391                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
14392                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
14393            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
14394            return more;
14395        }
14396        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
14397
14398        if (hardwareAccelerated) {
14399            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
14400            // retain the flag's value temporarily in the mRecreateDisplayList flag
14401            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
14402            mPrivateFlags &= ~PFLAG_INVALIDATED;
14403        }
14404
14405        RenderNode displayList = null;
14406        Bitmap cache = null;
14407        boolean hasDisplayList = false;
14408        if (caching) {
14409            if (!hardwareAccelerated) {
14410                if (layerType != LAYER_TYPE_NONE) {
14411                    layerType = LAYER_TYPE_SOFTWARE;
14412                    buildDrawingCache(true);
14413                }
14414                cache = getDrawingCache(true);
14415            } else {
14416                switch (layerType) {
14417                    case LAYER_TYPE_SOFTWARE:
14418                        if (useDisplayListProperties) {
14419                            hasDisplayList = canHaveDisplayList();
14420                        } else {
14421                            buildDrawingCache(true);
14422                            cache = getDrawingCache(true);
14423                        }
14424                        break;
14425                    case LAYER_TYPE_HARDWARE:
14426                        if (useDisplayListProperties) {
14427                            hasDisplayList = canHaveDisplayList();
14428                        }
14429                        break;
14430                    case LAYER_TYPE_NONE:
14431                        // Delay getting the display list until animation-driven alpha values are
14432                        // set up and possibly passed on to the view
14433                        hasDisplayList = canHaveDisplayList();
14434                        break;
14435                }
14436            }
14437        }
14438        useDisplayListProperties &= hasDisplayList;
14439        if (useDisplayListProperties) {
14440            displayList = getDisplayList();
14441            if (!displayList.isValid()) {
14442                // Uncommon, but possible. If a view is removed from the hierarchy during the call
14443                // to getDisplayList(), the display list will be marked invalid and we should not
14444                // try to use it again.
14445                displayList = null;
14446                hasDisplayList = false;
14447                useDisplayListProperties = false;
14448            }
14449        }
14450
14451        int sx = 0;
14452        int sy = 0;
14453        if (!hasDisplayList) {
14454            computeScroll();
14455            sx = mScrollX;
14456            sy = mScrollY;
14457        }
14458
14459        final boolean hasNoCache = cache == null || hasDisplayList;
14460        final boolean offsetForScroll = cache == null && !hasDisplayList &&
14461                layerType != LAYER_TYPE_HARDWARE;
14462
14463        int restoreTo = -1;
14464        if (!useDisplayListProperties || transformToApply != null) {
14465            restoreTo = canvas.save();
14466        }
14467        if (offsetForScroll) {
14468            canvas.translate(mLeft - sx, mTop - sy);
14469        } else {
14470            if (!useDisplayListProperties) {
14471                canvas.translate(mLeft, mTop);
14472            }
14473            if (scalingRequired) {
14474                if (useDisplayListProperties) {
14475                    // TODO: Might not need this if we put everything inside the DL
14476                    restoreTo = canvas.save();
14477                }
14478                // mAttachInfo cannot be null, otherwise scalingRequired == false
14479                final float scale = 1.0f / mAttachInfo.mApplicationScale;
14480                canvas.scale(scale, scale);
14481            }
14482        }
14483
14484        float alpha = useDisplayListProperties ? 1 : (getAlpha() * getTransitionAlpha());
14485        if (transformToApply != null || alpha < 1 ||  !hasIdentityMatrix() ||
14486                (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
14487            if (transformToApply != null || !childHasIdentityMatrix) {
14488                int transX = 0;
14489                int transY = 0;
14490
14491                if (offsetForScroll) {
14492                    transX = -sx;
14493                    transY = -sy;
14494                }
14495
14496                if (transformToApply != null) {
14497                    if (concatMatrix) {
14498                        if (useDisplayListProperties) {
14499                            displayList.setAnimationMatrix(transformToApply.getMatrix());
14500                        } else {
14501                            // Undo the scroll translation, apply the transformation matrix,
14502                            // then redo the scroll translate to get the correct result.
14503                            canvas.translate(-transX, -transY);
14504                            canvas.concat(transformToApply.getMatrix());
14505                            canvas.translate(transX, transY);
14506                        }
14507                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14508                    }
14509
14510                    float transformAlpha = transformToApply.getAlpha();
14511                    if (transformAlpha < 1) {
14512                        alpha *= transformAlpha;
14513                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14514                    }
14515                }
14516
14517                if (!childHasIdentityMatrix && !useDisplayListProperties) {
14518                    canvas.translate(-transX, -transY);
14519                    canvas.concat(getMatrix());
14520                    canvas.translate(transX, transY);
14521                }
14522            }
14523
14524            // Deal with alpha if it is or used to be <1
14525            if (alpha < 1 ||
14526                    (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
14527                if (alpha < 1) {
14528                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
14529                } else {
14530                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
14531                }
14532                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14533                if (hasNoCache) {
14534                    final int multipliedAlpha = (int) (255 * alpha);
14535                    if (!onSetAlpha(multipliedAlpha)) {
14536                        int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
14537                        if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
14538                                layerType != LAYER_TYPE_NONE) {
14539                            layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
14540                        }
14541                        if (useDisplayListProperties) {
14542                            displayList.setAlpha(alpha * getAlpha() * getTransitionAlpha());
14543                        } else  if (layerType == LAYER_TYPE_NONE) {
14544                            final int scrollX = hasDisplayList ? 0 : sx;
14545                            final int scrollY = hasDisplayList ? 0 : sy;
14546                            canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
14547                                    scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
14548                        }
14549                    } else {
14550                        // Alpha is handled by the child directly, clobber the layer's alpha
14551                        mPrivateFlags |= PFLAG_ALPHA_SET;
14552                    }
14553                }
14554            }
14555        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
14556            onSetAlpha(255);
14557            mPrivateFlags &= ~PFLAG_ALPHA_SET;
14558        }
14559
14560        if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
14561                !useDisplayListProperties && cache == null) {
14562            if (offsetForScroll) {
14563                canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
14564            } else {
14565                if (!scalingRequired || cache == null) {
14566                    canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
14567                } else {
14568                    canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
14569                }
14570            }
14571        }
14572
14573        if (!useDisplayListProperties && hasDisplayList) {
14574            displayList = getDisplayList();
14575            if (!displayList.isValid()) {
14576                // Uncommon, but possible. If a view is removed from the hierarchy during the call
14577                // to getDisplayList(), the display list will be marked invalid and we should not
14578                // try to use it again.
14579                displayList = null;
14580                hasDisplayList = false;
14581            }
14582        }
14583
14584        if (hasNoCache) {
14585            boolean layerRendered = false;
14586            if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) {
14587                final HardwareLayer layer = getHardwareLayer();
14588                if (layer != null && layer.isValid()) {
14589                    mLayerPaint.setAlpha((int) (alpha * 255));
14590                    ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
14591                    layerRendered = true;
14592                } else {
14593                    final int scrollX = hasDisplayList ? 0 : sx;
14594                    final int scrollY = hasDisplayList ? 0 : sy;
14595                    canvas.saveLayer(scrollX, scrollY,
14596                            scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
14597                            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
14598                }
14599            }
14600
14601            if (!layerRendered) {
14602                if (!hasDisplayList) {
14603                    // Fast path for layouts with no backgrounds
14604                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14605                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14606                        dispatchDraw(canvas);
14607                    } else {
14608                        draw(canvas);
14609                    }
14610                } else {
14611                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14612                    ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
14613                }
14614            }
14615        } else if (cache != null) {
14616            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14617            Paint cachePaint;
14618
14619            if (layerType == LAYER_TYPE_NONE) {
14620                cachePaint = parent.mCachePaint;
14621                if (cachePaint == null) {
14622                    cachePaint = new Paint();
14623                    cachePaint.setDither(false);
14624                    parent.mCachePaint = cachePaint;
14625                }
14626                if (alpha < 1) {
14627                    cachePaint.setAlpha((int) (alpha * 255));
14628                    parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
14629                } else if  ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) {
14630                    cachePaint.setAlpha(255);
14631                    parent.mGroupFlags &= ~ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
14632                }
14633            } else {
14634                cachePaint = mLayerPaint;
14635                cachePaint.setAlpha((int) (alpha * 255));
14636            }
14637            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
14638        }
14639
14640        if (restoreTo >= 0) {
14641            canvas.restoreToCount(restoreTo);
14642        }
14643
14644        if (a != null && !more) {
14645            if (!hardwareAccelerated && !a.getFillAfter()) {
14646                onSetAlpha(255);
14647            }
14648            parent.finishAnimatingView(this, a);
14649        }
14650
14651        if (more && hardwareAccelerated) {
14652            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
14653                // alpha animations should cause the child to recreate its display list
14654                invalidate(true);
14655            }
14656        }
14657
14658        mRecreateDisplayList = false;
14659
14660        return more;
14661    }
14662
14663    /**
14664     * Manually render this view (and all of its children) to the given Canvas.
14665     * The view must have already done a full layout before this function is
14666     * called.  When implementing a view, implement
14667     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
14668     * If you do need to override this method, call the superclass version.
14669     *
14670     * @param canvas The Canvas to which the View is rendered.
14671     */
14672    public void draw(Canvas canvas) {
14673        if (mClipBounds != null) {
14674            canvas.clipRect(mClipBounds);
14675        }
14676        final int privateFlags = mPrivateFlags;
14677        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
14678                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
14679        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
14680
14681        /*
14682         * Draw traversal performs several drawing steps which must be executed
14683         * in the appropriate order:
14684         *
14685         *      1. Draw the background
14686         *      2. If necessary, save the canvas' layers to prepare for fading
14687         *      3. Draw view's content
14688         *      4. Draw children
14689         *      5. If necessary, draw the fading edges and restore layers
14690         *      6. Draw decorations (scrollbars for instance)
14691         */
14692
14693        // Step 1, draw the background, if needed
14694        int saveCount;
14695
14696        if (!dirtyOpaque) {
14697            drawBackground(canvas);
14698        }
14699
14700        // skip step 2 & 5 if possible (common case)
14701        final int viewFlags = mViewFlags;
14702        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
14703        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
14704        if (!verticalEdges && !horizontalEdges) {
14705            // Step 3, draw the content
14706            if (!dirtyOpaque) onDraw(canvas);
14707
14708            // Step 4, draw the children
14709            dispatchDraw(canvas);
14710
14711            // Step 6, draw decorations (scrollbars)
14712            onDrawScrollBars(canvas);
14713
14714            if (mOverlay != null && !mOverlay.isEmpty()) {
14715                mOverlay.getOverlayView().dispatchDraw(canvas);
14716            }
14717
14718            // we're done...
14719            return;
14720        }
14721
14722        /*
14723         * Here we do the full fledged routine...
14724         * (this is an uncommon case where speed matters less,
14725         * this is why we repeat some of the tests that have been
14726         * done above)
14727         */
14728
14729        boolean drawTop = false;
14730        boolean drawBottom = false;
14731        boolean drawLeft = false;
14732        boolean drawRight = false;
14733
14734        float topFadeStrength = 0.0f;
14735        float bottomFadeStrength = 0.0f;
14736        float leftFadeStrength = 0.0f;
14737        float rightFadeStrength = 0.0f;
14738
14739        // Step 2, save the canvas' layers
14740        int paddingLeft = mPaddingLeft;
14741
14742        final boolean offsetRequired = isPaddingOffsetRequired();
14743        if (offsetRequired) {
14744            paddingLeft += getLeftPaddingOffset();
14745        }
14746
14747        int left = mScrollX + paddingLeft;
14748        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
14749        int top = mScrollY + getFadeTop(offsetRequired);
14750        int bottom = top + getFadeHeight(offsetRequired);
14751
14752        if (offsetRequired) {
14753            right += getRightPaddingOffset();
14754            bottom += getBottomPaddingOffset();
14755        }
14756
14757        final ScrollabilityCache scrollabilityCache = mScrollCache;
14758        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
14759        int length = (int) fadeHeight;
14760
14761        // clip the fade length if top and bottom fades overlap
14762        // overlapping fades produce odd-looking artifacts
14763        if (verticalEdges && (top + length > bottom - length)) {
14764            length = (bottom - top) / 2;
14765        }
14766
14767        // also clip horizontal fades if necessary
14768        if (horizontalEdges && (left + length > right - length)) {
14769            length = (right - left) / 2;
14770        }
14771
14772        if (verticalEdges) {
14773            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
14774            drawTop = topFadeStrength * fadeHeight > 1.0f;
14775            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
14776            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
14777        }
14778
14779        if (horizontalEdges) {
14780            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
14781            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
14782            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
14783            drawRight = rightFadeStrength * fadeHeight > 1.0f;
14784        }
14785
14786        saveCount = canvas.getSaveCount();
14787
14788        int solidColor = getSolidColor();
14789        if (solidColor == 0) {
14790            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
14791
14792            if (drawTop) {
14793                canvas.saveLayer(left, top, right, top + length, null, flags);
14794            }
14795
14796            if (drawBottom) {
14797                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
14798            }
14799
14800            if (drawLeft) {
14801                canvas.saveLayer(left, top, left + length, bottom, null, flags);
14802            }
14803
14804            if (drawRight) {
14805                canvas.saveLayer(right - length, top, right, bottom, null, flags);
14806            }
14807        } else {
14808            scrollabilityCache.setFadeColor(solidColor);
14809        }
14810
14811        // Step 3, draw the content
14812        if (!dirtyOpaque) onDraw(canvas);
14813
14814        // Step 4, draw the children
14815        dispatchDraw(canvas);
14816
14817        // Step 5, draw the fade effect and restore layers
14818        final Paint p = scrollabilityCache.paint;
14819        final Matrix matrix = scrollabilityCache.matrix;
14820        final Shader fade = scrollabilityCache.shader;
14821
14822        if (drawTop) {
14823            matrix.setScale(1, fadeHeight * topFadeStrength);
14824            matrix.postTranslate(left, top);
14825            fade.setLocalMatrix(matrix);
14826            canvas.drawRect(left, top, right, top + length, p);
14827        }
14828
14829        if (drawBottom) {
14830            matrix.setScale(1, fadeHeight * bottomFadeStrength);
14831            matrix.postRotate(180);
14832            matrix.postTranslate(left, bottom);
14833            fade.setLocalMatrix(matrix);
14834            canvas.drawRect(left, bottom - length, right, bottom, p);
14835        }
14836
14837        if (drawLeft) {
14838            matrix.setScale(1, fadeHeight * leftFadeStrength);
14839            matrix.postRotate(-90);
14840            matrix.postTranslate(left, top);
14841            fade.setLocalMatrix(matrix);
14842            canvas.drawRect(left, top, left + length, bottom, p);
14843        }
14844
14845        if (drawRight) {
14846            matrix.setScale(1, fadeHeight * rightFadeStrength);
14847            matrix.postRotate(90);
14848            matrix.postTranslate(right, top);
14849            fade.setLocalMatrix(matrix);
14850            canvas.drawRect(right - length, top, right, bottom, p);
14851        }
14852
14853        canvas.restoreToCount(saveCount);
14854
14855        // Step 6, draw decorations (scrollbars)
14856        onDrawScrollBars(canvas);
14857
14858        if (mOverlay != null && !mOverlay.isEmpty()) {
14859            mOverlay.getOverlayView().dispatchDraw(canvas);
14860        }
14861    }
14862
14863    /**
14864     * Draws the background onto the specified canvas.
14865     *
14866     * @param canvas Canvas on which to draw the background
14867     */
14868    private void drawBackground(Canvas canvas) {
14869        final Drawable background = mBackground;
14870        if (background == null) {
14871            return;
14872        }
14873
14874        if (mBackgroundSizeChanged) {
14875            background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
14876            mBackgroundSizeChanged = false;
14877            queryOutlineFromBackgroundIfUndefined();
14878        }
14879
14880        // Attempt to use a display list if requested.
14881        if (canvas.isHardwareAccelerated() && mAttachInfo != null
14882                && mAttachInfo.mHardwareRenderer != null) {
14883            mBackgroundDisplayList = getDrawableDisplayList(background, mBackgroundDisplayList);
14884
14885            final RenderNode displayList = mBackgroundDisplayList;
14886            if (displayList != null && displayList.isValid()) {
14887                setBackgroundDisplayListProperties(displayList);
14888                ((HardwareCanvas) canvas).drawDisplayList(displayList);
14889                return;
14890            }
14891        }
14892
14893        final int scrollX = mScrollX;
14894        final int scrollY = mScrollY;
14895        if ((scrollX | scrollY) == 0) {
14896            background.draw(canvas);
14897        } else {
14898            canvas.translate(scrollX, scrollY);
14899            background.draw(canvas);
14900            canvas.translate(-scrollX, -scrollY);
14901        }
14902    }
14903
14904    /**
14905     * Set up background drawable display list properties.
14906     *
14907     * @param displayList Valid display list for the background drawable
14908     */
14909    private void setBackgroundDisplayListProperties(RenderNode displayList) {
14910        displayList.setTranslationX(mScrollX);
14911        displayList.setTranslationY(mScrollY);
14912    }
14913
14914    /**
14915     * Creates a new display list or updates the existing display list for the
14916     * specified Drawable.
14917     *
14918     * @param drawable Drawable for which to create a display list
14919     * @param displayList Existing display list, or {@code null}
14920     * @return A valid display list for the specified drawable
14921     */
14922    private RenderNode getDrawableDisplayList(Drawable drawable, RenderNode displayList) {
14923        if (displayList == null) {
14924            displayList = RenderNode.create(drawable.getClass().getName());
14925        }
14926
14927        final Rect bounds = drawable.getBounds();
14928        final int width = bounds.width();
14929        final int height = bounds.height();
14930        final HardwareCanvas canvas = displayList.start(width, height);
14931        try {
14932            drawable.draw(canvas);
14933        } finally {
14934            displayList.end(canvas);
14935        }
14936
14937        // Set up drawable properties that are view-independent.
14938        displayList.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
14939        displayList.setProjectBackwards(drawable.isProjected());
14940        displayList.setProjectionReceiver(true);
14941        displayList.setClipToBounds(false);
14942        return displayList;
14943    }
14944
14945    /**
14946     * Returns the overlay for this view, creating it if it does not yet exist.
14947     * Adding drawables to the overlay will cause them to be displayed whenever
14948     * the view itself is redrawn. Objects in the overlay should be actively
14949     * managed: remove them when they should not be displayed anymore. The
14950     * overlay will always have the same size as its host view.
14951     *
14952     * <p>Note: Overlays do not currently work correctly with {@link
14953     * SurfaceView} or {@link TextureView}; contents in overlays for these
14954     * types of views may not display correctly.</p>
14955     *
14956     * @return The ViewOverlay object for this view.
14957     * @see ViewOverlay
14958     */
14959    public ViewOverlay getOverlay() {
14960        if (mOverlay == null) {
14961            mOverlay = new ViewOverlay(mContext, this);
14962        }
14963        return mOverlay;
14964    }
14965
14966    /**
14967     * Override this if your view is known to always be drawn on top of a solid color background,
14968     * and needs to draw fading edges. Returning a non-zero color enables the view system to
14969     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
14970     * should be set to 0xFF.
14971     *
14972     * @see #setVerticalFadingEdgeEnabled(boolean)
14973     * @see #setHorizontalFadingEdgeEnabled(boolean)
14974     *
14975     * @return The known solid color background for this view, or 0 if the color may vary
14976     */
14977    @ViewDebug.ExportedProperty(category = "drawing")
14978    public int getSolidColor() {
14979        return 0;
14980    }
14981
14982    /**
14983     * Build a human readable string representation of the specified view flags.
14984     *
14985     * @param flags the view flags to convert to a string
14986     * @return a String representing the supplied flags
14987     */
14988    private static String printFlags(int flags) {
14989        String output = "";
14990        int numFlags = 0;
14991        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
14992            output += "TAKES_FOCUS";
14993            numFlags++;
14994        }
14995
14996        switch (flags & VISIBILITY_MASK) {
14997        case INVISIBLE:
14998            if (numFlags > 0) {
14999                output += " ";
15000            }
15001            output += "INVISIBLE";
15002            // USELESS HERE numFlags++;
15003            break;
15004        case GONE:
15005            if (numFlags > 0) {
15006                output += " ";
15007            }
15008            output += "GONE";
15009            // USELESS HERE numFlags++;
15010            break;
15011        default:
15012            break;
15013        }
15014        return output;
15015    }
15016
15017    /**
15018     * Build a human readable string representation of the specified private
15019     * view flags.
15020     *
15021     * @param privateFlags the private view flags to convert to a string
15022     * @return a String representing the supplied flags
15023     */
15024    private static String printPrivateFlags(int privateFlags) {
15025        String output = "";
15026        int numFlags = 0;
15027
15028        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
15029            output += "WANTS_FOCUS";
15030            numFlags++;
15031        }
15032
15033        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
15034            if (numFlags > 0) {
15035                output += " ";
15036            }
15037            output += "FOCUSED";
15038            numFlags++;
15039        }
15040
15041        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
15042            if (numFlags > 0) {
15043                output += " ";
15044            }
15045            output += "SELECTED";
15046            numFlags++;
15047        }
15048
15049        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
15050            if (numFlags > 0) {
15051                output += " ";
15052            }
15053            output += "IS_ROOT_NAMESPACE";
15054            numFlags++;
15055        }
15056
15057        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
15058            if (numFlags > 0) {
15059                output += " ";
15060            }
15061            output += "HAS_BOUNDS";
15062            numFlags++;
15063        }
15064
15065        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
15066            if (numFlags > 0) {
15067                output += " ";
15068            }
15069            output += "DRAWN";
15070            // USELESS HERE numFlags++;
15071        }
15072        return output;
15073    }
15074
15075    /**
15076     * <p>Indicates whether or not this view's layout will be requested during
15077     * the next hierarchy layout pass.</p>
15078     *
15079     * @return true if the layout will be forced during next layout pass
15080     */
15081    public boolean isLayoutRequested() {
15082        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
15083    }
15084
15085    /**
15086     * Return true if o is a ViewGroup that is laying out using optical bounds.
15087     * @hide
15088     */
15089    public static boolean isLayoutModeOptical(Object o) {
15090        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
15091    }
15092
15093    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
15094        Insets parentInsets = mParent instanceof View ?
15095                ((View) mParent).getOpticalInsets() : Insets.NONE;
15096        Insets childInsets = getOpticalInsets();
15097        return setFrame(
15098                left   + parentInsets.left - childInsets.left,
15099                top    + parentInsets.top  - childInsets.top,
15100                right  + parentInsets.left + childInsets.right,
15101                bottom + parentInsets.top  + childInsets.bottom);
15102    }
15103
15104    /**
15105     * Assign a size and position to a view and all of its
15106     * descendants
15107     *
15108     * <p>This is the second phase of the layout mechanism.
15109     * (The first is measuring). In this phase, each parent calls
15110     * layout on all of its children to position them.
15111     * This is typically done using the child measurements
15112     * that were stored in the measure pass().</p>
15113     *
15114     * <p>Derived classes should not override this method.
15115     * Derived classes with children should override
15116     * onLayout. In that method, they should
15117     * call layout on each of their children.</p>
15118     *
15119     * @param l Left position, relative to parent
15120     * @param t Top position, relative to parent
15121     * @param r Right position, relative to parent
15122     * @param b Bottom position, relative to parent
15123     */
15124    @SuppressWarnings({"unchecked"})
15125    public void layout(int l, int t, int r, int b) {
15126        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
15127            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
15128            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
15129        }
15130
15131        int oldL = mLeft;
15132        int oldT = mTop;
15133        int oldB = mBottom;
15134        int oldR = mRight;
15135
15136        boolean changed = isLayoutModeOptical(mParent) ?
15137                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
15138
15139        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
15140            onLayout(changed, l, t, r, b);
15141            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
15142
15143            ListenerInfo li = mListenerInfo;
15144            if (li != null && li.mOnLayoutChangeListeners != null) {
15145                ArrayList<OnLayoutChangeListener> listenersCopy =
15146                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
15147                int numListeners = listenersCopy.size();
15148                for (int i = 0; i < numListeners; ++i) {
15149                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
15150                }
15151            }
15152        }
15153
15154        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
15155        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
15156    }
15157
15158    /**
15159     * Called from layout when this view should
15160     * assign a size and position to each of its children.
15161     *
15162     * Derived classes with children should override
15163     * this method and call layout on each of
15164     * their children.
15165     * @param changed This is a new size or position for this view
15166     * @param left Left position, relative to parent
15167     * @param top Top position, relative to parent
15168     * @param right Right position, relative to parent
15169     * @param bottom Bottom position, relative to parent
15170     */
15171    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
15172    }
15173
15174    /**
15175     * Assign a size and position to this view.
15176     *
15177     * This is called from layout.
15178     *
15179     * @param left Left position, relative to parent
15180     * @param top Top position, relative to parent
15181     * @param right Right position, relative to parent
15182     * @param bottom Bottom position, relative to parent
15183     * @return true if the new size and position are different than the
15184     *         previous ones
15185     * {@hide}
15186     */
15187    protected boolean setFrame(int left, int top, int right, int bottom) {
15188        boolean changed = false;
15189
15190        if (DBG) {
15191            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
15192                    + right + "," + bottom + ")");
15193        }
15194
15195        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
15196            changed = true;
15197
15198            // Remember our drawn bit
15199            int drawn = mPrivateFlags & PFLAG_DRAWN;
15200
15201            int oldWidth = mRight - mLeft;
15202            int oldHeight = mBottom - mTop;
15203            int newWidth = right - left;
15204            int newHeight = bottom - top;
15205            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
15206
15207            // Invalidate our old position
15208            invalidate(sizeChanged);
15209
15210            mLeft = left;
15211            mTop = top;
15212            mRight = right;
15213            mBottom = bottom;
15214            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
15215
15216            mPrivateFlags |= PFLAG_HAS_BOUNDS;
15217
15218
15219            if (sizeChanged) {
15220                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
15221            }
15222
15223            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
15224                // If we are visible, force the DRAWN bit to on so that
15225                // this invalidate will go through (at least to our parent).
15226                // This is because someone may have invalidated this view
15227                // before this call to setFrame came in, thereby clearing
15228                // the DRAWN bit.
15229                mPrivateFlags |= PFLAG_DRAWN;
15230                invalidate(sizeChanged);
15231                // parent display list may need to be recreated based on a change in the bounds
15232                // of any child
15233                invalidateParentCaches();
15234            }
15235
15236            // Reset drawn bit to original value (invalidate turns it off)
15237            mPrivateFlags |= drawn;
15238
15239            mBackgroundSizeChanged = true;
15240
15241            notifySubtreeAccessibilityStateChangedIfNeeded();
15242        }
15243        return changed;
15244    }
15245
15246    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
15247        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
15248        if (mOverlay != null) {
15249            mOverlay.getOverlayView().setRight(newWidth);
15250            mOverlay.getOverlayView().setBottom(newHeight);
15251        }
15252    }
15253
15254    /**
15255     * Finalize inflating a view from XML.  This is called as the last phase
15256     * of inflation, after all child views have been added.
15257     *
15258     * <p>Even if the subclass overrides onFinishInflate, they should always be
15259     * sure to call the super method, so that we get called.
15260     */
15261    protected void onFinishInflate() {
15262    }
15263
15264    /**
15265     * Returns the resources associated with this view.
15266     *
15267     * @return Resources object.
15268     */
15269    public Resources getResources() {
15270        return mResources;
15271    }
15272
15273    /**
15274     * Invalidates the specified Drawable.
15275     *
15276     * @param drawable the drawable to invalidate
15277     */
15278    @Override
15279    public void invalidateDrawable(@NonNull Drawable drawable) {
15280        if (verifyDrawable(drawable)) {
15281            final Rect dirty = drawable.getDirtyBounds();
15282            final int scrollX = mScrollX;
15283            final int scrollY = mScrollY;
15284
15285            invalidate(dirty.left + scrollX, dirty.top + scrollY,
15286                    dirty.right + scrollX, dirty.bottom + scrollY);
15287
15288            if (drawable == mBackground) {
15289                queryOutlineFromBackgroundIfUndefined();
15290            }
15291        }
15292    }
15293
15294    /**
15295     * Schedules an action on a drawable to occur at a specified time.
15296     *
15297     * @param who the recipient of the action
15298     * @param what the action to run on the drawable
15299     * @param when the time at which the action must occur. Uses the
15300     *        {@link SystemClock#uptimeMillis} timebase.
15301     */
15302    @Override
15303    public void scheduleDrawable(Drawable who, Runnable what, long when) {
15304        if (verifyDrawable(who) && what != null) {
15305            final long delay = when - SystemClock.uptimeMillis();
15306            if (mAttachInfo != null) {
15307                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15308                        Choreographer.CALLBACK_ANIMATION, what, who,
15309                        Choreographer.subtractFrameDelay(delay));
15310            } else {
15311                ViewRootImpl.getRunQueue().postDelayed(what, delay);
15312            }
15313        }
15314    }
15315
15316    /**
15317     * Cancels a scheduled action on a drawable.
15318     *
15319     * @param who the recipient of the action
15320     * @param what the action to cancel
15321     */
15322    @Override
15323    public void unscheduleDrawable(Drawable who, Runnable what) {
15324        if (verifyDrawable(who) && what != null) {
15325            if (mAttachInfo != null) {
15326                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15327                        Choreographer.CALLBACK_ANIMATION, what, who);
15328            }
15329            ViewRootImpl.getRunQueue().removeCallbacks(what);
15330        }
15331    }
15332
15333    /**
15334     * Unschedule any events associated with the given Drawable.  This can be
15335     * used when selecting a new Drawable into a view, so that the previous
15336     * one is completely unscheduled.
15337     *
15338     * @param who The Drawable to unschedule.
15339     *
15340     * @see #drawableStateChanged
15341     */
15342    public void unscheduleDrawable(Drawable who) {
15343        if (mAttachInfo != null && who != null) {
15344            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15345                    Choreographer.CALLBACK_ANIMATION, null, who);
15346        }
15347    }
15348
15349    /**
15350     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
15351     * that the View directionality can and will be resolved before its Drawables.
15352     *
15353     * Will call {@link View#onResolveDrawables} when resolution is done.
15354     *
15355     * @hide
15356     */
15357    protected void resolveDrawables() {
15358        // Drawables resolution may need to happen before resolving the layout direction (which is
15359        // done only during the measure() call).
15360        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
15361        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
15362        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
15363        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
15364        // direction to be resolved as its resolved value will be the same as its raw value.
15365        if (!isLayoutDirectionResolved() &&
15366                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
15367            return;
15368        }
15369
15370        final int layoutDirection = isLayoutDirectionResolved() ?
15371                getLayoutDirection() : getRawLayoutDirection();
15372
15373        if (mBackground != null) {
15374            mBackground.setLayoutDirection(layoutDirection);
15375        }
15376        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
15377        onResolveDrawables(layoutDirection);
15378    }
15379
15380    /**
15381     * Called when layout direction has been resolved.
15382     *
15383     * The default implementation does nothing.
15384     *
15385     * @param layoutDirection The resolved layout direction.
15386     *
15387     * @see #LAYOUT_DIRECTION_LTR
15388     * @see #LAYOUT_DIRECTION_RTL
15389     *
15390     * @hide
15391     */
15392    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
15393    }
15394
15395    /**
15396     * @hide
15397     */
15398    protected void resetResolvedDrawables() {
15399        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
15400    }
15401
15402    private boolean isDrawablesResolved() {
15403        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
15404    }
15405
15406    /**
15407     * If your view subclass is displaying its own Drawable objects, it should
15408     * override this function and return true for any Drawable it is
15409     * displaying.  This allows animations for those drawables to be
15410     * scheduled.
15411     *
15412     * <p>Be sure to call through to the super class when overriding this
15413     * function.
15414     *
15415     * @param who The Drawable to verify.  Return true if it is one you are
15416     *            displaying, else return the result of calling through to the
15417     *            super class.
15418     *
15419     * @return boolean If true than the Drawable is being displayed in the
15420     *         view; else false and it is not allowed to animate.
15421     *
15422     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
15423     * @see #drawableStateChanged()
15424     */
15425    protected boolean verifyDrawable(Drawable who) {
15426        return who == mBackground;
15427    }
15428
15429    /**
15430     * This function is called whenever the state of the view changes in such
15431     * a way that it impacts the state of drawables being shown.
15432     *
15433     * <p>Be sure to call through to the superclass when overriding this
15434     * function.
15435     *
15436     * @see Drawable#setState(int[])
15437     */
15438    protected void drawableStateChanged() {
15439        final Drawable d = mBackground;
15440        if (d != null && d.isStateful()) {
15441            d.setState(getDrawableState());
15442        }
15443    }
15444
15445    /**
15446     * Call this to force a view to update its drawable state. This will cause
15447     * drawableStateChanged to be called on this view. Views that are interested
15448     * in the new state should call getDrawableState.
15449     *
15450     * @see #drawableStateChanged
15451     * @see #getDrawableState
15452     */
15453    public void refreshDrawableState() {
15454        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15455        drawableStateChanged();
15456
15457        ViewParent parent = mParent;
15458        if (parent != null) {
15459            parent.childDrawableStateChanged(this);
15460        }
15461    }
15462
15463    /**
15464     * Return an array of resource IDs of the drawable states representing the
15465     * current state of the view.
15466     *
15467     * @return The current drawable state
15468     *
15469     * @see Drawable#setState(int[])
15470     * @see #drawableStateChanged()
15471     * @see #onCreateDrawableState(int)
15472     */
15473    public final int[] getDrawableState() {
15474        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
15475            return mDrawableState;
15476        } else {
15477            mDrawableState = onCreateDrawableState(0);
15478            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
15479            return mDrawableState;
15480        }
15481    }
15482
15483    /**
15484     * Generate the new {@link android.graphics.drawable.Drawable} state for
15485     * this view. This is called by the view
15486     * system when the cached Drawable state is determined to be invalid.  To
15487     * retrieve the current state, you should use {@link #getDrawableState}.
15488     *
15489     * @param extraSpace if non-zero, this is the number of extra entries you
15490     * would like in the returned array in which you can place your own
15491     * states.
15492     *
15493     * @return Returns an array holding the current {@link Drawable} state of
15494     * the view.
15495     *
15496     * @see #mergeDrawableStates(int[], int[])
15497     */
15498    protected int[] onCreateDrawableState(int extraSpace) {
15499        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
15500                mParent instanceof View) {
15501            return ((View) mParent).onCreateDrawableState(extraSpace);
15502        }
15503
15504        int[] drawableState;
15505
15506        int privateFlags = mPrivateFlags;
15507
15508        int viewStateIndex = 0;
15509        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
15510        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
15511        if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
15512        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
15513        if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
15514        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
15515        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
15516                HardwareRenderer.isAvailable()) {
15517            // This is set if HW acceleration is requested, even if the current
15518            // process doesn't allow it.  This is just to allow app preview
15519            // windows to better match their app.
15520            viewStateIndex |= VIEW_STATE_ACCELERATED;
15521        }
15522        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
15523
15524        final int privateFlags2 = mPrivateFlags2;
15525        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
15526        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
15527
15528        drawableState = VIEW_STATE_SETS[viewStateIndex];
15529
15530        //noinspection ConstantIfStatement
15531        if (false) {
15532            Log.i("View", "drawableStateIndex=" + viewStateIndex);
15533            Log.i("View", toString()
15534                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
15535                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
15536                    + " fo=" + hasFocus()
15537                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
15538                    + " wf=" + hasWindowFocus()
15539                    + ": " + Arrays.toString(drawableState));
15540        }
15541
15542        if (extraSpace == 0) {
15543            return drawableState;
15544        }
15545
15546        final int[] fullState;
15547        if (drawableState != null) {
15548            fullState = new int[drawableState.length + extraSpace];
15549            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
15550        } else {
15551            fullState = new int[extraSpace];
15552        }
15553
15554        return fullState;
15555    }
15556
15557    /**
15558     * Merge your own state values in <var>additionalState</var> into the base
15559     * state values <var>baseState</var> that were returned by
15560     * {@link #onCreateDrawableState(int)}.
15561     *
15562     * @param baseState The base state values returned by
15563     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
15564     * own additional state values.
15565     *
15566     * @param additionalState The additional state values you would like
15567     * added to <var>baseState</var>; this array is not modified.
15568     *
15569     * @return As a convenience, the <var>baseState</var> array you originally
15570     * passed into the function is returned.
15571     *
15572     * @see #onCreateDrawableState(int)
15573     */
15574    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
15575        final int N = baseState.length;
15576        int i = N - 1;
15577        while (i >= 0 && baseState[i] == 0) {
15578            i--;
15579        }
15580        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
15581        return baseState;
15582    }
15583
15584    /**
15585     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
15586     * on all Drawable objects associated with this view.
15587     */
15588    public void jumpDrawablesToCurrentState() {
15589        if (mBackground != null) {
15590            mBackground.jumpToCurrentState();
15591        }
15592    }
15593
15594    /**
15595     * Sets the background color for this view.
15596     * @param color the color of the background
15597     */
15598    @RemotableViewMethod
15599    public void setBackgroundColor(int color) {
15600        if (mBackground instanceof ColorDrawable) {
15601            ((ColorDrawable) mBackground.mutate()).setColor(color);
15602            computeOpaqueFlags();
15603            mBackgroundResource = 0;
15604        } else {
15605            setBackground(new ColorDrawable(color));
15606        }
15607    }
15608
15609    /**
15610     * Set the background to a given resource. The resource should refer to
15611     * a Drawable object or 0 to remove the background.
15612     * @param resid The identifier of the resource.
15613     *
15614     * @attr ref android.R.styleable#View_background
15615     */
15616    @RemotableViewMethod
15617    public void setBackgroundResource(int resid) {
15618        if (resid != 0 && resid == mBackgroundResource) {
15619            return;
15620        }
15621
15622        Drawable d= null;
15623        if (resid != 0) {
15624            d = mContext.getDrawable(resid);
15625        }
15626        setBackground(d);
15627
15628        mBackgroundResource = resid;
15629    }
15630
15631    /**
15632     * Set the background to a given Drawable, or remove the background. If the
15633     * background has padding, this View's padding is set to the background's
15634     * padding. However, when a background is removed, this View's padding isn't
15635     * touched. If setting the padding is desired, please use
15636     * {@link #setPadding(int, int, int, int)}.
15637     *
15638     * @param background The Drawable to use as the background, or null to remove the
15639     *        background
15640     */
15641    public void setBackground(Drawable background) {
15642        //noinspection deprecation
15643        setBackgroundDrawable(background);
15644    }
15645
15646    /**
15647     * @deprecated use {@link #setBackground(Drawable)} instead
15648     */
15649    @Deprecated
15650    public void setBackgroundDrawable(Drawable background) {
15651        computeOpaqueFlags();
15652
15653        if (background == mBackground) {
15654            return;
15655        }
15656
15657        boolean requestLayout = false;
15658
15659        mBackgroundResource = 0;
15660
15661        /*
15662         * Regardless of whether we're setting a new background or not, we want
15663         * to clear the previous drawable.
15664         */
15665        if (mBackground != null) {
15666            mBackground.setCallback(null);
15667            unscheduleDrawable(mBackground);
15668        }
15669
15670        if (background != null) {
15671            Rect padding = sThreadLocal.get();
15672            if (padding == null) {
15673                padding = new Rect();
15674                sThreadLocal.set(padding);
15675            }
15676            resetResolvedDrawables();
15677            background.setLayoutDirection(getLayoutDirection());
15678            if (background.getPadding(padding)) {
15679                resetResolvedPadding();
15680                switch (background.getLayoutDirection()) {
15681                    case LAYOUT_DIRECTION_RTL:
15682                        mUserPaddingLeftInitial = padding.right;
15683                        mUserPaddingRightInitial = padding.left;
15684                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
15685                        break;
15686                    case LAYOUT_DIRECTION_LTR:
15687                    default:
15688                        mUserPaddingLeftInitial = padding.left;
15689                        mUserPaddingRightInitial = padding.right;
15690                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
15691                }
15692                mLeftPaddingDefined = false;
15693                mRightPaddingDefined = false;
15694            }
15695
15696            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
15697            // if it has a different minimum size, we should layout again
15698            if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() ||
15699                    mBackground.getMinimumWidth() != background.getMinimumWidth()) {
15700                requestLayout = true;
15701            }
15702
15703            background.setCallback(this);
15704            if (background.isStateful()) {
15705                background.setState(getDrawableState());
15706            }
15707            background.setVisible(getVisibility() == VISIBLE, false);
15708            mBackground = background;
15709
15710            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
15711                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
15712                mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
15713                requestLayout = true;
15714            }
15715        } else {
15716            /* Remove the background */
15717            mBackground = null;
15718
15719            if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
15720                /*
15721                 * This view ONLY drew the background before and we're removing
15722                 * the background, so now it won't draw anything
15723                 * (hence we SKIP_DRAW)
15724                 */
15725                mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
15726                mPrivateFlags |= PFLAG_SKIP_DRAW;
15727            }
15728
15729            /*
15730             * When the background is set, we try to apply its padding to this
15731             * View. When the background is removed, we don't touch this View's
15732             * padding. This is noted in the Javadocs. Hence, we don't need to
15733             * requestLayout(), the invalidate() below is sufficient.
15734             */
15735
15736            // The old background's minimum size could have affected this
15737            // View's layout, so let's requestLayout
15738            requestLayout = true;
15739        }
15740
15741        computeOpaqueFlags();
15742
15743        if (requestLayout) {
15744            requestLayout();
15745        }
15746
15747        mBackgroundSizeChanged = true;
15748        invalidate(true);
15749    }
15750
15751    /**
15752     * Gets the background drawable
15753     *
15754     * @return The drawable used as the background for this view, if any.
15755     *
15756     * @see #setBackground(Drawable)
15757     *
15758     * @attr ref android.R.styleable#View_background
15759     */
15760    public Drawable getBackground() {
15761        return mBackground;
15762    }
15763
15764    /**
15765     * Sets the padding. The view may add on the space required to display
15766     * the scrollbars, depending on the style and visibility of the scrollbars.
15767     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
15768     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
15769     * from the values set in this call.
15770     *
15771     * @attr ref android.R.styleable#View_padding
15772     * @attr ref android.R.styleable#View_paddingBottom
15773     * @attr ref android.R.styleable#View_paddingLeft
15774     * @attr ref android.R.styleable#View_paddingRight
15775     * @attr ref android.R.styleable#View_paddingTop
15776     * @param left the left padding in pixels
15777     * @param top the top padding in pixels
15778     * @param right the right padding in pixels
15779     * @param bottom the bottom padding in pixels
15780     */
15781    public void setPadding(int left, int top, int right, int bottom) {
15782        resetResolvedPadding();
15783
15784        mUserPaddingStart = UNDEFINED_PADDING;
15785        mUserPaddingEnd = UNDEFINED_PADDING;
15786
15787        mUserPaddingLeftInitial = left;
15788        mUserPaddingRightInitial = right;
15789
15790        mLeftPaddingDefined = true;
15791        mRightPaddingDefined = true;
15792
15793        internalSetPadding(left, top, right, bottom);
15794    }
15795
15796    /**
15797     * @hide
15798     */
15799    protected void internalSetPadding(int left, int top, int right, int bottom) {
15800        mUserPaddingLeft = left;
15801        mUserPaddingRight = right;
15802        mUserPaddingBottom = bottom;
15803
15804        final int viewFlags = mViewFlags;
15805        boolean changed = false;
15806
15807        // Common case is there are no scroll bars.
15808        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
15809            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
15810                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
15811                        ? 0 : getVerticalScrollbarWidth();
15812                switch (mVerticalScrollbarPosition) {
15813                    case SCROLLBAR_POSITION_DEFAULT:
15814                        if (isLayoutRtl()) {
15815                            left += offset;
15816                        } else {
15817                            right += offset;
15818                        }
15819                        break;
15820                    case SCROLLBAR_POSITION_RIGHT:
15821                        right += offset;
15822                        break;
15823                    case SCROLLBAR_POSITION_LEFT:
15824                        left += offset;
15825                        break;
15826                }
15827            }
15828            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
15829                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
15830                        ? 0 : getHorizontalScrollbarHeight();
15831            }
15832        }
15833
15834        if (mPaddingLeft != left) {
15835            changed = true;
15836            mPaddingLeft = left;
15837        }
15838        if (mPaddingTop != top) {
15839            changed = true;
15840            mPaddingTop = top;
15841        }
15842        if (mPaddingRight != right) {
15843            changed = true;
15844            mPaddingRight = right;
15845        }
15846        if (mPaddingBottom != bottom) {
15847            changed = true;
15848            mPaddingBottom = bottom;
15849        }
15850
15851        if (changed) {
15852            requestLayout();
15853        }
15854    }
15855
15856    /**
15857     * Sets the relative padding. The view may add on the space required to display
15858     * the scrollbars, depending on the style and visibility of the scrollbars.
15859     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
15860     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
15861     * from the values set in this call.
15862     *
15863     * @attr ref android.R.styleable#View_padding
15864     * @attr ref android.R.styleable#View_paddingBottom
15865     * @attr ref android.R.styleable#View_paddingStart
15866     * @attr ref android.R.styleable#View_paddingEnd
15867     * @attr ref android.R.styleable#View_paddingTop
15868     * @param start the start padding in pixels
15869     * @param top the top padding in pixels
15870     * @param end the end padding in pixels
15871     * @param bottom the bottom padding in pixels
15872     */
15873    public void setPaddingRelative(int start, int top, int end, int bottom) {
15874        resetResolvedPadding();
15875
15876        mUserPaddingStart = start;
15877        mUserPaddingEnd = end;
15878        mLeftPaddingDefined = true;
15879        mRightPaddingDefined = true;
15880
15881        switch(getLayoutDirection()) {
15882            case LAYOUT_DIRECTION_RTL:
15883                mUserPaddingLeftInitial = end;
15884                mUserPaddingRightInitial = start;
15885                internalSetPadding(end, top, start, bottom);
15886                break;
15887            case LAYOUT_DIRECTION_LTR:
15888            default:
15889                mUserPaddingLeftInitial = start;
15890                mUserPaddingRightInitial = end;
15891                internalSetPadding(start, top, end, bottom);
15892        }
15893    }
15894
15895    /**
15896     * Returns the top padding of this view.
15897     *
15898     * @return the top padding in pixels
15899     */
15900    public int getPaddingTop() {
15901        return mPaddingTop;
15902    }
15903
15904    /**
15905     * Returns the bottom padding of this view. If there are inset and enabled
15906     * scrollbars, this value may include the space required to display the
15907     * scrollbars as well.
15908     *
15909     * @return the bottom padding in pixels
15910     */
15911    public int getPaddingBottom() {
15912        return mPaddingBottom;
15913    }
15914
15915    /**
15916     * Returns the left padding of this view. If there are inset and enabled
15917     * scrollbars, this value may include the space required to display the
15918     * scrollbars as well.
15919     *
15920     * @return the left padding in pixels
15921     */
15922    public int getPaddingLeft() {
15923        if (!isPaddingResolved()) {
15924            resolvePadding();
15925        }
15926        return mPaddingLeft;
15927    }
15928
15929    /**
15930     * Returns the start padding of this view depending on its resolved layout direction.
15931     * If there are inset and enabled scrollbars, this value may include the space
15932     * required to display the scrollbars as well.
15933     *
15934     * @return the start padding in pixels
15935     */
15936    public int getPaddingStart() {
15937        if (!isPaddingResolved()) {
15938            resolvePadding();
15939        }
15940        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
15941                mPaddingRight : mPaddingLeft;
15942    }
15943
15944    /**
15945     * Returns the right padding of this view. If there are inset and enabled
15946     * scrollbars, this value may include the space required to display the
15947     * scrollbars as well.
15948     *
15949     * @return the right padding in pixels
15950     */
15951    public int getPaddingRight() {
15952        if (!isPaddingResolved()) {
15953            resolvePadding();
15954        }
15955        return mPaddingRight;
15956    }
15957
15958    /**
15959     * Returns the end padding of this view depending on its resolved layout direction.
15960     * If there are inset and enabled scrollbars, this value may include the space
15961     * required to display the scrollbars as well.
15962     *
15963     * @return the end padding in pixels
15964     */
15965    public int getPaddingEnd() {
15966        if (!isPaddingResolved()) {
15967            resolvePadding();
15968        }
15969        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
15970                mPaddingLeft : mPaddingRight;
15971    }
15972
15973    /**
15974     * Return if the padding as been set thru relative values
15975     * {@link #setPaddingRelative(int, int, int, int)} or thru
15976     * @attr ref android.R.styleable#View_paddingStart or
15977     * @attr ref android.R.styleable#View_paddingEnd
15978     *
15979     * @return true if the padding is relative or false if it is not.
15980     */
15981    public boolean isPaddingRelative() {
15982        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
15983    }
15984
15985    Insets computeOpticalInsets() {
15986        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
15987    }
15988
15989    /**
15990     * @hide
15991     */
15992    public void resetPaddingToInitialValues() {
15993        if (isRtlCompatibilityMode()) {
15994            mPaddingLeft = mUserPaddingLeftInitial;
15995            mPaddingRight = mUserPaddingRightInitial;
15996            return;
15997        }
15998        if (isLayoutRtl()) {
15999            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
16000            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
16001        } else {
16002            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
16003            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
16004        }
16005    }
16006
16007    /**
16008     * @hide
16009     */
16010    public Insets getOpticalInsets() {
16011        if (mLayoutInsets == null) {
16012            mLayoutInsets = computeOpticalInsets();
16013        }
16014        return mLayoutInsets;
16015    }
16016
16017    /**
16018     * Changes the selection state of this view. A view can be selected or not.
16019     * Note that selection is not the same as focus. Views are typically
16020     * selected in the context of an AdapterView like ListView or GridView;
16021     * the selected view is the view that is highlighted.
16022     *
16023     * @param selected true if the view must be selected, false otherwise
16024     */
16025    public void setSelected(boolean selected) {
16026        //noinspection DoubleNegation
16027        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
16028            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
16029            if (!selected) resetPressedState();
16030            invalidate(true);
16031            refreshDrawableState();
16032            dispatchSetSelected(selected);
16033            notifyViewAccessibilityStateChangedIfNeeded(
16034                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16035        }
16036    }
16037
16038    /**
16039     * Dispatch setSelected to all of this View's children.
16040     *
16041     * @see #setSelected(boolean)
16042     *
16043     * @param selected The new selected state
16044     */
16045    protected void dispatchSetSelected(boolean selected) {
16046    }
16047
16048    /**
16049     * Indicates the selection state of this view.
16050     *
16051     * @return true if the view is selected, false otherwise
16052     */
16053    @ViewDebug.ExportedProperty
16054    public boolean isSelected() {
16055        return (mPrivateFlags & PFLAG_SELECTED) != 0;
16056    }
16057
16058    /**
16059     * Changes the activated state of this view. A view can be activated or not.
16060     * Note that activation is not the same as selection.  Selection is
16061     * a transient property, representing the view (hierarchy) the user is
16062     * currently interacting with.  Activation is a longer-term state that the
16063     * user can move views in and out of.  For example, in a list view with
16064     * single or multiple selection enabled, the views in the current selection
16065     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
16066     * here.)  The activated state is propagated down to children of the view it
16067     * is set on.
16068     *
16069     * @param activated true if the view must be activated, false otherwise
16070     */
16071    public void setActivated(boolean activated) {
16072        //noinspection DoubleNegation
16073        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
16074            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
16075            invalidate(true);
16076            refreshDrawableState();
16077            dispatchSetActivated(activated);
16078        }
16079    }
16080
16081    /**
16082     * Dispatch setActivated to all of this View's children.
16083     *
16084     * @see #setActivated(boolean)
16085     *
16086     * @param activated The new activated state
16087     */
16088    protected void dispatchSetActivated(boolean activated) {
16089    }
16090
16091    /**
16092     * Indicates the activation state of this view.
16093     *
16094     * @return true if the view is activated, false otherwise
16095     */
16096    @ViewDebug.ExportedProperty
16097    public boolean isActivated() {
16098        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
16099    }
16100
16101    /**
16102     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
16103     * observer can be used to get notifications when global events, like
16104     * layout, happen.
16105     *
16106     * The returned ViewTreeObserver observer is not guaranteed to remain
16107     * valid for the lifetime of this View. If the caller of this method keeps
16108     * a long-lived reference to ViewTreeObserver, it should always check for
16109     * the return value of {@link ViewTreeObserver#isAlive()}.
16110     *
16111     * @return The ViewTreeObserver for this view's hierarchy.
16112     */
16113    public ViewTreeObserver getViewTreeObserver() {
16114        if (mAttachInfo != null) {
16115            return mAttachInfo.mTreeObserver;
16116        }
16117        if (mFloatingTreeObserver == null) {
16118            mFloatingTreeObserver = new ViewTreeObserver();
16119        }
16120        return mFloatingTreeObserver;
16121    }
16122
16123    /**
16124     * <p>Finds the topmost view in the current view hierarchy.</p>
16125     *
16126     * @return the topmost view containing this view
16127     */
16128    public View getRootView() {
16129        if (mAttachInfo != null) {
16130            final View v = mAttachInfo.mRootView;
16131            if (v != null) {
16132                return v;
16133            }
16134        }
16135
16136        View parent = this;
16137
16138        while (parent.mParent != null && parent.mParent instanceof View) {
16139            parent = (View) parent.mParent;
16140        }
16141
16142        return parent;
16143    }
16144
16145    /**
16146     * Transforms a motion event from view-local coordinates to on-screen
16147     * coordinates.
16148     *
16149     * @param ev the view-local motion event
16150     * @return false if the transformation could not be applied
16151     * @hide
16152     */
16153    public boolean toGlobalMotionEvent(MotionEvent ev) {
16154        final AttachInfo info = mAttachInfo;
16155        if (info == null) {
16156            return false;
16157        }
16158
16159        final Matrix m = info.mTmpMatrix;
16160        m.set(Matrix.IDENTITY_MATRIX);
16161        transformMatrixToGlobal(m);
16162        ev.transform(m);
16163        return true;
16164    }
16165
16166    /**
16167     * Transforms a motion event from on-screen coordinates to view-local
16168     * coordinates.
16169     *
16170     * @param ev the on-screen motion event
16171     * @return false if the transformation could not be applied
16172     * @hide
16173     */
16174    public boolean toLocalMotionEvent(MotionEvent ev) {
16175        final AttachInfo info = mAttachInfo;
16176        if (info == null) {
16177            return false;
16178        }
16179
16180        final Matrix m = info.mTmpMatrix;
16181        m.set(Matrix.IDENTITY_MATRIX);
16182        transformMatrixToLocal(m);
16183        ev.transform(m);
16184        return true;
16185    }
16186
16187    /**
16188     * Modifies the input matrix such that it maps view-local coordinates to
16189     * on-screen coordinates.
16190     *
16191     * @param m input matrix to modify
16192     */
16193    void transformMatrixToGlobal(Matrix m) {
16194        final ViewParent parent = mParent;
16195        if (parent instanceof View) {
16196            final View vp = (View) parent;
16197            vp.transformMatrixToGlobal(m);
16198            m.postTranslate(-vp.mScrollX, -vp.mScrollY);
16199        } else if (parent instanceof ViewRootImpl) {
16200            final ViewRootImpl vr = (ViewRootImpl) parent;
16201            vr.transformMatrixToGlobal(m);
16202            m.postTranslate(0, -vr.mCurScrollY);
16203        }
16204
16205        m.postTranslate(mLeft, mTop);
16206
16207        if (!hasIdentityMatrix()) {
16208            m.postConcat(getMatrix());
16209        }
16210    }
16211
16212    /**
16213     * Modifies the input matrix such that it maps on-screen coordinates to
16214     * view-local coordinates.
16215     *
16216     * @param m input matrix to modify
16217     */
16218    void transformMatrixToLocal(Matrix m) {
16219        final ViewParent parent = mParent;
16220        if (parent instanceof View) {
16221            final View vp = (View) parent;
16222            vp.transformMatrixToLocal(m);
16223            m.preTranslate(vp.mScrollX, vp.mScrollY);
16224        } else if (parent instanceof ViewRootImpl) {
16225            final ViewRootImpl vr = (ViewRootImpl) parent;
16226            vr.transformMatrixToLocal(m);
16227            m.preTranslate(0, vr.mCurScrollY);
16228        }
16229
16230        m.preTranslate(-mLeft, -mTop);
16231
16232        if (!hasIdentityMatrix()) {
16233            m.preConcat(getInverseMatrix());
16234        }
16235    }
16236
16237    /**
16238     * <p>Computes the coordinates of this view on the screen. The argument
16239     * must be an array of two integers. After the method returns, the array
16240     * contains the x and y location in that order.</p>
16241     *
16242     * @param location an array of two integers in which to hold the coordinates
16243     */
16244    public void getLocationOnScreen(int[] location) {
16245        getLocationInWindow(location);
16246
16247        final AttachInfo info = mAttachInfo;
16248        if (info != null) {
16249            location[0] += info.mWindowLeft;
16250            location[1] += info.mWindowTop;
16251        }
16252    }
16253
16254    /**
16255     * <p>Computes the coordinates of this view in its window. The argument
16256     * must be an array of two integers. After the method returns, the array
16257     * contains the x and y location in that order.</p>
16258     *
16259     * @param location an array of two integers in which to hold the coordinates
16260     */
16261    public void getLocationInWindow(int[] location) {
16262        if (location == null || location.length < 2) {
16263            throw new IllegalArgumentException("location must be an array of two integers");
16264        }
16265
16266        if (mAttachInfo == null) {
16267            // When the view is not attached to a window, this method does not make sense
16268            location[0] = location[1] = 0;
16269            return;
16270        }
16271
16272        float[] position = mAttachInfo.mTmpTransformLocation;
16273        position[0] = position[1] = 0.0f;
16274
16275        if (!hasIdentityMatrix()) {
16276            getMatrix().mapPoints(position);
16277        }
16278
16279        position[0] += mLeft;
16280        position[1] += mTop;
16281
16282        ViewParent viewParent = mParent;
16283        while (viewParent instanceof View) {
16284            final View view = (View) viewParent;
16285
16286            position[0] -= view.mScrollX;
16287            position[1] -= view.mScrollY;
16288
16289            if (!view.hasIdentityMatrix()) {
16290                view.getMatrix().mapPoints(position);
16291            }
16292
16293            position[0] += view.mLeft;
16294            position[1] += view.mTop;
16295
16296            viewParent = view.mParent;
16297         }
16298
16299        if (viewParent instanceof ViewRootImpl) {
16300            // *cough*
16301            final ViewRootImpl vr = (ViewRootImpl) viewParent;
16302            position[1] -= vr.mCurScrollY;
16303        }
16304
16305        location[0] = (int) (position[0] + 0.5f);
16306        location[1] = (int) (position[1] + 0.5f);
16307    }
16308
16309    /**
16310     * {@hide}
16311     * @param id the id of the view to be found
16312     * @return the view of the specified id, null if cannot be found
16313     */
16314    protected View findViewTraversal(int id) {
16315        if (id == mID) {
16316            return this;
16317        }
16318        return null;
16319    }
16320
16321    /**
16322     * {@hide}
16323     * @param tag the tag of the view to be found
16324     * @return the view of specified tag, null if cannot be found
16325     */
16326    protected View findViewWithTagTraversal(Object tag) {
16327        if (tag != null && tag.equals(mTag)) {
16328            return this;
16329        }
16330        return null;
16331    }
16332
16333    /**
16334     * {@hide}
16335     * @param predicate The predicate to evaluate.
16336     * @param childToSkip If not null, ignores this child during the recursive traversal.
16337     * @return The first view that matches the predicate or null.
16338     */
16339    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
16340        if (predicate.apply(this)) {
16341            return this;
16342        }
16343        return null;
16344    }
16345
16346    /**
16347     * Look for a child view with the given id.  If this view has the given
16348     * id, return this view.
16349     *
16350     * @param id The id to search for.
16351     * @return The view that has the given id in the hierarchy or null
16352     */
16353    public final View findViewById(int id) {
16354        if (id < 0) {
16355            return null;
16356        }
16357        return findViewTraversal(id);
16358    }
16359
16360    /**
16361     * Finds a view by its unuque and stable accessibility id.
16362     *
16363     * @param accessibilityId The searched accessibility id.
16364     * @return The found view.
16365     */
16366    final View findViewByAccessibilityId(int accessibilityId) {
16367        if (accessibilityId < 0) {
16368            return null;
16369        }
16370        return findViewByAccessibilityIdTraversal(accessibilityId);
16371    }
16372
16373    /**
16374     * Performs the traversal to find a view by its unuque and stable accessibility id.
16375     *
16376     * <strong>Note:</strong>This method does not stop at the root namespace
16377     * boundary since the user can touch the screen at an arbitrary location
16378     * potentially crossing the root namespace bounday which will send an
16379     * accessibility event to accessibility services and they should be able
16380     * to obtain the event source. Also accessibility ids are guaranteed to be
16381     * unique in the window.
16382     *
16383     * @param accessibilityId The accessibility id.
16384     * @return The found view.
16385     *
16386     * @hide
16387     */
16388    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
16389        if (getAccessibilityViewId() == accessibilityId) {
16390            return this;
16391        }
16392        return null;
16393    }
16394
16395    /**
16396     * Look for a child view with the given tag.  If this view has the given
16397     * tag, return this view.
16398     *
16399     * @param tag The tag to search for, using "tag.equals(getTag())".
16400     * @return The View that has the given tag in the hierarchy or null
16401     */
16402    public final View findViewWithTag(Object tag) {
16403        if (tag == null) {
16404            return null;
16405        }
16406        return findViewWithTagTraversal(tag);
16407    }
16408
16409    /**
16410     * {@hide}
16411     * Look for a child view that matches the specified predicate.
16412     * If this view matches the predicate, return this view.
16413     *
16414     * @param predicate The predicate to evaluate.
16415     * @return The first view that matches the predicate or null.
16416     */
16417    public final View findViewByPredicate(Predicate<View> predicate) {
16418        return findViewByPredicateTraversal(predicate, null);
16419    }
16420
16421    /**
16422     * {@hide}
16423     * Look for a child view that matches the specified predicate,
16424     * starting with the specified view and its descendents and then
16425     * recusively searching the ancestors and siblings of that view
16426     * until this view is reached.
16427     *
16428     * This method is useful in cases where the predicate does not match
16429     * a single unique view (perhaps multiple views use the same id)
16430     * and we are trying to find the view that is "closest" in scope to the
16431     * starting view.
16432     *
16433     * @param start The view to start from.
16434     * @param predicate The predicate to evaluate.
16435     * @return The first view that matches the predicate or null.
16436     */
16437    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
16438        View childToSkip = null;
16439        for (;;) {
16440            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
16441            if (view != null || start == this) {
16442                return view;
16443            }
16444
16445            ViewParent parent = start.getParent();
16446            if (parent == null || !(parent instanceof View)) {
16447                return null;
16448            }
16449
16450            childToSkip = start;
16451            start = (View) parent;
16452        }
16453    }
16454
16455    /**
16456     * Sets the identifier for this view. The identifier does not have to be
16457     * unique in this view's hierarchy. The identifier should be a positive
16458     * number.
16459     *
16460     * @see #NO_ID
16461     * @see #getId()
16462     * @see #findViewById(int)
16463     *
16464     * @param id a number used to identify the view
16465     *
16466     * @attr ref android.R.styleable#View_id
16467     */
16468    public void setId(int id) {
16469        mID = id;
16470        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
16471            mID = generateViewId();
16472        }
16473    }
16474
16475    /**
16476     * {@hide}
16477     *
16478     * @param isRoot true if the view belongs to the root namespace, false
16479     *        otherwise
16480     */
16481    public void setIsRootNamespace(boolean isRoot) {
16482        if (isRoot) {
16483            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
16484        } else {
16485            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
16486        }
16487    }
16488
16489    /**
16490     * {@hide}
16491     *
16492     * @return true if the view belongs to the root namespace, false otherwise
16493     */
16494    public boolean isRootNamespace() {
16495        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
16496    }
16497
16498    /**
16499     * Returns this view's identifier.
16500     *
16501     * @return a positive integer used to identify the view or {@link #NO_ID}
16502     *         if the view has no ID
16503     *
16504     * @see #setId(int)
16505     * @see #findViewById(int)
16506     * @attr ref android.R.styleable#View_id
16507     */
16508    @ViewDebug.CapturedViewProperty
16509    public int getId() {
16510        return mID;
16511    }
16512
16513    /**
16514     * Returns this view's tag.
16515     *
16516     * @return the Object stored in this view as a tag, or {@code null} if not
16517     *         set
16518     *
16519     * @see #setTag(Object)
16520     * @see #getTag(int)
16521     */
16522    @ViewDebug.ExportedProperty
16523    public Object getTag() {
16524        return mTag;
16525    }
16526
16527    /**
16528     * Sets the tag associated with this view. A tag can be used to mark
16529     * a view in its hierarchy and does not have to be unique within the
16530     * hierarchy. Tags can also be used to store data within a view without
16531     * resorting to another data structure.
16532     *
16533     * @param tag an Object to tag the view with
16534     *
16535     * @see #getTag()
16536     * @see #setTag(int, Object)
16537     */
16538    public void setTag(final Object tag) {
16539        mTag = tag;
16540    }
16541
16542    /**
16543     * Returns the tag associated with this view and the specified key.
16544     *
16545     * @param key The key identifying the tag
16546     *
16547     * @return the Object stored in this view as a tag, or {@code null} if not
16548     *         set
16549     *
16550     * @see #setTag(int, Object)
16551     * @see #getTag()
16552     */
16553    public Object getTag(int key) {
16554        if (mKeyedTags != null) return mKeyedTags.get(key);
16555        return null;
16556    }
16557
16558    /**
16559     * Sets a tag associated with this view and a key. A tag can be used
16560     * to mark a view in its hierarchy and does not have to be unique within
16561     * the hierarchy. Tags can also be used to store data within a view
16562     * without resorting to another data structure.
16563     *
16564     * The specified key should be an id declared in the resources of the
16565     * application to ensure it is unique (see the <a
16566     * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
16567     * Keys identified as belonging to
16568     * the Android framework or not associated with any package will cause
16569     * an {@link IllegalArgumentException} to be thrown.
16570     *
16571     * @param key The key identifying the tag
16572     * @param tag An Object to tag the view with
16573     *
16574     * @throws IllegalArgumentException If they specified key is not valid
16575     *
16576     * @see #setTag(Object)
16577     * @see #getTag(int)
16578     */
16579    public void setTag(int key, final Object tag) {
16580        // If the package id is 0x00 or 0x01, it's either an undefined package
16581        // or a framework id
16582        if ((key >>> 24) < 2) {
16583            throw new IllegalArgumentException("The key must be an application-specific "
16584                    + "resource id.");
16585        }
16586
16587        setKeyedTag(key, tag);
16588    }
16589
16590    /**
16591     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
16592     * framework id.
16593     *
16594     * @hide
16595     */
16596    public void setTagInternal(int key, Object tag) {
16597        if ((key >>> 24) != 0x1) {
16598            throw new IllegalArgumentException("The key must be a framework-specific "
16599                    + "resource id.");
16600        }
16601
16602        setKeyedTag(key, tag);
16603    }
16604
16605    private void setKeyedTag(int key, Object tag) {
16606        if (mKeyedTags == null) {
16607            mKeyedTags = new SparseArray<Object>(2);
16608        }
16609
16610        mKeyedTags.put(key, tag);
16611    }
16612
16613    /**
16614     * Prints information about this view in the log output, with the tag
16615     * {@link #VIEW_LOG_TAG}.
16616     *
16617     * @hide
16618     */
16619    public void debug() {
16620        debug(0);
16621    }
16622
16623    /**
16624     * Prints information about this view in the log output, with the tag
16625     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
16626     * indentation defined by the <code>depth</code>.
16627     *
16628     * @param depth the indentation level
16629     *
16630     * @hide
16631     */
16632    protected void debug(int depth) {
16633        String output = debugIndent(depth - 1);
16634
16635        output += "+ " + this;
16636        int id = getId();
16637        if (id != -1) {
16638            output += " (id=" + id + ")";
16639        }
16640        Object tag = getTag();
16641        if (tag != null) {
16642            output += " (tag=" + tag + ")";
16643        }
16644        Log.d(VIEW_LOG_TAG, output);
16645
16646        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
16647            output = debugIndent(depth) + " FOCUSED";
16648            Log.d(VIEW_LOG_TAG, output);
16649        }
16650
16651        output = debugIndent(depth);
16652        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
16653                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
16654                + "} ";
16655        Log.d(VIEW_LOG_TAG, output);
16656
16657        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
16658                || mPaddingBottom != 0) {
16659            output = debugIndent(depth);
16660            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
16661                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
16662            Log.d(VIEW_LOG_TAG, output);
16663        }
16664
16665        output = debugIndent(depth);
16666        output += "mMeasureWidth=" + mMeasuredWidth +
16667                " mMeasureHeight=" + mMeasuredHeight;
16668        Log.d(VIEW_LOG_TAG, output);
16669
16670        output = debugIndent(depth);
16671        if (mLayoutParams == null) {
16672            output += "BAD! no layout params";
16673        } else {
16674            output = mLayoutParams.debug(output);
16675        }
16676        Log.d(VIEW_LOG_TAG, output);
16677
16678        output = debugIndent(depth);
16679        output += "flags={";
16680        output += View.printFlags(mViewFlags);
16681        output += "}";
16682        Log.d(VIEW_LOG_TAG, output);
16683
16684        output = debugIndent(depth);
16685        output += "privateFlags={";
16686        output += View.printPrivateFlags(mPrivateFlags);
16687        output += "}";
16688        Log.d(VIEW_LOG_TAG, output);
16689    }
16690
16691    /**
16692     * Creates a string of whitespaces used for indentation.
16693     *
16694     * @param depth the indentation level
16695     * @return a String containing (depth * 2 + 3) * 2 white spaces
16696     *
16697     * @hide
16698     */
16699    protected static String debugIndent(int depth) {
16700        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
16701        for (int i = 0; i < (depth * 2) + 3; i++) {
16702            spaces.append(' ').append(' ');
16703        }
16704        return spaces.toString();
16705    }
16706
16707    /**
16708     * <p>Return the offset of the widget's text baseline from the widget's top
16709     * boundary. If this widget does not support baseline alignment, this
16710     * method returns -1. </p>
16711     *
16712     * @return the offset of the baseline within the widget's bounds or -1
16713     *         if baseline alignment is not supported
16714     */
16715    @ViewDebug.ExportedProperty(category = "layout")
16716    public int getBaseline() {
16717        return -1;
16718    }
16719
16720    /**
16721     * Returns whether the view hierarchy is currently undergoing a layout pass. This
16722     * information is useful to avoid situations such as calling {@link #requestLayout()} during
16723     * a layout pass.
16724     *
16725     * @return whether the view hierarchy is currently undergoing a layout pass
16726     */
16727    public boolean isInLayout() {
16728        ViewRootImpl viewRoot = getViewRootImpl();
16729        return (viewRoot != null && viewRoot.isInLayout());
16730    }
16731
16732    /**
16733     * Call this when something has changed which has invalidated the
16734     * layout of this view. This will schedule a layout pass of the view
16735     * tree. This should not be called while the view hierarchy is currently in a layout
16736     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
16737     * end of the current layout pass (and then layout will run again) or after the current
16738     * frame is drawn and the next layout occurs.
16739     *
16740     * <p>Subclasses which override this method should call the superclass method to
16741     * handle possible request-during-layout errors correctly.</p>
16742     */
16743    public void requestLayout() {
16744        if (mMeasureCache != null) mMeasureCache.clear();
16745
16746        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
16747            // Only trigger request-during-layout logic if this is the view requesting it,
16748            // not the views in its parent hierarchy
16749            ViewRootImpl viewRoot = getViewRootImpl();
16750            if (viewRoot != null && viewRoot.isInLayout()) {
16751                if (!viewRoot.requestLayoutDuringLayout(this)) {
16752                    return;
16753                }
16754            }
16755            mAttachInfo.mViewRequestingLayout = this;
16756        }
16757
16758        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
16759        mPrivateFlags |= PFLAG_INVALIDATED;
16760
16761        if (mParent != null && !mParent.isLayoutRequested()) {
16762            mParent.requestLayout();
16763        }
16764        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
16765            mAttachInfo.mViewRequestingLayout = null;
16766        }
16767    }
16768
16769    /**
16770     * Forces this view to be laid out during the next layout pass.
16771     * This method does not call requestLayout() or forceLayout()
16772     * on the parent.
16773     */
16774    public void forceLayout() {
16775        if (mMeasureCache != null) mMeasureCache.clear();
16776
16777        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
16778        mPrivateFlags |= PFLAG_INVALIDATED;
16779    }
16780
16781    /**
16782     * <p>
16783     * This is called to find out how big a view should be. The parent
16784     * supplies constraint information in the width and height parameters.
16785     * </p>
16786     *
16787     * <p>
16788     * The actual measurement work of a view is performed in
16789     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
16790     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
16791     * </p>
16792     *
16793     *
16794     * @param widthMeasureSpec Horizontal space requirements as imposed by the
16795     *        parent
16796     * @param heightMeasureSpec Vertical space requirements as imposed by the
16797     *        parent
16798     *
16799     * @see #onMeasure(int, int)
16800     */
16801    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
16802        boolean optical = isLayoutModeOptical(this);
16803        if (optical != isLayoutModeOptical(mParent)) {
16804            Insets insets = getOpticalInsets();
16805            int oWidth  = insets.left + insets.right;
16806            int oHeight = insets.top  + insets.bottom;
16807            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
16808            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
16809        }
16810
16811        // Suppress sign extension for the low bytes
16812        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
16813        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
16814
16815        if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
16816                widthMeasureSpec != mOldWidthMeasureSpec ||
16817                heightMeasureSpec != mOldHeightMeasureSpec) {
16818
16819            // first clears the measured dimension flag
16820            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
16821
16822            resolveRtlPropertiesIfNeeded();
16823
16824            int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
16825                    mMeasureCache.indexOfKey(key);
16826            if (cacheIndex < 0 || sIgnoreMeasureCache) {
16827                // measure ourselves, this should set the measured dimension flag back
16828                onMeasure(widthMeasureSpec, heightMeasureSpec);
16829                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16830            } else {
16831                long value = mMeasureCache.valueAt(cacheIndex);
16832                // Casting a long to int drops the high 32 bits, no mask needed
16833                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
16834                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16835            }
16836
16837            // flag not set, setMeasuredDimension() was not invoked, we raise
16838            // an exception to warn the developer
16839            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
16840                throw new IllegalStateException("onMeasure() did not set the"
16841                        + " measured dimension by calling"
16842                        + " setMeasuredDimension()");
16843            }
16844
16845            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
16846        }
16847
16848        mOldWidthMeasureSpec = widthMeasureSpec;
16849        mOldHeightMeasureSpec = heightMeasureSpec;
16850
16851        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
16852                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
16853    }
16854
16855    /**
16856     * <p>
16857     * Measure the view and its content to determine the measured width and the
16858     * measured height. This method is invoked by {@link #measure(int, int)} and
16859     * should be overriden by subclasses to provide accurate and efficient
16860     * measurement of their contents.
16861     * </p>
16862     *
16863     * <p>
16864     * <strong>CONTRACT:</strong> When overriding this method, you
16865     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
16866     * measured width and height of this view. Failure to do so will trigger an
16867     * <code>IllegalStateException</code>, thrown by
16868     * {@link #measure(int, int)}. Calling the superclass'
16869     * {@link #onMeasure(int, int)} is a valid use.
16870     * </p>
16871     *
16872     * <p>
16873     * The base class implementation of measure defaults to the background size,
16874     * unless a larger size is allowed by the MeasureSpec. Subclasses should
16875     * override {@link #onMeasure(int, int)} to provide better measurements of
16876     * their content.
16877     * </p>
16878     *
16879     * <p>
16880     * If this method is overridden, it is the subclass's responsibility to make
16881     * sure the measured height and width are at least the view's minimum height
16882     * and width ({@link #getSuggestedMinimumHeight()} and
16883     * {@link #getSuggestedMinimumWidth()}).
16884     * </p>
16885     *
16886     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
16887     *                         The requirements are encoded with
16888     *                         {@link android.view.View.MeasureSpec}.
16889     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
16890     *                         The requirements are encoded with
16891     *                         {@link android.view.View.MeasureSpec}.
16892     *
16893     * @see #getMeasuredWidth()
16894     * @see #getMeasuredHeight()
16895     * @see #setMeasuredDimension(int, int)
16896     * @see #getSuggestedMinimumHeight()
16897     * @see #getSuggestedMinimumWidth()
16898     * @see android.view.View.MeasureSpec#getMode(int)
16899     * @see android.view.View.MeasureSpec#getSize(int)
16900     */
16901    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
16902        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
16903                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
16904    }
16905
16906    /**
16907     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
16908     * measured width and measured height. Failing to do so will trigger an
16909     * exception at measurement time.</p>
16910     *
16911     * @param measuredWidth The measured width of this view.  May be a complex
16912     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
16913     * {@link #MEASURED_STATE_TOO_SMALL}.
16914     * @param measuredHeight The measured height of this view.  May be a complex
16915     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
16916     * {@link #MEASURED_STATE_TOO_SMALL}.
16917     */
16918    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
16919        boolean optical = isLayoutModeOptical(this);
16920        if (optical != isLayoutModeOptical(mParent)) {
16921            Insets insets = getOpticalInsets();
16922            int opticalWidth  = insets.left + insets.right;
16923            int opticalHeight = insets.top  + insets.bottom;
16924
16925            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
16926            measuredHeight += optical ? opticalHeight : -opticalHeight;
16927        }
16928        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
16929    }
16930
16931    /**
16932     * Sets the measured dimension without extra processing for things like optical bounds.
16933     * Useful for reapplying consistent values that have already been cooked with adjustments
16934     * for optical bounds, etc. such as those from the measurement cache.
16935     *
16936     * @param measuredWidth The measured width of this view.  May be a complex
16937     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
16938     * {@link #MEASURED_STATE_TOO_SMALL}.
16939     * @param measuredHeight The measured height of this view.  May be a complex
16940     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
16941     * {@link #MEASURED_STATE_TOO_SMALL}.
16942     */
16943    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
16944        mMeasuredWidth = measuredWidth;
16945        mMeasuredHeight = measuredHeight;
16946
16947        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
16948    }
16949
16950    /**
16951     * Merge two states as returned by {@link #getMeasuredState()}.
16952     * @param curState The current state as returned from a view or the result
16953     * of combining multiple views.
16954     * @param newState The new view state to combine.
16955     * @return Returns a new integer reflecting the combination of the two
16956     * states.
16957     */
16958    public static int combineMeasuredStates(int curState, int newState) {
16959        return curState | newState;
16960    }
16961
16962    /**
16963     * Version of {@link #resolveSizeAndState(int, int, int)}
16964     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
16965     */
16966    public static int resolveSize(int size, int measureSpec) {
16967        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
16968    }
16969
16970    /**
16971     * Utility to reconcile a desired size and state, with constraints imposed
16972     * by a MeasureSpec.  Will take the desired size, unless a different size
16973     * is imposed by the constraints.  The returned value is a compound integer,
16974     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
16975     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
16976     * size is smaller than the size the view wants to be.
16977     *
16978     * @param size How big the view wants to be
16979     * @param measureSpec Constraints imposed by the parent
16980     * @return Size information bit mask as defined by
16981     * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
16982     */
16983    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
16984        int result = size;
16985        int specMode = MeasureSpec.getMode(measureSpec);
16986        int specSize =  MeasureSpec.getSize(measureSpec);
16987        switch (specMode) {
16988        case MeasureSpec.UNSPECIFIED:
16989            result = size;
16990            break;
16991        case MeasureSpec.AT_MOST:
16992            if (specSize < size) {
16993                result = specSize | MEASURED_STATE_TOO_SMALL;
16994            } else {
16995                result = size;
16996            }
16997            break;
16998        case MeasureSpec.EXACTLY:
16999            result = specSize;
17000            break;
17001        }
17002        return result | (childMeasuredState&MEASURED_STATE_MASK);
17003    }
17004
17005    /**
17006     * Utility to return a default size. Uses the supplied size if the
17007     * MeasureSpec imposed no constraints. Will get larger if allowed
17008     * by the MeasureSpec.
17009     *
17010     * @param size Default size for this view
17011     * @param measureSpec Constraints imposed by the parent
17012     * @return The size this view should be.
17013     */
17014    public static int getDefaultSize(int size, int measureSpec) {
17015        int result = size;
17016        int specMode = MeasureSpec.getMode(measureSpec);
17017        int specSize = MeasureSpec.getSize(measureSpec);
17018
17019        switch (specMode) {
17020        case MeasureSpec.UNSPECIFIED:
17021            result = size;
17022            break;
17023        case MeasureSpec.AT_MOST:
17024        case MeasureSpec.EXACTLY:
17025            result = specSize;
17026            break;
17027        }
17028        return result;
17029    }
17030
17031    /**
17032     * Returns the suggested minimum height that the view should use. This
17033     * returns the maximum of the view's minimum height
17034     * and the background's minimum height
17035     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
17036     * <p>
17037     * When being used in {@link #onMeasure(int, int)}, the caller should still
17038     * ensure the returned height is within the requirements of the parent.
17039     *
17040     * @return The suggested minimum height of the view.
17041     */
17042    protected int getSuggestedMinimumHeight() {
17043        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
17044
17045    }
17046
17047    /**
17048     * Returns the suggested minimum width that the view should use. This
17049     * returns the maximum of the view's minimum width)
17050     * and the background's minimum width
17051     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
17052     * <p>
17053     * When being used in {@link #onMeasure(int, int)}, the caller should still
17054     * ensure the returned width is within the requirements of the parent.
17055     *
17056     * @return The suggested minimum width of the view.
17057     */
17058    protected int getSuggestedMinimumWidth() {
17059        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
17060    }
17061
17062    /**
17063     * Returns the minimum height of the view.
17064     *
17065     * @return the minimum height the view will try to be.
17066     *
17067     * @see #setMinimumHeight(int)
17068     *
17069     * @attr ref android.R.styleable#View_minHeight
17070     */
17071    public int getMinimumHeight() {
17072        return mMinHeight;
17073    }
17074
17075    /**
17076     * Sets the minimum height of the view. It is not guaranteed the view will
17077     * be able to achieve this minimum height (for example, if its parent layout
17078     * constrains it with less available height).
17079     *
17080     * @param minHeight The minimum height the view will try to be.
17081     *
17082     * @see #getMinimumHeight()
17083     *
17084     * @attr ref android.R.styleable#View_minHeight
17085     */
17086    public void setMinimumHeight(int minHeight) {
17087        mMinHeight = minHeight;
17088        requestLayout();
17089    }
17090
17091    /**
17092     * Returns the minimum width of the view.
17093     *
17094     * @return the minimum width the view will try to be.
17095     *
17096     * @see #setMinimumWidth(int)
17097     *
17098     * @attr ref android.R.styleable#View_minWidth
17099     */
17100    public int getMinimumWidth() {
17101        return mMinWidth;
17102    }
17103
17104    /**
17105     * Sets the minimum width of the view. It is not guaranteed the view will
17106     * be able to achieve this minimum width (for example, if its parent layout
17107     * constrains it with less available width).
17108     *
17109     * @param minWidth The minimum width the view will try to be.
17110     *
17111     * @see #getMinimumWidth()
17112     *
17113     * @attr ref android.R.styleable#View_minWidth
17114     */
17115    public void setMinimumWidth(int minWidth) {
17116        mMinWidth = minWidth;
17117        requestLayout();
17118
17119    }
17120
17121    /**
17122     * Get the animation currently associated with this view.
17123     *
17124     * @return The animation that is currently playing or
17125     *         scheduled to play for this view.
17126     */
17127    public Animation getAnimation() {
17128        return mCurrentAnimation;
17129    }
17130
17131    /**
17132     * Start the specified animation now.
17133     *
17134     * @param animation the animation to start now
17135     */
17136    public void startAnimation(Animation animation) {
17137        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
17138        setAnimation(animation);
17139        invalidateParentCaches();
17140        invalidate(true);
17141    }
17142
17143    /**
17144     * Cancels any animations for this view.
17145     */
17146    public void clearAnimation() {
17147        if (mCurrentAnimation != null) {
17148            mCurrentAnimation.detach();
17149        }
17150        mCurrentAnimation = null;
17151        invalidateParentIfNeeded();
17152    }
17153
17154    /**
17155     * Sets the next animation to play for this view.
17156     * If you want the animation to play immediately, use
17157     * {@link #startAnimation(android.view.animation.Animation)} instead.
17158     * This method provides allows fine-grained
17159     * control over the start time and invalidation, but you
17160     * must make sure that 1) the animation has a start time set, and
17161     * 2) the view's parent (which controls animations on its children)
17162     * will be invalidated when the animation is supposed to
17163     * start.
17164     *
17165     * @param animation The next animation, or null.
17166     */
17167    public void setAnimation(Animation animation) {
17168        mCurrentAnimation = animation;
17169
17170        if (animation != null) {
17171            // If the screen is off assume the animation start time is now instead of
17172            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
17173            // would cause the animation to start when the screen turns back on
17174            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
17175                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
17176                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
17177            }
17178            animation.reset();
17179        }
17180    }
17181
17182    /**
17183     * Invoked by a parent ViewGroup to notify the start of the animation
17184     * currently associated with this view. If you override this method,
17185     * always call super.onAnimationStart();
17186     *
17187     * @see #setAnimation(android.view.animation.Animation)
17188     * @see #getAnimation()
17189     */
17190    protected void onAnimationStart() {
17191        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
17192    }
17193
17194    /**
17195     * Invoked by a parent ViewGroup to notify the end of the animation
17196     * currently associated with this view. If you override this method,
17197     * always call super.onAnimationEnd();
17198     *
17199     * @see #setAnimation(android.view.animation.Animation)
17200     * @see #getAnimation()
17201     */
17202    protected void onAnimationEnd() {
17203        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
17204    }
17205
17206    /**
17207     * Invoked if there is a Transform that involves alpha. Subclass that can
17208     * draw themselves with the specified alpha should return true, and then
17209     * respect that alpha when their onDraw() is called. If this returns false
17210     * then the view may be redirected to draw into an offscreen buffer to
17211     * fulfill the request, which will look fine, but may be slower than if the
17212     * subclass handles it internally. The default implementation returns false.
17213     *
17214     * @param alpha The alpha (0..255) to apply to the view's drawing
17215     * @return true if the view can draw with the specified alpha.
17216     */
17217    protected boolean onSetAlpha(int alpha) {
17218        return false;
17219    }
17220
17221    /**
17222     * This is used by the RootView to perform an optimization when
17223     * the view hierarchy contains one or several SurfaceView.
17224     * SurfaceView is always considered transparent, but its children are not,
17225     * therefore all View objects remove themselves from the global transparent
17226     * region (passed as a parameter to this function).
17227     *
17228     * @param region The transparent region for this ViewAncestor (window).
17229     *
17230     * @return Returns true if the effective visibility of the view at this
17231     * point is opaque, regardless of the transparent region; returns false
17232     * if it is possible for underlying windows to be seen behind the view.
17233     *
17234     * {@hide}
17235     */
17236    public boolean gatherTransparentRegion(Region region) {
17237        final AttachInfo attachInfo = mAttachInfo;
17238        if (region != null && attachInfo != null) {
17239            final int pflags = mPrivateFlags;
17240            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
17241                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
17242                // remove it from the transparent region.
17243                final int[] location = attachInfo.mTransparentLocation;
17244                getLocationInWindow(location);
17245                region.op(location[0], location[1], location[0] + mRight - mLeft,
17246                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
17247            } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
17248                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
17249                // exists, so we remove the background drawable's non-transparent
17250                // parts from this transparent region.
17251                applyDrawableToTransparentRegion(mBackground, region);
17252            }
17253        }
17254        return true;
17255    }
17256
17257    /**
17258     * Play a sound effect for this view.
17259     *
17260     * <p>The framework will play sound effects for some built in actions, such as
17261     * clicking, but you may wish to play these effects in your widget,
17262     * for instance, for internal navigation.
17263     *
17264     * <p>The sound effect will only be played if sound effects are enabled by the user, and
17265     * {@link #isSoundEffectsEnabled()} is true.
17266     *
17267     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
17268     */
17269    public void playSoundEffect(int soundConstant) {
17270        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
17271            return;
17272        }
17273        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
17274    }
17275
17276    /**
17277     * BZZZTT!!1!
17278     *
17279     * <p>Provide haptic feedback to the user for this view.
17280     *
17281     * <p>The framework will provide haptic feedback for some built in actions,
17282     * such as long presses, but you may wish to provide feedback for your
17283     * own widget.
17284     *
17285     * <p>The feedback will only be performed if
17286     * {@link #isHapticFeedbackEnabled()} is true.
17287     *
17288     * @param feedbackConstant One of the constants defined in
17289     * {@link HapticFeedbackConstants}
17290     */
17291    public boolean performHapticFeedback(int feedbackConstant) {
17292        return performHapticFeedback(feedbackConstant, 0);
17293    }
17294
17295    /**
17296     * BZZZTT!!1!
17297     *
17298     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
17299     *
17300     * @param feedbackConstant One of the constants defined in
17301     * {@link HapticFeedbackConstants}
17302     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
17303     */
17304    public boolean performHapticFeedback(int feedbackConstant, int flags) {
17305        if (mAttachInfo == null) {
17306            return false;
17307        }
17308        //noinspection SimplifiableIfStatement
17309        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
17310                && !isHapticFeedbackEnabled()) {
17311            return false;
17312        }
17313        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
17314                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
17315    }
17316
17317    /**
17318     * Request that the visibility of the status bar or other screen/window
17319     * decorations be changed.
17320     *
17321     * <p>This method is used to put the over device UI into temporary modes
17322     * where the user's attention is focused more on the application content,
17323     * by dimming or hiding surrounding system affordances.  This is typically
17324     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
17325     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
17326     * to be placed behind the action bar (and with these flags other system
17327     * affordances) so that smooth transitions between hiding and showing them
17328     * can be done.
17329     *
17330     * <p>Two representative examples of the use of system UI visibility is
17331     * implementing a content browsing application (like a magazine reader)
17332     * and a video playing application.
17333     *
17334     * <p>The first code shows a typical implementation of a View in a content
17335     * browsing application.  In this implementation, the application goes
17336     * into a content-oriented mode by hiding the status bar and action bar,
17337     * and putting the navigation elements into lights out mode.  The user can
17338     * then interact with content while in this mode.  Such an application should
17339     * provide an easy way for the user to toggle out of the mode (such as to
17340     * check information in the status bar or access notifications).  In the
17341     * implementation here, this is done simply by tapping on the content.
17342     *
17343     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
17344     *      content}
17345     *
17346     * <p>This second code sample shows a typical implementation of a View
17347     * in a video playing application.  In this situation, while the video is
17348     * playing the application would like to go into a complete full-screen mode,
17349     * to use as much of the display as possible for the video.  When in this state
17350     * the user can not interact with the application; the system intercepts
17351     * touching on the screen to pop the UI out of full screen mode.  See
17352     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
17353     *
17354     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
17355     *      content}
17356     *
17357     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17358     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
17359     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
17360     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
17361     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
17362     */
17363    public void setSystemUiVisibility(int visibility) {
17364        if (visibility != mSystemUiVisibility) {
17365            mSystemUiVisibility = visibility;
17366            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
17367                mParent.recomputeViewAttributes(this);
17368            }
17369        }
17370    }
17371
17372    /**
17373     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
17374     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17375     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
17376     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
17377     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
17378     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
17379     */
17380    public int getSystemUiVisibility() {
17381        return mSystemUiVisibility;
17382    }
17383
17384    /**
17385     * Returns the current system UI visibility that is currently set for
17386     * the entire window.  This is the combination of the
17387     * {@link #setSystemUiVisibility(int)} values supplied by all of the
17388     * views in the window.
17389     */
17390    public int getWindowSystemUiVisibility() {
17391        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
17392    }
17393
17394    /**
17395     * Override to find out when the window's requested system UI visibility
17396     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
17397     * This is different from the callbacks received through
17398     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
17399     * in that this is only telling you about the local request of the window,
17400     * not the actual values applied by the system.
17401     */
17402    public void onWindowSystemUiVisibilityChanged(int visible) {
17403    }
17404
17405    /**
17406     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
17407     * the view hierarchy.
17408     */
17409    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
17410        onWindowSystemUiVisibilityChanged(visible);
17411    }
17412
17413    /**
17414     * Set a listener to receive callbacks when the visibility of the system bar changes.
17415     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
17416     */
17417    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
17418        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
17419        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
17420            mParent.recomputeViewAttributes(this);
17421        }
17422    }
17423
17424    /**
17425     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
17426     * the view hierarchy.
17427     */
17428    public void dispatchSystemUiVisibilityChanged(int visibility) {
17429        ListenerInfo li = mListenerInfo;
17430        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
17431            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
17432                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
17433        }
17434    }
17435
17436    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
17437        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
17438        if (val != mSystemUiVisibility) {
17439            setSystemUiVisibility(val);
17440            return true;
17441        }
17442        return false;
17443    }
17444
17445    /** @hide */
17446    public void setDisabledSystemUiVisibility(int flags) {
17447        if (mAttachInfo != null) {
17448            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
17449                mAttachInfo.mDisabledSystemUiVisibility = flags;
17450                if (mParent != null) {
17451                    mParent.recomputeViewAttributes(this);
17452                }
17453            }
17454        }
17455    }
17456
17457    /**
17458     * Creates an image that the system displays during the drag and drop
17459     * operation. This is called a &quot;drag shadow&quot;. The default implementation
17460     * for a DragShadowBuilder based on a View returns an image that has exactly the same
17461     * appearance as the given View. The default also positions the center of the drag shadow
17462     * directly under the touch point. If no View is provided (the constructor with no parameters
17463     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
17464     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
17465     * default is an invisible drag shadow.
17466     * <p>
17467     * You are not required to use the View you provide to the constructor as the basis of the
17468     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
17469     * anything you want as the drag shadow.
17470     * </p>
17471     * <p>
17472     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
17473     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
17474     *  size and position of the drag shadow. It uses this data to construct a
17475     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
17476     *  so that your application can draw the shadow image in the Canvas.
17477     * </p>
17478     *
17479     * <div class="special reference">
17480     * <h3>Developer Guides</h3>
17481     * <p>For a guide to implementing drag and drop features, read the
17482     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
17483     * </div>
17484     */
17485    public static class DragShadowBuilder {
17486        private final WeakReference<View> mView;
17487
17488        /**
17489         * Constructs a shadow image builder based on a View. By default, the resulting drag
17490         * shadow will have the same appearance and dimensions as the View, with the touch point
17491         * over the center of the View.
17492         * @param view A View. Any View in scope can be used.
17493         */
17494        public DragShadowBuilder(View view) {
17495            mView = new WeakReference<View>(view);
17496        }
17497
17498        /**
17499         * Construct a shadow builder object with no associated View.  This
17500         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
17501         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
17502         * to supply the drag shadow's dimensions and appearance without
17503         * reference to any View object. If they are not overridden, then the result is an
17504         * invisible drag shadow.
17505         */
17506        public DragShadowBuilder() {
17507            mView = new WeakReference<View>(null);
17508        }
17509
17510        /**
17511         * Returns the View object that had been passed to the
17512         * {@link #View.DragShadowBuilder(View)}
17513         * constructor.  If that View parameter was {@code null} or if the
17514         * {@link #View.DragShadowBuilder()}
17515         * constructor was used to instantiate the builder object, this method will return
17516         * null.
17517         *
17518         * @return The View object associate with this builder object.
17519         */
17520        @SuppressWarnings({"JavadocReference"})
17521        final public View getView() {
17522            return mView.get();
17523        }
17524
17525        /**
17526         * Provides the metrics for the shadow image. These include the dimensions of
17527         * the shadow image, and the point within that shadow that should
17528         * be centered under the touch location while dragging.
17529         * <p>
17530         * The default implementation sets the dimensions of the shadow to be the
17531         * same as the dimensions of the View itself and centers the shadow under
17532         * the touch point.
17533         * </p>
17534         *
17535         * @param shadowSize A {@link android.graphics.Point} containing the width and height
17536         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
17537         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
17538         * image.
17539         *
17540         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
17541         * shadow image that should be underneath the touch point during the drag and drop
17542         * operation. Your application must set {@link android.graphics.Point#x} to the
17543         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
17544         */
17545        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
17546            final View view = mView.get();
17547            if (view != null) {
17548                shadowSize.set(view.getWidth(), view.getHeight());
17549                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
17550            } else {
17551                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
17552            }
17553        }
17554
17555        /**
17556         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
17557         * based on the dimensions it received from the
17558         * {@link #onProvideShadowMetrics(Point, Point)} callback.
17559         *
17560         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
17561         */
17562        public void onDrawShadow(Canvas canvas) {
17563            final View view = mView.get();
17564            if (view != null) {
17565                view.draw(canvas);
17566            } else {
17567                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
17568            }
17569        }
17570    }
17571
17572    /**
17573     * Starts a drag and drop operation. When your application calls this method, it passes a
17574     * {@link android.view.View.DragShadowBuilder} object to the system. The
17575     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
17576     * to get metrics for the drag shadow, and then calls the object's
17577     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
17578     * <p>
17579     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
17580     *  drag events to all the View objects in your application that are currently visible. It does
17581     *  this either by calling the View object's drag listener (an implementation of
17582     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
17583     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
17584     *  Both are passed a {@link android.view.DragEvent} object that has a
17585     *  {@link android.view.DragEvent#getAction()} value of
17586     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
17587     * </p>
17588     * <p>
17589     * Your application can invoke startDrag() on any attached View object. The View object does not
17590     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
17591     * be related to the View the user selected for dragging.
17592     * </p>
17593     * @param data A {@link android.content.ClipData} object pointing to the data to be
17594     * transferred by the drag and drop operation.
17595     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
17596     * drag shadow.
17597     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
17598     * drop operation. This Object is put into every DragEvent object sent by the system during the
17599     * current drag.
17600     * <p>
17601     * myLocalState is a lightweight mechanism for the sending information from the dragged View
17602     * to the target Views. For example, it can contain flags that differentiate between a
17603     * a copy operation and a move operation.
17604     * </p>
17605     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
17606     * so the parameter should be set to 0.
17607     * @return {@code true} if the method completes successfully, or
17608     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
17609     * do a drag, and so no drag operation is in progress.
17610     */
17611    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
17612            Object myLocalState, int flags) {
17613        if (ViewDebug.DEBUG_DRAG) {
17614            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
17615        }
17616        boolean okay = false;
17617
17618        Point shadowSize = new Point();
17619        Point shadowTouchPoint = new Point();
17620        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
17621
17622        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
17623                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
17624            throw new IllegalStateException("Drag shadow dimensions must not be negative");
17625        }
17626
17627        if (ViewDebug.DEBUG_DRAG) {
17628            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
17629                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
17630        }
17631        Surface surface = new Surface();
17632        try {
17633            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
17634                    flags, shadowSize.x, shadowSize.y, surface);
17635            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
17636                    + " surface=" + surface);
17637            if (token != null) {
17638                Canvas canvas = surface.lockCanvas(null);
17639                try {
17640                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
17641                    shadowBuilder.onDrawShadow(canvas);
17642                } finally {
17643                    surface.unlockCanvasAndPost(canvas);
17644                }
17645
17646                final ViewRootImpl root = getViewRootImpl();
17647
17648                // Cache the local state object for delivery with DragEvents
17649                root.setLocalDragState(myLocalState);
17650
17651                // repurpose 'shadowSize' for the last touch point
17652                root.getLastTouchPoint(shadowSize);
17653
17654                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
17655                        shadowSize.x, shadowSize.y,
17656                        shadowTouchPoint.x, shadowTouchPoint.y, data);
17657                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
17658
17659                // Off and running!  Release our local surface instance; the drag
17660                // shadow surface is now managed by the system process.
17661                surface.release();
17662            }
17663        } catch (Exception e) {
17664            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
17665            surface.destroy();
17666        }
17667
17668        return okay;
17669    }
17670
17671    /**
17672     * Handles drag events sent by the system following a call to
17673     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
17674     *<p>
17675     * When the system calls this method, it passes a
17676     * {@link android.view.DragEvent} object. A call to
17677     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
17678     * in DragEvent. The method uses these to determine what is happening in the drag and drop
17679     * operation.
17680     * @param event The {@link android.view.DragEvent} sent by the system.
17681     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
17682     * in DragEvent, indicating the type of drag event represented by this object.
17683     * @return {@code true} if the method was successful, otherwise {@code false}.
17684     * <p>
17685     *  The method should return {@code true} in response to an action type of
17686     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
17687     *  operation.
17688     * </p>
17689     * <p>
17690     *  The method should also return {@code true} in response to an action type of
17691     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
17692     *  {@code false} if it didn't.
17693     * </p>
17694     */
17695    public boolean onDragEvent(DragEvent event) {
17696        return false;
17697    }
17698
17699    /**
17700     * Detects if this View is enabled and has a drag event listener.
17701     * If both are true, then it calls the drag event listener with the
17702     * {@link android.view.DragEvent} it received. If the drag event listener returns
17703     * {@code true}, then dispatchDragEvent() returns {@code true}.
17704     * <p>
17705     * For all other cases, the method calls the
17706     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
17707     * method and returns its result.
17708     * </p>
17709     * <p>
17710     * This ensures that a drag event is always consumed, even if the View does not have a drag
17711     * event listener. However, if the View has a listener and the listener returns true, then
17712     * onDragEvent() is not called.
17713     * </p>
17714     */
17715    public boolean dispatchDragEvent(DragEvent event) {
17716        ListenerInfo li = mListenerInfo;
17717        //noinspection SimplifiableIfStatement
17718        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
17719                && li.mOnDragListener.onDrag(this, event)) {
17720            return true;
17721        }
17722        return onDragEvent(event);
17723    }
17724
17725    boolean canAcceptDrag() {
17726        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
17727    }
17728
17729    /**
17730     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
17731     * it is ever exposed at all.
17732     * @hide
17733     */
17734    public void onCloseSystemDialogs(String reason) {
17735    }
17736
17737    /**
17738     * Given a Drawable whose bounds have been set to draw into this view,
17739     * update a Region being computed for
17740     * {@link #gatherTransparentRegion(android.graphics.Region)} so
17741     * that any non-transparent parts of the Drawable are removed from the
17742     * given transparent region.
17743     *
17744     * @param dr The Drawable whose transparency is to be applied to the region.
17745     * @param region A Region holding the current transparency information,
17746     * where any parts of the region that are set are considered to be
17747     * transparent.  On return, this region will be modified to have the
17748     * transparency information reduced by the corresponding parts of the
17749     * Drawable that are not transparent.
17750     * {@hide}
17751     */
17752    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
17753        if (DBG) {
17754            Log.i("View", "Getting transparent region for: " + this);
17755        }
17756        final Region r = dr.getTransparentRegion();
17757        final Rect db = dr.getBounds();
17758        final AttachInfo attachInfo = mAttachInfo;
17759        if (r != null && attachInfo != null) {
17760            final int w = getRight()-getLeft();
17761            final int h = getBottom()-getTop();
17762            if (db.left > 0) {
17763                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
17764                r.op(0, 0, db.left, h, Region.Op.UNION);
17765            }
17766            if (db.right < w) {
17767                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
17768                r.op(db.right, 0, w, h, Region.Op.UNION);
17769            }
17770            if (db.top > 0) {
17771                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
17772                r.op(0, 0, w, db.top, Region.Op.UNION);
17773            }
17774            if (db.bottom < h) {
17775                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
17776                r.op(0, db.bottom, w, h, Region.Op.UNION);
17777            }
17778            final int[] location = attachInfo.mTransparentLocation;
17779            getLocationInWindow(location);
17780            r.translate(location[0], location[1]);
17781            region.op(r, Region.Op.INTERSECT);
17782        } else {
17783            region.op(db, Region.Op.DIFFERENCE);
17784        }
17785    }
17786
17787    private void checkForLongClick(int delayOffset) {
17788        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
17789            mHasPerformedLongPress = false;
17790
17791            if (mPendingCheckForLongPress == null) {
17792                mPendingCheckForLongPress = new CheckForLongPress();
17793            }
17794            mPendingCheckForLongPress.rememberWindowAttachCount();
17795            postDelayed(mPendingCheckForLongPress,
17796                    ViewConfiguration.getLongPressTimeout() - delayOffset);
17797        }
17798    }
17799
17800    /**
17801     * Inflate a view from an XML resource.  This convenience method wraps the {@link
17802     * LayoutInflater} class, which provides a full range of options for view inflation.
17803     *
17804     * @param context The Context object for your activity or application.
17805     * @param resource The resource ID to inflate
17806     * @param root A view group that will be the parent.  Used to properly inflate the
17807     * layout_* parameters.
17808     * @see LayoutInflater
17809     */
17810    public static View inflate(Context context, int resource, ViewGroup root) {
17811        LayoutInflater factory = LayoutInflater.from(context);
17812        return factory.inflate(resource, root);
17813    }
17814
17815    /**
17816     * Scroll the view with standard behavior for scrolling beyond the normal
17817     * content boundaries. Views that call this method should override
17818     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
17819     * results of an over-scroll operation.
17820     *
17821     * Views can use this method to handle any touch or fling-based scrolling.
17822     *
17823     * @param deltaX Change in X in pixels
17824     * @param deltaY Change in Y in pixels
17825     * @param scrollX Current X scroll value in pixels before applying deltaX
17826     * @param scrollY Current Y scroll value in pixels before applying deltaY
17827     * @param scrollRangeX Maximum content scroll range along the X axis
17828     * @param scrollRangeY Maximum content scroll range along the Y axis
17829     * @param maxOverScrollX Number of pixels to overscroll by in either direction
17830     *          along the X axis.
17831     * @param maxOverScrollY Number of pixels to overscroll by in either direction
17832     *          along the Y axis.
17833     * @param isTouchEvent true if this scroll operation is the result of a touch event.
17834     * @return true if scrolling was clamped to an over-scroll boundary along either
17835     *          axis, false otherwise.
17836     */
17837    @SuppressWarnings({"UnusedParameters"})
17838    protected boolean overScrollBy(int deltaX, int deltaY,
17839            int scrollX, int scrollY,
17840            int scrollRangeX, int scrollRangeY,
17841            int maxOverScrollX, int maxOverScrollY,
17842            boolean isTouchEvent) {
17843        final int overScrollMode = mOverScrollMode;
17844        final boolean canScrollHorizontal =
17845                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
17846        final boolean canScrollVertical =
17847                computeVerticalScrollRange() > computeVerticalScrollExtent();
17848        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
17849                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
17850        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
17851                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
17852
17853        int newScrollX = scrollX + deltaX;
17854        if (!overScrollHorizontal) {
17855            maxOverScrollX = 0;
17856        }
17857
17858        int newScrollY = scrollY + deltaY;
17859        if (!overScrollVertical) {
17860            maxOverScrollY = 0;
17861        }
17862
17863        // Clamp values if at the limits and record
17864        final int left = -maxOverScrollX;
17865        final int right = maxOverScrollX + scrollRangeX;
17866        final int top = -maxOverScrollY;
17867        final int bottom = maxOverScrollY + scrollRangeY;
17868
17869        boolean clampedX = false;
17870        if (newScrollX > right) {
17871            newScrollX = right;
17872            clampedX = true;
17873        } else if (newScrollX < left) {
17874            newScrollX = left;
17875            clampedX = true;
17876        }
17877
17878        boolean clampedY = false;
17879        if (newScrollY > bottom) {
17880            newScrollY = bottom;
17881            clampedY = true;
17882        } else if (newScrollY < top) {
17883            newScrollY = top;
17884            clampedY = true;
17885        }
17886
17887        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
17888
17889        return clampedX || clampedY;
17890    }
17891
17892    /**
17893     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
17894     * respond to the results of an over-scroll operation.
17895     *
17896     * @param scrollX New X scroll value in pixels
17897     * @param scrollY New Y scroll value in pixels
17898     * @param clampedX True if scrollX was clamped to an over-scroll boundary
17899     * @param clampedY True if scrollY was clamped to an over-scroll boundary
17900     */
17901    protected void onOverScrolled(int scrollX, int scrollY,
17902            boolean clampedX, boolean clampedY) {
17903        // Intentionally empty.
17904    }
17905
17906    /**
17907     * Returns the over-scroll mode for this view. The result will be
17908     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
17909     * (allow over-scrolling only if the view content is larger than the container),
17910     * or {@link #OVER_SCROLL_NEVER}.
17911     *
17912     * @return This view's over-scroll mode.
17913     */
17914    public int getOverScrollMode() {
17915        return mOverScrollMode;
17916    }
17917
17918    /**
17919     * Set the over-scroll mode for this view. Valid over-scroll modes are
17920     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
17921     * (allow over-scrolling only if the view content is larger than the container),
17922     * or {@link #OVER_SCROLL_NEVER}.
17923     *
17924     * Setting the over-scroll mode of a view will have an effect only if the
17925     * view is capable of scrolling.
17926     *
17927     * @param overScrollMode The new over-scroll mode for this view.
17928     */
17929    public void setOverScrollMode(int overScrollMode) {
17930        if (overScrollMode != OVER_SCROLL_ALWAYS &&
17931                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
17932                overScrollMode != OVER_SCROLL_NEVER) {
17933            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
17934        }
17935        mOverScrollMode = overScrollMode;
17936    }
17937
17938    /**
17939     * Enable or disable nested scrolling for this view.
17940     *
17941     * <p>If this property is set to true the view will be permitted to initiate nested
17942     * scrolling operations with a compatible parent view in the current hierarchy. If this
17943     * view does not implement nested scrolling this will have no effect.</p>
17944     *
17945     * @param enabled true to enable nested scrolling, false to disable
17946     *
17947     * @see #isNestedScrollingEnabled()
17948     */
17949    public void setNestedScrollingEnabled(boolean enabled) {
17950        if (enabled) {
17951            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
17952        } else {
17953            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
17954        }
17955    }
17956
17957    /**
17958     * Returns true if nested scrolling is enabled for this view.
17959     *
17960     * <p>If nested scrolling is enabled and this View class implementation supports it,
17961     * this view will act as a nested scrolling child view when applicable, forwarding data
17962     * about the scroll operation in progress to a compatible and cooperating nested scrolling
17963     * parent.</p>
17964     *
17965     * @return true if nested scrolling is enabled
17966     *
17967     * @see #setNestedScrollingEnabled(boolean)
17968     */
17969    public boolean isNestedScrollingEnabled() {
17970        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
17971                PFLAG3_NESTED_SCROLLING_ENABLED;
17972    }
17973
17974    /**
17975     * Begin a nestable scroll operation along the given axes.
17976     *
17977     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
17978     *
17979     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
17980     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
17981     * In the case of touch scrolling the nested scroll will be terminated automatically in
17982     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
17983     * In the event of programmatic scrolling the caller must explicitly call
17984     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
17985     *
17986     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
17987     * If it returns false the caller may ignore the rest of this contract until the next scroll.
17988     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
17989     *
17990     * <p>At each incremental step of the scroll the caller should invoke
17991     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
17992     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
17993     * parent at least partially consumed the scroll and the caller should adjust the amount it
17994     * scrolls by.</p>
17995     *
17996     * <p>After applying the remainder of the scroll delta the caller should invoke
17997     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
17998     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
17999     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
18000     * </p>
18001     *
18002     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
18003     *             {@link #SCROLL_AXIS_VERTICAL}.
18004     * @return true if a cooperative parent was found and nested scrolling has been enabled for
18005     *         the current gesture.
18006     *
18007     * @see #stopNestedScroll()
18008     * @see #dispatchNestedPreScroll(int, int, int[], int[])
18009     * @see #dispatchNestedScroll(int, int, int, int, int[])
18010     */
18011    public boolean startNestedScroll(int axes) {
18012        if (hasNestedScrollingParent()) {
18013            // Already in progress
18014            return true;
18015        }
18016        if (isNestedScrollingEnabled()) {
18017            ViewParent p = getParent();
18018            View child = this;
18019            while (p != null) {
18020                try {
18021                    if (p.onStartNestedScroll(child, this, axes)) {
18022                        mNestedScrollingParent = p;
18023                        p.onNestedScrollAccepted(child, this, axes);
18024                        return true;
18025                    }
18026                } catch (AbstractMethodError e) {
18027                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
18028                            "method onStartNestedScroll", e);
18029                    // Allow the search upward to continue
18030                }
18031                if (p instanceof View) {
18032                    child = (View) p;
18033                }
18034                p = p.getParent();
18035            }
18036        }
18037        return false;
18038    }
18039
18040    /**
18041     * Stop a nested scroll in progress.
18042     *
18043     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
18044     *
18045     * @see #startNestedScroll(int)
18046     */
18047    public void stopNestedScroll() {
18048        if (mNestedScrollingParent != null) {
18049            mNestedScrollingParent.onStopNestedScroll(this);
18050            mNestedScrollingParent = null;
18051        }
18052    }
18053
18054    /**
18055     * Returns true if this view has a nested scrolling parent.
18056     *
18057     * <p>The presence of a nested scrolling parent indicates that this view has initiated
18058     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
18059     *
18060     * @return whether this view has a nested scrolling parent
18061     */
18062    public boolean hasNestedScrollingParent() {
18063        return mNestedScrollingParent != null;
18064    }
18065
18066    /**
18067     * Dispatch one step of a nested scroll in progress.
18068     *
18069     * <p>Implementations of views that support nested scrolling should call this to report
18070     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
18071     * is not currently in progress or nested scrolling is not
18072     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
18073     *
18074     * <p>Compatible View implementations should also call
18075     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
18076     * consuming a component of the scroll event themselves.</p>
18077     *
18078     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
18079     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
18080     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
18081     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
18082     * @param offsetInWindow Optional. If not null, on return this will contain the offset
18083     *                       in local view coordinates of this view from before this operation
18084     *                       to after it completes. View implementations may use this to adjust
18085     *                       expected input coordinate tracking.
18086     * @return true if the event was dispatched, false if it could not be dispatched.
18087     * @see #dispatchNestedPreScroll(int, int, int[], int[])
18088     */
18089    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
18090            int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
18091        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18092            int startX = 0;
18093            int startY = 0;
18094            if (offsetInWindow != null) {
18095                getLocationInWindow(offsetInWindow);
18096                startX = offsetInWindow[0];
18097                startY = offsetInWindow[1];
18098            }
18099
18100            mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
18101                    dxUnconsumed, dyUnconsumed);
18102
18103            if (offsetInWindow != null) {
18104                getLocationInWindow(offsetInWindow);
18105                offsetInWindow[0] -= startX;
18106                offsetInWindow[1] -= startY;
18107            }
18108            return true;
18109        }
18110        return false;
18111    }
18112
18113    /**
18114     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
18115     *
18116     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
18117     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
18118     * scrolling operation to consume some or all of the scroll operation before the child view
18119     * consumes it.</p>
18120     *
18121     * @param dx Horizontal scroll distance in pixels
18122     * @param dy Vertical scroll distance in pixels
18123     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
18124     *                 and consumed[1] the consumed dy.
18125     * @param offsetInWindow Optional. If not null, on return this will contain the offset
18126     *                       in local view coordinates of this view from before this operation
18127     *                       to after it completes. View implementations may use this to adjust
18128     *                       expected input coordinate tracking.
18129     * @return true if the parent consumed some or all of the scroll delta
18130     * @see #dispatchNestedScroll(int, int, int, int, int[])
18131     */
18132    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
18133        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18134            int startX = 0;
18135            int startY = 0;
18136            if (offsetInWindow != null) {
18137                getLocationInWindow(offsetInWindow);
18138                startX = offsetInWindow[0];
18139                startY = offsetInWindow[1];
18140            }
18141
18142            if (consumed == null) {
18143                if (mTempNestedScrollConsumed == null) {
18144                    mTempNestedScrollConsumed = new int[2];
18145                }
18146                consumed = mTempNestedScrollConsumed;
18147            }
18148            consumed[0] = 0;
18149            consumed[1] = 0;
18150            mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
18151
18152            if (offsetInWindow != null) {
18153                getLocationInWindow(offsetInWindow);
18154                offsetInWindow[0] -= startX;
18155                offsetInWindow[1] -= startY;
18156            }
18157            return consumed[0] != 0 || consumed[1] != 0;
18158        }
18159        return false;
18160    }
18161
18162    /**
18163     * Dispatch a fling to a nested scrolling parent.
18164     *
18165     * <p>If a nested scrolling child view would normally fling but it is at the edge of its
18166     * own content it should use this method to delegate the fling to its nested scrolling parent.
18167     * The view implementation can use a {@link VelocityTracker} to obtain the velocity values
18168     * to pass.</p>
18169     *
18170     * @param velocityX Horizontal fling velocity in pixels per second
18171     * @param velocityY Vertical fling velocity in pixels per second
18172     * @return true if the nested scrolling parent consumed the fling
18173     */
18174    public boolean dispatchNestedFling(float velocityX, float velocityY) {
18175        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18176            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY);
18177        }
18178        return false;
18179    }
18180
18181    /**
18182     * Gets a scale factor that determines the distance the view should scroll
18183     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
18184     * @return The vertical scroll scale factor.
18185     * @hide
18186     */
18187    protected float getVerticalScrollFactor() {
18188        if (mVerticalScrollFactor == 0) {
18189            TypedValue outValue = new TypedValue();
18190            if (!mContext.getTheme().resolveAttribute(
18191                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
18192                throw new IllegalStateException(
18193                        "Expected theme to define listPreferredItemHeight.");
18194            }
18195            mVerticalScrollFactor = outValue.getDimension(
18196                    mContext.getResources().getDisplayMetrics());
18197        }
18198        return mVerticalScrollFactor;
18199    }
18200
18201    /**
18202     * Gets a scale factor that determines the distance the view should scroll
18203     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
18204     * @return The horizontal scroll scale factor.
18205     * @hide
18206     */
18207    protected float getHorizontalScrollFactor() {
18208        // TODO: Should use something else.
18209        return getVerticalScrollFactor();
18210    }
18211
18212    /**
18213     * Return the value specifying the text direction or policy that was set with
18214     * {@link #setTextDirection(int)}.
18215     *
18216     * @return the defined text direction. It can be one of:
18217     *
18218     * {@link #TEXT_DIRECTION_INHERIT},
18219     * {@link #TEXT_DIRECTION_FIRST_STRONG}
18220     * {@link #TEXT_DIRECTION_ANY_RTL},
18221     * {@link #TEXT_DIRECTION_LTR},
18222     * {@link #TEXT_DIRECTION_RTL},
18223     * {@link #TEXT_DIRECTION_LOCALE}
18224     *
18225     * @attr ref android.R.styleable#View_textDirection
18226     *
18227     * @hide
18228     */
18229    @ViewDebug.ExportedProperty(category = "text", mapping = {
18230            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
18231            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
18232            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
18233            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
18234            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
18235            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
18236    })
18237    public int getRawTextDirection() {
18238        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
18239    }
18240
18241    /**
18242     * Set the text direction.
18243     *
18244     * @param textDirection the direction to set. Should be one of:
18245     *
18246     * {@link #TEXT_DIRECTION_INHERIT},
18247     * {@link #TEXT_DIRECTION_FIRST_STRONG}
18248     * {@link #TEXT_DIRECTION_ANY_RTL},
18249     * {@link #TEXT_DIRECTION_LTR},
18250     * {@link #TEXT_DIRECTION_RTL},
18251     * {@link #TEXT_DIRECTION_LOCALE}
18252     *
18253     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
18254     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
18255     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
18256     *
18257     * @attr ref android.R.styleable#View_textDirection
18258     */
18259    public void setTextDirection(int textDirection) {
18260        if (getRawTextDirection() != textDirection) {
18261            // Reset the current text direction and the resolved one
18262            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
18263            resetResolvedTextDirection();
18264            // Set the new text direction
18265            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
18266            // Do resolution
18267            resolveTextDirection();
18268            // Notify change
18269            onRtlPropertiesChanged(getLayoutDirection());
18270            // Refresh
18271            requestLayout();
18272            invalidate(true);
18273        }
18274    }
18275
18276    /**
18277     * Return the resolved text direction.
18278     *
18279     * @return the resolved text direction. Returns one of:
18280     *
18281     * {@link #TEXT_DIRECTION_FIRST_STRONG}
18282     * {@link #TEXT_DIRECTION_ANY_RTL},
18283     * {@link #TEXT_DIRECTION_LTR},
18284     * {@link #TEXT_DIRECTION_RTL},
18285     * {@link #TEXT_DIRECTION_LOCALE}
18286     *
18287     * @attr ref android.R.styleable#View_textDirection
18288     */
18289    @ViewDebug.ExportedProperty(category = "text", mapping = {
18290            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
18291            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
18292            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
18293            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
18294            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
18295            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
18296    })
18297    public int getTextDirection() {
18298        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
18299    }
18300
18301    /**
18302     * Resolve the text direction.
18303     *
18304     * @return true if resolution has been done, false otherwise.
18305     *
18306     * @hide
18307     */
18308    public boolean resolveTextDirection() {
18309        // Reset any previous text direction resolution
18310        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
18311
18312        if (hasRtlSupport()) {
18313            // Set resolved text direction flag depending on text direction flag
18314            final int textDirection = getRawTextDirection();
18315            switch(textDirection) {
18316                case TEXT_DIRECTION_INHERIT:
18317                    if (!canResolveTextDirection()) {
18318                        // We cannot do the resolution if there is no parent, so use the default one
18319                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18320                        // Resolution will need to happen again later
18321                        return false;
18322                    }
18323
18324                    // Parent has not yet resolved, so we still return the default
18325                    try {
18326                        if (!mParent.isTextDirectionResolved()) {
18327                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18328                            // Resolution will need to happen again later
18329                            return false;
18330                        }
18331                    } catch (AbstractMethodError e) {
18332                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18333                                " does not fully implement ViewParent", e);
18334                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
18335                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18336                        return true;
18337                    }
18338
18339                    // Set current resolved direction to the same value as the parent's one
18340                    int parentResolvedDirection;
18341                    try {
18342                        parentResolvedDirection = mParent.getTextDirection();
18343                    } catch (AbstractMethodError e) {
18344                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18345                                " does not fully implement ViewParent", e);
18346                        parentResolvedDirection = TEXT_DIRECTION_LTR;
18347                    }
18348                    switch (parentResolvedDirection) {
18349                        case TEXT_DIRECTION_FIRST_STRONG:
18350                        case TEXT_DIRECTION_ANY_RTL:
18351                        case TEXT_DIRECTION_LTR:
18352                        case TEXT_DIRECTION_RTL:
18353                        case TEXT_DIRECTION_LOCALE:
18354                            mPrivateFlags2 |=
18355                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
18356                            break;
18357                        default:
18358                            // Default resolved direction is "first strong" heuristic
18359                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18360                    }
18361                    break;
18362                case TEXT_DIRECTION_FIRST_STRONG:
18363                case TEXT_DIRECTION_ANY_RTL:
18364                case TEXT_DIRECTION_LTR:
18365                case TEXT_DIRECTION_RTL:
18366                case TEXT_DIRECTION_LOCALE:
18367                    // Resolved direction is the same as text direction
18368                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
18369                    break;
18370                default:
18371                    // Default resolved direction is "first strong" heuristic
18372                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18373            }
18374        } else {
18375            // Default resolved direction is "first strong" heuristic
18376            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18377        }
18378
18379        // Set to resolved
18380        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
18381        return true;
18382    }
18383
18384    /**
18385     * Check if text direction resolution can be done.
18386     *
18387     * @return true if text direction resolution can be done otherwise return false.
18388     */
18389    public boolean canResolveTextDirection() {
18390        switch (getRawTextDirection()) {
18391            case TEXT_DIRECTION_INHERIT:
18392                if (mParent != null) {
18393                    try {
18394                        return mParent.canResolveTextDirection();
18395                    } catch (AbstractMethodError e) {
18396                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18397                                " does not fully implement ViewParent", e);
18398                    }
18399                }
18400                return false;
18401
18402            default:
18403                return true;
18404        }
18405    }
18406
18407    /**
18408     * Reset resolved text direction. Text direction will be resolved during a call to
18409     * {@link #onMeasure(int, int)}.
18410     *
18411     * @hide
18412     */
18413    public void resetResolvedTextDirection() {
18414        // Reset any previous text direction resolution
18415        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
18416        // Set to default value
18417        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18418    }
18419
18420    /**
18421     * @return true if text direction is inherited.
18422     *
18423     * @hide
18424     */
18425    public boolean isTextDirectionInherited() {
18426        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
18427    }
18428
18429    /**
18430     * @return true if text direction is resolved.
18431     */
18432    public boolean isTextDirectionResolved() {
18433        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
18434    }
18435
18436    /**
18437     * Return the value specifying the text alignment or policy that was set with
18438     * {@link #setTextAlignment(int)}.
18439     *
18440     * @return the defined text alignment. It can be one of:
18441     *
18442     * {@link #TEXT_ALIGNMENT_INHERIT},
18443     * {@link #TEXT_ALIGNMENT_GRAVITY},
18444     * {@link #TEXT_ALIGNMENT_CENTER},
18445     * {@link #TEXT_ALIGNMENT_TEXT_START},
18446     * {@link #TEXT_ALIGNMENT_TEXT_END},
18447     * {@link #TEXT_ALIGNMENT_VIEW_START},
18448     * {@link #TEXT_ALIGNMENT_VIEW_END}
18449     *
18450     * @attr ref android.R.styleable#View_textAlignment
18451     *
18452     * @hide
18453     */
18454    @ViewDebug.ExportedProperty(category = "text", mapping = {
18455            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
18456            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
18457            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
18458            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
18459            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
18460            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
18461            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
18462    })
18463    @TextAlignment
18464    public int getRawTextAlignment() {
18465        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
18466    }
18467
18468    /**
18469     * Set the text alignment.
18470     *
18471     * @param textAlignment The text alignment to set. Should be one of
18472     *
18473     * {@link #TEXT_ALIGNMENT_INHERIT},
18474     * {@link #TEXT_ALIGNMENT_GRAVITY},
18475     * {@link #TEXT_ALIGNMENT_CENTER},
18476     * {@link #TEXT_ALIGNMENT_TEXT_START},
18477     * {@link #TEXT_ALIGNMENT_TEXT_END},
18478     * {@link #TEXT_ALIGNMENT_VIEW_START},
18479     * {@link #TEXT_ALIGNMENT_VIEW_END}
18480     *
18481     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
18482     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
18483     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
18484     *
18485     * @attr ref android.R.styleable#View_textAlignment
18486     */
18487    public void setTextAlignment(@TextAlignment int textAlignment) {
18488        if (textAlignment != getRawTextAlignment()) {
18489            // Reset the current and resolved text alignment
18490            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
18491            resetResolvedTextAlignment();
18492            // Set the new text alignment
18493            mPrivateFlags2 |=
18494                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
18495            // Do resolution
18496            resolveTextAlignment();
18497            // Notify change
18498            onRtlPropertiesChanged(getLayoutDirection());
18499            // Refresh
18500            requestLayout();
18501            invalidate(true);
18502        }
18503    }
18504
18505    /**
18506     * Return the resolved text alignment.
18507     *
18508     * @return the resolved text alignment. Returns one of:
18509     *
18510     * {@link #TEXT_ALIGNMENT_GRAVITY},
18511     * {@link #TEXT_ALIGNMENT_CENTER},
18512     * {@link #TEXT_ALIGNMENT_TEXT_START},
18513     * {@link #TEXT_ALIGNMENT_TEXT_END},
18514     * {@link #TEXT_ALIGNMENT_VIEW_START},
18515     * {@link #TEXT_ALIGNMENT_VIEW_END}
18516     *
18517     * @attr ref android.R.styleable#View_textAlignment
18518     */
18519    @ViewDebug.ExportedProperty(category = "text", mapping = {
18520            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
18521            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
18522            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
18523            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
18524            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
18525            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
18526            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
18527    })
18528    @TextAlignment
18529    public int getTextAlignment() {
18530        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
18531                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
18532    }
18533
18534    /**
18535     * Resolve the text alignment.
18536     *
18537     * @return true if resolution has been done, false otherwise.
18538     *
18539     * @hide
18540     */
18541    public boolean resolveTextAlignment() {
18542        // Reset any previous text alignment resolution
18543        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
18544
18545        if (hasRtlSupport()) {
18546            // Set resolved text alignment flag depending on text alignment flag
18547            final int textAlignment = getRawTextAlignment();
18548            switch (textAlignment) {
18549                case TEXT_ALIGNMENT_INHERIT:
18550                    // Check if we can resolve the text alignment
18551                    if (!canResolveTextAlignment()) {
18552                        // We cannot do the resolution if there is no parent so use the default
18553                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18554                        // Resolution will need to happen again later
18555                        return false;
18556                    }
18557
18558                    // Parent has not yet resolved, so we still return the default
18559                    try {
18560                        if (!mParent.isTextAlignmentResolved()) {
18561                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18562                            // Resolution will need to happen again later
18563                            return false;
18564                        }
18565                    } catch (AbstractMethodError e) {
18566                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18567                                " does not fully implement ViewParent", e);
18568                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
18569                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18570                        return true;
18571                    }
18572
18573                    int parentResolvedTextAlignment;
18574                    try {
18575                        parentResolvedTextAlignment = mParent.getTextAlignment();
18576                    } catch (AbstractMethodError e) {
18577                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18578                                " does not fully implement ViewParent", e);
18579                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
18580                    }
18581                    switch (parentResolvedTextAlignment) {
18582                        case TEXT_ALIGNMENT_GRAVITY:
18583                        case TEXT_ALIGNMENT_TEXT_START:
18584                        case TEXT_ALIGNMENT_TEXT_END:
18585                        case TEXT_ALIGNMENT_CENTER:
18586                        case TEXT_ALIGNMENT_VIEW_START:
18587                        case TEXT_ALIGNMENT_VIEW_END:
18588                            // Resolved text alignment is the same as the parent resolved
18589                            // text alignment
18590                            mPrivateFlags2 |=
18591                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
18592                            break;
18593                        default:
18594                            // Use default resolved text alignment
18595                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18596                    }
18597                    break;
18598                case TEXT_ALIGNMENT_GRAVITY:
18599                case TEXT_ALIGNMENT_TEXT_START:
18600                case TEXT_ALIGNMENT_TEXT_END:
18601                case TEXT_ALIGNMENT_CENTER:
18602                case TEXT_ALIGNMENT_VIEW_START:
18603                case TEXT_ALIGNMENT_VIEW_END:
18604                    // Resolved text alignment is the same as text alignment
18605                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
18606                    break;
18607                default:
18608                    // Use default resolved text alignment
18609                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18610            }
18611        } else {
18612            // Use default resolved text alignment
18613            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18614        }
18615
18616        // Set the resolved
18617        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
18618        return true;
18619    }
18620
18621    /**
18622     * Check if text alignment resolution can be done.
18623     *
18624     * @return true if text alignment resolution can be done otherwise return false.
18625     */
18626    public boolean canResolveTextAlignment() {
18627        switch (getRawTextAlignment()) {
18628            case TEXT_DIRECTION_INHERIT:
18629                if (mParent != null) {
18630                    try {
18631                        return mParent.canResolveTextAlignment();
18632                    } catch (AbstractMethodError e) {
18633                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18634                                " does not fully implement ViewParent", e);
18635                    }
18636                }
18637                return false;
18638
18639            default:
18640                return true;
18641        }
18642    }
18643
18644    /**
18645     * Reset resolved text alignment. Text alignment will be resolved during a call to
18646     * {@link #onMeasure(int, int)}.
18647     *
18648     * @hide
18649     */
18650    public void resetResolvedTextAlignment() {
18651        // Reset any previous text alignment resolution
18652        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
18653        // Set to default
18654        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18655    }
18656
18657    /**
18658     * @return true if text alignment is inherited.
18659     *
18660     * @hide
18661     */
18662    public boolean isTextAlignmentInherited() {
18663        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
18664    }
18665
18666    /**
18667     * @return true if text alignment is resolved.
18668     */
18669    public boolean isTextAlignmentResolved() {
18670        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
18671    }
18672
18673    /**
18674     * Generate a value suitable for use in {@link #setId(int)}.
18675     * This value will not collide with ID values generated at build time by aapt for R.id.
18676     *
18677     * @return a generated ID value
18678     */
18679    public static int generateViewId() {
18680        for (;;) {
18681            final int result = sNextGeneratedId.get();
18682            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
18683            int newValue = result + 1;
18684            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
18685            if (sNextGeneratedId.compareAndSet(result, newValue)) {
18686                return result;
18687            }
18688        }
18689    }
18690
18691    /**
18692     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
18693     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
18694     *                           a normal View or a ViewGroup with
18695     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
18696     * @hide
18697     */
18698    public void captureTransitioningViews(List<View> transitioningViews) {
18699        if (getVisibility() == View.VISIBLE) {
18700            transitioningViews.add(this);
18701        }
18702    }
18703
18704    /**
18705     * Adds all Views that have {@link #getSharedElementName()} non-null to sharedElements.
18706     * @param sharedElements Will contain all Views in the hierarchy having a shared element name.
18707     * @hide
18708     */
18709    public void findSharedElements(Map<String, View> sharedElements) {
18710        if (getVisibility() == VISIBLE) {
18711            String sharedElementName = getSharedElementName();
18712            if (sharedElementName != null) {
18713                sharedElements.put(sharedElementName, this);
18714            }
18715        }
18716    }
18717
18718    //
18719    // Properties
18720    //
18721    /**
18722     * A Property wrapper around the <code>alpha</code> functionality handled by the
18723     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
18724     */
18725    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
18726        @Override
18727        public void setValue(View object, float value) {
18728            object.setAlpha(value);
18729        }
18730
18731        @Override
18732        public Float get(View object) {
18733            return object.getAlpha();
18734        }
18735    };
18736
18737    /**
18738     * A Property wrapper around the <code>translationX</code> functionality handled by the
18739     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
18740     */
18741    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
18742        @Override
18743        public void setValue(View object, float value) {
18744            object.setTranslationX(value);
18745        }
18746
18747                @Override
18748        public Float get(View object) {
18749            return object.getTranslationX();
18750        }
18751    };
18752
18753    /**
18754     * A Property wrapper around the <code>translationY</code> functionality handled by the
18755     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
18756     */
18757    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
18758        @Override
18759        public void setValue(View object, float value) {
18760            object.setTranslationY(value);
18761        }
18762
18763        @Override
18764        public Float get(View object) {
18765            return object.getTranslationY();
18766        }
18767    };
18768
18769    /**
18770     * A Property wrapper around the <code>translationZ</code> functionality handled by the
18771     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
18772     */
18773    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
18774        @Override
18775        public void setValue(View object, float value) {
18776            object.setTranslationZ(value);
18777        }
18778
18779        @Override
18780        public Float get(View object) {
18781            return object.getTranslationZ();
18782        }
18783    };
18784
18785    /**
18786     * A Property wrapper around the <code>x</code> functionality handled by the
18787     * {@link View#setX(float)} and {@link View#getX()} methods.
18788     */
18789    public static final Property<View, Float> X = new FloatProperty<View>("x") {
18790        @Override
18791        public void setValue(View object, float value) {
18792            object.setX(value);
18793        }
18794
18795        @Override
18796        public Float get(View object) {
18797            return object.getX();
18798        }
18799    };
18800
18801    /**
18802     * A Property wrapper around the <code>y</code> functionality handled by the
18803     * {@link View#setY(float)} and {@link View#getY()} methods.
18804     */
18805    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
18806        @Override
18807        public void setValue(View object, float value) {
18808            object.setY(value);
18809        }
18810
18811        @Override
18812        public Float get(View object) {
18813            return object.getY();
18814        }
18815    };
18816
18817    /**
18818     * A Property wrapper around the <code>rotation</code> functionality handled by the
18819     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
18820     */
18821    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
18822        @Override
18823        public void setValue(View object, float value) {
18824            object.setRotation(value);
18825        }
18826
18827        @Override
18828        public Float get(View object) {
18829            return object.getRotation();
18830        }
18831    };
18832
18833    /**
18834     * A Property wrapper around the <code>rotationX</code> functionality handled by the
18835     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
18836     */
18837    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
18838        @Override
18839        public void setValue(View object, float value) {
18840            object.setRotationX(value);
18841        }
18842
18843        @Override
18844        public Float get(View object) {
18845            return object.getRotationX();
18846        }
18847    };
18848
18849    /**
18850     * A Property wrapper around the <code>rotationY</code> functionality handled by the
18851     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
18852     */
18853    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
18854        @Override
18855        public void setValue(View object, float value) {
18856            object.setRotationY(value);
18857        }
18858
18859        @Override
18860        public Float get(View object) {
18861            return object.getRotationY();
18862        }
18863    };
18864
18865    /**
18866     * A Property wrapper around the <code>scaleX</code> functionality handled by the
18867     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
18868     */
18869    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
18870        @Override
18871        public void setValue(View object, float value) {
18872            object.setScaleX(value);
18873        }
18874
18875        @Override
18876        public Float get(View object) {
18877            return object.getScaleX();
18878        }
18879    };
18880
18881    /**
18882     * A Property wrapper around the <code>scaleY</code> functionality handled by the
18883     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
18884     */
18885    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
18886        @Override
18887        public void setValue(View object, float value) {
18888            object.setScaleY(value);
18889        }
18890
18891        @Override
18892        public Float get(View object) {
18893            return object.getScaleY();
18894        }
18895    };
18896
18897    /**
18898     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
18899     * Each MeasureSpec represents a requirement for either the width or the height.
18900     * A MeasureSpec is comprised of a size and a mode. There are three possible
18901     * modes:
18902     * <dl>
18903     * <dt>UNSPECIFIED</dt>
18904     * <dd>
18905     * The parent has not imposed any constraint on the child. It can be whatever size
18906     * it wants.
18907     * </dd>
18908     *
18909     * <dt>EXACTLY</dt>
18910     * <dd>
18911     * The parent has determined an exact size for the child. The child is going to be
18912     * given those bounds regardless of how big it wants to be.
18913     * </dd>
18914     *
18915     * <dt>AT_MOST</dt>
18916     * <dd>
18917     * The child can be as large as it wants up to the specified size.
18918     * </dd>
18919     * </dl>
18920     *
18921     * MeasureSpecs are implemented as ints to reduce object allocation. This class
18922     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
18923     */
18924    public static class MeasureSpec {
18925        private static final int MODE_SHIFT = 30;
18926        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
18927
18928        /**
18929         * Measure specification mode: The parent has not imposed any constraint
18930         * on the child. It can be whatever size it wants.
18931         */
18932        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
18933
18934        /**
18935         * Measure specification mode: The parent has determined an exact size
18936         * for the child. The child is going to be given those bounds regardless
18937         * of how big it wants to be.
18938         */
18939        public static final int EXACTLY     = 1 << MODE_SHIFT;
18940
18941        /**
18942         * Measure specification mode: The child can be as large as it wants up
18943         * to the specified size.
18944         */
18945        public static final int AT_MOST     = 2 << MODE_SHIFT;
18946
18947        /**
18948         * Creates a measure specification based on the supplied size and mode.
18949         *
18950         * The mode must always be one of the following:
18951         * <ul>
18952         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
18953         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
18954         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
18955         * </ul>
18956         *
18957         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
18958         * implementation was such that the order of arguments did not matter
18959         * and overflow in either value could impact the resulting MeasureSpec.
18960         * {@link android.widget.RelativeLayout} was affected by this bug.
18961         * Apps targeting API levels greater than 17 will get the fixed, more strict
18962         * behavior.</p>
18963         *
18964         * @param size the size of the measure specification
18965         * @param mode the mode of the measure specification
18966         * @return the measure specification based on size and mode
18967         */
18968        public static int makeMeasureSpec(int size, int mode) {
18969            if (sUseBrokenMakeMeasureSpec) {
18970                return size + mode;
18971            } else {
18972                return (size & ~MODE_MASK) | (mode & MODE_MASK);
18973            }
18974        }
18975
18976        /**
18977         * Extracts the mode from the supplied measure specification.
18978         *
18979         * @param measureSpec the measure specification to extract the mode from
18980         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
18981         *         {@link android.view.View.MeasureSpec#AT_MOST} or
18982         *         {@link android.view.View.MeasureSpec#EXACTLY}
18983         */
18984        public static int getMode(int measureSpec) {
18985            return (measureSpec & MODE_MASK);
18986        }
18987
18988        /**
18989         * Extracts the size from the supplied measure specification.
18990         *
18991         * @param measureSpec the measure specification to extract the size from
18992         * @return the size in pixels defined in the supplied measure specification
18993         */
18994        public static int getSize(int measureSpec) {
18995            return (measureSpec & ~MODE_MASK);
18996        }
18997
18998        static int adjust(int measureSpec, int delta) {
18999            final int mode = getMode(measureSpec);
19000            if (mode == UNSPECIFIED) {
19001                // No need to adjust size for UNSPECIFIED mode.
19002                return makeMeasureSpec(0, UNSPECIFIED);
19003            }
19004            int size = getSize(measureSpec) + delta;
19005            if (size < 0) {
19006                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
19007                        ") spec: " + toString(measureSpec) + " delta: " + delta);
19008                size = 0;
19009            }
19010            return makeMeasureSpec(size, mode);
19011        }
19012
19013        /**
19014         * Returns a String representation of the specified measure
19015         * specification.
19016         *
19017         * @param measureSpec the measure specification to convert to a String
19018         * @return a String with the following format: "MeasureSpec: MODE SIZE"
19019         */
19020        public static String toString(int measureSpec) {
19021            int mode = getMode(measureSpec);
19022            int size = getSize(measureSpec);
19023
19024            StringBuilder sb = new StringBuilder("MeasureSpec: ");
19025
19026            if (mode == UNSPECIFIED)
19027                sb.append("UNSPECIFIED ");
19028            else if (mode == EXACTLY)
19029                sb.append("EXACTLY ");
19030            else if (mode == AT_MOST)
19031                sb.append("AT_MOST ");
19032            else
19033                sb.append(mode).append(" ");
19034
19035            sb.append(size);
19036            return sb.toString();
19037        }
19038    }
19039
19040    private final class CheckForLongPress implements Runnable {
19041        private int mOriginalWindowAttachCount;
19042
19043        @Override
19044        public void run() {
19045            if (isPressed() && (mParent != null)
19046                    && mOriginalWindowAttachCount == mWindowAttachCount) {
19047                if (performLongClick()) {
19048                    mHasPerformedLongPress = true;
19049                }
19050            }
19051        }
19052
19053        public void rememberWindowAttachCount() {
19054            mOriginalWindowAttachCount = mWindowAttachCount;
19055        }
19056    }
19057
19058    private final class CheckForTap implements Runnable {
19059        public float x;
19060        public float y;
19061
19062        @Override
19063        public void run() {
19064            mPrivateFlags &= ~PFLAG_PREPRESSED;
19065            setHotspot(R.attr.state_pressed, x, y);
19066            setPressed(true);
19067            checkForLongClick(ViewConfiguration.getTapTimeout());
19068        }
19069    }
19070
19071    private final class PerformClick implements Runnable {
19072        @Override
19073        public void run() {
19074            performClick();
19075        }
19076    }
19077
19078    /** @hide */
19079    public void hackTurnOffWindowResizeAnim(boolean off) {
19080        mAttachInfo.mTurnOffWindowResizeAnim = off;
19081    }
19082
19083    /**
19084     * This method returns a ViewPropertyAnimator object, which can be used to animate
19085     * specific properties on this View.
19086     *
19087     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
19088     */
19089    public ViewPropertyAnimator animate() {
19090        if (mAnimator == null) {
19091            mAnimator = new ViewPropertyAnimator(this);
19092        }
19093        return mAnimator;
19094    }
19095
19096    /**
19097     * Specifies that the shared name of the View to be shared with another Activity.
19098     * When transitioning between Activities, the name links a UI element in the starting
19099     * Activity to UI element in the called Activity. Names should be unique in the
19100     * View hierarchy.
19101     *
19102     * @param sharedElementName The cross-Activity View identifier. The called Activity will use
19103     *                 the name to match the location with a View in its layout.
19104     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.os.Bundle)
19105     */
19106    public void setSharedElementName(String sharedElementName) {
19107        setTagInternal(com.android.internal.R.id.shared_element_name, sharedElementName);
19108    }
19109
19110    /**
19111     * Returns the shared name of the View to be shared with another Activity.
19112     * When transitioning between Activities, the name links a UI element in the starting
19113     * Activity to UI element in the called Activity. Names should be unique in the
19114     * View hierarchy.
19115     *
19116     * <p>This returns null if the View is not a shared element or the name if it is.</p>
19117     *
19118     * @return The name used for this View for cross-Activity transitions or null if
19119     * this View has not been identified as shared.
19120     */
19121    public String getSharedElementName() {
19122        return (String) getTag(com.android.internal.R.id.shared_element_name);
19123    }
19124
19125    /**
19126     * Interface definition for a callback to be invoked when a hardware key event is
19127     * dispatched to this view. The callback will be invoked before the key event is
19128     * given to the view. This is only useful for hardware keyboards; a software input
19129     * method has no obligation to trigger this listener.
19130     */
19131    public interface OnKeyListener {
19132        /**
19133         * Called when a hardware key is dispatched to a view. This allows listeners to
19134         * get a chance to respond before the target view.
19135         * <p>Key presses in software keyboards will generally NOT trigger this method,
19136         * although some may elect to do so in some situations. Do not assume a
19137         * software input method has to be key-based; even if it is, it may use key presses
19138         * in a different way than you expect, so there is no way to reliably catch soft
19139         * input key presses.
19140         *
19141         * @param v The view the key has been dispatched to.
19142         * @param keyCode The code for the physical key that was pressed
19143         * @param event The KeyEvent object containing full information about
19144         *        the event.
19145         * @return True if the listener has consumed the event, false otherwise.
19146         */
19147        boolean onKey(View v, int keyCode, KeyEvent event);
19148    }
19149
19150    /**
19151     * Interface definition for a callback to be invoked when a touch event is
19152     * dispatched to this view. The callback will be invoked before the touch
19153     * event is given to the view.
19154     */
19155    public interface OnTouchListener {
19156        /**
19157         * Called when a touch event is dispatched to a view. This allows listeners to
19158         * get a chance to respond before the target view.
19159         *
19160         * @param v The view the touch event has been dispatched to.
19161         * @param event The MotionEvent object containing full information about
19162         *        the event.
19163         * @return True if the listener has consumed the event, false otherwise.
19164         */
19165        boolean onTouch(View v, MotionEvent event);
19166    }
19167
19168    /**
19169     * Interface definition for a callback to be invoked when a hover event is
19170     * dispatched to this view. The callback will be invoked before the hover
19171     * event is given to the view.
19172     */
19173    public interface OnHoverListener {
19174        /**
19175         * Called when a hover event is dispatched to a view. This allows listeners to
19176         * get a chance to respond before the target view.
19177         *
19178         * @param v The view the hover event has been dispatched to.
19179         * @param event The MotionEvent object containing full information about
19180         *        the event.
19181         * @return True if the listener has consumed the event, false otherwise.
19182         */
19183        boolean onHover(View v, MotionEvent event);
19184    }
19185
19186    /**
19187     * Interface definition for a callback to be invoked when a generic motion event is
19188     * dispatched to this view. The callback will be invoked before the generic motion
19189     * event is given to the view.
19190     */
19191    public interface OnGenericMotionListener {
19192        /**
19193         * Called when a generic motion event is dispatched to a view. This allows listeners to
19194         * get a chance to respond before the target view.
19195         *
19196         * @param v The view the generic motion event has been dispatched to.
19197         * @param event The MotionEvent object containing full information about
19198         *        the event.
19199         * @return True if the listener has consumed the event, false otherwise.
19200         */
19201        boolean onGenericMotion(View v, MotionEvent event);
19202    }
19203
19204    /**
19205     * Interface definition for a callback to be invoked when a view has been clicked and held.
19206     */
19207    public interface OnLongClickListener {
19208        /**
19209         * Called when a view has been clicked and held.
19210         *
19211         * @param v The view that was clicked and held.
19212         *
19213         * @return true if the callback consumed the long click, false otherwise.
19214         */
19215        boolean onLongClick(View v);
19216    }
19217
19218    /**
19219     * Interface definition for a callback to be invoked when a drag is being dispatched
19220     * to this view.  The callback will be invoked before the hosting view's own
19221     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
19222     * onDrag(event) behavior, it should return 'false' from this callback.
19223     *
19224     * <div class="special reference">
19225     * <h3>Developer Guides</h3>
19226     * <p>For a guide to implementing drag and drop features, read the
19227     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19228     * </div>
19229     */
19230    public interface OnDragListener {
19231        /**
19232         * Called when a drag event is dispatched to a view. This allows listeners
19233         * to get a chance to override base View behavior.
19234         *
19235         * @param v The View that received the drag event.
19236         * @param event The {@link android.view.DragEvent} object for the drag event.
19237         * @return {@code true} if the drag event was handled successfully, or {@code false}
19238         * if the drag event was not handled. Note that {@code false} will trigger the View
19239         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
19240         */
19241        boolean onDrag(View v, DragEvent event);
19242    }
19243
19244    /**
19245     * Interface definition for a callback to be invoked when the focus state of
19246     * a view changed.
19247     */
19248    public interface OnFocusChangeListener {
19249        /**
19250         * Called when the focus state of a view has changed.
19251         *
19252         * @param v The view whose state has changed.
19253         * @param hasFocus The new focus state of v.
19254         */
19255        void onFocusChange(View v, boolean hasFocus);
19256    }
19257
19258    /**
19259     * Interface definition for a callback to be invoked when a view is clicked.
19260     */
19261    public interface OnClickListener {
19262        /**
19263         * Called when a view has been clicked.
19264         *
19265         * @param v The view that was clicked.
19266         */
19267        void onClick(View v);
19268    }
19269
19270    /**
19271     * Interface definition for a callback to be invoked when the context menu
19272     * for this view is being built.
19273     */
19274    public interface OnCreateContextMenuListener {
19275        /**
19276         * Called when the context menu for this view is being built. It is not
19277         * safe to hold onto the menu after this method returns.
19278         *
19279         * @param menu The context menu that is being built
19280         * @param v The view for which the context menu is being built
19281         * @param menuInfo Extra information about the item for which the
19282         *            context menu should be shown. This information will vary
19283         *            depending on the class of v.
19284         */
19285        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
19286    }
19287
19288    /**
19289     * Interface definition for a callback to be invoked when the status bar changes
19290     * visibility.  This reports <strong>global</strong> changes to the system UI
19291     * state, not what the application is requesting.
19292     *
19293     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
19294     */
19295    public interface OnSystemUiVisibilityChangeListener {
19296        /**
19297         * Called when the status bar changes visibility because of a call to
19298         * {@link View#setSystemUiVisibility(int)}.
19299         *
19300         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19301         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
19302         * This tells you the <strong>global</strong> state of these UI visibility
19303         * flags, not what your app is currently applying.
19304         */
19305        public void onSystemUiVisibilityChange(int visibility);
19306    }
19307
19308    /**
19309     * Interface definition for a callback to be invoked when this view is attached
19310     * or detached from its window.
19311     */
19312    public interface OnAttachStateChangeListener {
19313        /**
19314         * Called when the view is attached to a window.
19315         * @param v The view that was attached
19316         */
19317        public void onViewAttachedToWindow(View v);
19318        /**
19319         * Called when the view is detached from a window.
19320         * @param v The view that was detached
19321         */
19322        public void onViewDetachedFromWindow(View v);
19323    }
19324
19325    /**
19326     * Listener for applying window insets on a view in a custom way.
19327     *
19328     * <p>Apps may choose to implement this interface if they want to apply custom policy
19329     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
19330     * is set, its
19331     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
19332     * method will be called instead of the View's own
19333     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
19334     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
19335     * the View's normal behavior as part of its own.</p>
19336     */
19337    public interface OnApplyWindowInsetsListener {
19338        /**
19339         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
19340         * on a View, this listener method will be called instead of the view's own
19341         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
19342         *
19343         * @param v The view applying window insets
19344         * @param insets The insets to apply
19345         * @return The insets supplied, minus any insets that were consumed
19346         */
19347        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
19348    }
19349
19350    private final class UnsetPressedState implements Runnable {
19351        @Override
19352        public void run() {
19353            clearHotspot(R.attr.state_pressed);
19354            setPressed(false);
19355        }
19356    }
19357
19358    /**
19359     * Base class for derived classes that want to save and restore their own
19360     * state in {@link android.view.View#onSaveInstanceState()}.
19361     */
19362    public static class BaseSavedState extends AbsSavedState {
19363        /**
19364         * Constructor used when reading from a parcel. Reads the state of the superclass.
19365         *
19366         * @param source
19367         */
19368        public BaseSavedState(Parcel source) {
19369            super(source);
19370        }
19371
19372        /**
19373         * Constructor called by derived classes when creating their SavedState objects
19374         *
19375         * @param superState The state of the superclass of this view
19376         */
19377        public BaseSavedState(Parcelable superState) {
19378            super(superState);
19379        }
19380
19381        public static final Parcelable.Creator<BaseSavedState> CREATOR =
19382                new Parcelable.Creator<BaseSavedState>() {
19383            public BaseSavedState createFromParcel(Parcel in) {
19384                return new BaseSavedState(in);
19385            }
19386
19387            public BaseSavedState[] newArray(int size) {
19388                return new BaseSavedState[size];
19389            }
19390        };
19391    }
19392
19393    /**
19394     * A set of information given to a view when it is attached to its parent
19395     * window.
19396     */
19397    final static class AttachInfo {
19398        interface Callbacks {
19399            void playSoundEffect(int effectId);
19400            boolean performHapticFeedback(int effectId, boolean always);
19401        }
19402
19403        /**
19404         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
19405         * to a Handler. This class contains the target (View) to invalidate and
19406         * the coordinates of the dirty rectangle.
19407         *
19408         * For performance purposes, this class also implements a pool of up to
19409         * POOL_LIMIT objects that get reused. This reduces memory allocations
19410         * whenever possible.
19411         */
19412        static class InvalidateInfo {
19413            private static final int POOL_LIMIT = 10;
19414
19415            private static final SynchronizedPool<InvalidateInfo> sPool =
19416                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
19417
19418            View target;
19419
19420            int left;
19421            int top;
19422            int right;
19423            int bottom;
19424
19425            public static InvalidateInfo obtain() {
19426                InvalidateInfo instance = sPool.acquire();
19427                return (instance != null) ? instance : new InvalidateInfo();
19428            }
19429
19430            public void recycle() {
19431                target = null;
19432                sPool.release(this);
19433            }
19434        }
19435
19436        final IWindowSession mSession;
19437
19438        final IWindow mWindow;
19439
19440        final IBinder mWindowToken;
19441
19442        final Display mDisplay;
19443
19444        final Callbacks mRootCallbacks;
19445
19446        IWindowId mIWindowId;
19447        WindowId mWindowId;
19448
19449        /**
19450         * The top view of the hierarchy.
19451         */
19452        View mRootView;
19453
19454        IBinder mPanelParentWindowToken;
19455
19456        boolean mHardwareAccelerated;
19457        boolean mHardwareAccelerationRequested;
19458        HardwareRenderer mHardwareRenderer;
19459
19460        /**
19461         * The state of the display to which the window is attached, as reported
19462         * by {@link Display#getState()}.  Note that the display state constants
19463         * declared by {@link Display} do not exactly line up with the screen state
19464         * constants declared by {@link View} (there are more display states than
19465         * screen states).
19466         */
19467        int mDisplayState = Display.STATE_UNKNOWN;
19468
19469        /**
19470         * Scale factor used by the compatibility mode
19471         */
19472        float mApplicationScale;
19473
19474        /**
19475         * Indicates whether the application is in compatibility mode
19476         */
19477        boolean mScalingRequired;
19478
19479        /**
19480         * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
19481         */
19482        boolean mTurnOffWindowResizeAnim;
19483
19484        /**
19485         * Left position of this view's window
19486         */
19487        int mWindowLeft;
19488
19489        /**
19490         * Top position of this view's window
19491         */
19492        int mWindowTop;
19493
19494        /**
19495         * Indicates whether views need to use 32-bit drawing caches
19496         */
19497        boolean mUse32BitDrawingCache;
19498
19499        /**
19500         * For windows that are full-screen but using insets to layout inside
19501         * of the screen areas, these are the current insets to appear inside
19502         * the overscan area of the display.
19503         */
19504        final Rect mOverscanInsets = new Rect();
19505
19506        /**
19507         * For windows that are full-screen but using insets to layout inside
19508         * of the screen decorations, these are the current insets for the
19509         * content of the window.
19510         */
19511        final Rect mContentInsets = new Rect();
19512
19513        /**
19514         * For windows that are full-screen but using insets to layout inside
19515         * of the screen decorations, these are the current insets for the
19516         * actual visible parts of the window.
19517         */
19518        final Rect mVisibleInsets = new Rect();
19519
19520        /**
19521         * The internal insets given by this window.  This value is
19522         * supplied by the client (through
19523         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
19524         * be given to the window manager when changed to be used in laying
19525         * out windows behind it.
19526         */
19527        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
19528                = new ViewTreeObserver.InternalInsetsInfo();
19529
19530        /**
19531         * Set to true when mGivenInternalInsets is non-empty.
19532         */
19533        boolean mHasNonEmptyGivenInternalInsets;
19534
19535        /**
19536         * All views in the window's hierarchy that serve as scroll containers,
19537         * used to determine if the window can be resized or must be panned
19538         * to adjust for a soft input area.
19539         */
19540        final ArrayList<View> mScrollContainers = new ArrayList<View>();
19541
19542        final KeyEvent.DispatcherState mKeyDispatchState
19543                = new KeyEvent.DispatcherState();
19544
19545        /**
19546         * Indicates whether the view's window currently has the focus.
19547         */
19548        boolean mHasWindowFocus;
19549
19550        /**
19551         * The current visibility of the window.
19552         */
19553        int mWindowVisibility;
19554
19555        /**
19556         * Indicates the time at which drawing started to occur.
19557         */
19558        long mDrawingTime;
19559
19560        /**
19561         * Indicates whether or not ignoring the DIRTY_MASK flags.
19562         */
19563        boolean mIgnoreDirtyState;
19564
19565        /**
19566         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
19567         * to avoid clearing that flag prematurely.
19568         */
19569        boolean mSetIgnoreDirtyState = false;
19570
19571        /**
19572         * Indicates whether the view's window is currently in touch mode.
19573         */
19574        boolean mInTouchMode;
19575
19576        /**
19577         * Indicates that ViewAncestor should trigger a global layout change
19578         * the next time it performs a traversal
19579         */
19580        boolean mRecomputeGlobalAttributes;
19581
19582        /**
19583         * Always report new attributes at next traversal.
19584         */
19585        boolean mForceReportNewAttributes;
19586
19587        /**
19588         * Set during a traveral if any views want to keep the screen on.
19589         */
19590        boolean mKeepScreenOn;
19591
19592        /**
19593         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
19594         */
19595        int mSystemUiVisibility;
19596
19597        /**
19598         * Hack to force certain system UI visibility flags to be cleared.
19599         */
19600        int mDisabledSystemUiVisibility;
19601
19602        /**
19603         * Last global system UI visibility reported by the window manager.
19604         */
19605        int mGlobalSystemUiVisibility;
19606
19607        /**
19608         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
19609         * attached.
19610         */
19611        boolean mHasSystemUiListeners;
19612
19613        /**
19614         * Set if the window has requested to extend into the overscan region
19615         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
19616         */
19617        boolean mOverscanRequested;
19618
19619        /**
19620         * Set if the visibility of any views has changed.
19621         */
19622        boolean mViewVisibilityChanged;
19623
19624        /**
19625         * Set to true if a view has been scrolled.
19626         */
19627        boolean mViewScrollChanged;
19628
19629        /**
19630         * Global to the view hierarchy used as a temporary for dealing with
19631         * x/y points in the transparent region computations.
19632         */
19633        final int[] mTransparentLocation = new int[2];
19634
19635        /**
19636         * Global to the view hierarchy used as a temporary for dealing with
19637         * x/y points in the ViewGroup.invalidateChild implementation.
19638         */
19639        final int[] mInvalidateChildLocation = new int[2];
19640
19641
19642        /**
19643         * Global to the view hierarchy used as a temporary for dealing with
19644         * x/y location when view is transformed.
19645         */
19646        final float[] mTmpTransformLocation = new float[2];
19647
19648        /**
19649         * The view tree observer used to dispatch global events like
19650         * layout, pre-draw, touch mode change, etc.
19651         */
19652        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
19653
19654        /**
19655         * A Canvas used by the view hierarchy to perform bitmap caching.
19656         */
19657        Canvas mCanvas;
19658
19659        /**
19660         * The view root impl.
19661         */
19662        final ViewRootImpl mViewRootImpl;
19663
19664        /**
19665         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
19666         * handler can be used to pump events in the UI events queue.
19667         */
19668        final Handler mHandler;
19669
19670        /**
19671         * Temporary for use in computing invalidate rectangles while
19672         * calling up the hierarchy.
19673         */
19674        final Rect mTmpInvalRect = new Rect();
19675
19676        /**
19677         * Temporary for use in computing hit areas with transformed views
19678         */
19679        final RectF mTmpTransformRect = new RectF();
19680
19681        /**
19682         * Temporary for use in transforming invalidation rect
19683         */
19684        final Matrix mTmpMatrix = new Matrix();
19685
19686        /**
19687         * Temporary for use in transforming invalidation rect
19688         */
19689        final Transformation mTmpTransformation = new Transformation();
19690
19691        /**
19692         * Temporary list for use in collecting focusable descendents of a view.
19693         */
19694        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
19695
19696        /**
19697         * The id of the window for accessibility purposes.
19698         */
19699        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
19700
19701        /**
19702         * Flags related to accessibility processing.
19703         *
19704         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
19705         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
19706         */
19707        int mAccessibilityFetchFlags;
19708
19709        /**
19710         * The drawable for highlighting accessibility focus.
19711         */
19712        Drawable mAccessibilityFocusDrawable;
19713
19714        /**
19715         * Show where the margins, bounds and layout bounds are for each view.
19716         */
19717        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
19718
19719        /**
19720         * Point used to compute visible regions.
19721         */
19722        final Point mPoint = new Point();
19723
19724        /**
19725         * Used to track which View originated a requestLayout() call, used when
19726         * requestLayout() is called during layout.
19727         */
19728        View mViewRequestingLayout;
19729
19730        /**
19731         * Creates a new set of attachment information with the specified
19732         * events handler and thread.
19733         *
19734         * @param handler the events handler the view must use
19735         */
19736        AttachInfo(IWindowSession session, IWindow window, Display display,
19737                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
19738            mSession = session;
19739            mWindow = window;
19740            mWindowToken = window.asBinder();
19741            mDisplay = display;
19742            mViewRootImpl = viewRootImpl;
19743            mHandler = handler;
19744            mRootCallbacks = effectPlayer;
19745        }
19746    }
19747
19748    /**
19749     * <p>ScrollabilityCache holds various fields used by a View when scrolling
19750     * is supported. This avoids keeping too many unused fields in most
19751     * instances of View.</p>
19752     */
19753    private static class ScrollabilityCache implements Runnable {
19754
19755        /**
19756         * Scrollbars are not visible
19757         */
19758        public static final int OFF = 0;
19759
19760        /**
19761         * Scrollbars are visible
19762         */
19763        public static final int ON = 1;
19764
19765        /**
19766         * Scrollbars are fading away
19767         */
19768        public static final int FADING = 2;
19769
19770        public boolean fadeScrollBars;
19771
19772        public int fadingEdgeLength;
19773        public int scrollBarDefaultDelayBeforeFade;
19774        public int scrollBarFadeDuration;
19775
19776        public int scrollBarSize;
19777        public ScrollBarDrawable scrollBar;
19778        public float[] interpolatorValues;
19779        public View host;
19780
19781        public final Paint paint;
19782        public final Matrix matrix;
19783        public Shader shader;
19784
19785        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
19786
19787        private static final float[] OPAQUE = { 255 };
19788        private static final float[] TRANSPARENT = { 0.0f };
19789
19790        /**
19791         * When fading should start. This time moves into the future every time
19792         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
19793         */
19794        public long fadeStartTime;
19795
19796
19797        /**
19798         * The current state of the scrollbars: ON, OFF, or FADING
19799         */
19800        public int state = OFF;
19801
19802        private int mLastColor;
19803
19804        public ScrollabilityCache(ViewConfiguration configuration, View host) {
19805            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
19806            scrollBarSize = configuration.getScaledScrollBarSize();
19807            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
19808            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
19809
19810            paint = new Paint();
19811            matrix = new Matrix();
19812            // use use a height of 1, and then wack the matrix each time we
19813            // actually use it.
19814            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
19815            paint.setShader(shader);
19816            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
19817
19818            this.host = host;
19819        }
19820
19821        public void setFadeColor(int color) {
19822            if (color != mLastColor) {
19823                mLastColor = color;
19824
19825                if (color != 0) {
19826                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
19827                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
19828                    paint.setShader(shader);
19829                    // Restore the default transfer mode (src_over)
19830                    paint.setXfermode(null);
19831                } else {
19832                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
19833                    paint.setShader(shader);
19834                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
19835                }
19836            }
19837        }
19838
19839        public void run() {
19840            long now = AnimationUtils.currentAnimationTimeMillis();
19841            if (now >= fadeStartTime) {
19842
19843                // the animation fades the scrollbars out by changing
19844                // the opacity (alpha) from fully opaque to fully
19845                // transparent
19846                int nextFrame = (int) now;
19847                int framesCount = 0;
19848
19849                Interpolator interpolator = scrollBarInterpolator;
19850
19851                // Start opaque
19852                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
19853
19854                // End transparent
19855                nextFrame += scrollBarFadeDuration;
19856                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
19857
19858                state = FADING;
19859
19860                // Kick off the fade animation
19861                host.invalidate(true);
19862            }
19863        }
19864    }
19865
19866    /**
19867     * Resuable callback for sending
19868     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
19869     */
19870    private class SendViewScrolledAccessibilityEvent implements Runnable {
19871        public volatile boolean mIsPending;
19872
19873        public void run() {
19874            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
19875            mIsPending = false;
19876        }
19877    }
19878
19879    /**
19880     * <p>
19881     * This class represents a delegate that can be registered in a {@link View}
19882     * to enhance accessibility support via composition rather via inheritance.
19883     * It is specifically targeted to widget developers that extend basic View
19884     * classes i.e. classes in package android.view, that would like their
19885     * applications to be backwards compatible.
19886     * </p>
19887     * <div class="special reference">
19888     * <h3>Developer Guides</h3>
19889     * <p>For more information about making applications accessible, read the
19890     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
19891     * developer guide.</p>
19892     * </div>
19893     * <p>
19894     * A scenario in which a developer would like to use an accessibility delegate
19895     * is overriding a method introduced in a later API version then the minimal API
19896     * version supported by the application. For example, the method
19897     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
19898     * in API version 4 when the accessibility APIs were first introduced. If a
19899     * developer would like his application to run on API version 4 devices (assuming
19900     * all other APIs used by the application are version 4 or lower) and take advantage
19901     * of this method, instead of overriding the method which would break the application's
19902     * backwards compatibility, he can override the corresponding method in this
19903     * delegate and register the delegate in the target View if the API version of
19904     * the system is high enough i.e. the API version is same or higher to the API
19905     * version that introduced
19906     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
19907     * </p>
19908     * <p>
19909     * Here is an example implementation:
19910     * </p>
19911     * <code><pre><p>
19912     * if (Build.VERSION.SDK_INT >= 14) {
19913     *     // If the API version is equal of higher than the version in
19914     *     // which onInitializeAccessibilityNodeInfo was introduced we
19915     *     // register a delegate with a customized implementation.
19916     *     View view = findViewById(R.id.view_id);
19917     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
19918     *         public void onInitializeAccessibilityNodeInfo(View host,
19919     *                 AccessibilityNodeInfo info) {
19920     *             // Let the default implementation populate the info.
19921     *             super.onInitializeAccessibilityNodeInfo(host, info);
19922     *             // Set some other information.
19923     *             info.setEnabled(host.isEnabled());
19924     *         }
19925     *     });
19926     * }
19927     * </code></pre></p>
19928     * <p>
19929     * This delegate contains methods that correspond to the accessibility methods
19930     * in View. If a delegate has been specified the implementation in View hands
19931     * off handling to the corresponding method in this delegate. The default
19932     * implementation the delegate methods behaves exactly as the corresponding
19933     * method in View for the case of no accessibility delegate been set. Hence,
19934     * to customize the behavior of a View method, clients can override only the
19935     * corresponding delegate method without altering the behavior of the rest
19936     * accessibility related methods of the host view.
19937     * </p>
19938     */
19939    public static class AccessibilityDelegate {
19940
19941        /**
19942         * Sends an accessibility event of the given type. If accessibility is not
19943         * enabled this method has no effect.
19944         * <p>
19945         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
19946         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
19947         * been set.
19948         * </p>
19949         *
19950         * @param host The View hosting the delegate.
19951         * @param eventType The type of the event to send.
19952         *
19953         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
19954         */
19955        public void sendAccessibilityEvent(View host, int eventType) {
19956            host.sendAccessibilityEventInternal(eventType);
19957        }
19958
19959        /**
19960         * Performs the specified accessibility action on the view. For
19961         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
19962         * <p>
19963         * The default implementation behaves as
19964         * {@link View#performAccessibilityAction(int, Bundle)
19965         *  View#performAccessibilityAction(int, Bundle)} for the case of
19966         *  no accessibility delegate been set.
19967         * </p>
19968         *
19969         * @param action The action to perform.
19970         * @return Whether the action was performed.
19971         *
19972         * @see View#performAccessibilityAction(int, Bundle)
19973         *      View#performAccessibilityAction(int, Bundle)
19974         */
19975        public boolean performAccessibilityAction(View host, int action, Bundle args) {
19976            return host.performAccessibilityActionInternal(action, args);
19977        }
19978
19979        /**
19980         * Sends an accessibility event. This method behaves exactly as
19981         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
19982         * empty {@link AccessibilityEvent} and does not perform a check whether
19983         * accessibility is enabled.
19984         * <p>
19985         * The default implementation behaves as
19986         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
19987         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
19988         * the case of no accessibility delegate been set.
19989         * </p>
19990         *
19991         * @param host The View hosting the delegate.
19992         * @param event The event to send.
19993         *
19994         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
19995         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
19996         */
19997        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
19998            host.sendAccessibilityEventUncheckedInternal(event);
19999        }
20000
20001        /**
20002         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
20003         * to its children for adding their text content to the event.
20004         * <p>
20005         * The default implementation behaves as
20006         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20007         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
20008         * the case of no accessibility delegate been set.
20009         * </p>
20010         *
20011         * @param host The View hosting the delegate.
20012         * @param event The event.
20013         * @return True if the event population was completed.
20014         *
20015         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20016         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20017         */
20018        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20019            return host.dispatchPopulateAccessibilityEventInternal(event);
20020        }
20021
20022        /**
20023         * Gives a chance to the host View to populate the accessibility event with its
20024         * text content.
20025         * <p>
20026         * The default implementation behaves as
20027         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
20028         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
20029         * the case of no accessibility delegate been set.
20030         * </p>
20031         *
20032         * @param host The View hosting the delegate.
20033         * @param event The accessibility event which to populate.
20034         *
20035         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
20036         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
20037         */
20038        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20039            host.onPopulateAccessibilityEventInternal(event);
20040        }
20041
20042        /**
20043         * Initializes an {@link AccessibilityEvent} with information about the
20044         * the host View which is the event source.
20045         * <p>
20046         * The default implementation behaves as
20047         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
20048         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
20049         * the case of no accessibility delegate been set.
20050         * </p>
20051         *
20052         * @param host The View hosting the delegate.
20053         * @param event The event to initialize.
20054         *
20055         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
20056         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
20057         */
20058        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
20059            host.onInitializeAccessibilityEventInternal(event);
20060        }
20061
20062        /**
20063         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
20064         * <p>
20065         * The default implementation behaves as
20066         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20067         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
20068         * the case of no accessibility delegate been set.
20069         * </p>
20070         *
20071         * @param host The View hosting the delegate.
20072         * @param info The instance to initialize.
20073         *
20074         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20075         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20076         */
20077        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
20078            host.onInitializeAccessibilityNodeInfoInternal(info);
20079        }
20080
20081        /**
20082         * Called when a child of the host View has requested sending an
20083         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
20084         * to augment the event.
20085         * <p>
20086         * The default implementation behaves as
20087         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20088         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
20089         * the case of no accessibility delegate been set.
20090         * </p>
20091         *
20092         * @param host The View hosting the delegate.
20093         * @param child The child which requests sending the event.
20094         * @param event The event to be sent.
20095         * @return True if the event should be sent
20096         *
20097         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20098         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20099         */
20100        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
20101                AccessibilityEvent event) {
20102            return host.onRequestSendAccessibilityEventInternal(child, event);
20103        }
20104
20105        /**
20106         * Gets the provider for managing a virtual view hierarchy rooted at this View
20107         * and reported to {@link android.accessibilityservice.AccessibilityService}s
20108         * that explore the window content.
20109         * <p>
20110         * The default implementation behaves as
20111         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
20112         * the case of no accessibility delegate been set.
20113         * </p>
20114         *
20115         * @return The provider.
20116         *
20117         * @see AccessibilityNodeProvider
20118         */
20119        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
20120            return null;
20121        }
20122
20123        /**
20124         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
20125         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
20126         * This method is responsible for obtaining an accessibility node info from a
20127         * pool of reusable instances and calling
20128         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
20129         * view to initialize the former.
20130         * <p>
20131         * <strong>Note:</strong> The client is responsible for recycling the obtained
20132         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
20133         * creation.
20134         * </p>
20135         * <p>
20136         * The default implementation behaves as
20137         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
20138         * the case of no accessibility delegate been set.
20139         * </p>
20140         * @return A populated {@link AccessibilityNodeInfo}.
20141         *
20142         * @see AccessibilityNodeInfo
20143         *
20144         * @hide
20145         */
20146        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
20147            return host.createAccessibilityNodeInfoInternal();
20148        }
20149    }
20150
20151    private class MatchIdPredicate implements Predicate<View> {
20152        public int mId;
20153
20154        @Override
20155        public boolean apply(View view) {
20156            return (view.mID == mId);
20157        }
20158    }
20159
20160    private class MatchLabelForPredicate implements Predicate<View> {
20161        private int mLabeledId;
20162
20163        @Override
20164        public boolean apply(View view) {
20165            return (view.mLabelForId == mLabeledId);
20166        }
20167    }
20168
20169    private class SendViewStateChangedAccessibilityEvent implements Runnable {
20170        private int mChangeTypes = 0;
20171        private boolean mPosted;
20172        private boolean mPostedWithDelay;
20173        private long mLastEventTimeMillis;
20174
20175        @Override
20176        public void run() {
20177            mPosted = false;
20178            mPostedWithDelay = false;
20179            mLastEventTimeMillis = SystemClock.uptimeMillis();
20180            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
20181                final AccessibilityEvent event = AccessibilityEvent.obtain();
20182                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
20183                event.setContentChangeTypes(mChangeTypes);
20184                sendAccessibilityEventUnchecked(event);
20185            }
20186            mChangeTypes = 0;
20187        }
20188
20189        public void runOrPost(int changeType) {
20190            mChangeTypes |= changeType;
20191
20192            // If this is a live region or the child of a live region, collect
20193            // all events from this frame and send them on the next frame.
20194            if (inLiveRegion()) {
20195                // If we're already posted with a delay, remove that.
20196                if (mPostedWithDelay) {
20197                    removeCallbacks(this);
20198                    mPostedWithDelay = false;
20199                }
20200                // Only post if we're not already posted.
20201                if (!mPosted) {
20202                    post(this);
20203                    mPosted = true;
20204                }
20205                return;
20206            }
20207
20208            if (mPosted) {
20209                return;
20210            }
20211            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
20212            final long minEventIntevalMillis =
20213                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
20214            if (timeSinceLastMillis >= minEventIntevalMillis) {
20215                removeCallbacks(this);
20216                run();
20217            } else {
20218                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
20219                mPosted = true;
20220                mPostedWithDelay = true;
20221            }
20222        }
20223    }
20224
20225    private boolean inLiveRegion() {
20226        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
20227            return true;
20228        }
20229
20230        ViewParent parent = getParent();
20231        while (parent instanceof View) {
20232            if (((View) parent).getAccessibilityLiveRegion()
20233                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
20234                return true;
20235            }
20236            parent = parent.getParent();
20237        }
20238
20239        return false;
20240    }
20241
20242    /**
20243     * Dump all private flags in readable format, useful for documentation and
20244     * sanity checking.
20245     */
20246    private static void dumpFlags() {
20247        final HashMap<String, String> found = Maps.newHashMap();
20248        try {
20249            for (Field field : View.class.getDeclaredFields()) {
20250                final int modifiers = field.getModifiers();
20251                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
20252                    if (field.getType().equals(int.class)) {
20253                        final int value = field.getInt(null);
20254                        dumpFlag(found, field.getName(), value);
20255                    } else if (field.getType().equals(int[].class)) {
20256                        final int[] values = (int[]) field.get(null);
20257                        for (int i = 0; i < values.length; i++) {
20258                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
20259                        }
20260                    }
20261                }
20262            }
20263        } catch (IllegalAccessException e) {
20264            throw new RuntimeException(e);
20265        }
20266
20267        final ArrayList<String> keys = Lists.newArrayList();
20268        keys.addAll(found.keySet());
20269        Collections.sort(keys);
20270        for (String key : keys) {
20271            Log.d(VIEW_LOG_TAG, found.get(key));
20272        }
20273    }
20274
20275    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
20276        // Sort flags by prefix, then by bits, always keeping unique keys
20277        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
20278        final int prefix = name.indexOf('_');
20279        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
20280        final String output = bits + " " + name;
20281        found.put(key, output);
20282    }
20283}
20284