View.java revision 7b7ca3cdf25bee73aa9e58aaaf6ce75fe81bd045
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.AnimatorInflater;
20import android.animation.RevealAnimator;
21import android.animation.StateListAnimator;
22import android.animation.ValueAnimator;
23import android.annotation.IntDef;
24import android.annotation.NonNull;
25import android.annotation.Nullable;
26import android.content.ClipData;
27import android.content.Context;
28import android.content.res.ColorStateList;
29import android.content.res.Configuration;
30import android.content.res.Resources;
31import android.content.res.TypedArray;
32import android.graphics.Bitmap;
33import android.graphics.Canvas;
34import android.graphics.Insets;
35import android.graphics.Interpolator;
36import android.graphics.LinearGradient;
37import android.graphics.Matrix;
38import android.graphics.Outline;
39import android.graphics.Paint;
40import android.graphics.PixelFormat;
41import android.graphics.Point;
42import android.graphics.PorterDuff;
43import android.graphics.PorterDuffXfermode;
44import android.graphics.Rect;
45import android.graphics.RectF;
46import android.graphics.Region;
47import android.graphics.Shader;
48import android.graphics.drawable.ColorDrawable;
49import android.graphics.drawable.Drawable;
50import android.hardware.display.DisplayManagerGlobal;
51import android.os.Bundle;
52import android.os.Handler;
53import android.os.IBinder;
54import android.os.Parcel;
55import android.os.Parcelable;
56import android.os.RemoteException;
57import android.os.SystemClock;
58import android.os.SystemProperties;
59import android.text.TextUtils;
60import android.util.AttributeSet;
61import android.util.FloatProperty;
62import android.util.LayoutDirection;
63import android.util.Log;
64import android.util.LongSparseLongArray;
65import android.util.Pools.SynchronizedPool;
66import android.util.Property;
67import android.util.SparseArray;
68import android.util.SuperNotCalledException;
69import android.util.TypedValue;
70import android.view.ContextMenu.ContextMenuInfo;
71import android.view.AccessibilityIterators.TextSegmentIterator;
72import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
73import android.view.AccessibilityIterators.WordTextSegmentIterator;
74import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
75import android.view.accessibility.AccessibilityEvent;
76import android.view.accessibility.AccessibilityEventSource;
77import android.view.accessibility.AccessibilityManager;
78import android.view.accessibility.AccessibilityNodeInfo;
79import android.view.accessibility.AccessibilityNodeProvider;
80import android.view.animation.Animation;
81import android.view.animation.AnimationUtils;
82import android.view.animation.Transformation;
83import android.view.inputmethod.EditorInfo;
84import android.view.inputmethod.InputConnection;
85import android.view.inputmethod.InputMethodManager;
86import android.widget.ScrollBarDrawable;
87
88import static android.os.Build.VERSION_CODES.*;
89import static java.lang.Math.max;
90
91import com.android.internal.R;
92import com.android.internal.util.Predicate;
93import com.android.internal.view.menu.MenuBuilder;
94
95import com.google.android.collect.Lists;
96import com.google.android.collect.Maps;
97
98import java.lang.annotation.Retention;
99import java.lang.annotation.RetentionPolicy;
100import java.lang.ref.WeakReference;
101import java.lang.reflect.Field;
102import java.lang.reflect.InvocationTargetException;
103import java.lang.reflect.Method;
104import java.lang.reflect.Modifier;
105import java.util.ArrayList;
106import java.util.Arrays;
107import java.util.Collections;
108import java.util.HashMap;
109import java.util.List;
110import java.util.Locale;
111import java.util.Map;
112import java.util.concurrent.CopyOnWriteArrayList;
113import java.util.concurrent.atomic.AtomicInteger;
114
115/**
116 * <p>
117 * This class represents the basic building block for user interface components. A View
118 * occupies a rectangular area on the screen and is responsible for drawing and
119 * event handling. View is the base class for <em>widgets</em>, which are
120 * used to create interactive UI components (buttons, text fields, etc.). The
121 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
122 * are invisible containers that hold other Views (or other ViewGroups) and define
123 * their layout properties.
124 * </p>
125 *
126 * <div class="special reference">
127 * <h3>Developer Guides</h3>
128 * <p>For information about using this class to develop your application's user interface,
129 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
130 * </div>
131 *
132 * <a name="Using"></a>
133 * <h3>Using Views</h3>
134 * <p>
135 * All of the views in a window are arranged in a single tree. You can add views
136 * either from code or by specifying a tree of views in one or more XML layout
137 * files. There are many specialized subclasses of views that act as controls or
138 * are capable of displaying text, images, or other content.
139 * </p>
140 * <p>
141 * Once you have created a tree of views, there are typically a few types of
142 * common operations you may wish to perform:
143 * <ul>
144 * <li><strong>Set properties:</strong> for example setting the text of a
145 * {@link android.widget.TextView}. The available properties and the methods
146 * that set them will vary among the different subclasses of views. Note that
147 * properties that are known at build time can be set in the XML layout
148 * files.</li>
149 * <li><strong>Set focus:</strong> The framework will handled moving focus in
150 * response to user input. To force focus to a specific view, call
151 * {@link #requestFocus}.</li>
152 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
153 * that will be notified when something interesting happens to the view. For
154 * example, all views will let you set a listener to be notified when the view
155 * gains or loses focus. You can register such a listener using
156 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
157 * Other view subclasses offer more specialized listeners. For example, a Button
158 * exposes a listener to notify clients when the button is clicked.</li>
159 * <li><strong>Set visibility:</strong> You can hide or show views using
160 * {@link #setVisibility(int)}.</li>
161 * </ul>
162 * </p>
163 * <p><em>
164 * Note: The Android framework is responsible for measuring, laying out and
165 * drawing views. You should not call methods that perform these actions on
166 * views yourself unless you are actually implementing a
167 * {@link android.view.ViewGroup}.
168 * </em></p>
169 *
170 * <a name="Lifecycle"></a>
171 * <h3>Implementing a Custom View</h3>
172 *
173 * <p>
174 * To implement a custom view, you will usually begin by providing overrides for
175 * some of the standard methods that the framework calls on all views. You do
176 * not need to override all of these methods. In fact, you can start by just
177 * overriding {@link #onDraw(android.graphics.Canvas)}.
178 * <table border="2" width="85%" align="center" cellpadding="5">
179 *     <thead>
180 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
181 *     </thead>
182 *
183 *     <tbody>
184 *     <tr>
185 *         <td rowspan="2">Creation</td>
186 *         <td>Constructors</td>
187 *         <td>There is a form of the constructor that are called when the view
188 *         is created from code and a form that is called when the view is
189 *         inflated from a layout file. The second form should parse and apply
190 *         any attributes defined in the layout file.
191 *         </td>
192 *     </tr>
193 *     <tr>
194 *         <td><code>{@link #onFinishInflate()}</code></td>
195 *         <td>Called after a view and all of its children has been inflated
196 *         from XML.</td>
197 *     </tr>
198 *
199 *     <tr>
200 *         <td rowspan="3">Layout</td>
201 *         <td><code>{@link #onMeasure(int, int)}</code></td>
202 *         <td>Called to determine the size requirements for this view and all
203 *         of its children.
204 *         </td>
205 *     </tr>
206 *     <tr>
207 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
208 *         <td>Called when this view should assign a size and position to all
209 *         of its children.
210 *         </td>
211 *     </tr>
212 *     <tr>
213 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
214 *         <td>Called when the size of this view has changed.
215 *         </td>
216 *     </tr>
217 *
218 *     <tr>
219 *         <td>Drawing</td>
220 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
221 *         <td>Called when the view should render its content.
222 *         </td>
223 *     </tr>
224 *
225 *     <tr>
226 *         <td rowspan="4">Event processing</td>
227 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
228 *         <td>Called when a new hardware key event occurs.
229 *         </td>
230 *     </tr>
231 *     <tr>
232 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
233 *         <td>Called when a hardware key up event occurs.
234 *         </td>
235 *     </tr>
236 *     <tr>
237 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
238 *         <td>Called when a trackball motion event occurs.
239 *         </td>
240 *     </tr>
241 *     <tr>
242 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
243 *         <td>Called when a touch screen motion event occurs.
244 *         </td>
245 *     </tr>
246 *
247 *     <tr>
248 *         <td rowspan="2">Focus</td>
249 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
250 *         <td>Called when the view gains or loses focus.
251 *         </td>
252 *     </tr>
253 *
254 *     <tr>
255 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
256 *         <td>Called when the window containing the view gains or loses focus.
257 *         </td>
258 *     </tr>
259 *
260 *     <tr>
261 *         <td rowspan="3">Attaching</td>
262 *         <td><code>{@link #onAttachedToWindow()}</code></td>
263 *         <td>Called when the view is attached to a window.
264 *         </td>
265 *     </tr>
266 *
267 *     <tr>
268 *         <td><code>{@link #onDetachedFromWindow}</code></td>
269 *         <td>Called when the view is detached from its window.
270 *         </td>
271 *     </tr>
272 *
273 *     <tr>
274 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
275 *         <td>Called when the visibility of the window containing the view
276 *         has changed.
277 *         </td>
278 *     </tr>
279 *     </tbody>
280 *
281 * </table>
282 * </p>
283 *
284 * <a name="IDs"></a>
285 * <h3>IDs</h3>
286 * Views may have an integer id associated with them. These ids are typically
287 * assigned in the layout XML files, and are used to find specific views within
288 * the view tree. A common pattern is to:
289 * <ul>
290 * <li>Define a Button in the layout file and assign it a unique ID.
291 * <pre>
292 * &lt;Button
293 *     android:id="@+id/my_button"
294 *     android:layout_width="wrap_content"
295 *     android:layout_height="wrap_content"
296 *     android:text="@string/my_button_text"/&gt;
297 * </pre></li>
298 * <li>From the onCreate method of an Activity, find the Button
299 * <pre class="prettyprint">
300 *      Button myButton = (Button) findViewById(R.id.my_button);
301 * </pre></li>
302 * </ul>
303 * <p>
304 * View IDs need not be unique throughout the tree, but it is good practice to
305 * ensure that they are at least unique within the part of the tree you are
306 * searching.
307 * </p>
308 *
309 * <a name="Position"></a>
310 * <h3>Position</h3>
311 * <p>
312 * The geometry of a view is that of a rectangle. A view has a location,
313 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
314 * two dimensions, expressed as a width and a height. The unit for location
315 * and dimensions is the pixel.
316 * </p>
317 *
318 * <p>
319 * It is possible to retrieve the location of a view by invoking the methods
320 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
321 * coordinate of the rectangle representing the view. The latter returns the
322 * top, or Y, coordinate of the rectangle representing the view. These methods
323 * both return the location of the view relative to its parent. For instance,
324 * when getLeft() returns 20, that means the view is located 20 pixels to the
325 * right of the left edge of its direct parent.
326 * </p>
327 *
328 * <p>
329 * In addition, several convenience methods are offered to avoid unnecessary
330 * computations, namely {@link #getRight()} and {@link #getBottom()}.
331 * These methods return the coordinates of the right and bottom edges of the
332 * rectangle representing the view. For instance, calling {@link #getRight()}
333 * is similar to the following computation: <code>getLeft() + getWidth()</code>
334 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
335 * </p>
336 *
337 * <a name="SizePaddingMargins"></a>
338 * <h3>Size, padding and margins</h3>
339 * <p>
340 * The size of a view is expressed with a width and a height. A view actually
341 * possess two pairs of width and height values.
342 * </p>
343 *
344 * <p>
345 * The first pair is known as <em>measured width</em> and
346 * <em>measured height</em>. These dimensions define how big a view wants to be
347 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
348 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
349 * and {@link #getMeasuredHeight()}.
350 * </p>
351 *
352 * <p>
353 * The second pair is simply known as <em>width</em> and <em>height</em>, or
354 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
355 * dimensions define the actual size of the view on screen, at drawing time and
356 * after layout. These values may, but do not have to, be different from the
357 * measured width and height. The width and height can be obtained by calling
358 * {@link #getWidth()} and {@link #getHeight()}.
359 * </p>
360 *
361 * <p>
362 * To measure its dimensions, a view takes into account its padding. The padding
363 * is expressed in pixels for the left, top, right and bottom parts of the view.
364 * Padding can be used to offset the content of the view by a specific amount of
365 * pixels. For instance, a left padding of 2 will push the view's content by
366 * 2 pixels to the right of the left edge. Padding can be set using the
367 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
368 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
369 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
370 * {@link #getPaddingEnd()}.
371 * </p>
372 *
373 * <p>
374 * Even though a view can define a padding, it does not provide any support for
375 * margins. However, view groups provide such a support. Refer to
376 * {@link android.view.ViewGroup} and
377 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
378 * </p>
379 *
380 * <a name="Layout"></a>
381 * <h3>Layout</h3>
382 * <p>
383 * Layout is a two pass process: a measure pass and a layout pass. The measuring
384 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
385 * of the view tree. Each view pushes dimension specifications down the tree
386 * during the recursion. At the end of the measure pass, every view has stored
387 * its measurements. The second pass happens in
388 * {@link #layout(int,int,int,int)} and is also top-down. During
389 * this pass each parent is responsible for positioning all of its children
390 * using the sizes computed in the measure pass.
391 * </p>
392 *
393 * <p>
394 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
395 * {@link #getMeasuredHeight()} values must be set, along with those for all of
396 * that view's descendants. A view's measured width and measured height values
397 * must respect the constraints imposed by the view's parents. This guarantees
398 * that at the end of the measure pass, all parents accept all of their
399 * children's measurements. A parent view may call measure() more than once on
400 * its children. For example, the parent may measure each child once with
401 * unspecified dimensions to find out how big they want to be, then call
402 * measure() on them again with actual numbers if the sum of all the children's
403 * unconstrained sizes is too big or too small.
404 * </p>
405 *
406 * <p>
407 * The measure pass uses two classes to communicate dimensions. The
408 * {@link MeasureSpec} class is used by views to tell their parents how they
409 * want to be measured and positioned. The base LayoutParams class just
410 * describes how big the view wants to be for both width and height. For each
411 * dimension, it can specify one of:
412 * <ul>
413 * <li> an exact number
414 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
415 * (minus padding)
416 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
417 * enclose its content (plus padding).
418 * </ul>
419 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
420 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
421 * an X and Y value.
422 * </p>
423 *
424 * <p>
425 * MeasureSpecs are used to push requirements down the tree from parent to
426 * child. A MeasureSpec can be in one of three modes:
427 * <ul>
428 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
429 * of a child view. For example, a LinearLayout may call measure() on its child
430 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
431 * tall the child view wants to be given a width of 240 pixels.
432 * <li>EXACTLY: This is used by the parent to impose an exact size on the
433 * child. The child must use this size, and guarantee that all of its
434 * descendants will fit within this size.
435 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
436 * child. The child must guarantee that it and all of its descendants will fit
437 * within this size.
438 * </ul>
439 * </p>
440 *
441 * <p>
442 * To intiate a layout, call {@link #requestLayout}. This method is typically
443 * called by a view on itself when it believes that is can no longer fit within
444 * its current bounds.
445 * </p>
446 *
447 * <a name="Drawing"></a>
448 * <h3>Drawing</h3>
449 * <p>
450 * Drawing is handled by walking the tree and rendering each view that
451 * intersects the invalid region. Because the tree is traversed in-order,
452 * this means that parents will draw before (i.e., behind) their children, with
453 * siblings drawn in the order they appear in the tree.
454 * If you set a background drawable for a View, then the View will draw it for you
455 * before calling back to its <code>onDraw()</code> method.
456 * </p>
457 *
458 * <p>
459 * Note that the framework will not draw views that are not in the invalid region.
460 * </p>
461 *
462 * <p>
463 * To force a view to draw, call {@link #invalidate()}.
464 * </p>
465 *
466 * <a name="EventHandlingThreading"></a>
467 * <h3>Event Handling and Threading</h3>
468 * <p>
469 * The basic cycle of a view is as follows:
470 * <ol>
471 * <li>An event comes in and is dispatched to the appropriate view. The view
472 * handles the event and notifies any listeners.</li>
473 * <li>If in the course of processing the event, the view's bounds may need
474 * to be changed, the view will call {@link #requestLayout()}.</li>
475 * <li>Similarly, if in the course of processing the event the view's appearance
476 * may need to be changed, the view will call {@link #invalidate()}.</li>
477 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
478 * the framework will take care of measuring, laying out, and drawing the tree
479 * as appropriate.</li>
480 * </ol>
481 * </p>
482 *
483 * <p><em>Note: The entire view tree is single threaded. You must always be on
484 * the UI thread when calling any method on any view.</em>
485 * If you are doing work on other threads and want to update the state of a view
486 * from that thread, you should use a {@link Handler}.
487 * </p>
488 *
489 * <a name="FocusHandling"></a>
490 * <h3>Focus Handling</h3>
491 * <p>
492 * The framework will handle routine focus movement in response to user input.
493 * This includes changing the focus as views are removed or hidden, or as new
494 * views become available. Views indicate their willingness to take focus
495 * through the {@link #isFocusable} method. To change whether a view can take
496 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
497 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
498 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
499 * </p>
500 * <p>
501 * Focus movement is based on an algorithm which finds the nearest neighbor in a
502 * given direction. In rare cases, the default algorithm may not match the
503 * intended behavior of the developer. In these situations, you can provide
504 * explicit overrides by using these XML attributes in the layout file:
505 * <pre>
506 * nextFocusDown
507 * nextFocusLeft
508 * nextFocusRight
509 * nextFocusUp
510 * </pre>
511 * </p>
512 *
513 *
514 * <p>
515 * To get a particular view to take focus, call {@link #requestFocus()}.
516 * </p>
517 *
518 * <a name="TouchMode"></a>
519 * <h3>Touch Mode</h3>
520 * <p>
521 * When a user is navigating a user interface via directional keys such as a D-pad, it is
522 * necessary to give focus to actionable items such as buttons so the user can see
523 * what will take input.  If the device has touch capabilities, however, and the user
524 * begins interacting with the interface by touching it, it is no longer necessary to
525 * always highlight, or give focus to, a particular view.  This motivates a mode
526 * for interaction named 'touch mode'.
527 * </p>
528 * <p>
529 * For a touch capable device, once the user touches the screen, the device
530 * will enter touch mode.  From this point onward, only views for which
531 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
532 * Other views that are touchable, like buttons, will not take focus when touched; they will
533 * only fire the on click listeners.
534 * </p>
535 * <p>
536 * Any time a user hits a directional key, such as a D-pad direction, the view device will
537 * exit touch mode, and find a view to take focus, so that the user may resume interacting
538 * with the user interface without touching the screen again.
539 * </p>
540 * <p>
541 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
542 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
543 * </p>
544 *
545 * <a name="Scrolling"></a>
546 * <h3>Scrolling</h3>
547 * <p>
548 * The framework provides basic support for views that wish to internally
549 * scroll their content. This includes keeping track of the X and Y scroll
550 * offset as well as mechanisms for drawing scrollbars. See
551 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
552 * {@link #awakenScrollBars()} for more details.
553 * </p>
554 *
555 * <a name="Tags"></a>
556 * <h3>Tags</h3>
557 * <p>
558 * Unlike IDs, tags are not used to identify views. Tags are essentially an
559 * extra piece of information that can be associated with a view. They are most
560 * often used as a convenience to store data related to views in the views
561 * themselves rather than by putting them in a separate structure.
562 * </p>
563 *
564 * <a name="Properties"></a>
565 * <h3>Properties</h3>
566 * <p>
567 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
568 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
569 * available both in the {@link Property} form as well as in similarly-named setter/getter
570 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
571 * be used to set persistent state associated with these rendering-related properties on the view.
572 * The properties and methods can also be used in conjunction with
573 * {@link android.animation.Animator Animator}-based animations, described more in the
574 * <a href="#Animation">Animation</a> section.
575 * </p>
576 *
577 * <a name="Animation"></a>
578 * <h3>Animation</h3>
579 * <p>
580 * Starting with Android 3.0, the preferred way of animating views is to use the
581 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
582 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
583 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
584 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
585 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
586 * makes animating these View properties particularly easy and efficient.
587 * </p>
588 * <p>
589 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
590 * You can attach an {@link Animation} object to a view using
591 * {@link #setAnimation(Animation)} or
592 * {@link #startAnimation(Animation)}. The animation can alter the scale,
593 * rotation, translation and alpha of a view over time. If the animation is
594 * attached to a view that has children, the animation will affect the entire
595 * subtree rooted by that node. When an animation is started, the framework will
596 * take care of redrawing the appropriate views until the animation completes.
597 * </p>
598 *
599 * <a name="Security"></a>
600 * <h3>Security</h3>
601 * <p>
602 * Sometimes it is essential that an application be able to verify that an action
603 * is being performed with the full knowledge and consent of the user, such as
604 * granting a permission request, making a purchase or clicking on an advertisement.
605 * Unfortunately, a malicious application could try to spoof the user into
606 * performing these actions, unaware, by concealing the intended purpose of the view.
607 * As a remedy, the framework offers a touch filtering mechanism that can be used to
608 * improve the security of views that provide access to sensitive functionality.
609 * </p><p>
610 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
611 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
612 * will discard touches that are received whenever the view's window is obscured by
613 * another visible window.  As a result, the view will not receive touches whenever a
614 * toast, dialog or other window appears above the view's window.
615 * </p><p>
616 * For more fine-grained control over security, consider overriding the
617 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
618 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
619 * </p>
620 *
621 * @attr ref android.R.styleable#View_alpha
622 * @attr ref android.R.styleable#View_background
623 * @attr ref android.R.styleable#View_clickable
624 * @attr ref android.R.styleable#View_contentDescription
625 * @attr ref android.R.styleable#View_drawingCacheQuality
626 * @attr ref android.R.styleable#View_duplicateParentState
627 * @attr ref android.R.styleable#View_id
628 * @attr ref android.R.styleable#View_requiresFadingEdge
629 * @attr ref android.R.styleable#View_fadeScrollbars
630 * @attr ref android.R.styleable#View_fadingEdgeLength
631 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
632 * @attr ref android.R.styleable#View_fitsSystemWindows
633 * @attr ref android.R.styleable#View_isScrollContainer
634 * @attr ref android.R.styleable#View_focusable
635 * @attr ref android.R.styleable#View_focusableInTouchMode
636 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
637 * @attr ref android.R.styleable#View_keepScreenOn
638 * @attr ref android.R.styleable#View_layerType
639 * @attr ref android.R.styleable#View_layoutDirection
640 * @attr ref android.R.styleable#View_longClickable
641 * @attr ref android.R.styleable#View_minHeight
642 * @attr ref android.R.styleable#View_minWidth
643 * @attr ref android.R.styleable#View_nextFocusDown
644 * @attr ref android.R.styleable#View_nextFocusLeft
645 * @attr ref android.R.styleable#View_nextFocusRight
646 * @attr ref android.R.styleable#View_nextFocusUp
647 * @attr ref android.R.styleable#View_onClick
648 * @attr ref android.R.styleable#View_padding
649 * @attr ref android.R.styleable#View_paddingBottom
650 * @attr ref android.R.styleable#View_paddingLeft
651 * @attr ref android.R.styleable#View_paddingRight
652 * @attr ref android.R.styleable#View_paddingTop
653 * @attr ref android.R.styleable#View_paddingStart
654 * @attr ref android.R.styleable#View_paddingEnd
655 * @attr ref android.R.styleable#View_saveEnabled
656 * @attr ref android.R.styleable#View_rotation
657 * @attr ref android.R.styleable#View_rotationX
658 * @attr ref android.R.styleable#View_rotationY
659 * @attr ref android.R.styleable#View_scaleX
660 * @attr ref android.R.styleable#View_scaleY
661 * @attr ref android.R.styleable#View_scrollX
662 * @attr ref android.R.styleable#View_scrollY
663 * @attr ref android.R.styleable#View_scrollbarSize
664 * @attr ref android.R.styleable#View_scrollbarStyle
665 * @attr ref android.R.styleable#View_scrollbars
666 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
667 * @attr ref android.R.styleable#View_scrollbarFadeDuration
668 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
669 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
670 * @attr ref android.R.styleable#View_scrollbarThumbVertical
671 * @attr ref android.R.styleable#View_scrollbarTrackVertical
672 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
673 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
674 * @attr ref android.R.styleable#View_stateListAnimator
675 * @attr ref android.R.styleable#View_transitionName
676 * @attr ref android.R.styleable#View_soundEffectsEnabled
677 * @attr ref android.R.styleable#View_tag
678 * @attr ref android.R.styleable#View_textAlignment
679 * @attr ref android.R.styleable#View_textDirection
680 * @attr ref android.R.styleable#View_transformPivotX
681 * @attr ref android.R.styleable#View_transformPivotY
682 * @attr ref android.R.styleable#View_translationX
683 * @attr ref android.R.styleable#View_translationY
684 * @attr ref android.R.styleable#View_translationZ
685 * @attr ref android.R.styleable#View_visibility
686 *
687 * @see android.view.ViewGroup
688 */
689public class View implements Drawable.Callback, KeyEvent.Callback,
690        AccessibilityEventSource {
691    private static final boolean DBG = false;
692
693    /**
694     * The logging tag used by this class with android.util.Log.
695     */
696    protected static final String VIEW_LOG_TAG = "View";
697
698    /**
699     * When set to true, apps will draw debugging information about their layouts.
700     *
701     * @hide
702     */
703    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
704
705    /**
706     * Used to mark a View that has no ID.
707     */
708    public static final int NO_ID = -1;
709
710    /**
711     * Signals that compatibility booleans have been initialized according to
712     * target SDK versions.
713     */
714    private static boolean sCompatibilityDone = false;
715
716    /**
717     * Use the old (broken) way of building MeasureSpecs.
718     */
719    private static boolean sUseBrokenMakeMeasureSpec = false;
720
721    /**
722     * Ignore any optimizations using the measure cache.
723     */
724    private static boolean sIgnoreMeasureCache = false;
725
726    /**
727     * Ignore the clipBounds of this view for the children.
728     */
729    static boolean sIgnoreClipBoundsForChildren = false;
730
731    /**
732     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
733     * calling setFlags.
734     */
735    private static final int NOT_FOCUSABLE = 0x00000000;
736
737    /**
738     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
739     * setFlags.
740     */
741    private static final int FOCUSABLE = 0x00000001;
742
743    /**
744     * Mask for use with setFlags indicating bits used for focus.
745     */
746    private static final int FOCUSABLE_MASK = 0x00000001;
747
748    /**
749     * This view will adjust its padding to fit sytem windows (e.g. status bar)
750     */
751    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
752
753    /** @hide */
754    @IntDef({VISIBLE, INVISIBLE, GONE})
755    @Retention(RetentionPolicy.SOURCE)
756    public @interface Visibility {}
757
758    /**
759     * This view is visible.
760     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
761     * android:visibility}.
762     */
763    public static final int VISIBLE = 0x00000000;
764
765    /**
766     * This view is invisible, but it still takes up space for layout purposes.
767     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
768     * android:visibility}.
769     */
770    public static final int INVISIBLE = 0x00000004;
771
772    /**
773     * This view is invisible, and it doesn't take any space for layout
774     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
775     * android:visibility}.
776     */
777    public static final int GONE = 0x00000008;
778
779    /**
780     * Mask for use with setFlags indicating bits used for visibility.
781     * {@hide}
782     */
783    static final int VISIBILITY_MASK = 0x0000000C;
784
785    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
786
787    /**
788     * This view is enabled. Interpretation varies by subclass.
789     * Use with ENABLED_MASK when calling setFlags.
790     * {@hide}
791     */
792    static final int ENABLED = 0x00000000;
793
794    /**
795     * This view is disabled. Interpretation varies by subclass.
796     * Use with ENABLED_MASK when calling setFlags.
797     * {@hide}
798     */
799    static final int DISABLED = 0x00000020;
800
801   /**
802    * Mask for use with setFlags indicating bits used for indicating whether
803    * this view is enabled
804    * {@hide}
805    */
806    static final int ENABLED_MASK = 0x00000020;
807
808    /**
809     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
810     * called and further optimizations will be performed. It is okay to have
811     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
812     * {@hide}
813     */
814    static final int WILL_NOT_DRAW = 0x00000080;
815
816    /**
817     * Mask for use with setFlags indicating bits used for indicating whether
818     * this view is will draw
819     * {@hide}
820     */
821    static final int DRAW_MASK = 0x00000080;
822
823    /**
824     * <p>This view doesn't show scrollbars.</p>
825     * {@hide}
826     */
827    static final int SCROLLBARS_NONE = 0x00000000;
828
829    /**
830     * <p>This view shows horizontal scrollbars.</p>
831     * {@hide}
832     */
833    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
834
835    /**
836     * <p>This view shows vertical scrollbars.</p>
837     * {@hide}
838     */
839    static final int SCROLLBARS_VERTICAL = 0x00000200;
840
841    /**
842     * <p>Mask for use with setFlags indicating bits used for indicating which
843     * scrollbars are enabled.</p>
844     * {@hide}
845     */
846    static final int SCROLLBARS_MASK = 0x00000300;
847
848    /**
849     * Indicates that the view should filter touches when its window is obscured.
850     * Refer to the class comments for more information about this security feature.
851     * {@hide}
852     */
853    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
854
855    /**
856     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
857     * that they are optional and should be skipped if the window has
858     * requested system UI flags that ignore those insets for layout.
859     */
860    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
861
862    /**
863     * <p>This view doesn't show fading edges.</p>
864     * {@hide}
865     */
866    static final int FADING_EDGE_NONE = 0x00000000;
867
868    /**
869     * <p>This view shows horizontal fading edges.</p>
870     * {@hide}
871     */
872    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
873
874    /**
875     * <p>This view shows vertical fading edges.</p>
876     * {@hide}
877     */
878    static final int FADING_EDGE_VERTICAL = 0x00002000;
879
880    /**
881     * <p>Mask for use with setFlags indicating bits used for indicating which
882     * fading edges are enabled.</p>
883     * {@hide}
884     */
885    static final int FADING_EDGE_MASK = 0x00003000;
886
887    /**
888     * <p>Indicates this view can be clicked. When clickable, a View reacts
889     * to clicks by notifying the OnClickListener.<p>
890     * {@hide}
891     */
892    static final int CLICKABLE = 0x00004000;
893
894    /**
895     * <p>Indicates this view is caching its drawing into a bitmap.</p>
896     * {@hide}
897     */
898    static final int DRAWING_CACHE_ENABLED = 0x00008000;
899
900    /**
901     * <p>Indicates that no icicle should be saved for this view.<p>
902     * {@hide}
903     */
904    static final int SAVE_DISABLED = 0x000010000;
905
906    /**
907     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
908     * property.</p>
909     * {@hide}
910     */
911    static final int SAVE_DISABLED_MASK = 0x000010000;
912
913    /**
914     * <p>Indicates that no drawing cache should ever be created for this view.<p>
915     * {@hide}
916     */
917    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
918
919    /**
920     * <p>Indicates this view can take / keep focus when int touch mode.</p>
921     * {@hide}
922     */
923    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
924
925    /** @hide */
926    @Retention(RetentionPolicy.SOURCE)
927    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
928    public @interface DrawingCacheQuality {}
929
930    /**
931     * <p>Enables low quality mode for the drawing cache.</p>
932     */
933    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
934
935    /**
936     * <p>Enables high quality mode for the drawing cache.</p>
937     */
938    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
939
940    /**
941     * <p>Enables automatic quality mode for the drawing cache.</p>
942     */
943    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
944
945    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
946            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
947    };
948
949    /**
950     * <p>Mask for use with setFlags indicating bits used for the cache
951     * quality property.</p>
952     * {@hide}
953     */
954    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
955
956    /**
957     * <p>
958     * Indicates this view can be long clicked. When long clickable, a View
959     * reacts to long clicks by notifying the OnLongClickListener or showing a
960     * context menu.
961     * </p>
962     * {@hide}
963     */
964    static final int LONG_CLICKABLE = 0x00200000;
965
966    /**
967     * <p>Indicates that this view gets its drawable states from its direct parent
968     * and ignores its original internal states.</p>
969     *
970     * @hide
971     */
972    static final int DUPLICATE_PARENT_STATE = 0x00400000;
973
974    /** @hide */
975    @IntDef({
976        SCROLLBARS_INSIDE_OVERLAY,
977        SCROLLBARS_INSIDE_INSET,
978        SCROLLBARS_OUTSIDE_OVERLAY,
979        SCROLLBARS_OUTSIDE_INSET
980    })
981    @Retention(RetentionPolicy.SOURCE)
982    public @interface ScrollBarStyle {}
983
984    /**
985     * The scrollbar style to display the scrollbars inside the content area,
986     * without increasing the padding. The scrollbars will be overlaid with
987     * translucency on the view's content.
988     */
989    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
990
991    /**
992     * The scrollbar style to display the scrollbars inside the padded area,
993     * increasing the padding of the view. The scrollbars will not overlap the
994     * content area of the view.
995     */
996    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
997
998    /**
999     * The scrollbar style to display the scrollbars at the edge of the view,
1000     * without increasing the padding. The scrollbars will be overlaid with
1001     * translucency.
1002     */
1003    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1004
1005    /**
1006     * The scrollbar style to display the scrollbars at the edge of the view,
1007     * increasing the padding of the view. The scrollbars will only overlap the
1008     * background, if any.
1009     */
1010    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1011
1012    /**
1013     * Mask to check if the scrollbar style is overlay or inset.
1014     * {@hide}
1015     */
1016    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1017
1018    /**
1019     * Mask to check if the scrollbar style is inside or outside.
1020     * {@hide}
1021     */
1022    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1023
1024    /**
1025     * Mask for scrollbar style.
1026     * {@hide}
1027     */
1028    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1029
1030    /**
1031     * View flag indicating that the screen should remain on while the
1032     * window containing this view is visible to the user.  This effectively
1033     * takes care of automatically setting the WindowManager's
1034     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1035     */
1036    public static final int KEEP_SCREEN_ON = 0x04000000;
1037
1038    /**
1039     * View flag indicating whether this view should have sound effects enabled
1040     * for events such as clicking and touching.
1041     */
1042    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1043
1044    /**
1045     * View flag indicating whether this view should have haptic feedback
1046     * enabled for events such as long presses.
1047     */
1048    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1049
1050    /**
1051     * <p>Indicates that the view hierarchy should stop saving state when
1052     * it reaches this view.  If state saving is initiated immediately at
1053     * the view, it will be allowed.
1054     * {@hide}
1055     */
1056    static final int PARENT_SAVE_DISABLED = 0x20000000;
1057
1058    /**
1059     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1060     * {@hide}
1061     */
1062    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1063
1064    /** @hide */
1065    @IntDef(flag = true,
1066            value = {
1067                FOCUSABLES_ALL,
1068                FOCUSABLES_TOUCH_MODE
1069            })
1070    @Retention(RetentionPolicy.SOURCE)
1071    public @interface FocusableMode {}
1072
1073    /**
1074     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1075     * should add all focusable Views regardless if they are focusable in touch mode.
1076     */
1077    public static final int FOCUSABLES_ALL = 0x00000000;
1078
1079    /**
1080     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1081     * should add only Views focusable in touch mode.
1082     */
1083    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1084
1085    /** @hide */
1086    @IntDef({
1087            FOCUS_BACKWARD,
1088            FOCUS_FORWARD,
1089            FOCUS_LEFT,
1090            FOCUS_UP,
1091            FOCUS_RIGHT,
1092            FOCUS_DOWN
1093    })
1094    @Retention(RetentionPolicy.SOURCE)
1095    public @interface FocusDirection {}
1096
1097    /** @hide */
1098    @IntDef({
1099            FOCUS_LEFT,
1100            FOCUS_UP,
1101            FOCUS_RIGHT,
1102            FOCUS_DOWN
1103    })
1104    @Retention(RetentionPolicy.SOURCE)
1105    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1106
1107    /**
1108     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1109     * item.
1110     */
1111    public static final int FOCUS_BACKWARD = 0x00000001;
1112
1113    /**
1114     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1115     * item.
1116     */
1117    public static final int FOCUS_FORWARD = 0x00000002;
1118
1119    /**
1120     * Use with {@link #focusSearch(int)}. Move focus to the left.
1121     */
1122    public static final int FOCUS_LEFT = 0x00000011;
1123
1124    /**
1125     * Use with {@link #focusSearch(int)}. Move focus up.
1126     */
1127    public static final int FOCUS_UP = 0x00000021;
1128
1129    /**
1130     * Use with {@link #focusSearch(int)}. Move focus to the right.
1131     */
1132    public static final int FOCUS_RIGHT = 0x00000042;
1133
1134    /**
1135     * Use with {@link #focusSearch(int)}. Move focus down.
1136     */
1137    public static final int FOCUS_DOWN = 0x00000082;
1138
1139    /**
1140     * Bits of {@link #getMeasuredWidthAndState()} and
1141     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1142     */
1143    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1144
1145    /**
1146     * Bits of {@link #getMeasuredWidthAndState()} and
1147     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1148     */
1149    public static final int MEASURED_STATE_MASK = 0xff000000;
1150
1151    /**
1152     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1153     * for functions that combine both width and height into a single int,
1154     * such as {@link #getMeasuredState()} and the childState argument of
1155     * {@link #resolveSizeAndState(int, int, int)}.
1156     */
1157    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1158
1159    /**
1160     * Bit of {@link #getMeasuredWidthAndState()} and
1161     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1162     * is smaller that the space the view would like to have.
1163     */
1164    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1165
1166    /**
1167     * Base View state sets
1168     */
1169    // Singles
1170    /**
1171     * Indicates the view has no states set. States are used with
1172     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1173     * view depending on its state.
1174     *
1175     * @see android.graphics.drawable.Drawable
1176     * @see #getDrawableState()
1177     */
1178    protected static final int[] EMPTY_STATE_SET;
1179    /**
1180     * Indicates the view is enabled. States are used with
1181     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1182     * view depending on its state.
1183     *
1184     * @see android.graphics.drawable.Drawable
1185     * @see #getDrawableState()
1186     */
1187    protected static final int[] ENABLED_STATE_SET;
1188    /**
1189     * Indicates the view is focused. States are used with
1190     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1191     * view depending on its state.
1192     *
1193     * @see android.graphics.drawable.Drawable
1194     * @see #getDrawableState()
1195     */
1196    protected static final int[] FOCUSED_STATE_SET;
1197    /**
1198     * Indicates the view is selected. States are used with
1199     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1200     * view depending on its state.
1201     *
1202     * @see android.graphics.drawable.Drawable
1203     * @see #getDrawableState()
1204     */
1205    protected static final int[] SELECTED_STATE_SET;
1206    /**
1207     * Indicates the view is pressed. States are used with
1208     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1209     * view depending on its state.
1210     *
1211     * @see android.graphics.drawable.Drawable
1212     * @see #getDrawableState()
1213     */
1214    protected static final int[] PRESSED_STATE_SET;
1215    /**
1216     * Indicates the view's window has focus. States are used with
1217     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1218     * view depending on its state.
1219     *
1220     * @see android.graphics.drawable.Drawable
1221     * @see #getDrawableState()
1222     */
1223    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1224    // Doubles
1225    /**
1226     * Indicates the view is enabled and has the focus.
1227     *
1228     * @see #ENABLED_STATE_SET
1229     * @see #FOCUSED_STATE_SET
1230     */
1231    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1232    /**
1233     * Indicates the view is enabled and selected.
1234     *
1235     * @see #ENABLED_STATE_SET
1236     * @see #SELECTED_STATE_SET
1237     */
1238    protected static final int[] ENABLED_SELECTED_STATE_SET;
1239    /**
1240     * Indicates the view is enabled and that its window has focus.
1241     *
1242     * @see #ENABLED_STATE_SET
1243     * @see #WINDOW_FOCUSED_STATE_SET
1244     */
1245    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1246    /**
1247     * Indicates the view is focused and selected.
1248     *
1249     * @see #FOCUSED_STATE_SET
1250     * @see #SELECTED_STATE_SET
1251     */
1252    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1253    /**
1254     * Indicates the view has the focus and that its window has the focus.
1255     *
1256     * @see #FOCUSED_STATE_SET
1257     * @see #WINDOW_FOCUSED_STATE_SET
1258     */
1259    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1260    /**
1261     * Indicates the view is selected and that its window has the focus.
1262     *
1263     * @see #SELECTED_STATE_SET
1264     * @see #WINDOW_FOCUSED_STATE_SET
1265     */
1266    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1267    // Triples
1268    /**
1269     * Indicates the view is enabled, focused and selected.
1270     *
1271     * @see #ENABLED_STATE_SET
1272     * @see #FOCUSED_STATE_SET
1273     * @see #SELECTED_STATE_SET
1274     */
1275    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1276    /**
1277     * Indicates the view is enabled, focused and its window has the focus.
1278     *
1279     * @see #ENABLED_STATE_SET
1280     * @see #FOCUSED_STATE_SET
1281     * @see #WINDOW_FOCUSED_STATE_SET
1282     */
1283    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1284    /**
1285     * Indicates the view is enabled, selected and its window has the focus.
1286     *
1287     * @see #ENABLED_STATE_SET
1288     * @see #SELECTED_STATE_SET
1289     * @see #WINDOW_FOCUSED_STATE_SET
1290     */
1291    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1292    /**
1293     * Indicates the view is focused, selected and its window has the focus.
1294     *
1295     * @see #FOCUSED_STATE_SET
1296     * @see #SELECTED_STATE_SET
1297     * @see #WINDOW_FOCUSED_STATE_SET
1298     */
1299    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1300    /**
1301     * Indicates the view is enabled, focused, selected and its window
1302     * has the focus.
1303     *
1304     * @see #ENABLED_STATE_SET
1305     * @see #FOCUSED_STATE_SET
1306     * @see #SELECTED_STATE_SET
1307     * @see #WINDOW_FOCUSED_STATE_SET
1308     */
1309    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1310    /**
1311     * Indicates the view is pressed and its window has the focus.
1312     *
1313     * @see #PRESSED_STATE_SET
1314     * @see #WINDOW_FOCUSED_STATE_SET
1315     */
1316    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1317    /**
1318     * Indicates the view is pressed and selected.
1319     *
1320     * @see #PRESSED_STATE_SET
1321     * @see #SELECTED_STATE_SET
1322     */
1323    protected static final int[] PRESSED_SELECTED_STATE_SET;
1324    /**
1325     * Indicates the view is pressed, selected and its window has the focus.
1326     *
1327     * @see #PRESSED_STATE_SET
1328     * @see #SELECTED_STATE_SET
1329     * @see #WINDOW_FOCUSED_STATE_SET
1330     */
1331    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1332    /**
1333     * Indicates the view is pressed and focused.
1334     *
1335     * @see #PRESSED_STATE_SET
1336     * @see #FOCUSED_STATE_SET
1337     */
1338    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1339    /**
1340     * Indicates the view is pressed, focused and its window has the focus.
1341     *
1342     * @see #PRESSED_STATE_SET
1343     * @see #FOCUSED_STATE_SET
1344     * @see #WINDOW_FOCUSED_STATE_SET
1345     */
1346    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1347    /**
1348     * Indicates the view is pressed, focused and selected.
1349     *
1350     * @see #PRESSED_STATE_SET
1351     * @see #SELECTED_STATE_SET
1352     * @see #FOCUSED_STATE_SET
1353     */
1354    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1355    /**
1356     * Indicates the view is pressed, focused, selected and its window has the focus.
1357     *
1358     * @see #PRESSED_STATE_SET
1359     * @see #FOCUSED_STATE_SET
1360     * @see #SELECTED_STATE_SET
1361     * @see #WINDOW_FOCUSED_STATE_SET
1362     */
1363    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1364    /**
1365     * Indicates the view is pressed and enabled.
1366     *
1367     * @see #PRESSED_STATE_SET
1368     * @see #ENABLED_STATE_SET
1369     */
1370    protected static final int[] PRESSED_ENABLED_STATE_SET;
1371    /**
1372     * Indicates the view is pressed, enabled and its window has the focus.
1373     *
1374     * @see #PRESSED_STATE_SET
1375     * @see #ENABLED_STATE_SET
1376     * @see #WINDOW_FOCUSED_STATE_SET
1377     */
1378    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1379    /**
1380     * Indicates the view is pressed, enabled and selected.
1381     *
1382     * @see #PRESSED_STATE_SET
1383     * @see #ENABLED_STATE_SET
1384     * @see #SELECTED_STATE_SET
1385     */
1386    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1387    /**
1388     * Indicates the view is pressed, enabled, selected and its window has the
1389     * focus.
1390     *
1391     * @see #PRESSED_STATE_SET
1392     * @see #ENABLED_STATE_SET
1393     * @see #SELECTED_STATE_SET
1394     * @see #WINDOW_FOCUSED_STATE_SET
1395     */
1396    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1397    /**
1398     * Indicates the view is pressed, enabled and focused.
1399     *
1400     * @see #PRESSED_STATE_SET
1401     * @see #ENABLED_STATE_SET
1402     * @see #FOCUSED_STATE_SET
1403     */
1404    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1405    /**
1406     * Indicates the view is pressed, enabled, focused and its window has the
1407     * focus.
1408     *
1409     * @see #PRESSED_STATE_SET
1410     * @see #ENABLED_STATE_SET
1411     * @see #FOCUSED_STATE_SET
1412     * @see #WINDOW_FOCUSED_STATE_SET
1413     */
1414    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1415    /**
1416     * Indicates the view is pressed, enabled, focused and selected.
1417     *
1418     * @see #PRESSED_STATE_SET
1419     * @see #ENABLED_STATE_SET
1420     * @see #SELECTED_STATE_SET
1421     * @see #FOCUSED_STATE_SET
1422     */
1423    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1424    /**
1425     * Indicates the view is pressed, enabled, focused, selected and its window
1426     * has the focus.
1427     *
1428     * @see #PRESSED_STATE_SET
1429     * @see #ENABLED_STATE_SET
1430     * @see #SELECTED_STATE_SET
1431     * @see #FOCUSED_STATE_SET
1432     * @see #WINDOW_FOCUSED_STATE_SET
1433     */
1434    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1435
1436    /**
1437     * The order here is very important to {@link #getDrawableState()}
1438     */
1439    private static final int[][] VIEW_STATE_SETS;
1440
1441    static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1442    static final int VIEW_STATE_SELECTED = 1 << 1;
1443    static final int VIEW_STATE_FOCUSED = 1 << 2;
1444    static final int VIEW_STATE_ENABLED = 1 << 3;
1445    static final int VIEW_STATE_PRESSED = 1 << 4;
1446    static final int VIEW_STATE_ACTIVATED = 1 << 5;
1447    static final int VIEW_STATE_ACCELERATED = 1 << 6;
1448    static final int VIEW_STATE_HOVERED = 1 << 7;
1449    static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1450    static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
1451
1452    static final int[] VIEW_STATE_IDS = new int[] {
1453        R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
1454        R.attr.state_selected,          VIEW_STATE_SELECTED,
1455        R.attr.state_focused,           VIEW_STATE_FOCUSED,
1456        R.attr.state_enabled,           VIEW_STATE_ENABLED,
1457        R.attr.state_pressed,           VIEW_STATE_PRESSED,
1458        R.attr.state_activated,         VIEW_STATE_ACTIVATED,
1459        R.attr.state_accelerated,       VIEW_STATE_ACCELERATED,
1460        R.attr.state_hovered,           VIEW_STATE_HOVERED,
1461        R.attr.state_drag_can_accept,   VIEW_STATE_DRAG_CAN_ACCEPT,
1462        R.attr.state_drag_hovered,      VIEW_STATE_DRAG_HOVERED
1463    };
1464
1465    static {
1466        if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1467            throw new IllegalStateException(
1468                    "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1469        }
1470        int[] orderedIds = new int[VIEW_STATE_IDS.length];
1471        for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
1472            int viewState = R.styleable.ViewDrawableStates[i];
1473            for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
1474                if (VIEW_STATE_IDS[j] == viewState) {
1475                    orderedIds[i * 2] = viewState;
1476                    orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
1477                }
1478            }
1479        }
1480        final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1481        VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1482        for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
1483            int numBits = Integer.bitCount(i);
1484            int[] set = new int[numBits];
1485            int pos = 0;
1486            for (int j = 0; j < orderedIds.length; j += 2) {
1487                if ((i & orderedIds[j+1]) != 0) {
1488                    set[pos++] = orderedIds[j];
1489                }
1490            }
1491            VIEW_STATE_SETS[i] = set;
1492        }
1493
1494        EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1495        WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1496        SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1497        SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1498                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1499        FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1500        FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1501                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1502        FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1503                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1504        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1505                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1506                | VIEW_STATE_FOCUSED];
1507        ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1508        ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1509                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1510        ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1511                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1512        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1513                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1514                | VIEW_STATE_ENABLED];
1515        ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1516                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1517        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1518                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1519                | VIEW_STATE_ENABLED];
1520        ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1521                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1522                | VIEW_STATE_ENABLED];
1523        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1524                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1525                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1526
1527        PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1528        PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1529                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1530        PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1531                VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1532        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1533                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1534                | VIEW_STATE_PRESSED];
1535        PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1536                VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1537        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1538                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1539                | VIEW_STATE_PRESSED];
1540        PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1541                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1542                | VIEW_STATE_PRESSED];
1543        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1544                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1545                | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1546        PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1547                VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1548        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1549                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1550                | VIEW_STATE_PRESSED];
1551        PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1552                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1553                | VIEW_STATE_PRESSED];
1554        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1555                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1556                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1557        PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1558                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1559                | VIEW_STATE_PRESSED];
1560        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1561                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1562                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1563        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1564                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1565                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1566        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1567                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1568                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1569                | VIEW_STATE_PRESSED];
1570    }
1571
1572    /**
1573     * Accessibility event types that are dispatched for text population.
1574     */
1575    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1576            AccessibilityEvent.TYPE_VIEW_CLICKED
1577            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1578            | AccessibilityEvent.TYPE_VIEW_SELECTED
1579            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1580            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1581            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1582            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1583            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1584            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1585            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1586            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1587
1588    /**
1589     * Temporary Rect currently for use in setBackground().  This will probably
1590     * be extended in the future to hold our own class with more than just
1591     * a Rect. :)
1592     */
1593    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1594
1595    /**
1596     * Map used to store views' tags.
1597     */
1598    private SparseArray<Object> mKeyedTags;
1599
1600    /**
1601     * The next available accessibility id.
1602     */
1603    private static int sNextAccessibilityViewId;
1604
1605    /**
1606     * The animation currently associated with this view.
1607     * @hide
1608     */
1609    protected Animation mCurrentAnimation = null;
1610
1611    /**
1612     * Width as measured during measure pass.
1613     * {@hide}
1614     */
1615    @ViewDebug.ExportedProperty(category = "measurement")
1616    int mMeasuredWidth;
1617
1618    /**
1619     * Height as measured during measure pass.
1620     * {@hide}
1621     */
1622    @ViewDebug.ExportedProperty(category = "measurement")
1623    int mMeasuredHeight;
1624
1625    /**
1626     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1627     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1628     * its display list. This flag, used only when hw accelerated, allows us to clear the
1629     * flag while retaining this information until it's needed (at getDisplayList() time and
1630     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1631     *
1632     * {@hide}
1633     */
1634    boolean mRecreateDisplayList = false;
1635
1636    /**
1637     * The view's identifier.
1638     * {@hide}
1639     *
1640     * @see #setId(int)
1641     * @see #getId()
1642     */
1643    @ViewDebug.ExportedProperty(resolveId = true)
1644    int mID = NO_ID;
1645
1646    /**
1647     * The stable ID of this view for accessibility purposes.
1648     */
1649    int mAccessibilityViewId = NO_ID;
1650
1651    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1652
1653    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1654
1655    /**
1656     * The view's tag.
1657     * {@hide}
1658     *
1659     * @see #setTag(Object)
1660     * @see #getTag()
1661     */
1662    protected Object mTag = null;
1663
1664    // for mPrivateFlags:
1665    /** {@hide} */
1666    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1667    /** {@hide} */
1668    static final int PFLAG_FOCUSED                     = 0x00000002;
1669    /** {@hide} */
1670    static final int PFLAG_SELECTED                    = 0x00000004;
1671    /** {@hide} */
1672    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1673    /** {@hide} */
1674    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1675    /** {@hide} */
1676    static final int PFLAG_DRAWN                       = 0x00000020;
1677    /**
1678     * When this flag is set, this view is running an animation on behalf of its
1679     * children and should therefore not cancel invalidate requests, even if they
1680     * lie outside of this view's bounds.
1681     *
1682     * {@hide}
1683     */
1684    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1685    /** {@hide} */
1686    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1687    /** {@hide} */
1688    static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
1689    /** {@hide} */
1690    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1691    /** {@hide} */
1692    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1693    /** {@hide} */
1694    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1695    /** {@hide} */
1696    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1697    /** {@hide} */
1698    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1699
1700    private static final int PFLAG_PRESSED             = 0x00004000;
1701
1702    /** {@hide} */
1703    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1704    /**
1705     * Flag used to indicate that this view should be drawn once more (and only once
1706     * more) after its animation has completed.
1707     * {@hide}
1708     */
1709    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1710
1711    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1712
1713    /**
1714     * Indicates that the View returned true when onSetAlpha() was called and that
1715     * the alpha must be restored.
1716     * {@hide}
1717     */
1718    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1719
1720    /**
1721     * Set by {@link #setScrollContainer(boolean)}.
1722     */
1723    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1724
1725    /**
1726     * Set by {@link #setScrollContainer(boolean)}.
1727     */
1728    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1729
1730    /**
1731     * View flag indicating whether this view was invalidated (fully or partially.)
1732     *
1733     * @hide
1734     */
1735    static final int PFLAG_DIRTY                       = 0x00200000;
1736
1737    /**
1738     * View flag indicating whether this view was invalidated by an opaque
1739     * invalidate request.
1740     *
1741     * @hide
1742     */
1743    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1744
1745    /**
1746     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1747     *
1748     * @hide
1749     */
1750    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1751
1752    /**
1753     * Indicates whether the background is opaque.
1754     *
1755     * @hide
1756     */
1757    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1758
1759    /**
1760     * Indicates whether the scrollbars are opaque.
1761     *
1762     * @hide
1763     */
1764    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1765
1766    /**
1767     * Indicates whether the view is opaque.
1768     *
1769     * @hide
1770     */
1771    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1772
1773    /**
1774     * Indicates a prepressed state;
1775     * the short time between ACTION_DOWN and recognizing
1776     * a 'real' press. Prepressed is used to recognize quick taps
1777     * even when they are shorter than ViewConfiguration.getTapTimeout().
1778     *
1779     * @hide
1780     */
1781    private static final int PFLAG_PREPRESSED          = 0x02000000;
1782
1783    /**
1784     * Indicates whether the view is temporarily detached.
1785     *
1786     * @hide
1787     */
1788    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1789
1790    /**
1791     * Indicates that we should awaken scroll bars once attached
1792     *
1793     * @hide
1794     */
1795    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1796
1797    /**
1798     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1799     * @hide
1800     */
1801    private static final int PFLAG_HOVERED             = 0x10000000;
1802
1803    /**
1804     * no longer needed, should be reused
1805     */
1806    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1807
1808    /** {@hide} */
1809    static final int PFLAG_ACTIVATED                   = 0x40000000;
1810
1811    /**
1812     * Indicates that this view was specifically invalidated, not just dirtied because some
1813     * child view was invalidated. The flag is used to determine when we need to recreate
1814     * a view's display list (as opposed to just returning a reference to its existing
1815     * display list).
1816     *
1817     * @hide
1818     */
1819    static final int PFLAG_INVALIDATED                 = 0x80000000;
1820
1821    /**
1822     * Masks for mPrivateFlags2, as generated by dumpFlags():
1823     *
1824     * |-------|-------|-------|-------|
1825     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1826     *                                1  PFLAG2_DRAG_HOVERED
1827     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1828     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1829     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1830     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1831     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1832     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1833     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1834     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1835     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1836     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1837     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1838     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1839     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1840     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1841     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1842     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1843     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1844     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1845     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1846     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1847     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1848     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1849     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1850     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1851     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1852     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1853     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1854     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1855     *    1                              PFLAG2_PADDING_RESOLVED
1856     *   1                               PFLAG2_DRAWABLE_RESOLVED
1857     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1858     * |-------|-------|-------|-------|
1859     */
1860
1861    /**
1862     * Indicates that this view has reported that it can accept the current drag's content.
1863     * Cleared when the drag operation concludes.
1864     * @hide
1865     */
1866    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1867
1868    /**
1869     * Indicates that this view is currently directly under the drag location in a
1870     * drag-and-drop operation involving content that it can accept.  Cleared when
1871     * the drag exits the view, or when the drag operation concludes.
1872     * @hide
1873     */
1874    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1875
1876    /** @hide */
1877    @IntDef({
1878        LAYOUT_DIRECTION_LTR,
1879        LAYOUT_DIRECTION_RTL,
1880        LAYOUT_DIRECTION_INHERIT,
1881        LAYOUT_DIRECTION_LOCALE
1882    })
1883    @Retention(RetentionPolicy.SOURCE)
1884    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1885    public @interface LayoutDir {}
1886
1887    /** @hide */
1888    @IntDef({
1889        LAYOUT_DIRECTION_LTR,
1890        LAYOUT_DIRECTION_RTL
1891    })
1892    @Retention(RetentionPolicy.SOURCE)
1893    public @interface ResolvedLayoutDir {}
1894
1895    /**
1896     * Horizontal layout direction of this view is from Left to Right.
1897     * Use with {@link #setLayoutDirection}.
1898     */
1899    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1900
1901    /**
1902     * Horizontal layout direction of this view is from Right to Left.
1903     * Use with {@link #setLayoutDirection}.
1904     */
1905    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1906
1907    /**
1908     * Horizontal layout direction of this view is inherited from its parent.
1909     * Use with {@link #setLayoutDirection}.
1910     */
1911    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1912
1913    /**
1914     * Horizontal layout direction of this view is from deduced from the default language
1915     * script for the locale. Use with {@link #setLayoutDirection}.
1916     */
1917    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1918
1919    /**
1920     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1921     * @hide
1922     */
1923    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1924
1925    /**
1926     * Mask for use with private flags indicating bits used for horizontal layout direction.
1927     * @hide
1928     */
1929    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1930
1931    /**
1932     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1933     * right-to-left direction.
1934     * @hide
1935     */
1936    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1937
1938    /**
1939     * Indicates whether the view horizontal layout direction has been resolved.
1940     * @hide
1941     */
1942    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1943
1944    /**
1945     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1946     * @hide
1947     */
1948    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1949            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1950
1951    /*
1952     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1953     * flag value.
1954     * @hide
1955     */
1956    private static final int[] LAYOUT_DIRECTION_FLAGS = {
1957            LAYOUT_DIRECTION_LTR,
1958            LAYOUT_DIRECTION_RTL,
1959            LAYOUT_DIRECTION_INHERIT,
1960            LAYOUT_DIRECTION_LOCALE
1961    };
1962
1963    /**
1964     * Default horizontal layout direction.
1965     */
1966    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1967
1968    /**
1969     * Default horizontal layout direction.
1970     * @hide
1971     */
1972    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1973
1974    /**
1975     * Text direction is inherited thru {@link ViewGroup}
1976     */
1977    public static final int TEXT_DIRECTION_INHERIT = 0;
1978
1979    /**
1980     * Text direction is using "first strong algorithm". The first strong directional character
1981     * determines the paragraph direction. If there is no strong directional character, the
1982     * paragraph direction is the view's resolved layout direction.
1983     */
1984    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1985
1986    /**
1987     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1988     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1989     * If there are neither, the paragraph direction is the view's resolved layout direction.
1990     */
1991    public static final int TEXT_DIRECTION_ANY_RTL = 2;
1992
1993    /**
1994     * Text direction is forced to LTR.
1995     */
1996    public static final int TEXT_DIRECTION_LTR = 3;
1997
1998    /**
1999     * Text direction is forced to RTL.
2000     */
2001    public static final int TEXT_DIRECTION_RTL = 4;
2002
2003    /**
2004     * Text direction is coming from the system Locale.
2005     */
2006    public static final int TEXT_DIRECTION_LOCALE = 5;
2007
2008    /**
2009     * Default text direction is inherited
2010     */
2011    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2012
2013    /**
2014     * Default resolved text direction
2015     * @hide
2016     */
2017    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2018
2019    /**
2020     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2021     * @hide
2022     */
2023    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2024
2025    /**
2026     * Mask for use with private flags indicating bits used for text direction.
2027     * @hide
2028     */
2029    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2030            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2031
2032    /**
2033     * Array of text direction flags for mapping attribute "textDirection" to correct
2034     * flag value.
2035     * @hide
2036     */
2037    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2038            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2039            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2040            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2041            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2042            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2043            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2044    };
2045
2046    /**
2047     * Indicates whether the view text direction has been resolved.
2048     * @hide
2049     */
2050    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2051            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2052
2053    /**
2054     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2055     * @hide
2056     */
2057    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2058
2059    /**
2060     * Mask for use with private flags indicating bits used for resolved text direction.
2061     * @hide
2062     */
2063    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2064            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2065
2066    /**
2067     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2068     * @hide
2069     */
2070    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2071            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2072
2073    /** @hide */
2074    @IntDef({
2075        TEXT_ALIGNMENT_INHERIT,
2076        TEXT_ALIGNMENT_GRAVITY,
2077        TEXT_ALIGNMENT_CENTER,
2078        TEXT_ALIGNMENT_TEXT_START,
2079        TEXT_ALIGNMENT_TEXT_END,
2080        TEXT_ALIGNMENT_VIEW_START,
2081        TEXT_ALIGNMENT_VIEW_END
2082    })
2083    @Retention(RetentionPolicy.SOURCE)
2084    public @interface TextAlignment {}
2085
2086    /**
2087     * Default text alignment. The text alignment of this View is inherited from its parent.
2088     * Use with {@link #setTextAlignment(int)}
2089     */
2090    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2091
2092    /**
2093     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2094     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2095     *
2096     * Use with {@link #setTextAlignment(int)}
2097     */
2098    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2099
2100    /**
2101     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2102     *
2103     * Use with {@link #setTextAlignment(int)}
2104     */
2105    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2106
2107    /**
2108     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2109     *
2110     * Use with {@link #setTextAlignment(int)}
2111     */
2112    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2113
2114    /**
2115     * Center the paragraph, e.g. ALIGN_CENTER.
2116     *
2117     * Use with {@link #setTextAlignment(int)}
2118     */
2119    public static final int TEXT_ALIGNMENT_CENTER = 4;
2120
2121    /**
2122     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2123     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2124     *
2125     * Use with {@link #setTextAlignment(int)}
2126     */
2127    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2128
2129    /**
2130     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2131     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2132     *
2133     * Use with {@link #setTextAlignment(int)}
2134     */
2135    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2136
2137    /**
2138     * Default text alignment is inherited
2139     */
2140    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2141
2142    /**
2143     * Default resolved text alignment
2144     * @hide
2145     */
2146    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2147
2148    /**
2149      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2150      * @hide
2151      */
2152    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2153
2154    /**
2155      * Mask for use with private flags indicating bits used for text alignment.
2156      * @hide
2157      */
2158    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2159
2160    /**
2161     * Array of text direction flags for mapping attribute "textAlignment" to correct
2162     * flag value.
2163     * @hide
2164     */
2165    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2166            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2167            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2168            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2169            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2170            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2171            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2172            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2173    };
2174
2175    /**
2176     * Indicates whether the view text alignment has been resolved.
2177     * @hide
2178     */
2179    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2180
2181    /**
2182     * Bit shift to get the resolved text alignment.
2183     * @hide
2184     */
2185    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2186
2187    /**
2188     * Mask for use with private flags indicating bits used for text alignment.
2189     * @hide
2190     */
2191    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2192            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2193
2194    /**
2195     * Indicates whether if the view text alignment has been resolved to gravity
2196     */
2197    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2198            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2199
2200    // Accessiblity constants for mPrivateFlags2
2201
2202    /**
2203     * Shift for the bits in {@link #mPrivateFlags2} related to the
2204     * "importantForAccessibility" attribute.
2205     */
2206    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2207
2208    /**
2209     * Automatically determine whether a view is important for accessibility.
2210     */
2211    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2212
2213    /**
2214     * The view is important for accessibility.
2215     */
2216    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2217
2218    /**
2219     * The view is not important for accessibility.
2220     */
2221    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2222
2223    /**
2224     * The view is not important for accessibility, nor are any of its
2225     * descendant views.
2226     */
2227    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2228
2229    /**
2230     * The default whether the view is important for accessibility.
2231     */
2232    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2233
2234    /**
2235     * Mask for obtainig the bits which specify how to determine
2236     * whether a view is important for accessibility.
2237     */
2238    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2239        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2240        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2241        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2242
2243    /**
2244     * Shift for the bits in {@link #mPrivateFlags2} related to the
2245     * "accessibilityLiveRegion" attribute.
2246     */
2247    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2248
2249    /**
2250     * Live region mode specifying that accessibility services should not
2251     * automatically announce changes to this view. This is the default live
2252     * region mode for most views.
2253     * <p>
2254     * Use with {@link #setAccessibilityLiveRegion(int)}.
2255     */
2256    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2257
2258    /**
2259     * Live region mode specifying that accessibility services should announce
2260     * changes to this view.
2261     * <p>
2262     * Use with {@link #setAccessibilityLiveRegion(int)}.
2263     */
2264    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2265
2266    /**
2267     * Live region mode specifying that accessibility services should interrupt
2268     * ongoing speech to immediately announce changes to this view.
2269     * <p>
2270     * Use with {@link #setAccessibilityLiveRegion(int)}.
2271     */
2272    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2273
2274    /**
2275     * The default whether the view is important for accessibility.
2276     */
2277    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2278
2279    /**
2280     * Mask for obtaining the bits which specify a view's accessibility live
2281     * region mode.
2282     */
2283    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2284            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2285            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2286
2287    /**
2288     * Flag indicating whether a view has accessibility focus.
2289     */
2290    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2291
2292    /**
2293     * Flag whether the accessibility state of the subtree rooted at this view changed.
2294     */
2295    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2296
2297    /**
2298     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2299     * is used to check whether later changes to the view's transform should invalidate the
2300     * view to force the quickReject test to run again.
2301     */
2302    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2303
2304    /**
2305     * Flag indicating that start/end padding has been resolved into left/right padding
2306     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2307     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2308     * during measurement. In some special cases this is required such as when an adapter-based
2309     * view measures prospective children without attaching them to a window.
2310     */
2311    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2312
2313    /**
2314     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2315     */
2316    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2317
2318    /**
2319     * Indicates that the view is tracking some sort of transient state
2320     * that the app should not need to be aware of, but that the framework
2321     * should take special care to preserve.
2322     */
2323    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2324
2325    /**
2326     * Group of bits indicating that RTL properties resolution is done.
2327     */
2328    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2329            PFLAG2_TEXT_DIRECTION_RESOLVED |
2330            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2331            PFLAG2_PADDING_RESOLVED |
2332            PFLAG2_DRAWABLE_RESOLVED;
2333
2334    // There are a couple of flags left in mPrivateFlags2
2335
2336    /* End of masks for mPrivateFlags2 */
2337
2338    /**
2339     * Masks for mPrivateFlags3, as generated by dumpFlags():
2340     *
2341     * |-------|-------|-------|-------|
2342     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2343     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2344     *                               1   PFLAG3_IS_LAID_OUT
2345     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2346     *                             1     PFLAG3_CALLED_SUPER
2347     * |-------|-------|-------|-------|
2348     */
2349
2350    /**
2351     * Flag indicating that view has a transform animation set on it. This is used to track whether
2352     * an animation is cleared between successive frames, in order to tell the associated
2353     * DisplayList to clear its animation matrix.
2354     */
2355    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2356
2357    /**
2358     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2359     * animation is cleared between successive frames, in order to tell the associated
2360     * DisplayList to restore its alpha value.
2361     */
2362    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2363
2364    /**
2365     * Flag indicating that the view has been through at least one layout since it
2366     * was last attached to a window.
2367     */
2368    static final int PFLAG3_IS_LAID_OUT = 0x4;
2369
2370    /**
2371     * Flag indicating that a call to measure() was skipped and should be done
2372     * instead when layout() is invoked.
2373     */
2374    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2375
2376    /**
2377     * Flag indicating that an overridden method correctly called down to
2378     * the superclass implementation as required by the API spec.
2379     */
2380    static final int PFLAG3_CALLED_SUPER = 0x10;
2381
2382    /**
2383     * Flag indicating that we're in the process of applying window insets.
2384     */
2385    static final int PFLAG3_APPLYING_INSETS = 0x20;
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 = 0x40;
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 = 0x80;
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     * Whether Recents is visible or not.
2776     */
2777    public static final int RECENT_APPS_VISIBLE = 0x00004000;
2778
2779    /**
2780     * @hide
2781     *
2782     * Makes system ui transparent.
2783     */
2784    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2785
2786    /**
2787     * @hide
2788     */
2789    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2790
2791    /**
2792     * These are the system UI flags that can be cleared by events outside
2793     * of an application.  Currently this is just the ability to tap on the
2794     * screen while hiding the navigation bar to have it return.
2795     * @hide
2796     */
2797    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2798            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2799            | SYSTEM_UI_FLAG_FULLSCREEN;
2800
2801    /**
2802     * Flags that can impact the layout in relation to system UI.
2803     */
2804    public static final int SYSTEM_UI_LAYOUT_FLAGS =
2805            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2806            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2807
2808    /** @hide */
2809    @IntDef(flag = true,
2810            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2811    @Retention(RetentionPolicy.SOURCE)
2812    public @interface FindViewFlags {}
2813
2814    /**
2815     * Find views that render the specified text.
2816     *
2817     * @see #findViewsWithText(ArrayList, CharSequence, int)
2818     */
2819    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2820
2821    /**
2822     * Find find views that contain the specified content description.
2823     *
2824     * @see #findViewsWithText(ArrayList, CharSequence, int)
2825     */
2826    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2827
2828    /**
2829     * Find views that contain {@link AccessibilityNodeProvider}. Such
2830     * a View is a root of virtual view hierarchy and may contain the searched
2831     * text. If this flag is set Views with providers are automatically
2832     * added and it is a responsibility of the client to call the APIs of
2833     * the provider to determine whether the virtual tree rooted at this View
2834     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2835     * representing the virtual views with this text.
2836     *
2837     * @see #findViewsWithText(ArrayList, CharSequence, int)
2838     *
2839     * @hide
2840     */
2841    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2842
2843    /**
2844     * The undefined cursor position.
2845     *
2846     * @hide
2847     */
2848    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2849
2850    /**
2851     * Indicates that the screen has changed state and is now off.
2852     *
2853     * @see #onScreenStateChanged(int)
2854     */
2855    public static final int SCREEN_STATE_OFF = 0x0;
2856
2857    /**
2858     * Indicates that the screen has changed state and is now on.
2859     *
2860     * @see #onScreenStateChanged(int)
2861     */
2862    public static final int SCREEN_STATE_ON = 0x1;
2863
2864    /**
2865     * Indicates no axis of view scrolling.
2866     */
2867    public static final int SCROLL_AXIS_NONE = 0;
2868
2869    /**
2870     * Indicates scrolling along the horizontal axis.
2871     */
2872    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
2873
2874    /**
2875     * Indicates scrolling along the vertical axis.
2876     */
2877    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
2878
2879    /**
2880     * Controls the over-scroll mode for this view.
2881     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2882     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2883     * and {@link #OVER_SCROLL_NEVER}.
2884     */
2885    private int mOverScrollMode;
2886
2887    /**
2888     * The parent this view is attached to.
2889     * {@hide}
2890     *
2891     * @see #getParent()
2892     */
2893    protected ViewParent mParent;
2894
2895    /**
2896     * {@hide}
2897     */
2898    AttachInfo mAttachInfo;
2899
2900    /**
2901     * {@hide}
2902     */
2903    @ViewDebug.ExportedProperty(flagMapping = {
2904        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2905                name = "FORCE_LAYOUT"),
2906        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2907                name = "LAYOUT_REQUIRED"),
2908        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2909            name = "DRAWING_CACHE_INVALID", outputIf = false),
2910        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2911        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2912        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2913        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2914    })
2915    int mPrivateFlags;
2916    int mPrivateFlags2;
2917    int mPrivateFlags3;
2918
2919    /**
2920     * This view's request for the visibility of the status bar.
2921     * @hide
2922     */
2923    @ViewDebug.ExportedProperty(flagMapping = {
2924        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2925                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2926                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2927        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2928                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2929                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2930        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2931                                equals = SYSTEM_UI_FLAG_VISIBLE,
2932                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2933    })
2934    int mSystemUiVisibility;
2935
2936    /**
2937     * Reference count for transient state.
2938     * @see #setHasTransientState(boolean)
2939     */
2940    int mTransientStateCount = 0;
2941
2942    /**
2943     * Count of how many windows this view has been attached to.
2944     */
2945    int mWindowAttachCount;
2946
2947    /**
2948     * The layout parameters associated with this view and used by the parent
2949     * {@link android.view.ViewGroup} to determine how this view should be
2950     * laid out.
2951     * {@hide}
2952     */
2953    protected ViewGroup.LayoutParams mLayoutParams;
2954
2955    /**
2956     * The view flags hold various views states.
2957     * {@hide}
2958     */
2959    @ViewDebug.ExportedProperty
2960    int mViewFlags;
2961
2962    static class TransformationInfo {
2963        /**
2964         * The transform matrix for the View. This transform is calculated internally
2965         * based on the translation, rotation, and scale properties.
2966         *
2967         * Do *not* use this variable directly; instead call getMatrix(), which will
2968         * load the value from the View's RenderNode.
2969         */
2970        private final Matrix mMatrix = new Matrix();
2971
2972        /**
2973         * The inverse transform matrix for the View. This transform is calculated
2974         * internally based on the translation, rotation, and scale properties.
2975         *
2976         * Do *not* use this variable directly; instead call getInverseMatrix(),
2977         * which will load the value from the View's RenderNode.
2978         */
2979        private Matrix mInverseMatrix;
2980
2981        /**
2982         * The opacity of the View. This is a value from 0 to 1, where 0 means
2983         * completely transparent and 1 means completely opaque.
2984         */
2985        @ViewDebug.ExportedProperty
2986        float mAlpha = 1f;
2987
2988        /**
2989         * The opacity of the view as manipulated by the Fade transition. This is a hidden
2990         * property only used by transitions, which is composited with the other alpha
2991         * values to calculate the final visual alpha value.
2992         */
2993        float mTransitionAlpha = 1f;
2994    }
2995
2996    TransformationInfo mTransformationInfo;
2997
2998    /**
2999     * Current clip bounds. to which all drawing of this view are constrained.
3000     */
3001    Rect mClipBounds = null;
3002
3003    private boolean mLastIsOpaque;
3004
3005    /**
3006     * The distance in pixels from the left edge of this view's parent
3007     * to the left edge of this view.
3008     * {@hide}
3009     */
3010    @ViewDebug.ExportedProperty(category = "layout")
3011    protected int mLeft;
3012    /**
3013     * The distance in pixels from the left edge of this view's parent
3014     * to the right edge of this view.
3015     * {@hide}
3016     */
3017    @ViewDebug.ExportedProperty(category = "layout")
3018    protected int mRight;
3019    /**
3020     * The distance in pixels from the top edge of this view's parent
3021     * to the top edge of this view.
3022     * {@hide}
3023     */
3024    @ViewDebug.ExportedProperty(category = "layout")
3025    protected int mTop;
3026    /**
3027     * The distance in pixels from the top edge of this view's parent
3028     * to the bottom edge of this view.
3029     * {@hide}
3030     */
3031    @ViewDebug.ExportedProperty(category = "layout")
3032    protected int mBottom;
3033
3034    /**
3035     * The offset, in pixels, by which the content of this view is scrolled
3036     * horizontally.
3037     * {@hide}
3038     */
3039    @ViewDebug.ExportedProperty(category = "scrolling")
3040    protected int mScrollX;
3041    /**
3042     * The offset, in pixels, by which the content of this view is scrolled
3043     * vertically.
3044     * {@hide}
3045     */
3046    @ViewDebug.ExportedProperty(category = "scrolling")
3047    protected int mScrollY;
3048
3049    /**
3050     * The left padding in pixels, that is the distance in pixels between the
3051     * left edge of this view and the left edge of its content.
3052     * {@hide}
3053     */
3054    @ViewDebug.ExportedProperty(category = "padding")
3055    protected int mPaddingLeft = 0;
3056    /**
3057     * The right padding in pixels, that is the distance in pixels between the
3058     * right edge of this view and the right edge of its content.
3059     * {@hide}
3060     */
3061    @ViewDebug.ExportedProperty(category = "padding")
3062    protected int mPaddingRight = 0;
3063    /**
3064     * The top padding in pixels, that is the distance in pixels between the
3065     * top edge of this view and the top edge of its content.
3066     * {@hide}
3067     */
3068    @ViewDebug.ExportedProperty(category = "padding")
3069    protected int mPaddingTop;
3070    /**
3071     * The bottom padding in pixels, that is the distance in pixels between the
3072     * bottom edge of this view and the bottom edge of its content.
3073     * {@hide}
3074     */
3075    @ViewDebug.ExportedProperty(category = "padding")
3076    protected int mPaddingBottom;
3077
3078    /**
3079     * The layout insets in pixels, that is the distance in pixels between the
3080     * visible edges of this view its bounds.
3081     */
3082    private Insets mLayoutInsets;
3083
3084    /**
3085     * Briefly describes the view and is primarily used for accessibility support.
3086     */
3087    private CharSequence mContentDescription;
3088
3089    /**
3090     * Specifies the id of a view for which this view serves as a label for
3091     * accessibility purposes.
3092     */
3093    private int mLabelForId = View.NO_ID;
3094
3095    /**
3096     * Predicate for matching labeled view id with its label for
3097     * accessibility purposes.
3098     */
3099    private MatchLabelForPredicate mMatchLabelForPredicate;
3100
3101    /**
3102     * Predicate for matching a view by its id.
3103     */
3104    private MatchIdPredicate mMatchIdPredicate;
3105
3106    /**
3107     * Cache the paddingRight set by the user to append to the scrollbar's size.
3108     *
3109     * @hide
3110     */
3111    @ViewDebug.ExportedProperty(category = "padding")
3112    protected int mUserPaddingRight;
3113
3114    /**
3115     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3116     *
3117     * @hide
3118     */
3119    @ViewDebug.ExportedProperty(category = "padding")
3120    protected int mUserPaddingBottom;
3121
3122    /**
3123     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3124     *
3125     * @hide
3126     */
3127    @ViewDebug.ExportedProperty(category = "padding")
3128    protected int mUserPaddingLeft;
3129
3130    /**
3131     * Cache the paddingStart set by the user to append to the scrollbar's size.
3132     *
3133     */
3134    @ViewDebug.ExportedProperty(category = "padding")
3135    int mUserPaddingStart;
3136
3137    /**
3138     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3139     *
3140     */
3141    @ViewDebug.ExportedProperty(category = "padding")
3142    int mUserPaddingEnd;
3143
3144    /**
3145     * Cache initial left padding.
3146     *
3147     * @hide
3148     */
3149    int mUserPaddingLeftInitial;
3150
3151    /**
3152     * Cache initial right padding.
3153     *
3154     * @hide
3155     */
3156    int mUserPaddingRightInitial;
3157
3158    /**
3159     * Default undefined padding
3160     */
3161    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3162
3163    /**
3164     * Cache if a left padding has been defined
3165     */
3166    private boolean mLeftPaddingDefined = false;
3167
3168    /**
3169     * Cache if a right padding has been defined
3170     */
3171    private boolean mRightPaddingDefined = false;
3172
3173    /**
3174     * @hide
3175     */
3176    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3177    /**
3178     * @hide
3179     */
3180    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3181
3182    private LongSparseLongArray mMeasureCache;
3183
3184    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3185    private Drawable mBackground;
3186    private ColorStateList mBackgroundTint = null;
3187    private PorterDuff.Mode mBackgroundTintMode = PorterDuff.Mode.SRC_ATOP;
3188    private boolean mHasBackgroundTint = false;
3189
3190    /**
3191     * RenderNode used for backgrounds.
3192     * <p>
3193     * When non-null and valid, this is expected to contain an up-to-date copy
3194     * of the background drawable. It is cleared on temporary detach, and reset
3195     * on cleanup.
3196     */
3197    private RenderNode mBackgroundRenderNode;
3198
3199    private int mBackgroundResource;
3200    private boolean mBackgroundSizeChanged;
3201
3202    private String mTransitionName;
3203
3204    static class ListenerInfo {
3205        /**
3206         * Listener used to dispatch focus change events.
3207         * This field should be made private, so it is hidden from the SDK.
3208         * {@hide}
3209         */
3210        protected OnFocusChangeListener mOnFocusChangeListener;
3211
3212        /**
3213         * Listeners for layout change events.
3214         */
3215        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3216
3217        /**
3218         * Listeners for attach events.
3219         */
3220        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3221
3222        /**
3223         * Listener used to dispatch click events.
3224         * This field should be made private, so it is hidden from the SDK.
3225         * {@hide}
3226         */
3227        public OnClickListener mOnClickListener;
3228
3229        /**
3230         * Listener used to dispatch long click events.
3231         * This field should be made private, so it is hidden from the SDK.
3232         * {@hide}
3233         */
3234        protected OnLongClickListener mOnLongClickListener;
3235
3236        /**
3237         * Listener used to build the context menu.
3238         * This field should be made private, so it is hidden from the SDK.
3239         * {@hide}
3240         */
3241        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3242
3243        private OnKeyListener mOnKeyListener;
3244
3245        private OnTouchListener mOnTouchListener;
3246
3247        private OnHoverListener mOnHoverListener;
3248
3249        private OnGenericMotionListener mOnGenericMotionListener;
3250
3251        private OnDragListener mOnDragListener;
3252
3253        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3254
3255        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3256    }
3257
3258    ListenerInfo mListenerInfo;
3259
3260    /**
3261     * The application environment this view lives in.
3262     * This field should be made private, so it is hidden from the SDK.
3263     * {@hide}
3264     */
3265    protected Context mContext;
3266
3267    private final Resources mResources;
3268
3269    private ScrollabilityCache mScrollCache;
3270
3271    private int[] mDrawableState = null;
3272
3273    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3274
3275    /**
3276     * Animator that automatically runs based on state changes.
3277     */
3278    private StateListAnimator mStateListAnimator;
3279
3280    /**
3281     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3282     * the user may specify which view to go to next.
3283     */
3284    private int mNextFocusLeftId = View.NO_ID;
3285
3286    /**
3287     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3288     * the user may specify which view to go to next.
3289     */
3290    private int mNextFocusRightId = View.NO_ID;
3291
3292    /**
3293     * When this view has focus and the next focus is {@link #FOCUS_UP},
3294     * the user may specify which view to go to next.
3295     */
3296    private int mNextFocusUpId = View.NO_ID;
3297
3298    /**
3299     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3300     * the user may specify which view to go to next.
3301     */
3302    private int mNextFocusDownId = View.NO_ID;
3303
3304    /**
3305     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3306     * the user may specify which view to go to next.
3307     */
3308    int mNextFocusForwardId = View.NO_ID;
3309
3310    private CheckForLongPress mPendingCheckForLongPress;
3311    private CheckForTap mPendingCheckForTap = null;
3312    private PerformClick mPerformClick;
3313    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3314
3315    private UnsetPressedState mUnsetPressedState;
3316
3317    /**
3318     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3319     * up event while a long press is invoked as soon as the long press duration is reached, so
3320     * a long press could be performed before the tap is checked, in which case the tap's action
3321     * should not be invoked.
3322     */
3323    private boolean mHasPerformedLongPress;
3324
3325    /**
3326     * The minimum height of the view. We'll try our best to have the height
3327     * of this view to at least this amount.
3328     */
3329    @ViewDebug.ExportedProperty(category = "measurement")
3330    private int mMinHeight;
3331
3332    /**
3333     * The minimum width of the view. We'll try our best to have the width
3334     * of this view to at least this amount.
3335     */
3336    @ViewDebug.ExportedProperty(category = "measurement")
3337    private int mMinWidth;
3338
3339    /**
3340     * The delegate to handle touch events that are physically in this view
3341     * but should be handled by another view.
3342     */
3343    private TouchDelegate mTouchDelegate = null;
3344
3345    /**
3346     * Solid color to use as a background when creating the drawing cache. Enables
3347     * the cache to use 16 bit bitmaps instead of 32 bit.
3348     */
3349    private int mDrawingCacheBackgroundColor = 0;
3350
3351    /**
3352     * Special tree observer used when mAttachInfo is null.
3353     */
3354    private ViewTreeObserver mFloatingTreeObserver;
3355
3356    /**
3357     * Cache the touch slop from the context that created the view.
3358     */
3359    private int mTouchSlop;
3360
3361    /**
3362     * Object that handles automatic animation of view properties.
3363     */
3364    private ViewPropertyAnimator mAnimator = null;
3365
3366    /**
3367     * Flag indicating that a drag can cross window boundaries.  When
3368     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3369     * with this flag set, all visible applications will be able to participate
3370     * in the drag operation and receive the dragged content.
3371     *
3372     * @hide
3373     */
3374    public static final int DRAG_FLAG_GLOBAL = 1;
3375
3376    /**
3377     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3378     */
3379    private float mVerticalScrollFactor;
3380
3381    /**
3382     * Position of the vertical scroll bar.
3383     */
3384    private int mVerticalScrollbarPosition;
3385
3386    /**
3387     * Position the scroll bar at the default position as determined by the system.
3388     */
3389    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3390
3391    /**
3392     * Position the scroll bar along the left edge.
3393     */
3394    public static final int SCROLLBAR_POSITION_LEFT = 1;
3395
3396    /**
3397     * Position the scroll bar along the right edge.
3398     */
3399    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3400
3401    /**
3402     * Indicates that the view does not have a layer.
3403     *
3404     * @see #getLayerType()
3405     * @see #setLayerType(int, android.graphics.Paint)
3406     * @see #LAYER_TYPE_SOFTWARE
3407     * @see #LAYER_TYPE_HARDWARE
3408     */
3409    public static final int LAYER_TYPE_NONE = 0;
3410
3411    /**
3412     * <p>Indicates that the view has a software layer. A software layer is backed
3413     * by a bitmap and causes the view to be rendered using Android's software
3414     * rendering pipeline, even if hardware acceleration is enabled.</p>
3415     *
3416     * <p>Software layers have various usages:</p>
3417     * <p>When the application is not using hardware acceleration, a software layer
3418     * is useful to apply a specific color filter and/or blending mode and/or
3419     * translucency to a view and all its children.</p>
3420     * <p>When the application is using hardware acceleration, a software layer
3421     * is useful to render drawing primitives not supported by the hardware
3422     * accelerated pipeline. It can also be used to cache a complex view tree
3423     * into a texture and reduce the complexity of drawing operations. For instance,
3424     * when animating a complex view tree with a translation, a software layer can
3425     * be used to render the view tree only once.</p>
3426     * <p>Software layers should be avoided when the affected view tree updates
3427     * often. Every update will require to re-render the software layer, which can
3428     * potentially be slow (particularly when hardware acceleration is turned on
3429     * since the layer will have to be uploaded into a hardware texture after every
3430     * update.)</p>
3431     *
3432     * @see #getLayerType()
3433     * @see #setLayerType(int, android.graphics.Paint)
3434     * @see #LAYER_TYPE_NONE
3435     * @see #LAYER_TYPE_HARDWARE
3436     */
3437    public static final int LAYER_TYPE_SOFTWARE = 1;
3438
3439    /**
3440     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3441     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3442     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3443     * rendering pipeline, but only if hardware acceleration is turned on for the
3444     * view hierarchy. When hardware acceleration is turned off, hardware layers
3445     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3446     *
3447     * <p>A hardware layer is useful to apply a specific color filter and/or
3448     * blending mode and/or translucency to a view and all its children.</p>
3449     * <p>A hardware layer can be used to cache a complex view tree into a
3450     * texture and reduce the complexity of drawing operations. For instance,
3451     * when animating a complex view tree with a translation, a hardware layer can
3452     * be used to render the view tree only once.</p>
3453     * <p>A hardware layer can also be used to increase the rendering quality when
3454     * rotation transformations are applied on a view. It can also be used to
3455     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3456     *
3457     * @see #getLayerType()
3458     * @see #setLayerType(int, android.graphics.Paint)
3459     * @see #LAYER_TYPE_NONE
3460     * @see #LAYER_TYPE_SOFTWARE
3461     */
3462    public static final int LAYER_TYPE_HARDWARE = 2;
3463
3464    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3465            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3466            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3467            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3468    })
3469    int mLayerType = LAYER_TYPE_NONE;
3470    Paint mLayerPaint;
3471
3472    /**
3473     * Set to true when drawing cache is enabled and cannot be created.
3474     *
3475     * @hide
3476     */
3477    public boolean mCachingFailed;
3478    private Bitmap mDrawingCache;
3479    private Bitmap mUnscaledDrawingCache;
3480
3481    /**
3482     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3483     * <p>
3484     * When non-null and valid, this is expected to contain an up-to-date copy
3485     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3486     * cleanup.
3487     */
3488    final RenderNode mRenderNode;
3489
3490    /**
3491     * Set to true when the view is sending hover accessibility events because it
3492     * is the innermost hovered view.
3493     */
3494    private boolean mSendingHoverAccessibilityEvents;
3495
3496    /**
3497     * Delegate for injecting accessibility functionality.
3498     */
3499    AccessibilityDelegate mAccessibilityDelegate;
3500
3501    /**
3502     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3503     * and add/remove objects to/from the overlay directly through the Overlay methods.
3504     */
3505    ViewOverlay mOverlay;
3506
3507    /**
3508     * The currently active parent view for receiving delegated nested scrolling events.
3509     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3510     * by {@link #stopNestedScroll()} at the same point where we clear
3511     * requestDisallowInterceptTouchEvent.
3512     */
3513    private ViewParent mNestedScrollingParent;
3514
3515    /**
3516     * Consistency verifier for debugging purposes.
3517     * @hide
3518     */
3519    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3520            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3521                    new InputEventConsistencyVerifier(this, 0) : null;
3522
3523    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3524
3525    private int[] mTempNestedScrollConsumed;
3526
3527    /**
3528     * Simple constructor to use when creating a view from code.
3529     *
3530     * @param context The Context the view is running in, through which it can
3531     *        access the current theme, resources, etc.
3532     */
3533    public View(Context context) {
3534        mContext = context;
3535        mResources = context != null ? context.getResources() : null;
3536        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3537        // Set some flags defaults
3538        mPrivateFlags2 =
3539                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3540                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3541                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3542                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3543                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3544                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3545        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3546        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3547        mUserPaddingStart = UNDEFINED_PADDING;
3548        mUserPaddingEnd = UNDEFINED_PADDING;
3549        mRenderNode = RenderNode.create(getClass().getName());
3550
3551        if (!sCompatibilityDone && context != null) {
3552            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3553
3554            // Older apps may need this compatibility hack for measurement.
3555            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3556
3557            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3558            // of whether a layout was requested on that View.
3559            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3560
3561            // Older apps may need this to ignore the clip bounds
3562            sIgnoreClipBoundsForChildren = targetSdkVersion < L;
3563
3564            sCompatibilityDone = true;
3565        }
3566    }
3567
3568    /**
3569     * Constructor that is called when inflating a view from XML. This is called
3570     * when a view is being constructed from an XML file, supplying attributes
3571     * that were specified in the XML file. This version uses a default style of
3572     * 0, so the only attribute values applied are those in the Context's Theme
3573     * and the given AttributeSet.
3574     *
3575     * <p>
3576     * The method onFinishInflate() will be called after all children have been
3577     * added.
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     * @see #View(Context, AttributeSet, int)
3583     */
3584    public View(Context context, AttributeSet attrs) {
3585        this(context, attrs, 0);
3586    }
3587
3588    /**
3589     * Perform inflation from XML and apply a class-specific base style from a
3590     * theme attribute. This constructor of View allows subclasses to use their
3591     * own base style when they are inflating. For example, a Button class's
3592     * constructor would call this version of the super class constructor and
3593     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3594     * allows the theme's button style to modify all of the base view attributes
3595     * (in particular its background) as well as the Button class's attributes.
3596     *
3597     * @param context The Context the view is running in, through which it can
3598     *        access the current theme, resources, etc.
3599     * @param attrs The attributes of the XML tag that is inflating the view.
3600     * @param defStyleAttr An attribute in the current theme that contains a
3601     *        reference to a style resource that supplies default values for
3602     *        the view. Can be 0 to not look for defaults.
3603     * @see #View(Context, AttributeSet)
3604     */
3605    public View(Context context, AttributeSet attrs, int defStyleAttr) {
3606        this(context, attrs, defStyleAttr, 0);
3607    }
3608
3609    /**
3610     * Perform inflation from XML and apply a class-specific base style from a
3611     * theme attribute or style resource. This constructor of View allows
3612     * subclasses to use their own base style when they are inflating.
3613     * <p>
3614     * When determining the final value of a particular attribute, there are
3615     * four inputs that come into play:
3616     * <ol>
3617     * <li>Any attribute values in the given AttributeSet.
3618     * <li>The style resource specified in the AttributeSet (named "style").
3619     * <li>The default style specified by <var>defStyleAttr</var>.
3620     * <li>The default style specified by <var>defStyleRes</var>.
3621     * <li>The base values in this theme.
3622     * </ol>
3623     * <p>
3624     * Each of these inputs is considered in-order, with the first listed taking
3625     * precedence over the following ones. In other words, if in the
3626     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3627     * , then the button's text will <em>always</em> be black, regardless of
3628     * what is specified in any of the styles.
3629     *
3630     * @param context The Context the view is running in, through which it can
3631     *        access the current theme, resources, etc.
3632     * @param attrs The attributes of the XML tag that is inflating the view.
3633     * @param defStyleAttr An attribute in the current theme that contains a
3634     *        reference to a style resource that supplies default values for
3635     *        the view. Can be 0 to not look for defaults.
3636     * @param defStyleRes A resource identifier of a style resource that
3637     *        supplies default values for the view, used only if
3638     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3639     *        to not look for defaults.
3640     * @see #View(Context, AttributeSet, int)
3641     */
3642    public View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3643        this(context);
3644
3645        final TypedArray a = context.obtainStyledAttributes(
3646                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3647
3648        Drawable background = null;
3649
3650        int leftPadding = -1;
3651        int topPadding = -1;
3652        int rightPadding = -1;
3653        int bottomPadding = -1;
3654        int startPadding = UNDEFINED_PADDING;
3655        int endPadding = UNDEFINED_PADDING;
3656
3657        int padding = -1;
3658
3659        int viewFlagValues = 0;
3660        int viewFlagMasks = 0;
3661
3662        boolean setScrollContainer = false;
3663
3664        int x = 0;
3665        int y = 0;
3666
3667        float tx = 0;
3668        float ty = 0;
3669        float tz = 0;
3670        float elevation = 0;
3671        float rotation = 0;
3672        float rotationX = 0;
3673        float rotationY = 0;
3674        float sx = 1f;
3675        float sy = 1f;
3676        boolean transformSet = false;
3677
3678        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3679        int overScrollMode = mOverScrollMode;
3680        boolean initializeScrollbars = false;
3681
3682        boolean startPaddingDefined = false;
3683        boolean endPaddingDefined = false;
3684        boolean leftPaddingDefined = false;
3685        boolean rightPaddingDefined = false;
3686
3687        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3688
3689        final int N = a.getIndexCount();
3690        for (int i = 0; i < N; i++) {
3691            int attr = a.getIndex(i);
3692            switch (attr) {
3693                case com.android.internal.R.styleable.View_background:
3694                    background = a.getDrawable(attr);
3695                    break;
3696                case com.android.internal.R.styleable.View_padding:
3697                    padding = a.getDimensionPixelSize(attr, -1);
3698                    mUserPaddingLeftInitial = padding;
3699                    mUserPaddingRightInitial = padding;
3700                    leftPaddingDefined = true;
3701                    rightPaddingDefined = true;
3702                    break;
3703                 case com.android.internal.R.styleable.View_paddingLeft:
3704                    leftPadding = a.getDimensionPixelSize(attr, -1);
3705                    mUserPaddingLeftInitial = leftPadding;
3706                    leftPaddingDefined = true;
3707                    break;
3708                case com.android.internal.R.styleable.View_paddingTop:
3709                    topPadding = a.getDimensionPixelSize(attr, -1);
3710                    break;
3711                case com.android.internal.R.styleable.View_paddingRight:
3712                    rightPadding = a.getDimensionPixelSize(attr, -1);
3713                    mUserPaddingRightInitial = rightPadding;
3714                    rightPaddingDefined = true;
3715                    break;
3716                case com.android.internal.R.styleable.View_paddingBottom:
3717                    bottomPadding = a.getDimensionPixelSize(attr, -1);
3718                    break;
3719                case com.android.internal.R.styleable.View_paddingStart:
3720                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3721                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3722                    break;
3723                case com.android.internal.R.styleable.View_paddingEnd:
3724                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3725                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3726                    break;
3727                case com.android.internal.R.styleable.View_scrollX:
3728                    x = a.getDimensionPixelOffset(attr, 0);
3729                    break;
3730                case com.android.internal.R.styleable.View_scrollY:
3731                    y = a.getDimensionPixelOffset(attr, 0);
3732                    break;
3733                case com.android.internal.R.styleable.View_alpha:
3734                    setAlpha(a.getFloat(attr, 1f));
3735                    break;
3736                case com.android.internal.R.styleable.View_transformPivotX:
3737                    setPivotX(a.getDimensionPixelOffset(attr, 0));
3738                    break;
3739                case com.android.internal.R.styleable.View_transformPivotY:
3740                    setPivotY(a.getDimensionPixelOffset(attr, 0));
3741                    break;
3742                case com.android.internal.R.styleable.View_translationX:
3743                    tx = a.getDimensionPixelOffset(attr, 0);
3744                    transformSet = true;
3745                    break;
3746                case com.android.internal.R.styleable.View_translationY:
3747                    ty = a.getDimensionPixelOffset(attr, 0);
3748                    transformSet = true;
3749                    break;
3750                case com.android.internal.R.styleable.View_translationZ:
3751                    tz = a.getDimensionPixelOffset(attr, 0);
3752                    transformSet = true;
3753                    break;
3754                case com.android.internal.R.styleable.View_elevation:
3755                    elevation = a.getDimensionPixelOffset(attr, 0);
3756                    transformSet = true;
3757                    break;
3758                case com.android.internal.R.styleable.View_rotation:
3759                    rotation = a.getFloat(attr, 0);
3760                    transformSet = true;
3761                    break;
3762                case com.android.internal.R.styleable.View_rotationX:
3763                    rotationX = a.getFloat(attr, 0);
3764                    transformSet = true;
3765                    break;
3766                case com.android.internal.R.styleable.View_rotationY:
3767                    rotationY = a.getFloat(attr, 0);
3768                    transformSet = true;
3769                    break;
3770                case com.android.internal.R.styleable.View_scaleX:
3771                    sx = a.getFloat(attr, 1f);
3772                    transformSet = true;
3773                    break;
3774                case com.android.internal.R.styleable.View_scaleY:
3775                    sy = a.getFloat(attr, 1f);
3776                    transformSet = true;
3777                    break;
3778                case com.android.internal.R.styleable.View_id:
3779                    mID = a.getResourceId(attr, NO_ID);
3780                    break;
3781                case com.android.internal.R.styleable.View_tag:
3782                    mTag = a.getText(attr);
3783                    break;
3784                case com.android.internal.R.styleable.View_fitsSystemWindows:
3785                    if (a.getBoolean(attr, false)) {
3786                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
3787                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3788                    }
3789                    break;
3790                case com.android.internal.R.styleable.View_focusable:
3791                    if (a.getBoolean(attr, false)) {
3792                        viewFlagValues |= FOCUSABLE;
3793                        viewFlagMasks |= FOCUSABLE_MASK;
3794                    }
3795                    break;
3796                case com.android.internal.R.styleable.View_focusableInTouchMode:
3797                    if (a.getBoolean(attr, false)) {
3798                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3799                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3800                    }
3801                    break;
3802                case com.android.internal.R.styleable.View_clickable:
3803                    if (a.getBoolean(attr, false)) {
3804                        viewFlagValues |= CLICKABLE;
3805                        viewFlagMasks |= CLICKABLE;
3806                    }
3807                    break;
3808                case com.android.internal.R.styleable.View_longClickable:
3809                    if (a.getBoolean(attr, false)) {
3810                        viewFlagValues |= LONG_CLICKABLE;
3811                        viewFlagMasks |= LONG_CLICKABLE;
3812                    }
3813                    break;
3814                case com.android.internal.R.styleable.View_saveEnabled:
3815                    if (!a.getBoolean(attr, true)) {
3816                        viewFlagValues |= SAVE_DISABLED;
3817                        viewFlagMasks |= SAVE_DISABLED_MASK;
3818                    }
3819                    break;
3820                case com.android.internal.R.styleable.View_duplicateParentState:
3821                    if (a.getBoolean(attr, false)) {
3822                        viewFlagValues |= DUPLICATE_PARENT_STATE;
3823                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
3824                    }
3825                    break;
3826                case com.android.internal.R.styleable.View_visibility:
3827                    final int visibility = a.getInt(attr, 0);
3828                    if (visibility != 0) {
3829                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
3830                        viewFlagMasks |= VISIBILITY_MASK;
3831                    }
3832                    break;
3833                case com.android.internal.R.styleable.View_layoutDirection:
3834                    // Clear any layout direction flags (included resolved bits) already set
3835                    mPrivateFlags2 &=
3836                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3837                    // Set the layout direction flags depending on the value of the attribute
3838                    final int layoutDirection = a.getInt(attr, -1);
3839                    final int value = (layoutDirection != -1) ?
3840                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3841                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3842                    break;
3843                case com.android.internal.R.styleable.View_drawingCacheQuality:
3844                    final int cacheQuality = a.getInt(attr, 0);
3845                    if (cacheQuality != 0) {
3846                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3847                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3848                    }
3849                    break;
3850                case com.android.internal.R.styleable.View_contentDescription:
3851                    setContentDescription(a.getString(attr));
3852                    break;
3853                case com.android.internal.R.styleable.View_labelFor:
3854                    setLabelFor(a.getResourceId(attr, NO_ID));
3855                    break;
3856                case com.android.internal.R.styleable.View_soundEffectsEnabled:
3857                    if (!a.getBoolean(attr, true)) {
3858                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3859                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3860                    }
3861                    break;
3862                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3863                    if (!a.getBoolean(attr, true)) {
3864                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3865                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3866                    }
3867                    break;
3868                case R.styleable.View_scrollbars:
3869                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3870                    if (scrollbars != SCROLLBARS_NONE) {
3871                        viewFlagValues |= scrollbars;
3872                        viewFlagMasks |= SCROLLBARS_MASK;
3873                        initializeScrollbars = true;
3874                    }
3875                    break;
3876                //noinspection deprecation
3877                case R.styleable.View_fadingEdge:
3878                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3879                        // Ignore the attribute starting with ICS
3880                        break;
3881                    }
3882                    // With builds < ICS, fall through and apply fading edges
3883                case R.styleable.View_requiresFadingEdge:
3884                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3885                    if (fadingEdge != FADING_EDGE_NONE) {
3886                        viewFlagValues |= fadingEdge;
3887                        viewFlagMasks |= FADING_EDGE_MASK;
3888                        initializeFadingEdgeInternal(a);
3889                    }
3890                    break;
3891                case R.styleable.View_scrollbarStyle:
3892                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3893                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3894                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3895                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3896                    }
3897                    break;
3898                case R.styleable.View_isScrollContainer:
3899                    setScrollContainer = true;
3900                    if (a.getBoolean(attr, false)) {
3901                        setScrollContainer(true);
3902                    }
3903                    break;
3904                case com.android.internal.R.styleable.View_keepScreenOn:
3905                    if (a.getBoolean(attr, false)) {
3906                        viewFlagValues |= KEEP_SCREEN_ON;
3907                        viewFlagMasks |= KEEP_SCREEN_ON;
3908                    }
3909                    break;
3910                case R.styleable.View_filterTouchesWhenObscured:
3911                    if (a.getBoolean(attr, false)) {
3912                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3913                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3914                    }
3915                    break;
3916                case R.styleable.View_nextFocusLeft:
3917                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3918                    break;
3919                case R.styleable.View_nextFocusRight:
3920                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3921                    break;
3922                case R.styleable.View_nextFocusUp:
3923                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3924                    break;
3925                case R.styleable.View_nextFocusDown:
3926                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3927                    break;
3928                case R.styleable.View_nextFocusForward:
3929                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3930                    break;
3931                case R.styleable.View_minWidth:
3932                    mMinWidth = a.getDimensionPixelSize(attr, 0);
3933                    break;
3934                case R.styleable.View_minHeight:
3935                    mMinHeight = a.getDimensionPixelSize(attr, 0);
3936                    break;
3937                case R.styleable.View_onClick:
3938                    if (context.isRestricted()) {
3939                        throw new IllegalStateException("The android:onClick attribute cannot "
3940                                + "be used within a restricted context");
3941                    }
3942
3943                    final String handlerName = a.getString(attr);
3944                    if (handlerName != null) {
3945                        setOnClickListener(new OnClickListener() {
3946                            private Method mHandler;
3947
3948                            public void onClick(View v) {
3949                                if (mHandler == null) {
3950                                    try {
3951                                        mHandler = getContext().getClass().getMethod(handlerName,
3952                                                View.class);
3953                                    } catch (NoSuchMethodException e) {
3954                                        int id = getId();
3955                                        String idText = id == NO_ID ? "" : " with id '"
3956                                                + getContext().getResources().getResourceEntryName(
3957                                                    id) + "'";
3958                                        throw new IllegalStateException("Could not find a method " +
3959                                                handlerName + "(View) in the activity "
3960                                                + getContext().getClass() + " for onClick handler"
3961                                                + " on view " + View.this.getClass() + idText, e);
3962                                    }
3963                                }
3964
3965                                try {
3966                                    mHandler.invoke(getContext(), View.this);
3967                                } catch (IllegalAccessException e) {
3968                                    throw new IllegalStateException("Could not execute non "
3969                                            + "public method of the activity", e);
3970                                } catch (InvocationTargetException e) {
3971                                    throw new IllegalStateException("Could not execute "
3972                                            + "method of the activity", e);
3973                                }
3974                            }
3975                        });
3976                    }
3977                    break;
3978                case R.styleable.View_overScrollMode:
3979                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3980                    break;
3981                case R.styleable.View_verticalScrollbarPosition:
3982                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3983                    break;
3984                case R.styleable.View_layerType:
3985                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3986                    break;
3987                case R.styleable.View_textDirection:
3988                    // Clear any text direction flag already set
3989                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
3990                    // Set the text direction flags depending on the value of the attribute
3991                    final int textDirection = a.getInt(attr, -1);
3992                    if (textDirection != -1) {
3993                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
3994                    }
3995                    break;
3996                case R.styleable.View_textAlignment:
3997                    // Clear any text alignment flag already set
3998                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
3999                    // Set the text alignment flag depending on the value of the attribute
4000                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4001                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4002                    break;
4003                case R.styleable.View_importantForAccessibility:
4004                    setImportantForAccessibility(a.getInt(attr,
4005                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4006                    break;
4007                case R.styleable.View_accessibilityLiveRegion:
4008                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4009                    break;
4010                case R.styleable.View_transitionName:
4011                    setTransitionName(a.getString(attr));
4012                    break;
4013                case R.styleable.View_nestedScrollingEnabled:
4014                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4015                    break;
4016                case R.styleable.View_stateListAnimator:
4017                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4018                            a.getResourceId(attr, 0)));
4019                    break;
4020                case R.styleable.View_backgroundTint:
4021                    // This will get applied later during setBackground().
4022                    mBackgroundTint = a.getColorStateList(R.styleable.View_backgroundTint);
4023                    mHasBackgroundTint = true;
4024                    break;
4025                case R.styleable.View_backgroundTintMode:
4026                    // This will get applied later during setBackground().
4027                    mBackgroundTintMode = Drawable.parseTintMode(a.getInt(
4028                            R.styleable.View_backgroundTintMode, -1), mBackgroundTintMode);
4029                    break;
4030            }
4031        }
4032
4033        setOverScrollMode(overScrollMode);
4034
4035        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4036        // the resolved layout direction). Those cached values will be used later during padding
4037        // resolution.
4038        mUserPaddingStart = startPadding;
4039        mUserPaddingEnd = endPadding;
4040
4041        if (background != null) {
4042            setBackground(background);
4043        }
4044
4045        // setBackground above will record that padding is currently provided by the background.
4046        // If we have padding specified via xml, record that here instead and use it.
4047        mLeftPaddingDefined = leftPaddingDefined;
4048        mRightPaddingDefined = rightPaddingDefined;
4049
4050        if (padding >= 0) {
4051            leftPadding = padding;
4052            topPadding = padding;
4053            rightPadding = padding;
4054            bottomPadding = padding;
4055            mUserPaddingLeftInitial = padding;
4056            mUserPaddingRightInitial = padding;
4057        }
4058
4059        if (isRtlCompatibilityMode()) {
4060            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4061            // left / right padding are used if defined (meaning here nothing to do). If they are not
4062            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4063            // start / end and resolve them as left / right (layout direction is not taken into account).
4064            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4065            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4066            // defined.
4067            if (!mLeftPaddingDefined && startPaddingDefined) {
4068                leftPadding = startPadding;
4069            }
4070            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4071            if (!mRightPaddingDefined && endPaddingDefined) {
4072                rightPadding = endPadding;
4073            }
4074            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4075        } else {
4076            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4077            // values defined. Otherwise, left /right values are used.
4078            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4079            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4080            // defined.
4081            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4082
4083            if (mLeftPaddingDefined && !hasRelativePadding) {
4084                mUserPaddingLeftInitial = leftPadding;
4085            }
4086            if (mRightPaddingDefined && !hasRelativePadding) {
4087                mUserPaddingRightInitial = rightPadding;
4088            }
4089        }
4090
4091        internalSetPadding(
4092                mUserPaddingLeftInitial,
4093                topPadding >= 0 ? topPadding : mPaddingTop,
4094                mUserPaddingRightInitial,
4095                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4096
4097        if (viewFlagMasks != 0) {
4098            setFlags(viewFlagValues, viewFlagMasks);
4099        }
4100
4101        if (initializeScrollbars) {
4102            initializeScrollbarsInternal(a);
4103        }
4104
4105        a.recycle();
4106
4107        // Needs to be called after mViewFlags is set
4108        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4109            recomputePadding();
4110        }
4111
4112        if (x != 0 || y != 0) {
4113            scrollTo(x, y);
4114        }
4115
4116        if (transformSet) {
4117            setTranslationX(tx);
4118            setTranslationY(ty);
4119            setTranslationZ(tz);
4120            setElevation(elevation);
4121            setRotation(rotation);
4122            setRotationX(rotationX);
4123            setRotationY(rotationY);
4124            setScaleX(sx);
4125            setScaleY(sy);
4126        }
4127
4128        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4129            setScrollContainer(true);
4130        }
4131
4132        computeOpaqueFlags();
4133    }
4134
4135    /**
4136     * Non-public constructor for use in testing
4137     */
4138    View() {
4139        mResources = null;
4140        mRenderNode = RenderNode.create(getClass().getName());
4141    }
4142
4143    public String toString() {
4144        StringBuilder out = new StringBuilder(128);
4145        out.append(getClass().getName());
4146        out.append('{');
4147        out.append(Integer.toHexString(System.identityHashCode(this)));
4148        out.append(' ');
4149        switch (mViewFlags&VISIBILITY_MASK) {
4150            case VISIBLE: out.append('V'); break;
4151            case INVISIBLE: out.append('I'); break;
4152            case GONE: out.append('G'); break;
4153            default: out.append('.'); break;
4154        }
4155        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4156        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4157        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4158        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4159        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4160        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4161        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4162        out.append(' ');
4163        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4164        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4165        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4166        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4167            out.append('p');
4168        } else {
4169            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4170        }
4171        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4172        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4173        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4174        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4175        out.append(' ');
4176        out.append(mLeft);
4177        out.append(',');
4178        out.append(mTop);
4179        out.append('-');
4180        out.append(mRight);
4181        out.append(',');
4182        out.append(mBottom);
4183        final int id = getId();
4184        if (id != NO_ID) {
4185            out.append(" #");
4186            out.append(Integer.toHexString(id));
4187            final Resources r = mResources;
4188            if (Resources.resourceHasPackage(id) && r != null) {
4189                try {
4190                    String pkgname;
4191                    switch (id&0xff000000) {
4192                        case 0x7f000000:
4193                            pkgname="app";
4194                            break;
4195                        case 0x01000000:
4196                            pkgname="android";
4197                            break;
4198                        default:
4199                            pkgname = r.getResourcePackageName(id);
4200                            break;
4201                    }
4202                    String typename = r.getResourceTypeName(id);
4203                    String entryname = r.getResourceEntryName(id);
4204                    out.append(" ");
4205                    out.append(pkgname);
4206                    out.append(":");
4207                    out.append(typename);
4208                    out.append("/");
4209                    out.append(entryname);
4210                } catch (Resources.NotFoundException e) {
4211                }
4212            }
4213        }
4214        out.append("}");
4215        return out.toString();
4216    }
4217
4218    /**
4219     * <p>
4220     * Initializes the fading edges from a given set of styled attributes. This
4221     * method should be called by subclasses that need fading edges and when an
4222     * instance of these subclasses is created programmatically rather than
4223     * being inflated from XML. This method is automatically called when the XML
4224     * is inflated.
4225     * </p>
4226     *
4227     * @param a the styled attributes set to initialize the fading edges from
4228     */
4229    protected void initializeFadingEdge(TypedArray a) {
4230        // This method probably shouldn't have been included in the SDK to begin with.
4231        // It relies on 'a' having been initialized using an attribute filter array that is
4232        // not publicly available to the SDK. The old method has been renamed
4233        // to initializeFadingEdgeInternal and hidden for framework use only;
4234        // this one initializes using defaults to make it safe to call for apps.
4235
4236        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4237
4238        initializeFadingEdgeInternal(arr);
4239
4240        arr.recycle();
4241    }
4242
4243    /**
4244     * <p>
4245     * Initializes the fading edges from a given set of styled attributes. This
4246     * method should be called by subclasses that need fading edges and when an
4247     * instance of these subclasses is created programmatically rather than
4248     * being inflated from XML. This method is automatically called when the XML
4249     * is inflated.
4250     * </p>
4251     *
4252     * @param a the styled attributes set to initialize the fading edges from
4253     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4254     */
4255    protected void initializeFadingEdgeInternal(TypedArray a) {
4256        initScrollCache();
4257
4258        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4259                R.styleable.View_fadingEdgeLength,
4260                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4261    }
4262
4263    /**
4264     * Returns the size of the vertical faded edges used to indicate that more
4265     * content in this view is visible.
4266     *
4267     * @return The size in pixels of the vertical faded edge or 0 if vertical
4268     *         faded edges are not enabled for this view.
4269     * @attr ref android.R.styleable#View_fadingEdgeLength
4270     */
4271    public int getVerticalFadingEdgeLength() {
4272        if (isVerticalFadingEdgeEnabled()) {
4273            ScrollabilityCache cache = mScrollCache;
4274            if (cache != null) {
4275                return cache.fadingEdgeLength;
4276            }
4277        }
4278        return 0;
4279    }
4280
4281    /**
4282     * Set the size of the faded edge used to indicate that more content in this
4283     * view is available.  Will not change whether the fading edge is enabled; use
4284     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4285     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4286     * for the vertical or horizontal fading edges.
4287     *
4288     * @param length The size in pixels of the faded edge used to indicate that more
4289     *        content in this view is visible.
4290     */
4291    public void setFadingEdgeLength(int length) {
4292        initScrollCache();
4293        mScrollCache.fadingEdgeLength = length;
4294    }
4295
4296    /**
4297     * Returns the size of the horizontal faded edges used to indicate that more
4298     * content in this view is visible.
4299     *
4300     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4301     *         faded edges are not enabled for this view.
4302     * @attr ref android.R.styleable#View_fadingEdgeLength
4303     */
4304    public int getHorizontalFadingEdgeLength() {
4305        if (isHorizontalFadingEdgeEnabled()) {
4306            ScrollabilityCache cache = mScrollCache;
4307            if (cache != null) {
4308                return cache.fadingEdgeLength;
4309            }
4310        }
4311        return 0;
4312    }
4313
4314    /**
4315     * Returns the width of the vertical scrollbar.
4316     *
4317     * @return The width in pixels of the vertical scrollbar or 0 if there
4318     *         is no vertical scrollbar.
4319     */
4320    public int getVerticalScrollbarWidth() {
4321        ScrollabilityCache cache = mScrollCache;
4322        if (cache != null) {
4323            ScrollBarDrawable scrollBar = cache.scrollBar;
4324            if (scrollBar != null) {
4325                int size = scrollBar.getSize(true);
4326                if (size <= 0) {
4327                    size = cache.scrollBarSize;
4328                }
4329                return size;
4330            }
4331            return 0;
4332        }
4333        return 0;
4334    }
4335
4336    /**
4337     * Returns the height of the horizontal scrollbar.
4338     *
4339     * @return The height in pixels of the horizontal scrollbar or 0 if
4340     *         there is no horizontal scrollbar.
4341     */
4342    protected int getHorizontalScrollbarHeight() {
4343        ScrollabilityCache cache = mScrollCache;
4344        if (cache != null) {
4345            ScrollBarDrawable scrollBar = cache.scrollBar;
4346            if (scrollBar != null) {
4347                int size = scrollBar.getSize(false);
4348                if (size <= 0) {
4349                    size = cache.scrollBarSize;
4350                }
4351                return size;
4352            }
4353            return 0;
4354        }
4355        return 0;
4356    }
4357
4358    /**
4359     * <p>
4360     * Initializes the scrollbars from a given set of styled attributes. This
4361     * method should be called by subclasses that need scrollbars and when an
4362     * instance of these subclasses is created programmatically rather than
4363     * being inflated from XML. This method is automatically called when the XML
4364     * is inflated.
4365     * </p>
4366     *
4367     * @param a the styled attributes set to initialize the scrollbars from
4368     */
4369    protected void initializeScrollbars(TypedArray a) {
4370        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4371        // using the View filter array which is not available to the SDK. As such, internal
4372        // framework usage now uses initializeScrollbarsInternal and we grab a default
4373        // TypedArray with the right filter instead here.
4374        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4375
4376        initializeScrollbarsInternal(arr);
4377
4378        // We ignored the method parameter. Recycle the one we actually did use.
4379        arr.recycle();
4380    }
4381
4382    /**
4383     * <p>
4384     * Initializes the scrollbars from a given set of styled attributes. This
4385     * method should be called by subclasses that need scrollbars and when an
4386     * instance of these subclasses is created programmatically rather than
4387     * being inflated from XML. This method is automatically called when the XML
4388     * is inflated.
4389     * </p>
4390     *
4391     * @param a the styled attributes set to initialize the scrollbars from
4392     * @hide
4393     */
4394    protected void initializeScrollbarsInternal(TypedArray a) {
4395        initScrollCache();
4396
4397        final ScrollabilityCache scrollabilityCache = mScrollCache;
4398
4399        if (scrollabilityCache.scrollBar == null) {
4400            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4401        }
4402
4403        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4404
4405        if (!fadeScrollbars) {
4406            scrollabilityCache.state = ScrollabilityCache.ON;
4407        }
4408        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4409
4410
4411        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4412                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4413                        .getScrollBarFadeDuration());
4414        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4415                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4416                ViewConfiguration.getScrollDefaultDelay());
4417
4418
4419        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4420                com.android.internal.R.styleable.View_scrollbarSize,
4421                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4422
4423        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4424        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4425
4426        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4427        if (thumb != null) {
4428            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4429        }
4430
4431        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4432                false);
4433        if (alwaysDraw) {
4434            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4435        }
4436
4437        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4438        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4439
4440        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4441        if (thumb != null) {
4442            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4443        }
4444
4445        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4446                false);
4447        if (alwaysDraw) {
4448            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4449        }
4450
4451        // Apply layout direction to the new Drawables if needed
4452        final int layoutDirection = getLayoutDirection();
4453        if (track != null) {
4454            track.setLayoutDirection(layoutDirection);
4455        }
4456        if (thumb != null) {
4457            thumb.setLayoutDirection(layoutDirection);
4458        }
4459
4460        // Re-apply user/background padding so that scrollbar(s) get added
4461        resolvePadding();
4462    }
4463
4464    /**
4465     * <p>
4466     * Initalizes the scrollability cache if necessary.
4467     * </p>
4468     */
4469    private void initScrollCache() {
4470        if (mScrollCache == null) {
4471            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4472        }
4473    }
4474
4475    private ScrollabilityCache getScrollCache() {
4476        initScrollCache();
4477        return mScrollCache;
4478    }
4479
4480    /**
4481     * Set the position of the vertical scroll bar. Should be one of
4482     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4483     * {@link #SCROLLBAR_POSITION_RIGHT}.
4484     *
4485     * @param position Where the vertical scroll bar should be positioned.
4486     */
4487    public void setVerticalScrollbarPosition(int position) {
4488        if (mVerticalScrollbarPosition != position) {
4489            mVerticalScrollbarPosition = position;
4490            computeOpaqueFlags();
4491            resolvePadding();
4492        }
4493    }
4494
4495    /**
4496     * @return The position where the vertical scroll bar will show, if applicable.
4497     * @see #setVerticalScrollbarPosition(int)
4498     */
4499    public int getVerticalScrollbarPosition() {
4500        return mVerticalScrollbarPosition;
4501    }
4502
4503    ListenerInfo getListenerInfo() {
4504        if (mListenerInfo != null) {
4505            return mListenerInfo;
4506        }
4507        mListenerInfo = new ListenerInfo();
4508        return mListenerInfo;
4509    }
4510
4511    /**
4512     * Register a callback to be invoked when focus of this view changed.
4513     *
4514     * @param l The callback that will run.
4515     */
4516    public void setOnFocusChangeListener(OnFocusChangeListener l) {
4517        getListenerInfo().mOnFocusChangeListener = l;
4518    }
4519
4520    /**
4521     * Add a listener that will be called when the bounds of the view change due to
4522     * layout processing.
4523     *
4524     * @param listener The listener that will be called when layout bounds change.
4525     */
4526    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4527        ListenerInfo li = getListenerInfo();
4528        if (li.mOnLayoutChangeListeners == null) {
4529            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4530        }
4531        if (!li.mOnLayoutChangeListeners.contains(listener)) {
4532            li.mOnLayoutChangeListeners.add(listener);
4533        }
4534    }
4535
4536    /**
4537     * Remove a listener for layout changes.
4538     *
4539     * @param listener The listener for layout bounds change.
4540     */
4541    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4542        ListenerInfo li = mListenerInfo;
4543        if (li == null || li.mOnLayoutChangeListeners == null) {
4544            return;
4545        }
4546        li.mOnLayoutChangeListeners.remove(listener);
4547    }
4548
4549    /**
4550     * Add a listener for attach state changes.
4551     *
4552     * This listener will be called whenever this view is attached or detached
4553     * from a window. Remove the listener using
4554     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4555     *
4556     * @param listener Listener to attach
4557     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4558     */
4559    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4560        ListenerInfo li = getListenerInfo();
4561        if (li.mOnAttachStateChangeListeners == null) {
4562            li.mOnAttachStateChangeListeners
4563                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4564        }
4565        li.mOnAttachStateChangeListeners.add(listener);
4566    }
4567
4568    /**
4569     * Remove a listener for attach state changes. The listener will receive no further
4570     * notification of window attach/detach events.
4571     *
4572     * @param listener Listener to remove
4573     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4574     */
4575    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4576        ListenerInfo li = mListenerInfo;
4577        if (li == null || li.mOnAttachStateChangeListeners == null) {
4578            return;
4579        }
4580        li.mOnAttachStateChangeListeners.remove(listener);
4581    }
4582
4583    /**
4584     * Returns the focus-change callback registered for this view.
4585     *
4586     * @return The callback, or null if one is not registered.
4587     */
4588    public OnFocusChangeListener getOnFocusChangeListener() {
4589        ListenerInfo li = mListenerInfo;
4590        return li != null ? li.mOnFocusChangeListener : null;
4591    }
4592
4593    /**
4594     * Register a callback to be invoked when this view is clicked. If this view is not
4595     * clickable, it becomes clickable.
4596     *
4597     * @param l The callback that will run
4598     *
4599     * @see #setClickable(boolean)
4600     */
4601    public void setOnClickListener(OnClickListener l) {
4602        if (!isClickable()) {
4603            setClickable(true);
4604        }
4605        getListenerInfo().mOnClickListener = l;
4606    }
4607
4608    /**
4609     * Return whether this view has an attached OnClickListener.  Returns
4610     * true if there is a listener, false if there is none.
4611     */
4612    public boolean hasOnClickListeners() {
4613        ListenerInfo li = mListenerInfo;
4614        return (li != null && li.mOnClickListener != null);
4615    }
4616
4617    /**
4618     * Register a callback to be invoked when this view is clicked and held. If this view is not
4619     * long clickable, it becomes long clickable.
4620     *
4621     * @param l The callback that will run
4622     *
4623     * @see #setLongClickable(boolean)
4624     */
4625    public void setOnLongClickListener(OnLongClickListener l) {
4626        if (!isLongClickable()) {
4627            setLongClickable(true);
4628        }
4629        getListenerInfo().mOnLongClickListener = l;
4630    }
4631
4632    /**
4633     * Register a callback to be invoked when the context menu for this view is
4634     * being built. If this view is not long clickable, it becomes long clickable.
4635     *
4636     * @param l The callback that will run
4637     *
4638     */
4639    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4640        if (!isLongClickable()) {
4641            setLongClickable(true);
4642        }
4643        getListenerInfo().mOnCreateContextMenuListener = l;
4644    }
4645
4646    /**
4647     * Call this view's OnClickListener, if it is defined.  Performs all normal
4648     * actions associated with clicking: reporting accessibility event, playing
4649     * a sound, etc.
4650     *
4651     * @return True there was an assigned OnClickListener that was called, false
4652     *         otherwise is returned.
4653     */
4654    public boolean performClick() {
4655        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4656
4657        ListenerInfo li = mListenerInfo;
4658        if (li != null && li.mOnClickListener != null) {
4659            playSoundEffect(SoundEffectConstants.CLICK);
4660            li.mOnClickListener.onClick(this);
4661            return true;
4662        }
4663
4664        return false;
4665    }
4666
4667    /**
4668     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
4669     * this only calls the listener, and does not do any associated clicking
4670     * actions like reporting an accessibility event.
4671     *
4672     * @return True there was an assigned OnClickListener that was called, false
4673     *         otherwise is returned.
4674     */
4675    public boolean callOnClick() {
4676        ListenerInfo li = mListenerInfo;
4677        if (li != null && li.mOnClickListener != null) {
4678            li.mOnClickListener.onClick(this);
4679            return true;
4680        }
4681        return false;
4682    }
4683
4684    /**
4685     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4686     * OnLongClickListener did not consume the event.
4687     *
4688     * @return True if one of the above receivers consumed the event, false otherwise.
4689     */
4690    public boolean performLongClick() {
4691        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4692
4693        boolean handled = false;
4694        ListenerInfo li = mListenerInfo;
4695        if (li != null && li.mOnLongClickListener != null) {
4696            handled = li.mOnLongClickListener.onLongClick(View.this);
4697        }
4698        if (!handled) {
4699            handled = showContextMenu();
4700        }
4701        if (handled) {
4702            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4703        }
4704        return handled;
4705    }
4706
4707    /**
4708     * Performs button-related actions during a touch down event.
4709     *
4710     * @param event The event.
4711     * @return True if the down was consumed.
4712     *
4713     * @hide
4714     */
4715    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4716        if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4717            if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4718                return true;
4719            }
4720        }
4721        return false;
4722    }
4723
4724    /**
4725     * Bring up the context menu for this view.
4726     *
4727     * @return Whether a context menu was displayed.
4728     */
4729    public boolean showContextMenu() {
4730        return getParent().showContextMenuForChild(this);
4731    }
4732
4733    /**
4734     * Bring up the context menu for this view, referring to the item under the specified point.
4735     *
4736     * @param x The referenced x coordinate.
4737     * @param y The referenced y coordinate.
4738     * @param metaState The keyboard modifiers that were pressed.
4739     * @return Whether a context menu was displayed.
4740     *
4741     * @hide
4742     */
4743    public boolean showContextMenu(float x, float y, int metaState) {
4744        return showContextMenu();
4745    }
4746
4747    /**
4748     * Start an action mode.
4749     *
4750     * @param callback Callback that will control the lifecycle of the action mode
4751     * @return The new action mode if it is started, null otherwise
4752     *
4753     * @see ActionMode
4754     */
4755    public ActionMode startActionMode(ActionMode.Callback callback) {
4756        ViewParent parent = getParent();
4757        if (parent == null) return null;
4758        return parent.startActionModeForChild(this, callback);
4759    }
4760
4761    /**
4762     * Register a callback to be invoked when a hardware key is pressed in this view.
4763     * Key presses in software input methods will generally not trigger the methods of
4764     * this listener.
4765     * @param l the key listener to attach to this view
4766     */
4767    public void setOnKeyListener(OnKeyListener l) {
4768        getListenerInfo().mOnKeyListener = l;
4769    }
4770
4771    /**
4772     * Register a callback to be invoked when a touch event is sent to this view.
4773     * @param l the touch listener to attach to this view
4774     */
4775    public void setOnTouchListener(OnTouchListener l) {
4776        getListenerInfo().mOnTouchListener = l;
4777    }
4778
4779    /**
4780     * Register a callback to be invoked when a generic motion event is sent to this view.
4781     * @param l the generic motion listener to attach to this view
4782     */
4783    public void setOnGenericMotionListener(OnGenericMotionListener l) {
4784        getListenerInfo().mOnGenericMotionListener = l;
4785    }
4786
4787    /**
4788     * Register a callback to be invoked when a hover event is sent to this view.
4789     * @param l the hover listener to attach to this view
4790     */
4791    public void setOnHoverListener(OnHoverListener l) {
4792        getListenerInfo().mOnHoverListener = l;
4793    }
4794
4795    /**
4796     * Register a drag event listener callback object for this View. The parameter is
4797     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4798     * View, the system calls the
4799     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4800     * @param l An implementation of {@link android.view.View.OnDragListener}.
4801     */
4802    public void setOnDragListener(OnDragListener l) {
4803        getListenerInfo().mOnDragListener = l;
4804    }
4805
4806    /**
4807     * Give this view focus. This will cause
4808     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
4809     *
4810     * Note: this does not check whether this {@link View} should get focus, it just
4811     * gives it focus no matter what.  It should only be called internally by framework
4812     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4813     *
4814     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4815     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
4816     *        focus moved when requestFocus() is called. It may not always
4817     *        apply, in which case use the default View.FOCUS_DOWN.
4818     * @param previouslyFocusedRect The rectangle of the view that had focus
4819     *        prior in this View's coordinate system.
4820     */
4821    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
4822        if (DBG) {
4823            System.out.println(this + " requestFocus()");
4824        }
4825
4826        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4827            mPrivateFlags |= PFLAG_FOCUSED;
4828
4829            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
4830
4831            if (mParent != null) {
4832                mParent.requestChildFocus(this, this);
4833            }
4834
4835            if (mAttachInfo != null) {
4836                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
4837            }
4838
4839            onFocusChanged(true, direction, previouslyFocusedRect);
4840            manageFocusHotspot(true, oldFocus);
4841            refreshDrawableState();
4842        }
4843    }
4844
4845    /**
4846     * Forwards focus information to the background drawable, if necessary. When
4847     * the view is gaining focus, <code>v</code> is the previous focus holder.
4848     * When the view is losing focus, <code>v</code> is the next focus holder.
4849     *
4850     * @param focused whether this view is focused
4851     * @param v previous or the next focus holder, or null if none
4852     */
4853    private void manageFocusHotspot(boolean focused, View v) {
4854        final Rect r = new Rect();
4855        if (!focused && v != null && mAttachInfo != null) {
4856            v.getBoundsOnScreen(r);
4857            final int[] location = mAttachInfo.mTmpLocation;
4858            getLocationOnScreen(location);
4859            r.offset(-location[0], -location[1]);
4860        } else {
4861            r.set(0, 0, mRight - mLeft, mBottom - mTop);
4862        }
4863
4864        final float x = r.exactCenterX();
4865        final float y = r.exactCenterY();
4866        drawableHotspotChanged(x, y);
4867    }
4868
4869    /**
4870     * Request that a rectangle of this view be visible on the screen,
4871     * scrolling if necessary just enough.
4872     *
4873     * <p>A View should call this if it maintains some notion of which part
4874     * of its content is interesting.  For example, a text editing view
4875     * should call this when its cursor moves.
4876     *
4877     * @param rectangle The rectangle.
4878     * @return Whether any parent scrolled.
4879     */
4880    public boolean requestRectangleOnScreen(Rect rectangle) {
4881        return requestRectangleOnScreen(rectangle, false);
4882    }
4883
4884    /**
4885     * Request that a rectangle of this view be visible on the screen,
4886     * scrolling if necessary just enough.
4887     *
4888     * <p>A View should call this if it maintains some notion of which part
4889     * of its content is interesting.  For example, a text editing view
4890     * should call this when its cursor moves.
4891     *
4892     * <p>When <code>immediate</code> is set to true, scrolling will not be
4893     * animated.
4894     *
4895     * @param rectangle The rectangle.
4896     * @param immediate True to forbid animated scrolling, false otherwise
4897     * @return Whether any parent scrolled.
4898     */
4899    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
4900        if (mParent == null) {
4901            return false;
4902        }
4903
4904        View child = this;
4905
4906        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
4907        position.set(rectangle);
4908
4909        ViewParent parent = mParent;
4910        boolean scrolled = false;
4911        while (parent != null) {
4912            rectangle.set((int) position.left, (int) position.top,
4913                    (int) position.right, (int) position.bottom);
4914
4915            scrolled |= parent.requestChildRectangleOnScreen(child,
4916                    rectangle, immediate);
4917
4918            if (!child.hasIdentityMatrix()) {
4919                child.getMatrix().mapRect(position);
4920            }
4921
4922            position.offset(child.mLeft, child.mTop);
4923
4924            if (!(parent instanceof View)) {
4925                break;
4926            }
4927
4928            View parentView = (View) parent;
4929
4930            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
4931
4932            child = parentView;
4933            parent = child.getParent();
4934        }
4935
4936        return scrolled;
4937    }
4938
4939    /**
4940     * Called when this view wants to give up focus. If focus is cleared
4941     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
4942     * <p>
4943     * <strong>Note:</strong> When a View clears focus the framework is trying
4944     * to give focus to the first focusable View from the top. Hence, if this
4945     * View is the first from the top that can take focus, then all callbacks
4946     * related to clearing focus will be invoked after wich the framework will
4947     * give focus to this view.
4948     * </p>
4949     */
4950    public void clearFocus() {
4951        if (DBG) {
4952            System.out.println(this + " clearFocus()");
4953        }
4954
4955        clearFocusInternal(null, true, true);
4956    }
4957
4958    /**
4959     * Clears focus from the view, optionally propagating the change up through
4960     * the parent hierarchy and requesting that the root view place new focus.
4961     *
4962     * @param propagate whether to propagate the change up through the parent
4963     *            hierarchy
4964     * @param refocus when propagate is true, specifies whether to request the
4965     *            root view place new focus
4966     */
4967    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
4968        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4969            mPrivateFlags &= ~PFLAG_FOCUSED;
4970
4971            if (propagate && mParent != null) {
4972                mParent.clearChildFocus(this);
4973            }
4974
4975            onFocusChanged(false, 0, null);
4976
4977            manageFocusHotspot(false, focused);
4978            refreshDrawableState();
4979
4980            if (propagate && (!refocus || !rootViewRequestFocus())) {
4981                notifyGlobalFocusCleared(this);
4982            }
4983        }
4984    }
4985
4986    void notifyGlobalFocusCleared(View oldFocus) {
4987        if (oldFocus != null && mAttachInfo != null) {
4988            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
4989        }
4990    }
4991
4992    boolean rootViewRequestFocus() {
4993        final View root = getRootView();
4994        return root != null && root.requestFocus();
4995    }
4996
4997    /**
4998     * Called internally by the view system when a new view is getting focus.
4999     * This is what clears the old focus.
5000     * <p>
5001     * <b>NOTE:</b> The parent view's focused child must be updated manually
5002     * after calling this method. Otherwise, the view hierarchy may be left in
5003     * an inconstent state.
5004     */
5005    void unFocus(View focused) {
5006        if (DBG) {
5007            System.out.println(this + " unFocus()");
5008        }
5009
5010        clearFocusInternal(focused, false, false);
5011    }
5012
5013    /**
5014     * Returns true if this view has focus iteself, or is the ancestor of the
5015     * view that has focus.
5016     *
5017     * @return True if this view has or contains focus, false otherwise.
5018     */
5019    @ViewDebug.ExportedProperty(category = "focus")
5020    public boolean hasFocus() {
5021        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5022    }
5023
5024    /**
5025     * Returns true if this view is focusable or if it contains a reachable View
5026     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5027     * is a View whose parents do not block descendants focus.
5028     *
5029     * Only {@link #VISIBLE} views are considered focusable.
5030     *
5031     * @return True if the view is focusable or if the view contains a focusable
5032     *         View, false otherwise.
5033     *
5034     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5035     */
5036    public boolean hasFocusable() {
5037        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5038    }
5039
5040    /**
5041     * Called by the view system when the focus state of this view changes.
5042     * When the focus change event is caused by directional navigation, direction
5043     * and previouslyFocusedRect provide insight into where the focus is coming from.
5044     * When overriding, be sure to call up through to the super class so that
5045     * the standard focus handling will occur.
5046     *
5047     * @param gainFocus True if the View has focus; false otherwise.
5048     * @param direction The direction focus has moved when requestFocus()
5049     *                  is called to give this view focus. Values are
5050     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5051     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5052     *                  It may not always apply, in which case use the default.
5053     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5054     *        system, of the previously focused view.  If applicable, this will be
5055     *        passed in as finer grained information about where the focus is coming
5056     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5057     */
5058    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5059            @Nullable Rect previouslyFocusedRect) {
5060        if (gainFocus) {
5061            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5062        } else {
5063            notifyViewAccessibilityStateChangedIfNeeded(
5064                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5065        }
5066
5067        InputMethodManager imm = InputMethodManager.peekInstance();
5068        if (!gainFocus) {
5069            if (isPressed()) {
5070                setPressed(false);
5071            }
5072            if (imm != null && mAttachInfo != null
5073                    && mAttachInfo.mHasWindowFocus) {
5074                imm.focusOut(this);
5075            }
5076            onFocusLost();
5077        } else if (imm != null && mAttachInfo != null
5078                && mAttachInfo.mHasWindowFocus) {
5079            imm.focusIn(this);
5080        }
5081
5082        invalidate(true);
5083        ListenerInfo li = mListenerInfo;
5084        if (li != null && li.mOnFocusChangeListener != null) {
5085            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5086        }
5087
5088        if (mAttachInfo != null) {
5089            mAttachInfo.mKeyDispatchState.reset(this);
5090        }
5091    }
5092
5093    /**
5094     * Sends an accessibility event of the given type. If accessibility is
5095     * not enabled this method has no effect. The default implementation calls
5096     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5097     * to populate information about the event source (this View), then calls
5098     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5099     * populate the text content of the event source including its descendants,
5100     * and last calls
5101     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5102     * on its parent to resuest sending of the event to interested parties.
5103     * <p>
5104     * If an {@link AccessibilityDelegate} has been specified via calling
5105     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5106     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5107     * responsible for handling this call.
5108     * </p>
5109     *
5110     * @param eventType The type of the event to send, as defined by several types from
5111     * {@link android.view.accessibility.AccessibilityEvent}, such as
5112     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5113     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5114     *
5115     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5116     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5117     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5118     * @see AccessibilityDelegate
5119     */
5120    public void sendAccessibilityEvent(int eventType) {
5121        if (mAccessibilityDelegate != null) {
5122            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5123        } else {
5124            sendAccessibilityEventInternal(eventType);
5125        }
5126    }
5127
5128    /**
5129     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5130     * {@link AccessibilityEvent} to make an announcement which is related to some
5131     * sort of a context change for which none of the events representing UI transitions
5132     * is a good fit. For example, announcing a new page in a book. If accessibility
5133     * is not enabled this method does nothing.
5134     *
5135     * @param text The announcement text.
5136     */
5137    public void announceForAccessibility(CharSequence text) {
5138        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5139            AccessibilityEvent event = AccessibilityEvent.obtain(
5140                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5141            onInitializeAccessibilityEvent(event);
5142            event.getText().add(text);
5143            event.setContentDescription(null);
5144            mParent.requestSendAccessibilityEvent(this, event);
5145        }
5146    }
5147
5148    /**
5149     * @see #sendAccessibilityEvent(int)
5150     *
5151     * Note: Called from the default {@link AccessibilityDelegate}.
5152     */
5153    void sendAccessibilityEventInternal(int eventType) {
5154        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5155            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5156        }
5157    }
5158
5159    /**
5160     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5161     * takes as an argument an empty {@link AccessibilityEvent} and does not
5162     * perform a check whether accessibility is enabled.
5163     * <p>
5164     * If an {@link AccessibilityDelegate} has been specified via calling
5165     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5166     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5167     * is responsible for handling this call.
5168     * </p>
5169     *
5170     * @param event The event to send.
5171     *
5172     * @see #sendAccessibilityEvent(int)
5173     */
5174    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5175        if (mAccessibilityDelegate != null) {
5176            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5177        } else {
5178            sendAccessibilityEventUncheckedInternal(event);
5179        }
5180    }
5181
5182    /**
5183     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5184     *
5185     * Note: Called from the default {@link AccessibilityDelegate}.
5186     */
5187    void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5188        if (!isShown()) {
5189            return;
5190        }
5191        onInitializeAccessibilityEvent(event);
5192        // Only a subset of accessibility events populates text content.
5193        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5194            dispatchPopulateAccessibilityEvent(event);
5195        }
5196        // In the beginning we called #isShown(), so we know that getParent() is not null.
5197        getParent().requestSendAccessibilityEvent(this, event);
5198    }
5199
5200    /**
5201     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5202     * to its children for adding their text content to the event. Note that the
5203     * event text is populated in a separate dispatch path since we add to the
5204     * event not only the text of the source but also the text of all its descendants.
5205     * A typical implementation will call
5206     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5207     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5208     * on each child. Override this method if custom population of the event text
5209     * content is required.
5210     * <p>
5211     * If an {@link AccessibilityDelegate} has been specified via calling
5212     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5213     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5214     * is responsible for handling this call.
5215     * </p>
5216     * <p>
5217     * <em>Note:</em> Accessibility events of certain types are not dispatched for
5218     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5219     * </p>
5220     *
5221     * @param event The event.
5222     *
5223     * @return True if the event population was completed.
5224     */
5225    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5226        if (mAccessibilityDelegate != null) {
5227            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5228        } else {
5229            return dispatchPopulateAccessibilityEventInternal(event);
5230        }
5231    }
5232
5233    /**
5234     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5235     *
5236     * Note: Called from the default {@link AccessibilityDelegate}.
5237     */
5238    boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5239        onPopulateAccessibilityEvent(event);
5240        return false;
5241    }
5242
5243    /**
5244     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5245     * giving a chance to this View to populate the accessibility event with its
5246     * text content. While this method is free to modify event
5247     * attributes other than text content, doing so should normally be performed in
5248     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5249     * <p>
5250     * Example: Adding formatted date string to an accessibility event in addition
5251     *          to the text added by the super implementation:
5252     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5253     *     super.onPopulateAccessibilityEvent(event);
5254     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5255     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5256     *         mCurrentDate.getTimeInMillis(), flags);
5257     *     event.getText().add(selectedDateUtterance);
5258     * }</pre>
5259     * <p>
5260     * If an {@link AccessibilityDelegate} has been specified via calling
5261     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5262     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5263     * is responsible for handling this call.
5264     * </p>
5265     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5266     * information to the event, in case the default implementation has basic information to add.
5267     * </p>
5268     *
5269     * @param event The accessibility event which to populate.
5270     *
5271     * @see #sendAccessibilityEvent(int)
5272     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5273     */
5274    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5275        if (mAccessibilityDelegate != null) {
5276            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5277        } else {
5278            onPopulateAccessibilityEventInternal(event);
5279        }
5280    }
5281
5282    /**
5283     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5284     *
5285     * Note: Called from the default {@link AccessibilityDelegate}.
5286     */
5287    void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5288    }
5289
5290    /**
5291     * Initializes an {@link AccessibilityEvent} with information about
5292     * this View which is the event source. In other words, the source of
5293     * an accessibility event is the view whose state change triggered firing
5294     * the event.
5295     * <p>
5296     * Example: Setting the password property of an event in addition
5297     *          to properties set by the super implementation:
5298     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5299     *     super.onInitializeAccessibilityEvent(event);
5300     *     event.setPassword(true);
5301     * }</pre>
5302     * <p>
5303     * If an {@link AccessibilityDelegate} has been specified via calling
5304     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5305     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5306     * is responsible for handling this call.
5307     * </p>
5308     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5309     * information to the event, in case the default implementation has basic information to add.
5310     * </p>
5311     * @param event The event to initialize.
5312     *
5313     * @see #sendAccessibilityEvent(int)
5314     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5315     */
5316    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5317        if (mAccessibilityDelegate != null) {
5318            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5319        } else {
5320            onInitializeAccessibilityEventInternal(event);
5321        }
5322    }
5323
5324    /**
5325     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5326     *
5327     * Note: Called from the default {@link AccessibilityDelegate}.
5328     */
5329    void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5330        event.setSource(this);
5331        event.setClassName(View.class.getName());
5332        event.setPackageName(getContext().getPackageName());
5333        event.setEnabled(isEnabled());
5334        event.setContentDescription(mContentDescription);
5335
5336        switch (event.getEventType()) {
5337            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5338                ArrayList<View> focusablesTempList = (mAttachInfo != null)
5339                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5340                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5341                event.setItemCount(focusablesTempList.size());
5342                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5343                if (mAttachInfo != null) {
5344                    focusablesTempList.clear();
5345                }
5346            } break;
5347            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5348                CharSequence text = getIterableTextForAccessibility();
5349                if (text != null && text.length() > 0) {
5350                    event.setFromIndex(getAccessibilitySelectionStart());
5351                    event.setToIndex(getAccessibilitySelectionEnd());
5352                    event.setItemCount(text.length());
5353                }
5354            } break;
5355        }
5356    }
5357
5358    /**
5359     * Returns an {@link AccessibilityNodeInfo} representing this view from the
5360     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
5361     * This method is responsible for obtaining an accessibility node info from a
5362     * pool of reusable instances and calling
5363     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
5364     * initialize the former.
5365     * <p>
5366     * Note: The client is responsible for recycling the obtained instance by calling
5367     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
5368     * </p>
5369     *
5370     * @return A populated {@link AccessibilityNodeInfo}.
5371     *
5372     * @see AccessibilityNodeInfo
5373     */
5374    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
5375        if (mAccessibilityDelegate != null) {
5376            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
5377        } else {
5378            return createAccessibilityNodeInfoInternal();
5379        }
5380    }
5381
5382    /**
5383     * @see #createAccessibilityNodeInfo()
5384     */
5385    AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
5386        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5387        if (provider != null) {
5388            return provider.createAccessibilityNodeInfo(View.NO_ID);
5389        } else {
5390            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
5391            onInitializeAccessibilityNodeInfo(info);
5392            return info;
5393        }
5394    }
5395
5396    /**
5397     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
5398     * The base implementation sets:
5399     * <ul>
5400     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
5401     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
5402     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
5403     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
5404     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
5405     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
5406     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
5407     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
5408     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
5409     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
5410     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
5411     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
5412     * </ul>
5413     * <p>
5414     * Subclasses should override this method, call the super implementation,
5415     * and set additional attributes.
5416     * </p>
5417     * <p>
5418     * If an {@link AccessibilityDelegate} has been specified via calling
5419     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5420     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
5421     * is responsible for handling this call.
5422     * </p>
5423     *
5424     * @param info The instance to initialize.
5425     */
5426    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
5427        if (mAccessibilityDelegate != null) {
5428            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
5429        } else {
5430            onInitializeAccessibilityNodeInfoInternal(info);
5431        }
5432    }
5433
5434    /**
5435     * Gets the location of this view in screen coordintates.
5436     *
5437     * @param outRect The output location
5438     * @hide
5439     */
5440    public void getBoundsOnScreen(Rect outRect) {
5441        if (mAttachInfo == null) {
5442            return;
5443        }
5444
5445        RectF position = mAttachInfo.mTmpTransformRect;
5446        position.set(0, 0, mRight - mLeft, mBottom - mTop);
5447
5448        if (!hasIdentityMatrix()) {
5449            getMatrix().mapRect(position);
5450        }
5451
5452        position.offset(mLeft, mTop);
5453
5454        ViewParent parent = mParent;
5455        while (parent instanceof View) {
5456            View parentView = (View) parent;
5457
5458            position.offset(-parentView.mScrollX, -parentView.mScrollY);
5459
5460            if (!parentView.hasIdentityMatrix()) {
5461                parentView.getMatrix().mapRect(position);
5462            }
5463
5464            position.offset(parentView.mLeft, parentView.mTop);
5465
5466            parent = parentView.mParent;
5467        }
5468
5469        if (parent instanceof ViewRootImpl) {
5470            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
5471            position.offset(0, -viewRootImpl.mCurScrollY);
5472        }
5473
5474        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
5475
5476        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
5477                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
5478    }
5479
5480    /**
5481     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
5482     *
5483     * Note: Called from the default {@link AccessibilityDelegate}.
5484     */
5485    void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
5486        Rect bounds = mAttachInfo.mTmpInvalRect;
5487
5488        getDrawingRect(bounds);
5489        info.setBoundsInParent(bounds);
5490
5491        getBoundsOnScreen(bounds);
5492        info.setBoundsInScreen(bounds);
5493
5494        ViewParent parent = getParentForAccessibility();
5495        if (parent instanceof View) {
5496            info.setParent((View) parent);
5497        }
5498
5499        if (mID != View.NO_ID) {
5500            View rootView = getRootView();
5501            if (rootView == null) {
5502                rootView = this;
5503            }
5504            View label = rootView.findLabelForView(this, mID);
5505            if (label != null) {
5506                info.setLabeledBy(label);
5507            }
5508
5509            if ((mAttachInfo.mAccessibilityFetchFlags
5510                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
5511                    && Resources.resourceHasPackage(mID)) {
5512                try {
5513                    String viewId = getResources().getResourceName(mID);
5514                    info.setViewIdResourceName(viewId);
5515                } catch (Resources.NotFoundException nfe) {
5516                    /* ignore */
5517                }
5518            }
5519        }
5520
5521        if (mLabelForId != View.NO_ID) {
5522            View rootView = getRootView();
5523            if (rootView == null) {
5524                rootView = this;
5525            }
5526            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
5527            if (labeled != null) {
5528                info.setLabelFor(labeled);
5529            }
5530        }
5531
5532        info.setVisibleToUser(isVisibleToUser());
5533
5534        info.setPackageName(mContext.getPackageName());
5535        info.setClassName(View.class.getName());
5536        info.setContentDescription(getContentDescription());
5537
5538        info.setEnabled(isEnabled());
5539        info.setClickable(isClickable());
5540        info.setFocusable(isFocusable());
5541        info.setFocused(isFocused());
5542        info.setAccessibilityFocused(isAccessibilityFocused());
5543        info.setSelected(isSelected());
5544        info.setLongClickable(isLongClickable());
5545        info.setLiveRegion(getAccessibilityLiveRegion());
5546
5547        // TODO: These make sense only if we are in an AdapterView but all
5548        // views can be selected. Maybe from accessibility perspective
5549        // we should report as selectable view in an AdapterView.
5550        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
5551        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
5552
5553        if (isFocusable()) {
5554            if (isFocused()) {
5555                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
5556            } else {
5557                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
5558            }
5559        }
5560
5561        if (!isAccessibilityFocused()) {
5562            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
5563        } else {
5564            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
5565        }
5566
5567        if (isClickable() && isEnabled()) {
5568            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
5569        }
5570
5571        if (isLongClickable() && isEnabled()) {
5572            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
5573        }
5574
5575        CharSequence text = getIterableTextForAccessibility();
5576        if (text != null && text.length() > 0) {
5577            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
5578
5579            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
5580            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
5581            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
5582            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
5583                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
5584                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
5585        }
5586    }
5587
5588    private View findLabelForView(View view, int labeledId) {
5589        if (mMatchLabelForPredicate == null) {
5590            mMatchLabelForPredicate = new MatchLabelForPredicate();
5591        }
5592        mMatchLabelForPredicate.mLabeledId = labeledId;
5593        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
5594    }
5595
5596    /**
5597     * Computes whether this view is visible to the user. Such a view is
5598     * attached, visible, all its predecessors are visible, it is not clipped
5599     * entirely by its predecessors, and has an alpha greater than zero.
5600     *
5601     * @return Whether the view is visible on the screen.
5602     *
5603     * @hide
5604     */
5605    protected boolean isVisibleToUser() {
5606        return isVisibleToUser(null);
5607    }
5608
5609    /**
5610     * Computes whether the given portion of this view is visible to the user.
5611     * Such a view is attached, visible, all its predecessors are visible,
5612     * has an alpha greater than zero, and the specified portion is not
5613     * clipped entirely by its predecessors.
5614     *
5615     * @param boundInView the portion of the view to test; coordinates should be relative; may be
5616     *                    <code>null</code>, and the entire view will be tested in this case.
5617     *                    When <code>true</code> is returned by the function, the actual visible
5618     *                    region will be stored in this parameter; that is, if boundInView is fully
5619     *                    contained within the view, no modification will be made, otherwise regions
5620     *                    outside of the visible area of the view will be clipped.
5621     *
5622     * @return Whether the specified portion of the view is visible on the screen.
5623     *
5624     * @hide
5625     */
5626    protected boolean isVisibleToUser(Rect boundInView) {
5627        if (mAttachInfo != null) {
5628            // Attached to invisible window means this view is not visible.
5629            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
5630                return false;
5631            }
5632            // An invisible predecessor or one with alpha zero means
5633            // that this view is not visible to the user.
5634            Object current = this;
5635            while (current instanceof View) {
5636                View view = (View) current;
5637                // We have attach info so this view is attached and there is no
5638                // need to check whether we reach to ViewRootImpl on the way up.
5639                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
5640                        view.getVisibility() != VISIBLE) {
5641                    return false;
5642                }
5643                current = view.mParent;
5644            }
5645            // Check if the view is entirely covered by its predecessors.
5646            Rect visibleRect = mAttachInfo.mTmpInvalRect;
5647            Point offset = mAttachInfo.mPoint;
5648            if (!getGlobalVisibleRect(visibleRect, offset)) {
5649                return false;
5650            }
5651            // Check if the visible portion intersects the rectangle of interest.
5652            if (boundInView != null) {
5653                visibleRect.offset(-offset.x, -offset.y);
5654                return boundInView.intersect(visibleRect);
5655            }
5656            return true;
5657        }
5658        return false;
5659    }
5660
5661    /**
5662     * Returns the delegate for implementing accessibility support via
5663     * composition. For more details see {@link AccessibilityDelegate}.
5664     *
5665     * @return The delegate, or null if none set.
5666     *
5667     * @hide
5668     */
5669    public AccessibilityDelegate getAccessibilityDelegate() {
5670        return mAccessibilityDelegate;
5671    }
5672
5673    /**
5674     * Sets a delegate for implementing accessibility support via composition as
5675     * opposed to inheritance. The delegate's primary use is for implementing
5676     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
5677     *
5678     * @param delegate The delegate instance.
5679     *
5680     * @see AccessibilityDelegate
5681     */
5682    public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
5683        mAccessibilityDelegate = delegate;
5684    }
5685
5686    /**
5687     * Gets the provider for managing a virtual view hierarchy rooted at this View
5688     * and reported to {@link android.accessibilityservice.AccessibilityService}s
5689     * that explore the window content.
5690     * <p>
5691     * If this method returns an instance, this instance is responsible for managing
5692     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
5693     * View including the one representing the View itself. Similarly the returned
5694     * instance is responsible for performing accessibility actions on any virtual
5695     * view or the root view itself.
5696     * </p>
5697     * <p>
5698     * If an {@link AccessibilityDelegate} has been specified via calling
5699     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5700     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
5701     * is responsible for handling this call.
5702     * </p>
5703     *
5704     * @return The provider.
5705     *
5706     * @see AccessibilityNodeProvider
5707     */
5708    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
5709        if (mAccessibilityDelegate != null) {
5710            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
5711        } else {
5712            return null;
5713        }
5714    }
5715
5716    /**
5717     * Gets the unique identifier of this view on the screen for accessibility purposes.
5718     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
5719     *
5720     * @return The view accessibility id.
5721     *
5722     * @hide
5723     */
5724    public int getAccessibilityViewId() {
5725        if (mAccessibilityViewId == NO_ID) {
5726            mAccessibilityViewId = sNextAccessibilityViewId++;
5727        }
5728        return mAccessibilityViewId;
5729    }
5730
5731    /**
5732     * Gets the unique identifier of the window in which this View reseides.
5733     *
5734     * @return The window accessibility id.
5735     *
5736     * @hide
5737     */
5738    public int getAccessibilityWindowId() {
5739        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
5740                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
5741    }
5742
5743    /**
5744     * Gets the {@link View} description. It briefly describes the view and is
5745     * primarily used for accessibility support. Set this property to enable
5746     * better accessibility support for your application. This is especially
5747     * true for views that do not have textual representation (For example,
5748     * ImageButton).
5749     *
5750     * @return The content description.
5751     *
5752     * @attr ref android.R.styleable#View_contentDescription
5753     */
5754    @ViewDebug.ExportedProperty(category = "accessibility")
5755    public CharSequence getContentDescription() {
5756        return mContentDescription;
5757    }
5758
5759    /**
5760     * Sets the {@link View} description. It briefly describes the view and is
5761     * primarily used for accessibility support. Set this property to enable
5762     * better accessibility support for your application. This is especially
5763     * true for views that do not have textual representation (For example,
5764     * ImageButton).
5765     *
5766     * @param contentDescription The content description.
5767     *
5768     * @attr ref android.R.styleable#View_contentDescription
5769     */
5770    @RemotableViewMethod
5771    public void setContentDescription(CharSequence contentDescription) {
5772        if (mContentDescription == null) {
5773            if (contentDescription == null) {
5774                return;
5775            }
5776        } else if (mContentDescription.equals(contentDescription)) {
5777            return;
5778        }
5779        mContentDescription = contentDescription;
5780        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
5781        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
5782            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
5783            notifySubtreeAccessibilityStateChangedIfNeeded();
5784        } else {
5785            notifyViewAccessibilityStateChangedIfNeeded(
5786                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
5787        }
5788    }
5789
5790    /**
5791     * Gets the id of a view for which this view serves as a label for
5792     * accessibility purposes.
5793     *
5794     * @return The labeled view id.
5795     */
5796    @ViewDebug.ExportedProperty(category = "accessibility")
5797    public int getLabelFor() {
5798        return mLabelForId;
5799    }
5800
5801    /**
5802     * Sets the id of a view for which this view serves as a label for
5803     * accessibility purposes.
5804     *
5805     * @param id The labeled view id.
5806     */
5807    @RemotableViewMethod
5808    public void setLabelFor(int id) {
5809        mLabelForId = id;
5810        if (mLabelForId != View.NO_ID
5811                && mID == View.NO_ID) {
5812            mID = generateViewId();
5813        }
5814    }
5815
5816    /**
5817     * Invoked whenever this view loses focus, either by losing window focus or by losing
5818     * focus within its window. This method can be used to clear any state tied to the
5819     * focus. For instance, if a button is held pressed with the trackball and the window
5820     * loses focus, this method can be used to cancel the press.
5821     *
5822     * Subclasses of View overriding this method should always call super.onFocusLost().
5823     *
5824     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
5825     * @see #onWindowFocusChanged(boolean)
5826     *
5827     * @hide pending API council approval
5828     */
5829    protected void onFocusLost() {
5830        resetPressedState();
5831    }
5832
5833    private void resetPressedState() {
5834        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
5835            return;
5836        }
5837
5838        if (isPressed()) {
5839            setPressed(false);
5840
5841            if (!mHasPerformedLongPress) {
5842                removeLongPressCallback();
5843            }
5844        }
5845    }
5846
5847    /**
5848     * Returns true if this view has focus
5849     *
5850     * @return True if this view has focus, false otherwise.
5851     */
5852    @ViewDebug.ExportedProperty(category = "focus")
5853    public boolean isFocused() {
5854        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5855    }
5856
5857    /**
5858     * Find the view in the hierarchy rooted at this view that currently has
5859     * focus.
5860     *
5861     * @return The view that currently has focus, or null if no focused view can
5862     *         be found.
5863     */
5864    public View findFocus() {
5865        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
5866    }
5867
5868    /**
5869     * Indicates whether this view is one of the set of scrollable containers in
5870     * its window.
5871     *
5872     * @return whether this view is one of the set of scrollable containers in
5873     * its window
5874     *
5875     * @attr ref android.R.styleable#View_isScrollContainer
5876     */
5877    public boolean isScrollContainer() {
5878        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
5879    }
5880
5881    /**
5882     * Change whether this view is one of the set of scrollable containers in
5883     * its window.  This will be used to determine whether the window can
5884     * resize or must pan when a soft input area is open -- scrollable
5885     * containers allow the window to use resize mode since the container
5886     * will appropriately shrink.
5887     *
5888     * @attr ref android.R.styleable#View_isScrollContainer
5889     */
5890    public void setScrollContainer(boolean isScrollContainer) {
5891        if (isScrollContainer) {
5892            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
5893                mAttachInfo.mScrollContainers.add(this);
5894                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
5895            }
5896            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
5897        } else {
5898            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
5899                mAttachInfo.mScrollContainers.remove(this);
5900            }
5901            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
5902        }
5903    }
5904
5905    /**
5906     * Returns the quality of the drawing cache.
5907     *
5908     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5909     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5910     *
5911     * @see #setDrawingCacheQuality(int)
5912     * @see #setDrawingCacheEnabled(boolean)
5913     * @see #isDrawingCacheEnabled()
5914     *
5915     * @attr ref android.R.styleable#View_drawingCacheQuality
5916     */
5917    @DrawingCacheQuality
5918    public int getDrawingCacheQuality() {
5919        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
5920    }
5921
5922    /**
5923     * Set the drawing cache quality of this view. This value is used only when the
5924     * drawing cache is enabled
5925     *
5926     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5927     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5928     *
5929     * @see #getDrawingCacheQuality()
5930     * @see #setDrawingCacheEnabled(boolean)
5931     * @see #isDrawingCacheEnabled()
5932     *
5933     * @attr ref android.R.styleable#View_drawingCacheQuality
5934     */
5935    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
5936        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
5937    }
5938
5939    /**
5940     * Returns whether the screen should remain on, corresponding to the current
5941     * value of {@link #KEEP_SCREEN_ON}.
5942     *
5943     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
5944     *
5945     * @see #setKeepScreenOn(boolean)
5946     *
5947     * @attr ref android.R.styleable#View_keepScreenOn
5948     */
5949    public boolean getKeepScreenOn() {
5950        return (mViewFlags & KEEP_SCREEN_ON) != 0;
5951    }
5952
5953    /**
5954     * Controls whether the screen should remain on, modifying the
5955     * value of {@link #KEEP_SCREEN_ON}.
5956     *
5957     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
5958     *
5959     * @see #getKeepScreenOn()
5960     *
5961     * @attr ref android.R.styleable#View_keepScreenOn
5962     */
5963    public void setKeepScreenOn(boolean keepScreenOn) {
5964        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
5965    }
5966
5967    /**
5968     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5969     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5970     *
5971     * @attr ref android.R.styleable#View_nextFocusLeft
5972     */
5973    public int getNextFocusLeftId() {
5974        return mNextFocusLeftId;
5975    }
5976
5977    /**
5978     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5979     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
5980     * decide automatically.
5981     *
5982     * @attr ref android.R.styleable#View_nextFocusLeft
5983     */
5984    public void setNextFocusLeftId(int nextFocusLeftId) {
5985        mNextFocusLeftId = nextFocusLeftId;
5986    }
5987
5988    /**
5989     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5990     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5991     *
5992     * @attr ref android.R.styleable#View_nextFocusRight
5993     */
5994    public int getNextFocusRightId() {
5995        return mNextFocusRightId;
5996    }
5997
5998    /**
5999     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6000     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6001     * decide automatically.
6002     *
6003     * @attr ref android.R.styleable#View_nextFocusRight
6004     */
6005    public void setNextFocusRightId(int nextFocusRightId) {
6006        mNextFocusRightId = nextFocusRightId;
6007    }
6008
6009    /**
6010     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6011     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6012     *
6013     * @attr ref android.R.styleable#View_nextFocusUp
6014     */
6015    public int getNextFocusUpId() {
6016        return mNextFocusUpId;
6017    }
6018
6019    /**
6020     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6021     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6022     * decide automatically.
6023     *
6024     * @attr ref android.R.styleable#View_nextFocusUp
6025     */
6026    public void setNextFocusUpId(int nextFocusUpId) {
6027        mNextFocusUpId = nextFocusUpId;
6028    }
6029
6030    /**
6031     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6032     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6033     *
6034     * @attr ref android.R.styleable#View_nextFocusDown
6035     */
6036    public int getNextFocusDownId() {
6037        return mNextFocusDownId;
6038    }
6039
6040    /**
6041     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6042     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
6043     * decide automatically.
6044     *
6045     * @attr ref android.R.styleable#View_nextFocusDown
6046     */
6047    public void setNextFocusDownId(int nextFocusDownId) {
6048        mNextFocusDownId = nextFocusDownId;
6049    }
6050
6051    /**
6052     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6053     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6054     *
6055     * @attr ref android.R.styleable#View_nextFocusForward
6056     */
6057    public int getNextFocusForwardId() {
6058        return mNextFocusForwardId;
6059    }
6060
6061    /**
6062     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6063     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
6064     * decide automatically.
6065     *
6066     * @attr ref android.R.styleable#View_nextFocusForward
6067     */
6068    public void setNextFocusForwardId(int nextFocusForwardId) {
6069        mNextFocusForwardId = nextFocusForwardId;
6070    }
6071
6072    /**
6073     * Returns the visibility of this view and all of its ancestors
6074     *
6075     * @return True if this view and all of its ancestors are {@link #VISIBLE}
6076     */
6077    public boolean isShown() {
6078        View current = this;
6079        //noinspection ConstantConditions
6080        do {
6081            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6082                return false;
6083            }
6084            ViewParent parent = current.mParent;
6085            if (parent == null) {
6086                return false; // We are not attached to the view root
6087            }
6088            if (!(parent instanceof View)) {
6089                return true;
6090            }
6091            current = (View) parent;
6092        } while (current != null);
6093
6094        return false;
6095    }
6096
6097    /**
6098     * Called by the view hierarchy when the content insets for a window have
6099     * changed, to allow it to adjust its content to fit within those windows.
6100     * The content insets tell you the space that the status bar, input method,
6101     * and other system windows infringe on the application's window.
6102     *
6103     * <p>You do not normally need to deal with this function, since the default
6104     * window decoration given to applications takes care of applying it to the
6105     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
6106     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
6107     * and your content can be placed under those system elements.  You can then
6108     * use this method within your view hierarchy if you have parts of your UI
6109     * which you would like to ensure are not being covered.
6110     *
6111     * <p>The default implementation of this method simply applies the content
6112     * insets to the view's padding, consuming that content (modifying the
6113     * insets to be 0), and returning true.  This behavior is off by default, but can
6114     * be enabled through {@link #setFitsSystemWindows(boolean)}.
6115     *
6116     * <p>This function's traversal down the hierarchy is depth-first.  The same content
6117     * insets object is propagated down the hierarchy, so any changes made to it will
6118     * be seen by all following views (including potentially ones above in
6119     * the hierarchy since this is a depth-first traversal).  The first view
6120     * that returns true will abort the entire traversal.
6121     *
6122     * <p>The default implementation works well for a situation where it is
6123     * used with a container that covers the entire window, allowing it to
6124     * apply the appropriate insets to its content on all edges.  If you need
6125     * a more complicated layout (such as two different views fitting system
6126     * windows, one on the top of the window, and one on the bottom),
6127     * you can override the method and handle the insets however you would like.
6128     * Note that the insets provided by the framework are always relative to the
6129     * far edges of the window, not accounting for the location of the called view
6130     * within that window.  (In fact when this method is called you do not yet know
6131     * where the layout will place the view, as it is done before layout happens.)
6132     *
6133     * <p>Note: unlike many View methods, there is no dispatch phase to this
6134     * call.  If you are overriding it in a ViewGroup and want to allow the
6135     * call to continue to your children, you must be sure to call the super
6136     * implementation.
6137     *
6138     * <p>Here is a sample layout that makes use of fitting system windows
6139     * to have controls for a video view placed inside of the window decorations
6140     * that it hides and shows.  This can be used with code like the second
6141     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
6142     *
6143     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
6144     *
6145     * @param insets Current content insets of the window.  Prior to
6146     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
6147     * the insets or else you and Android will be unhappy.
6148     *
6149     * @return {@code true} if this view applied the insets and it should not
6150     * continue propagating further down the hierarchy, {@code false} otherwise.
6151     * @see #getFitsSystemWindows()
6152     * @see #setFitsSystemWindows(boolean)
6153     * @see #setSystemUiVisibility(int)
6154     *
6155     * @deprecated As of API XX use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
6156     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
6157     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
6158     * to implement handling their own insets.
6159     */
6160    protected boolean fitSystemWindows(Rect insets) {
6161        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
6162            if (insets == null) {
6163                // Null insets by definition have already been consumed.
6164                // This call cannot apply insets since there are none to apply,
6165                // so return false.
6166                return false;
6167            }
6168            // If we're not in the process of dispatching the newer apply insets call,
6169            // that means we're not in the compatibility path. Dispatch into the newer
6170            // apply insets path and take things from there.
6171            try {
6172                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
6173                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
6174            } finally {
6175                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
6176            }
6177        } else {
6178            // We're being called from the newer apply insets path.
6179            // Perform the standard fallback behavior.
6180            return fitSystemWindowsInt(insets);
6181        }
6182    }
6183
6184    private boolean fitSystemWindowsInt(Rect insets) {
6185        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
6186            mUserPaddingStart = UNDEFINED_PADDING;
6187            mUserPaddingEnd = UNDEFINED_PADDING;
6188            Rect localInsets = sThreadLocal.get();
6189            if (localInsets == null) {
6190                localInsets = new Rect();
6191                sThreadLocal.set(localInsets);
6192            }
6193            boolean res = computeFitSystemWindows(insets, localInsets);
6194            mUserPaddingLeftInitial = localInsets.left;
6195            mUserPaddingRightInitial = localInsets.right;
6196            internalSetPadding(localInsets.left, localInsets.top,
6197                    localInsets.right, localInsets.bottom);
6198            return res;
6199        }
6200        return false;
6201    }
6202
6203    /**
6204     * Called when the view should apply {@link WindowInsets} according to its internal policy.
6205     *
6206     * <p>This method should be overridden by views that wish to apply a policy different from or
6207     * in addition to the default behavior. Clients that wish to force a view subtree
6208     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
6209     *
6210     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
6211     * it will be called during dispatch instead of this method. The listener may optionally
6212     * call this method from its own implementation if it wishes to apply the view's default
6213     * insets policy in addition to its own.</p>
6214     *
6215     * <p>Implementations of this method should either return the insets parameter unchanged
6216     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
6217     * that this view applied itself. This allows new inset types added in future platform
6218     * versions to pass through existing implementations unchanged without being erroneously
6219     * consumed.</p>
6220     *
6221     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
6222     * property is set then the view will consume the system window insets and apply them
6223     * as padding for the view.</p>
6224     *
6225     * @param insets Insets to apply
6226     * @return The supplied insets with any applied insets consumed
6227     */
6228    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
6229        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
6230            // We weren't called from within a direct call to fitSystemWindows,
6231            // call into it as a fallback in case we're in a class that overrides it
6232            // and has logic to perform.
6233            if (fitSystemWindows(insets.getSystemWindowInsets())) {
6234                return insets.consumeSystemWindowInsets();
6235            }
6236        } else {
6237            // We were called from within a direct call to fitSystemWindows.
6238            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
6239                return insets.consumeSystemWindowInsets();
6240            }
6241        }
6242        return insets;
6243    }
6244
6245    /**
6246     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
6247     * window insets to this view. The listener's
6248     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
6249     * method will be called instead of the view's
6250     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
6251     *
6252     * @param listener Listener to set
6253     *
6254     * @see #onApplyWindowInsets(WindowInsets)
6255     */
6256    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
6257        getListenerInfo().mOnApplyWindowInsetsListener = listener;
6258    }
6259
6260    /**
6261     * Request to apply the given window insets to this view or another view in its subtree.
6262     *
6263     * <p>This method should be called by clients wishing to apply insets corresponding to areas
6264     * obscured by window decorations or overlays. This can include the status and navigation bars,
6265     * action bars, input methods and more. New inset categories may be added in the future.
6266     * The method returns the insets provided minus any that were applied by this view or its
6267     * children.</p>
6268     *
6269     * <p>Clients wishing to provide custom behavior should override the
6270     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
6271     * {@link OnApplyWindowInsetsListener} via the
6272     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
6273     * method.</p>
6274     *
6275     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
6276     * </p>
6277     *
6278     * @param insets Insets to apply
6279     * @return The provided insets minus the insets that were consumed
6280     */
6281    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
6282        try {
6283            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
6284            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
6285                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
6286            } else {
6287                return onApplyWindowInsets(insets);
6288            }
6289        } finally {
6290            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
6291        }
6292    }
6293
6294    /**
6295     * @hide Compute the insets that should be consumed by this view and the ones
6296     * that should propagate to those under it.
6297     */
6298    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
6299        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6300                || mAttachInfo == null
6301                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
6302                        && !mAttachInfo.mOverscanRequested)) {
6303            outLocalInsets.set(inoutInsets);
6304            inoutInsets.set(0, 0, 0, 0);
6305            return true;
6306        } else {
6307            // The application wants to take care of fitting system window for
6308            // the content...  however we still need to take care of any overscan here.
6309            final Rect overscan = mAttachInfo.mOverscanInsets;
6310            outLocalInsets.set(overscan);
6311            inoutInsets.left -= overscan.left;
6312            inoutInsets.top -= overscan.top;
6313            inoutInsets.right -= overscan.right;
6314            inoutInsets.bottom -= overscan.bottom;
6315            return false;
6316        }
6317    }
6318
6319    /**
6320     * Sets whether or not this view should account for system screen decorations
6321     * such as the status bar and inset its content; that is, controlling whether
6322     * the default implementation of {@link #fitSystemWindows(Rect)} will be
6323     * executed.  See that method for more details.
6324     *
6325     * <p>Note that if you are providing your own implementation of
6326     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
6327     * flag to true -- your implementation will be overriding the default
6328     * implementation that checks this flag.
6329     *
6330     * @param fitSystemWindows If true, then the default implementation of
6331     * {@link #fitSystemWindows(Rect)} will be executed.
6332     *
6333     * @attr ref android.R.styleable#View_fitsSystemWindows
6334     * @see #getFitsSystemWindows()
6335     * @see #fitSystemWindows(Rect)
6336     * @see #setSystemUiVisibility(int)
6337     */
6338    public void setFitsSystemWindows(boolean fitSystemWindows) {
6339        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
6340    }
6341
6342    /**
6343     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
6344     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
6345     * will be executed.
6346     *
6347     * @return {@code true} if the default implementation of
6348     * {@link #fitSystemWindows(Rect)} will be executed.
6349     *
6350     * @attr ref android.R.styleable#View_fitsSystemWindows
6351     * @see #setFitsSystemWindows(boolean)
6352     * @see #fitSystemWindows(Rect)
6353     * @see #setSystemUiVisibility(int)
6354     */
6355    public boolean getFitsSystemWindows() {
6356        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
6357    }
6358
6359    /** @hide */
6360    public boolean fitsSystemWindows() {
6361        return getFitsSystemWindows();
6362    }
6363
6364    /**
6365     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
6366     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
6367     */
6368    public void requestFitSystemWindows() {
6369        if (mParent != null) {
6370            mParent.requestFitSystemWindows();
6371        }
6372    }
6373
6374    /**
6375     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
6376     */
6377    public void requestApplyInsets() {
6378        requestFitSystemWindows();
6379    }
6380
6381    /**
6382     * For use by PhoneWindow to make its own system window fitting optional.
6383     * @hide
6384     */
6385    public void makeOptionalFitsSystemWindows() {
6386        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
6387    }
6388
6389    /**
6390     * Returns the visibility status for this view.
6391     *
6392     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6393     * @attr ref android.R.styleable#View_visibility
6394     */
6395    @ViewDebug.ExportedProperty(mapping = {
6396        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
6397        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
6398        @ViewDebug.IntToString(from = GONE,      to = "GONE")
6399    })
6400    @Visibility
6401    public int getVisibility() {
6402        return mViewFlags & VISIBILITY_MASK;
6403    }
6404
6405    /**
6406     * Set the enabled state of this view.
6407     *
6408     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6409     * @attr ref android.R.styleable#View_visibility
6410     */
6411    @RemotableViewMethod
6412    public void setVisibility(@Visibility int visibility) {
6413        setFlags(visibility, VISIBILITY_MASK);
6414        if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
6415    }
6416
6417    /**
6418     * Returns the enabled status for this view. The interpretation of the
6419     * enabled state varies by subclass.
6420     *
6421     * @return True if this view is enabled, false otherwise.
6422     */
6423    @ViewDebug.ExportedProperty
6424    public boolean isEnabled() {
6425        return (mViewFlags & ENABLED_MASK) == ENABLED;
6426    }
6427
6428    /**
6429     * Set the enabled state of this view. The interpretation of the enabled
6430     * state varies by subclass.
6431     *
6432     * @param enabled True if this view is enabled, false otherwise.
6433     */
6434    @RemotableViewMethod
6435    public void setEnabled(boolean enabled) {
6436        if (enabled == isEnabled()) return;
6437
6438        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
6439
6440        /*
6441         * The View most likely has to change its appearance, so refresh
6442         * the drawable state.
6443         */
6444        refreshDrawableState();
6445
6446        // Invalidate too, since the default behavior for views is to be
6447        // be drawn at 50% alpha rather than to change the drawable.
6448        invalidate(true);
6449
6450        if (!enabled) {
6451            cancelPendingInputEvents();
6452        }
6453    }
6454
6455    /**
6456     * Set whether this view can receive the focus.
6457     *
6458     * Setting this to false will also ensure that this view is not focusable
6459     * in touch mode.
6460     *
6461     * @param focusable If true, this view can receive the focus.
6462     *
6463     * @see #setFocusableInTouchMode(boolean)
6464     * @attr ref android.R.styleable#View_focusable
6465     */
6466    public void setFocusable(boolean focusable) {
6467        if (!focusable) {
6468            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
6469        }
6470        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
6471    }
6472
6473    /**
6474     * Set whether this view can receive focus while in touch mode.
6475     *
6476     * Setting this to true will also ensure that this view is focusable.
6477     *
6478     * @param focusableInTouchMode If true, this view can receive the focus while
6479     *   in touch mode.
6480     *
6481     * @see #setFocusable(boolean)
6482     * @attr ref android.R.styleable#View_focusableInTouchMode
6483     */
6484    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
6485        // Focusable in touch mode should always be set before the focusable flag
6486        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
6487        // which, in touch mode, will not successfully request focus on this view
6488        // because the focusable in touch mode flag is not set
6489        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
6490        if (focusableInTouchMode) {
6491            setFlags(FOCUSABLE, FOCUSABLE_MASK);
6492        }
6493    }
6494
6495    /**
6496     * Set whether this view should have sound effects enabled for events such as
6497     * clicking and touching.
6498     *
6499     * <p>You may wish to disable sound effects for a view if you already play sounds,
6500     * for instance, a dial key that plays dtmf tones.
6501     *
6502     * @param soundEffectsEnabled whether sound effects are enabled for this view.
6503     * @see #isSoundEffectsEnabled()
6504     * @see #playSoundEffect(int)
6505     * @attr ref android.R.styleable#View_soundEffectsEnabled
6506     */
6507    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
6508        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
6509    }
6510
6511    /**
6512     * @return whether this view should have sound effects enabled for events such as
6513     *     clicking and touching.
6514     *
6515     * @see #setSoundEffectsEnabled(boolean)
6516     * @see #playSoundEffect(int)
6517     * @attr ref android.R.styleable#View_soundEffectsEnabled
6518     */
6519    @ViewDebug.ExportedProperty
6520    public boolean isSoundEffectsEnabled() {
6521        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
6522    }
6523
6524    /**
6525     * Set whether this view should have haptic feedback for events such as
6526     * long presses.
6527     *
6528     * <p>You may wish to disable haptic feedback if your view already controls
6529     * its own haptic feedback.
6530     *
6531     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
6532     * @see #isHapticFeedbackEnabled()
6533     * @see #performHapticFeedback(int)
6534     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6535     */
6536    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
6537        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
6538    }
6539
6540    /**
6541     * @return whether this view should have haptic feedback enabled for events
6542     * long presses.
6543     *
6544     * @see #setHapticFeedbackEnabled(boolean)
6545     * @see #performHapticFeedback(int)
6546     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6547     */
6548    @ViewDebug.ExportedProperty
6549    public boolean isHapticFeedbackEnabled() {
6550        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
6551    }
6552
6553    /**
6554     * Returns the layout direction for this view.
6555     *
6556     * @return One of {@link #LAYOUT_DIRECTION_LTR},
6557     *   {@link #LAYOUT_DIRECTION_RTL},
6558     *   {@link #LAYOUT_DIRECTION_INHERIT} or
6559     *   {@link #LAYOUT_DIRECTION_LOCALE}.
6560     *
6561     * @attr ref android.R.styleable#View_layoutDirection
6562     *
6563     * @hide
6564     */
6565    @ViewDebug.ExportedProperty(category = "layout", mapping = {
6566        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
6567        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
6568        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
6569        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
6570    })
6571    @LayoutDir
6572    public int getRawLayoutDirection() {
6573        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
6574    }
6575
6576    /**
6577     * Set the layout direction for this view. This will propagate a reset of layout direction
6578     * resolution to the view's children and resolve layout direction for this view.
6579     *
6580     * @param layoutDirection the layout direction to set. Should be one of:
6581     *
6582     * {@link #LAYOUT_DIRECTION_LTR},
6583     * {@link #LAYOUT_DIRECTION_RTL},
6584     * {@link #LAYOUT_DIRECTION_INHERIT},
6585     * {@link #LAYOUT_DIRECTION_LOCALE}.
6586     *
6587     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
6588     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
6589     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
6590     *
6591     * @attr ref android.R.styleable#View_layoutDirection
6592     */
6593    @RemotableViewMethod
6594    public void setLayoutDirection(@LayoutDir int layoutDirection) {
6595        if (getRawLayoutDirection() != layoutDirection) {
6596            // Reset the current layout direction and the resolved one
6597            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
6598            resetRtlProperties();
6599            // Set the new layout direction (filtered)
6600            mPrivateFlags2 |=
6601                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
6602            // We need to resolve all RTL properties as they all depend on layout direction
6603            resolveRtlPropertiesIfNeeded();
6604            requestLayout();
6605            invalidate(true);
6606        }
6607    }
6608
6609    /**
6610     * Returns the resolved layout direction for this view.
6611     *
6612     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
6613     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
6614     *
6615     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
6616     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
6617     *
6618     * @attr ref android.R.styleable#View_layoutDirection
6619     */
6620    @ViewDebug.ExportedProperty(category = "layout", mapping = {
6621        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
6622        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
6623    })
6624    @ResolvedLayoutDir
6625    public int getLayoutDirection() {
6626        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
6627        if (targetSdkVersion < JELLY_BEAN_MR1) {
6628            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
6629            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
6630        }
6631        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
6632                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
6633    }
6634
6635    /**
6636     * Indicates whether or not this view's layout is right-to-left. This is resolved from
6637     * layout attribute and/or the inherited value from the parent
6638     *
6639     * @return true if the layout is right-to-left.
6640     *
6641     * @hide
6642     */
6643    @ViewDebug.ExportedProperty(category = "layout")
6644    public boolean isLayoutRtl() {
6645        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
6646    }
6647
6648    /**
6649     * Indicates whether the view is currently tracking transient state that the
6650     * app should not need to concern itself with saving and restoring, but that
6651     * the framework should take special note to preserve when possible.
6652     *
6653     * <p>A view with transient state cannot be trivially rebound from an external
6654     * data source, such as an adapter binding item views in a list. This may be
6655     * because the view is performing an animation, tracking user selection
6656     * of content, or similar.</p>
6657     *
6658     * @return true if the view has transient state
6659     */
6660    @ViewDebug.ExportedProperty(category = "layout")
6661    public boolean hasTransientState() {
6662        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
6663    }
6664
6665    /**
6666     * Set whether this view is currently tracking transient state that the
6667     * framework should attempt to preserve when possible. This flag is reference counted,
6668     * so every call to setHasTransientState(true) should be paired with a later call
6669     * to setHasTransientState(false).
6670     *
6671     * <p>A view with transient state cannot be trivially rebound from an external
6672     * data source, such as an adapter binding item views in a list. This may be
6673     * because the view is performing an animation, tracking user selection
6674     * of content, or similar.</p>
6675     *
6676     * @param hasTransientState true if this view has transient state
6677     */
6678    public void setHasTransientState(boolean hasTransientState) {
6679        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
6680                mTransientStateCount - 1;
6681        if (mTransientStateCount < 0) {
6682            mTransientStateCount = 0;
6683            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
6684                    "unmatched pair of setHasTransientState calls");
6685        } else if ((hasTransientState && mTransientStateCount == 1) ||
6686                (!hasTransientState && mTransientStateCount == 0)) {
6687            // update flag if we've just incremented up from 0 or decremented down to 0
6688            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
6689                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
6690            if (mParent != null) {
6691                try {
6692                    mParent.childHasTransientStateChanged(this, hasTransientState);
6693                } catch (AbstractMethodError e) {
6694                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
6695                            " does not fully implement ViewParent", e);
6696                }
6697            }
6698        }
6699    }
6700
6701    /**
6702     * Returns true if this view is currently attached to a window.
6703     */
6704    public boolean isAttachedToWindow() {
6705        return mAttachInfo != null;
6706    }
6707
6708    /**
6709     * Returns true if this view has been through at least one layout since it
6710     * was last attached to or detached from a window.
6711     */
6712    public boolean isLaidOut() {
6713        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
6714    }
6715
6716    /**
6717     * If this view doesn't do any drawing on its own, set this flag to
6718     * allow further optimizations. By default, this flag is not set on
6719     * View, but could be set on some View subclasses such as ViewGroup.
6720     *
6721     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
6722     * you should clear this flag.
6723     *
6724     * @param willNotDraw whether or not this View draw on its own
6725     */
6726    public void setWillNotDraw(boolean willNotDraw) {
6727        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
6728    }
6729
6730    /**
6731     * Returns whether or not this View draws on its own.
6732     *
6733     * @return true if this view has nothing to draw, false otherwise
6734     */
6735    @ViewDebug.ExportedProperty(category = "drawing")
6736    public boolean willNotDraw() {
6737        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
6738    }
6739
6740    /**
6741     * When a View's drawing cache is enabled, drawing is redirected to an
6742     * offscreen bitmap. Some views, like an ImageView, must be able to
6743     * bypass this mechanism if they already draw a single bitmap, to avoid
6744     * unnecessary usage of the memory.
6745     *
6746     * @param willNotCacheDrawing true if this view does not cache its
6747     *        drawing, false otherwise
6748     */
6749    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
6750        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
6751    }
6752
6753    /**
6754     * Returns whether or not this View can cache its drawing or not.
6755     *
6756     * @return true if this view does not cache its drawing, false otherwise
6757     */
6758    @ViewDebug.ExportedProperty(category = "drawing")
6759    public boolean willNotCacheDrawing() {
6760        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
6761    }
6762
6763    /**
6764     * Indicates whether this view reacts to click events or not.
6765     *
6766     * @return true if the view is clickable, false otherwise
6767     *
6768     * @see #setClickable(boolean)
6769     * @attr ref android.R.styleable#View_clickable
6770     */
6771    @ViewDebug.ExportedProperty
6772    public boolean isClickable() {
6773        return (mViewFlags & CLICKABLE) == CLICKABLE;
6774    }
6775
6776    /**
6777     * Enables or disables click events for this view. When a view
6778     * is clickable it will change its state to "pressed" on every click.
6779     * Subclasses should set the view clickable to visually react to
6780     * user's clicks.
6781     *
6782     * @param clickable true to make the view clickable, false otherwise
6783     *
6784     * @see #isClickable()
6785     * @attr ref android.R.styleable#View_clickable
6786     */
6787    public void setClickable(boolean clickable) {
6788        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
6789    }
6790
6791    /**
6792     * Indicates whether this view reacts to long click events or not.
6793     *
6794     * @return true if the view is long clickable, false otherwise
6795     *
6796     * @see #setLongClickable(boolean)
6797     * @attr ref android.R.styleable#View_longClickable
6798     */
6799    public boolean isLongClickable() {
6800        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
6801    }
6802
6803    /**
6804     * Enables or disables long click events for this view. When a view is long
6805     * clickable it reacts to the user holding down the button for a longer
6806     * duration than a tap. This event can either launch the listener or a
6807     * context menu.
6808     *
6809     * @param longClickable true to make the view long clickable, false otherwise
6810     * @see #isLongClickable()
6811     * @attr ref android.R.styleable#View_longClickable
6812     */
6813    public void setLongClickable(boolean longClickable) {
6814        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
6815    }
6816
6817    /**
6818     * Sets the pressed state for this view and provides a touch coordinate for
6819     * animation hinting.
6820     *
6821     * @param pressed Pass true to set the View's internal state to "pressed",
6822     *            or false to reverts the View's internal state from a
6823     *            previously set "pressed" state.
6824     * @param x The x coordinate of the touch that caused the press
6825     * @param y The y coordinate of the touch that caused the press
6826     */
6827    private void setPressed(boolean pressed, float x, float y) {
6828        if (pressed) {
6829            drawableHotspotChanged(x, y);
6830        }
6831
6832        setPressed(pressed);
6833    }
6834
6835    /**
6836     * Sets the pressed state for this view.
6837     *
6838     * @see #isClickable()
6839     * @see #setClickable(boolean)
6840     *
6841     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
6842     *        the View's internal state from a previously set "pressed" state.
6843     */
6844    public void setPressed(boolean pressed) {
6845        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
6846
6847        if (pressed) {
6848            mPrivateFlags |= PFLAG_PRESSED;
6849        } else {
6850            mPrivateFlags &= ~PFLAG_PRESSED;
6851        }
6852
6853        if (needsRefresh) {
6854            refreshDrawableState();
6855        }
6856        dispatchSetPressed(pressed);
6857    }
6858
6859    /**
6860     * Dispatch setPressed to all of this View's children.
6861     *
6862     * @see #setPressed(boolean)
6863     *
6864     * @param pressed The new pressed state
6865     */
6866    protected void dispatchSetPressed(boolean pressed) {
6867    }
6868
6869    /**
6870     * Indicates whether the view is currently in pressed state. Unless
6871     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
6872     * the pressed state.
6873     *
6874     * @see #setPressed(boolean)
6875     * @see #isClickable()
6876     * @see #setClickable(boolean)
6877     *
6878     * @return true if the view is currently pressed, false otherwise
6879     */
6880    public boolean isPressed() {
6881        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
6882    }
6883
6884    /**
6885     * Indicates whether this view will save its state (that is,
6886     * whether its {@link #onSaveInstanceState} method will be called).
6887     *
6888     * @return Returns true if the view state saving is enabled, else false.
6889     *
6890     * @see #setSaveEnabled(boolean)
6891     * @attr ref android.R.styleable#View_saveEnabled
6892     */
6893    public boolean isSaveEnabled() {
6894        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
6895    }
6896
6897    /**
6898     * Controls whether the saving of this view's state is
6899     * enabled (that is, whether its {@link #onSaveInstanceState} method
6900     * will be called).  Note that even if freezing is enabled, the
6901     * view still must have an id assigned to it (via {@link #setId(int)})
6902     * for its state to be saved.  This flag can only disable the
6903     * saving of this view; any child views may still have their state saved.
6904     *
6905     * @param enabled Set to false to <em>disable</em> state saving, or true
6906     * (the default) to allow it.
6907     *
6908     * @see #isSaveEnabled()
6909     * @see #setId(int)
6910     * @see #onSaveInstanceState()
6911     * @attr ref android.R.styleable#View_saveEnabled
6912     */
6913    public void setSaveEnabled(boolean enabled) {
6914        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
6915    }
6916
6917    /**
6918     * Gets whether the framework should discard touches when the view's
6919     * window is obscured by another visible window.
6920     * Refer to the {@link View} security documentation for more details.
6921     *
6922     * @return True if touch filtering is enabled.
6923     *
6924     * @see #setFilterTouchesWhenObscured(boolean)
6925     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
6926     */
6927    @ViewDebug.ExportedProperty
6928    public boolean getFilterTouchesWhenObscured() {
6929        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
6930    }
6931
6932    /**
6933     * Sets whether the framework should discard touches when the view's
6934     * window is obscured by another visible window.
6935     * Refer to the {@link View} security documentation for more details.
6936     *
6937     * @param enabled True if touch filtering should be enabled.
6938     *
6939     * @see #getFilterTouchesWhenObscured
6940     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
6941     */
6942    public void setFilterTouchesWhenObscured(boolean enabled) {
6943        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
6944                FILTER_TOUCHES_WHEN_OBSCURED);
6945    }
6946
6947    /**
6948     * Indicates whether the entire hierarchy under this view will save its
6949     * state when a state saving traversal occurs from its parent.  The default
6950     * is true; if false, these views will not be saved unless
6951     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
6952     *
6953     * @return Returns true if the view state saving from parent is enabled, else false.
6954     *
6955     * @see #setSaveFromParentEnabled(boolean)
6956     */
6957    public boolean isSaveFromParentEnabled() {
6958        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
6959    }
6960
6961    /**
6962     * Controls whether the entire hierarchy under this view will save its
6963     * state when a state saving traversal occurs from its parent.  The default
6964     * is true; if false, these views will not be saved unless
6965     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
6966     *
6967     * @param enabled Set to false to <em>disable</em> state saving, or true
6968     * (the default) to allow it.
6969     *
6970     * @see #isSaveFromParentEnabled()
6971     * @see #setId(int)
6972     * @see #onSaveInstanceState()
6973     */
6974    public void setSaveFromParentEnabled(boolean enabled) {
6975        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
6976    }
6977
6978
6979    /**
6980     * Returns whether this View is able to take focus.
6981     *
6982     * @return True if this view can take focus, or false otherwise.
6983     * @attr ref android.R.styleable#View_focusable
6984     */
6985    @ViewDebug.ExportedProperty(category = "focus")
6986    public final boolean isFocusable() {
6987        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
6988    }
6989
6990    /**
6991     * When a view is focusable, it may not want to take focus when in touch mode.
6992     * For example, a button would like focus when the user is navigating via a D-pad
6993     * so that the user can click on it, but once the user starts touching the screen,
6994     * the button shouldn't take focus
6995     * @return Whether the view is focusable in touch mode.
6996     * @attr ref android.R.styleable#View_focusableInTouchMode
6997     */
6998    @ViewDebug.ExportedProperty
6999    public final boolean isFocusableInTouchMode() {
7000        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
7001    }
7002
7003    /**
7004     * Find the nearest view in the specified direction that can take focus.
7005     * This does not actually give focus to that view.
7006     *
7007     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7008     *
7009     * @return The nearest focusable in the specified direction, or null if none
7010     *         can be found.
7011     */
7012    public View focusSearch(@FocusRealDirection int direction) {
7013        if (mParent != null) {
7014            return mParent.focusSearch(this, direction);
7015        } else {
7016            return null;
7017        }
7018    }
7019
7020    /**
7021     * This method is the last chance for the focused view and its ancestors to
7022     * respond to an arrow key. This is called when the focused view did not
7023     * consume the key internally, nor could the view system find a new view in
7024     * the requested direction to give focus to.
7025     *
7026     * @param focused The currently focused view.
7027     * @param direction The direction focus wants to move. One of FOCUS_UP,
7028     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
7029     * @return True if the this view consumed this unhandled move.
7030     */
7031    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
7032        return false;
7033    }
7034
7035    /**
7036     * If a user manually specified the next view id for a particular direction,
7037     * use the root to look up the view.
7038     * @param root The root view of the hierarchy containing this view.
7039     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
7040     * or FOCUS_BACKWARD.
7041     * @return The user specified next view, or null if there is none.
7042     */
7043    View findUserSetNextFocus(View root, @FocusDirection int direction) {
7044        switch (direction) {
7045            case FOCUS_LEFT:
7046                if (mNextFocusLeftId == View.NO_ID) return null;
7047                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
7048            case FOCUS_RIGHT:
7049                if (mNextFocusRightId == View.NO_ID) return null;
7050                return findViewInsideOutShouldExist(root, mNextFocusRightId);
7051            case FOCUS_UP:
7052                if (mNextFocusUpId == View.NO_ID) return null;
7053                return findViewInsideOutShouldExist(root, mNextFocusUpId);
7054            case FOCUS_DOWN:
7055                if (mNextFocusDownId == View.NO_ID) return null;
7056                return findViewInsideOutShouldExist(root, mNextFocusDownId);
7057            case FOCUS_FORWARD:
7058                if (mNextFocusForwardId == View.NO_ID) return null;
7059                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
7060            case FOCUS_BACKWARD: {
7061                if (mID == View.NO_ID) return null;
7062                final int id = mID;
7063                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
7064                    @Override
7065                    public boolean apply(View t) {
7066                        return t.mNextFocusForwardId == id;
7067                    }
7068                });
7069            }
7070        }
7071        return null;
7072    }
7073
7074    private View findViewInsideOutShouldExist(View root, int id) {
7075        if (mMatchIdPredicate == null) {
7076            mMatchIdPredicate = new MatchIdPredicate();
7077        }
7078        mMatchIdPredicate.mId = id;
7079        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
7080        if (result == null) {
7081            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
7082        }
7083        return result;
7084    }
7085
7086    /**
7087     * Find and return all focusable views that are descendants of this view,
7088     * possibly including this view if it is focusable itself.
7089     *
7090     * @param direction The direction of the focus
7091     * @return A list of focusable views
7092     */
7093    public ArrayList<View> getFocusables(@FocusDirection int direction) {
7094        ArrayList<View> result = new ArrayList<View>(24);
7095        addFocusables(result, direction);
7096        return result;
7097    }
7098
7099    /**
7100     * Add any focusable views that are descendants of this view (possibly
7101     * including this view if it is focusable itself) to views.  If we are in touch mode,
7102     * only add views that are also focusable in touch mode.
7103     *
7104     * @param views Focusable views found so far
7105     * @param direction The direction of the focus
7106     */
7107    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
7108        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
7109    }
7110
7111    /**
7112     * Adds any focusable views that are descendants of this view (possibly
7113     * including this view if it is focusable itself) to views. This method
7114     * adds all focusable views regardless if we are in touch mode or
7115     * only views focusable in touch mode if we are in touch mode or
7116     * only views that can take accessibility focus if accessibility is enabeld
7117     * depending on the focusable mode paramater.
7118     *
7119     * @param views Focusable views found so far or null if all we are interested is
7120     *        the number of focusables.
7121     * @param direction The direction of the focus.
7122     * @param focusableMode The type of focusables to be added.
7123     *
7124     * @see #FOCUSABLES_ALL
7125     * @see #FOCUSABLES_TOUCH_MODE
7126     */
7127    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
7128            @FocusableMode int focusableMode) {
7129        if (views == null) {
7130            return;
7131        }
7132        if (!isFocusable()) {
7133            return;
7134        }
7135        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
7136                && isInTouchMode() && !isFocusableInTouchMode()) {
7137            return;
7138        }
7139        views.add(this);
7140    }
7141
7142    /**
7143     * Finds the Views that contain given text. The containment is case insensitive.
7144     * The search is performed by either the text that the View renders or the content
7145     * description that describes the view for accessibility purposes and the view does
7146     * not render or both. Clients can specify how the search is to be performed via
7147     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
7148     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
7149     *
7150     * @param outViews The output list of matching Views.
7151     * @param searched The text to match against.
7152     *
7153     * @see #FIND_VIEWS_WITH_TEXT
7154     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
7155     * @see #setContentDescription(CharSequence)
7156     */
7157    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
7158            @FindViewFlags int flags) {
7159        if (getAccessibilityNodeProvider() != null) {
7160            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
7161                outViews.add(this);
7162            }
7163        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
7164                && (searched != null && searched.length() > 0)
7165                && (mContentDescription != null && mContentDescription.length() > 0)) {
7166            String searchedLowerCase = searched.toString().toLowerCase();
7167            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
7168            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
7169                outViews.add(this);
7170            }
7171        }
7172    }
7173
7174    /**
7175     * Find and return all touchable views that are descendants of this view,
7176     * possibly including this view if it is touchable itself.
7177     *
7178     * @return A list of touchable views
7179     */
7180    public ArrayList<View> getTouchables() {
7181        ArrayList<View> result = new ArrayList<View>();
7182        addTouchables(result);
7183        return result;
7184    }
7185
7186    /**
7187     * Add any touchable views that are descendants of this view (possibly
7188     * including this view if it is touchable itself) to views.
7189     *
7190     * @param views Touchable views found so far
7191     */
7192    public void addTouchables(ArrayList<View> views) {
7193        final int viewFlags = mViewFlags;
7194
7195        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
7196                && (viewFlags & ENABLED_MASK) == ENABLED) {
7197            views.add(this);
7198        }
7199    }
7200
7201    /**
7202     * Returns whether this View is accessibility focused.
7203     *
7204     * @return True if this View is accessibility focused.
7205     */
7206    public boolean isAccessibilityFocused() {
7207        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
7208    }
7209
7210    /**
7211     * Call this to try to give accessibility focus to this view.
7212     *
7213     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
7214     * returns false or the view is no visible or the view already has accessibility
7215     * focus.
7216     *
7217     * See also {@link #focusSearch(int)}, which is what you call to say that you
7218     * have focus, and you want your parent to look for the next one.
7219     *
7220     * @return Whether this view actually took accessibility focus.
7221     *
7222     * @hide
7223     */
7224    public boolean requestAccessibilityFocus() {
7225        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
7226        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
7227            return false;
7228        }
7229        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7230            return false;
7231        }
7232        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
7233            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
7234            ViewRootImpl viewRootImpl = getViewRootImpl();
7235            if (viewRootImpl != null) {
7236                viewRootImpl.setAccessibilityFocus(this, null);
7237            }
7238            invalidate();
7239            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
7240            return true;
7241        }
7242        return false;
7243    }
7244
7245    /**
7246     * Call this to try to clear accessibility focus of this view.
7247     *
7248     * See also {@link #focusSearch(int)}, which is what you call to say that you
7249     * have focus, and you want your parent to look for the next one.
7250     *
7251     * @hide
7252     */
7253    public void clearAccessibilityFocus() {
7254        clearAccessibilityFocusNoCallbacks();
7255        // Clear the global reference of accessibility focus if this
7256        // view or any of its descendants had accessibility focus.
7257        ViewRootImpl viewRootImpl = getViewRootImpl();
7258        if (viewRootImpl != null) {
7259            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
7260            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
7261                viewRootImpl.setAccessibilityFocus(null, null);
7262            }
7263        }
7264    }
7265
7266    private void sendAccessibilityHoverEvent(int eventType) {
7267        // Since we are not delivering to a client accessibility events from not
7268        // important views (unless the clinet request that) we need to fire the
7269        // event from the deepest view exposed to the client. As a consequence if
7270        // the user crosses a not exposed view the client will see enter and exit
7271        // of the exposed predecessor followed by and enter and exit of that same
7272        // predecessor when entering and exiting the not exposed descendant. This
7273        // is fine since the client has a clear idea which view is hovered at the
7274        // price of a couple more events being sent. This is a simple and
7275        // working solution.
7276        View source = this;
7277        while (true) {
7278            if (source.includeForAccessibility()) {
7279                source.sendAccessibilityEvent(eventType);
7280                return;
7281            }
7282            ViewParent parent = source.getParent();
7283            if (parent instanceof View) {
7284                source = (View) parent;
7285            } else {
7286                return;
7287            }
7288        }
7289    }
7290
7291    /**
7292     * Clears accessibility focus without calling any callback methods
7293     * normally invoked in {@link #clearAccessibilityFocus()}. This method
7294     * is used for clearing accessibility focus when giving this focus to
7295     * another view.
7296     */
7297    void clearAccessibilityFocusNoCallbacks() {
7298        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
7299            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
7300            invalidate();
7301            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
7302        }
7303    }
7304
7305    /**
7306     * Call this to try to give focus to a specific view or to one of its
7307     * descendants.
7308     *
7309     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7310     * false), or if it is focusable and it is not focusable in touch mode
7311     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7312     *
7313     * See also {@link #focusSearch(int)}, which is what you call to say that you
7314     * have focus, and you want your parent to look for the next one.
7315     *
7316     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
7317     * {@link #FOCUS_DOWN} and <code>null</code>.
7318     *
7319     * @return Whether this view or one of its descendants actually took focus.
7320     */
7321    public final boolean requestFocus() {
7322        return requestFocus(View.FOCUS_DOWN);
7323    }
7324
7325    /**
7326     * Call this to try to give focus to a specific view or to one of its
7327     * descendants and give it a hint about what direction focus is heading.
7328     *
7329     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7330     * false), or if it is focusable and it is not focusable in touch mode
7331     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7332     *
7333     * See also {@link #focusSearch(int)}, which is what you call to say that you
7334     * have focus, and you want your parent to look for the next one.
7335     *
7336     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
7337     * <code>null</code> set for the previously focused rectangle.
7338     *
7339     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7340     * @return Whether this view or one of its descendants actually took focus.
7341     */
7342    public final boolean requestFocus(int direction) {
7343        return requestFocus(direction, null);
7344    }
7345
7346    /**
7347     * Call this to try to give focus to a specific view or to one of its descendants
7348     * and give it hints about the direction and a specific rectangle that the focus
7349     * is coming from.  The rectangle can help give larger views a finer grained hint
7350     * about where focus is coming from, and therefore, where to show selection, or
7351     * forward focus change internally.
7352     *
7353     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7354     * false), or if it is focusable and it is not focusable in touch mode
7355     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7356     *
7357     * A View will not take focus if it is not visible.
7358     *
7359     * A View will not take focus if one of its parents has
7360     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
7361     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
7362     *
7363     * See also {@link #focusSearch(int)}, which is what you call to say that you
7364     * have focus, and you want your parent to look for the next one.
7365     *
7366     * You may wish to override this method if your custom {@link View} has an internal
7367     * {@link View} that it wishes to forward the request to.
7368     *
7369     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7370     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
7371     *        to give a finer grained hint about where focus is coming from.  May be null
7372     *        if there is no hint.
7373     * @return Whether this view or one of its descendants actually took focus.
7374     */
7375    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
7376        return requestFocusNoSearch(direction, previouslyFocusedRect);
7377    }
7378
7379    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
7380        // need to be focusable
7381        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
7382                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7383            return false;
7384        }
7385
7386        // need to be focusable in touch mode if in touch mode
7387        if (isInTouchMode() &&
7388            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
7389               return false;
7390        }
7391
7392        // need to not have any parents blocking us
7393        if (hasAncestorThatBlocksDescendantFocus()) {
7394            return false;
7395        }
7396
7397        handleFocusGainInternal(direction, previouslyFocusedRect);
7398        return true;
7399    }
7400
7401    /**
7402     * Call this to try to give focus to a specific view or to one of its descendants. This is a
7403     * special variant of {@link #requestFocus() } that will allow views that are not focuable in
7404     * touch mode to request focus when they are touched.
7405     *
7406     * @return Whether this view or one of its descendants actually took focus.
7407     *
7408     * @see #isInTouchMode()
7409     *
7410     */
7411    public final boolean requestFocusFromTouch() {
7412        // Leave touch mode if we need to
7413        if (isInTouchMode()) {
7414            ViewRootImpl viewRoot = getViewRootImpl();
7415            if (viewRoot != null) {
7416                viewRoot.ensureTouchMode(false);
7417            }
7418        }
7419        return requestFocus(View.FOCUS_DOWN);
7420    }
7421
7422    /**
7423     * @return Whether any ancestor of this view blocks descendant focus.
7424     */
7425    private boolean hasAncestorThatBlocksDescendantFocus() {
7426        ViewParent ancestor = mParent;
7427        while (ancestor instanceof ViewGroup) {
7428            final ViewGroup vgAncestor = (ViewGroup) ancestor;
7429            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
7430                    || vgAncestor.shouldBlockFocusForTouchscreen()) {
7431                return true;
7432            } else {
7433                ancestor = vgAncestor.getParent();
7434            }
7435        }
7436        return false;
7437    }
7438
7439    /**
7440     * Gets the mode for determining whether this View is important for accessibility
7441     * which is if it fires accessibility events and if it is reported to
7442     * accessibility services that query the screen.
7443     *
7444     * @return The mode for determining whether a View is important for accessibility.
7445     *
7446     * @attr ref android.R.styleable#View_importantForAccessibility
7447     *
7448     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7449     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7450     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7451     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7452     */
7453    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
7454            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
7455            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
7456            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
7457            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
7458                    to = "noHideDescendants")
7459        })
7460    public int getImportantForAccessibility() {
7461        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7462                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7463    }
7464
7465    /**
7466     * Sets the live region mode for this view. This indicates to accessibility
7467     * services whether they should automatically notify the user about changes
7468     * to the view's content description or text, or to the content descriptions
7469     * or text of the view's children (where applicable).
7470     * <p>
7471     * For example, in a login screen with a TextView that displays an "incorrect
7472     * password" notification, that view should be marked as a live region with
7473     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7474     * <p>
7475     * To disable change notifications for this view, use
7476     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
7477     * mode for most views.
7478     * <p>
7479     * To indicate that the user should be notified of changes, use
7480     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7481     * <p>
7482     * If the view's changes should interrupt ongoing speech and notify the user
7483     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
7484     *
7485     * @param mode The live region mode for this view, one of:
7486     *        <ul>
7487     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
7488     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
7489     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
7490     *        </ul>
7491     * @attr ref android.R.styleable#View_accessibilityLiveRegion
7492     */
7493    public void setAccessibilityLiveRegion(int mode) {
7494        if (mode != getAccessibilityLiveRegion()) {
7495            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7496            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
7497                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7498            notifyViewAccessibilityStateChangedIfNeeded(
7499                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7500        }
7501    }
7502
7503    /**
7504     * Gets the live region mode for this View.
7505     *
7506     * @return The live region mode for the view.
7507     *
7508     * @attr ref android.R.styleable#View_accessibilityLiveRegion
7509     *
7510     * @see #setAccessibilityLiveRegion(int)
7511     */
7512    public int getAccessibilityLiveRegion() {
7513        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
7514                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
7515    }
7516
7517    /**
7518     * Sets how to determine whether this view is important for accessibility
7519     * which is if it fires accessibility events and if it is reported to
7520     * accessibility services that query the screen.
7521     *
7522     * @param mode How to determine whether this view is important for accessibility.
7523     *
7524     * @attr ref android.R.styleable#View_importantForAccessibility
7525     *
7526     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7527     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7528     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7529     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7530     */
7531    public void setImportantForAccessibility(int mode) {
7532        final int oldMode = getImportantForAccessibility();
7533        if (mode != oldMode) {
7534            // If we're moving between AUTO and another state, we might not need
7535            // to send a subtree changed notification. We'll store the computed
7536            // importance, since we'll need to check it later to make sure.
7537            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
7538                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
7539            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
7540            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7541            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
7542                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7543            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
7544                notifySubtreeAccessibilityStateChangedIfNeeded();
7545            } else {
7546                notifyViewAccessibilityStateChangedIfNeeded(
7547                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7548            }
7549        }
7550    }
7551
7552    /**
7553     * Computes whether this view should be exposed for accessibility. In
7554     * general, views that are interactive or provide information are exposed
7555     * while views that serve only as containers are hidden.
7556     * <p>
7557     * If an ancestor of this view has importance
7558     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
7559     * returns <code>false</code>.
7560     * <p>
7561     * Otherwise, the value is computed according to the view's
7562     * {@link #getImportantForAccessibility()} value:
7563     * <ol>
7564     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
7565     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
7566     * </code>
7567     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
7568     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
7569     * view satisfies any of the following:
7570     * <ul>
7571     * <li>Is actionable, e.g. {@link #isClickable()},
7572     * {@link #isLongClickable()}, or {@link #isFocusable()}
7573     * <li>Has an {@link AccessibilityDelegate}
7574     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
7575     * {@link OnKeyListener}, etc.
7576     * <li>Is an accessibility live region, e.g.
7577     * {@link #getAccessibilityLiveRegion()} is not
7578     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
7579     * </ul>
7580     * </ol>
7581     *
7582     * @return Whether the view is exposed for accessibility.
7583     * @see #setImportantForAccessibility(int)
7584     * @see #getImportantForAccessibility()
7585     */
7586    public boolean isImportantForAccessibility() {
7587        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7588                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7589        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
7590                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7591            return false;
7592        }
7593
7594        // Check parent mode to ensure we're not hidden.
7595        ViewParent parent = mParent;
7596        while (parent instanceof View) {
7597            if (((View) parent).getImportantForAccessibility()
7598                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7599                return false;
7600            }
7601            parent = parent.getParent();
7602        }
7603
7604        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
7605                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
7606                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
7607    }
7608
7609    /**
7610     * Gets the parent for accessibility purposes. Note that the parent for
7611     * accessibility is not necessary the immediate parent. It is the first
7612     * predecessor that is important for accessibility.
7613     *
7614     * @return The parent for accessibility purposes.
7615     */
7616    public ViewParent getParentForAccessibility() {
7617        if (mParent instanceof View) {
7618            View parentView = (View) mParent;
7619            if (parentView.includeForAccessibility()) {
7620                return mParent;
7621            } else {
7622                return mParent.getParentForAccessibility();
7623            }
7624        }
7625        return null;
7626    }
7627
7628    /**
7629     * Adds the children of a given View for accessibility. Since some Views are
7630     * not important for accessibility the children for accessibility are not
7631     * necessarily direct children of the view, rather they are the first level of
7632     * descendants important for accessibility.
7633     *
7634     * @param children The list of children for accessibility.
7635     */
7636    public void addChildrenForAccessibility(ArrayList<View> children) {
7637
7638    }
7639
7640    /**
7641     * Whether to regard this view for accessibility. A view is regarded for
7642     * accessibility if it is important for accessibility or the querying
7643     * accessibility service has explicitly requested that view not
7644     * important for accessibility are regarded.
7645     *
7646     * @return Whether to regard the view for accessibility.
7647     *
7648     * @hide
7649     */
7650    public boolean includeForAccessibility() {
7651        if (mAttachInfo != null) {
7652            return (mAttachInfo.mAccessibilityFetchFlags
7653                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
7654                    || isImportantForAccessibility();
7655        }
7656        return false;
7657    }
7658
7659    /**
7660     * Returns whether the View is considered actionable from
7661     * accessibility perspective. Such view are important for
7662     * accessibility.
7663     *
7664     * @return True if the view is actionable for accessibility.
7665     *
7666     * @hide
7667     */
7668    public boolean isActionableForAccessibility() {
7669        return (isClickable() || isLongClickable() || isFocusable());
7670    }
7671
7672    /**
7673     * Returns whether the View has registered callbacks which makes it
7674     * important for accessibility.
7675     *
7676     * @return True if the view is actionable for accessibility.
7677     */
7678    private boolean hasListenersForAccessibility() {
7679        ListenerInfo info = getListenerInfo();
7680        return mTouchDelegate != null || info.mOnKeyListener != null
7681                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
7682                || info.mOnHoverListener != null || info.mOnDragListener != null;
7683    }
7684
7685    /**
7686     * Notifies that the accessibility state of this view changed. The change
7687     * is local to this view and does not represent structural changes such
7688     * as children and parent. For example, the view became focusable. The
7689     * notification is at at most once every
7690     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7691     * to avoid unnecessary load to the system. Also once a view has a pending
7692     * notification this method is a NOP until the notification has been sent.
7693     *
7694     * @hide
7695     */
7696    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
7697        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
7698            return;
7699        }
7700        if (mSendViewStateChangedAccessibilityEvent == null) {
7701            mSendViewStateChangedAccessibilityEvent =
7702                    new SendViewStateChangedAccessibilityEvent();
7703        }
7704        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
7705    }
7706
7707    /**
7708     * Notifies that the accessibility state of this view changed. The change
7709     * is *not* local to this view and does represent structural changes such
7710     * as children and parent. For example, the view size changed. The
7711     * notification is at at most once every
7712     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7713     * to avoid unnecessary load to the system. Also once a view has a pending
7714     * notification this method is a NOP until the notification has been sent.
7715     *
7716     * @hide
7717     */
7718    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
7719        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
7720            return;
7721        }
7722        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
7723            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
7724            if (mParent != null) {
7725                try {
7726                    mParent.notifySubtreeAccessibilityStateChanged(
7727                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
7728                } catch (AbstractMethodError e) {
7729                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7730                            " does not fully implement ViewParent", e);
7731                }
7732            }
7733        }
7734    }
7735
7736    /**
7737     * Reset the flag indicating the accessibility state of the subtree rooted
7738     * at this view changed.
7739     */
7740    void resetSubtreeAccessibilityStateChanged() {
7741        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
7742    }
7743
7744    /**
7745     * Performs the specified accessibility action on the view. For
7746     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
7747     * <p>
7748     * If an {@link AccessibilityDelegate} has been specified via calling
7749     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
7750     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
7751     * is responsible for handling this call.
7752     * </p>
7753     *
7754     * @param action The action to perform.
7755     * @param arguments Optional action arguments.
7756     * @return Whether the action was performed.
7757     */
7758    public boolean performAccessibilityAction(int action, Bundle arguments) {
7759      if (mAccessibilityDelegate != null) {
7760          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
7761      } else {
7762          return performAccessibilityActionInternal(action, arguments);
7763      }
7764    }
7765
7766   /**
7767    * @see #performAccessibilityAction(int, Bundle)
7768    *
7769    * Note: Called from the default {@link AccessibilityDelegate}.
7770    */
7771    boolean performAccessibilityActionInternal(int action, Bundle arguments) {
7772        switch (action) {
7773            case AccessibilityNodeInfo.ACTION_CLICK: {
7774                if (isClickable()) {
7775                    performClick();
7776                    return true;
7777                }
7778            } break;
7779            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
7780                if (isLongClickable()) {
7781                    performLongClick();
7782                    return true;
7783                }
7784            } break;
7785            case AccessibilityNodeInfo.ACTION_FOCUS: {
7786                if (!hasFocus()) {
7787                    // Get out of touch mode since accessibility
7788                    // wants to move focus around.
7789                    getViewRootImpl().ensureTouchMode(false);
7790                    return requestFocus();
7791                }
7792            } break;
7793            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
7794                if (hasFocus()) {
7795                    clearFocus();
7796                    return !isFocused();
7797                }
7798            } break;
7799            case AccessibilityNodeInfo.ACTION_SELECT: {
7800                if (!isSelected()) {
7801                    setSelected(true);
7802                    return isSelected();
7803                }
7804            } break;
7805            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
7806                if (isSelected()) {
7807                    setSelected(false);
7808                    return !isSelected();
7809                }
7810            } break;
7811            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
7812                if (!isAccessibilityFocused()) {
7813                    return requestAccessibilityFocus();
7814                }
7815            } break;
7816            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
7817                if (isAccessibilityFocused()) {
7818                    clearAccessibilityFocus();
7819                    return true;
7820                }
7821            } break;
7822            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
7823                if (arguments != null) {
7824                    final int granularity = arguments.getInt(
7825                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
7826                    final boolean extendSelection = arguments.getBoolean(
7827                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
7828                    return traverseAtGranularity(granularity, true, extendSelection);
7829                }
7830            } break;
7831            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
7832                if (arguments != null) {
7833                    final int granularity = arguments.getInt(
7834                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
7835                    final boolean extendSelection = arguments.getBoolean(
7836                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
7837                    return traverseAtGranularity(granularity, false, extendSelection);
7838                }
7839            } break;
7840            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
7841                CharSequence text = getIterableTextForAccessibility();
7842                if (text == null) {
7843                    return false;
7844                }
7845                final int start = (arguments != null) ? arguments.getInt(
7846                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
7847                final int end = (arguments != null) ? arguments.getInt(
7848                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
7849                // Only cursor position can be specified (selection length == 0)
7850                if ((getAccessibilitySelectionStart() != start
7851                        || getAccessibilitySelectionEnd() != end)
7852                        && (start == end)) {
7853                    setAccessibilitySelection(start, end);
7854                    notifyViewAccessibilityStateChangedIfNeeded(
7855                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7856                    return true;
7857                }
7858            } break;
7859        }
7860        return false;
7861    }
7862
7863    private boolean traverseAtGranularity(int granularity, boolean forward,
7864            boolean extendSelection) {
7865        CharSequence text = getIterableTextForAccessibility();
7866        if (text == null || text.length() == 0) {
7867            return false;
7868        }
7869        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
7870        if (iterator == null) {
7871            return false;
7872        }
7873        int current = getAccessibilitySelectionEnd();
7874        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
7875            current = forward ? 0 : text.length();
7876        }
7877        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
7878        if (range == null) {
7879            return false;
7880        }
7881        final int segmentStart = range[0];
7882        final int segmentEnd = range[1];
7883        int selectionStart;
7884        int selectionEnd;
7885        if (extendSelection && isAccessibilitySelectionExtendable()) {
7886            selectionStart = getAccessibilitySelectionStart();
7887            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
7888                selectionStart = forward ? segmentStart : segmentEnd;
7889            }
7890            selectionEnd = forward ? segmentEnd : segmentStart;
7891        } else {
7892            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
7893        }
7894        setAccessibilitySelection(selectionStart, selectionEnd);
7895        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
7896                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
7897        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
7898        return true;
7899    }
7900
7901    /**
7902     * Gets the text reported for accessibility purposes.
7903     *
7904     * @return The accessibility text.
7905     *
7906     * @hide
7907     */
7908    public CharSequence getIterableTextForAccessibility() {
7909        return getContentDescription();
7910    }
7911
7912    /**
7913     * Gets whether accessibility selection can be extended.
7914     *
7915     * @return If selection is extensible.
7916     *
7917     * @hide
7918     */
7919    public boolean isAccessibilitySelectionExtendable() {
7920        return false;
7921    }
7922
7923    /**
7924     * @hide
7925     */
7926    public int getAccessibilitySelectionStart() {
7927        return mAccessibilityCursorPosition;
7928    }
7929
7930    /**
7931     * @hide
7932     */
7933    public int getAccessibilitySelectionEnd() {
7934        return getAccessibilitySelectionStart();
7935    }
7936
7937    /**
7938     * @hide
7939     */
7940    public void setAccessibilitySelection(int start, int end) {
7941        if (start ==  end && end == mAccessibilityCursorPosition) {
7942            return;
7943        }
7944        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
7945            mAccessibilityCursorPosition = start;
7946        } else {
7947            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
7948        }
7949        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
7950    }
7951
7952    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
7953            int fromIndex, int toIndex) {
7954        if (mParent == null) {
7955            return;
7956        }
7957        AccessibilityEvent event = AccessibilityEvent.obtain(
7958                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
7959        onInitializeAccessibilityEvent(event);
7960        onPopulateAccessibilityEvent(event);
7961        event.setFromIndex(fromIndex);
7962        event.setToIndex(toIndex);
7963        event.setAction(action);
7964        event.setMovementGranularity(granularity);
7965        mParent.requestSendAccessibilityEvent(this, event);
7966    }
7967
7968    /**
7969     * @hide
7970     */
7971    public TextSegmentIterator getIteratorForGranularity(int granularity) {
7972        switch (granularity) {
7973            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
7974                CharSequence text = getIterableTextForAccessibility();
7975                if (text != null && text.length() > 0) {
7976                    CharacterTextSegmentIterator iterator =
7977                        CharacterTextSegmentIterator.getInstance(
7978                                mContext.getResources().getConfiguration().locale);
7979                    iterator.initialize(text.toString());
7980                    return iterator;
7981                }
7982            } break;
7983            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
7984                CharSequence text = getIterableTextForAccessibility();
7985                if (text != null && text.length() > 0) {
7986                    WordTextSegmentIterator iterator =
7987                        WordTextSegmentIterator.getInstance(
7988                                mContext.getResources().getConfiguration().locale);
7989                    iterator.initialize(text.toString());
7990                    return iterator;
7991                }
7992            } break;
7993            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
7994                CharSequence text = getIterableTextForAccessibility();
7995                if (text != null && text.length() > 0) {
7996                    ParagraphTextSegmentIterator iterator =
7997                        ParagraphTextSegmentIterator.getInstance();
7998                    iterator.initialize(text.toString());
7999                    return iterator;
8000                }
8001            } break;
8002        }
8003        return null;
8004    }
8005
8006    /**
8007     * @hide
8008     */
8009    public void dispatchStartTemporaryDetach() {
8010        onStartTemporaryDetach();
8011    }
8012
8013    /**
8014     * This is called when a container is going to temporarily detach a child, with
8015     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
8016     * It will either be followed by {@link #onFinishTemporaryDetach()} or
8017     * {@link #onDetachedFromWindow()} when the container is done.
8018     */
8019    public void onStartTemporaryDetach() {
8020        removeUnsetPressCallback();
8021        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
8022    }
8023
8024    /**
8025     * @hide
8026     */
8027    public void dispatchFinishTemporaryDetach() {
8028        onFinishTemporaryDetach();
8029    }
8030
8031    /**
8032     * Called after {@link #onStartTemporaryDetach} when the container is done
8033     * changing the view.
8034     */
8035    public void onFinishTemporaryDetach() {
8036    }
8037
8038    /**
8039     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
8040     * for this view's window.  Returns null if the view is not currently attached
8041     * to the window.  Normally you will not need to use this directly, but
8042     * just use the standard high-level event callbacks like
8043     * {@link #onKeyDown(int, KeyEvent)}.
8044     */
8045    public KeyEvent.DispatcherState getKeyDispatcherState() {
8046        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
8047    }
8048
8049    /**
8050     * Dispatch a key event before it is processed by any input method
8051     * associated with the view hierarchy.  This can be used to intercept
8052     * key events in special situations before the IME consumes them; a
8053     * typical example would be handling the BACK key to update the application's
8054     * UI instead of allowing the IME to see it and close itself.
8055     *
8056     * @param event The key event to be dispatched.
8057     * @return True if the event was handled, false otherwise.
8058     */
8059    public boolean dispatchKeyEventPreIme(KeyEvent event) {
8060        return onKeyPreIme(event.getKeyCode(), event);
8061    }
8062
8063    /**
8064     * Dispatch a key event to the next view on the focus path. This path runs
8065     * from the top of the view tree down to the currently focused view. If this
8066     * view has focus, it will dispatch to itself. Otherwise it will dispatch
8067     * the next node down the focus path. This method also fires any key
8068     * listeners.
8069     *
8070     * @param event The key event to be dispatched.
8071     * @return True if the event was handled, false otherwise.
8072     */
8073    public boolean dispatchKeyEvent(KeyEvent event) {
8074        if (mInputEventConsistencyVerifier != null) {
8075            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
8076        }
8077
8078        // Give any attached key listener a first crack at the event.
8079        //noinspection SimplifiableIfStatement
8080        ListenerInfo li = mListenerInfo;
8081        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
8082                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
8083            return true;
8084        }
8085
8086        if (event.dispatch(this, mAttachInfo != null
8087                ? mAttachInfo.mKeyDispatchState : null, this)) {
8088            return true;
8089        }
8090
8091        if (mInputEventConsistencyVerifier != null) {
8092            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8093        }
8094        return false;
8095    }
8096
8097    /**
8098     * Dispatches a key shortcut event.
8099     *
8100     * @param event The key event to be dispatched.
8101     * @return True if the event was handled by the view, false otherwise.
8102     */
8103    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
8104        return onKeyShortcut(event.getKeyCode(), event);
8105    }
8106
8107    /**
8108     * Pass the touch screen motion event down to the target view, or this
8109     * view if it is the target.
8110     *
8111     * @param event The motion event to be dispatched.
8112     * @return True if the event was handled by the view, false otherwise.
8113     */
8114    public boolean dispatchTouchEvent(MotionEvent event) {
8115        boolean result = false;
8116
8117        if (mInputEventConsistencyVerifier != null) {
8118            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
8119        }
8120
8121        final int actionMasked = event.getActionMasked();
8122        if (actionMasked == MotionEvent.ACTION_DOWN) {
8123            // Defensive cleanup for new gesture
8124            stopNestedScroll();
8125        }
8126
8127        if (onFilterTouchEventForSecurity(event)) {
8128            //noinspection SimplifiableIfStatement
8129            ListenerInfo li = mListenerInfo;
8130            if (li != null && li.mOnTouchListener != null
8131                    && (mViewFlags & ENABLED_MASK) == ENABLED
8132                    && li.mOnTouchListener.onTouch(this, event)) {
8133                result = true;
8134            }
8135
8136            if (!result && onTouchEvent(event)) {
8137                result = true;
8138            }
8139        }
8140
8141        if (!result && mInputEventConsistencyVerifier != null) {
8142            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8143        }
8144
8145        // Clean up after nested scrolls if this is the end of a gesture;
8146        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
8147        // of the gesture.
8148        if (actionMasked == MotionEvent.ACTION_UP ||
8149                actionMasked == MotionEvent.ACTION_CANCEL ||
8150                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
8151            stopNestedScroll();
8152        }
8153
8154        return result;
8155    }
8156
8157    /**
8158     * Filter the touch event to apply security policies.
8159     *
8160     * @param event The motion event to be filtered.
8161     * @return True if the event should be dispatched, false if the event should be dropped.
8162     *
8163     * @see #getFilterTouchesWhenObscured
8164     */
8165    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
8166        //noinspection RedundantIfStatement
8167        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
8168                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
8169            // Window is obscured, drop this touch.
8170            return false;
8171        }
8172        return true;
8173    }
8174
8175    /**
8176     * Pass a trackball motion event down to the focused view.
8177     *
8178     * @param event The motion event to be dispatched.
8179     * @return True if the event was handled by the view, false otherwise.
8180     */
8181    public boolean dispatchTrackballEvent(MotionEvent event) {
8182        if (mInputEventConsistencyVerifier != null) {
8183            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
8184        }
8185
8186        return onTrackballEvent(event);
8187    }
8188
8189    /**
8190     * Dispatch a generic motion event.
8191     * <p>
8192     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8193     * are delivered to the view under the pointer.  All other generic motion events are
8194     * delivered to the focused view.  Hover events are handled specially and are delivered
8195     * to {@link #onHoverEvent(MotionEvent)}.
8196     * </p>
8197     *
8198     * @param event The motion event to be dispatched.
8199     * @return True if the event was handled by the view, false otherwise.
8200     */
8201    public boolean dispatchGenericMotionEvent(MotionEvent event) {
8202        if (mInputEventConsistencyVerifier != null) {
8203            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
8204        }
8205
8206        final int source = event.getSource();
8207        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
8208            final int action = event.getAction();
8209            if (action == MotionEvent.ACTION_HOVER_ENTER
8210                    || action == MotionEvent.ACTION_HOVER_MOVE
8211                    || action == MotionEvent.ACTION_HOVER_EXIT) {
8212                if (dispatchHoverEvent(event)) {
8213                    return true;
8214                }
8215            } else if (dispatchGenericPointerEvent(event)) {
8216                return true;
8217            }
8218        } else if (dispatchGenericFocusedEvent(event)) {
8219            return true;
8220        }
8221
8222        if (dispatchGenericMotionEventInternal(event)) {
8223            return true;
8224        }
8225
8226        if (mInputEventConsistencyVerifier != null) {
8227            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8228        }
8229        return false;
8230    }
8231
8232    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
8233        //noinspection SimplifiableIfStatement
8234        ListenerInfo li = mListenerInfo;
8235        if (li != null && li.mOnGenericMotionListener != null
8236                && (mViewFlags & ENABLED_MASK) == ENABLED
8237                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
8238            return true;
8239        }
8240
8241        if (onGenericMotionEvent(event)) {
8242            return true;
8243        }
8244
8245        if (mInputEventConsistencyVerifier != null) {
8246            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8247        }
8248        return false;
8249    }
8250
8251    /**
8252     * Dispatch a hover event.
8253     * <p>
8254     * Do not call this method directly.
8255     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8256     * </p>
8257     *
8258     * @param event The motion event to be dispatched.
8259     * @return True if the event was handled by the view, false otherwise.
8260     */
8261    protected boolean dispatchHoverEvent(MotionEvent event) {
8262        ListenerInfo li = mListenerInfo;
8263        //noinspection SimplifiableIfStatement
8264        if (li != null && li.mOnHoverListener != null
8265                && (mViewFlags & ENABLED_MASK) == ENABLED
8266                && li.mOnHoverListener.onHover(this, event)) {
8267            return true;
8268        }
8269
8270        return onHoverEvent(event);
8271    }
8272
8273    /**
8274     * Returns true if the view has a child to which it has recently sent
8275     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
8276     * it does not have a hovered child, then it must be the innermost hovered view.
8277     * @hide
8278     */
8279    protected boolean hasHoveredChild() {
8280        return false;
8281    }
8282
8283    /**
8284     * Dispatch a generic motion event to the view under the first pointer.
8285     * <p>
8286     * Do not call this method directly.
8287     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8288     * </p>
8289     *
8290     * @param event The motion event to be dispatched.
8291     * @return True if the event was handled by the view, false otherwise.
8292     */
8293    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
8294        return false;
8295    }
8296
8297    /**
8298     * Dispatch a generic motion event to the currently focused view.
8299     * <p>
8300     * Do not call this method directly.
8301     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8302     * </p>
8303     *
8304     * @param event The motion event to be dispatched.
8305     * @return True if the event was handled by the view, false otherwise.
8306     */
8307    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
8308        return false;
8309    }
8310
8311    /**
8312     * Dispatch a pointer event.
8313     * <p>
8314     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
8315     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
8316     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
8317     * and should not be expected to handle other pointing device features.
8318     * </p>
8319     *
8320     * @param event The motion event to be dispatched.
8321     * @return True if the event was handled by the view, false otherwise.
8322     * @hide
8323     */
8324    public final boolean dispatchPointerEvent(MotionEvent event) {
8325        if (event.isTouchEvent()) {
8326            return dispatchTouchEvent(event);
8327        } else {
8328            return dispatchGenericMotionEvent(event);
8329        }
8330    }
8331
8332    /**
8333     * Called when the window containing this view gains or loses window focus.
8334     * ViewGroups should override to route to their children.
8335     *
8336     * @param hasFocus True if the window containing this view now has focus,
8337     *        false otherwise.
8338     */
8339    public void dispatchWindowFocusChanged(boolean hasFocus) {
8340        onWindowFocusChanged(hasFocus);
8341    }
8342
8343    /**
8344     * Called when the window containing this view gains or loses focus.  Note
8345     * that this is separate from view focus: to receive key events, both
8346     * your view and its window must have focus.  If a window is displayed
8347     * on top of yours that takes input focus, then your own window will lose
8348     * focus but the view focus will remain unchanged.
8349     *
8350     * @param hasWindowFocus True if the window containing this view now has
8351     *        focus, false otherwise.
8352     */
8353    public void onWindowFocusChanged(boolean hasWindowFocus) {
8354        InputMethodManager imm = InputMethodManager.peekInstance();
8355        if (!hasWindowFocus) {
8356            if (isPressed()) {
8357                setPressed(false);
8358            }
8359            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8360                imm.focusOut(this);
8361            }
8362            removeLongPressCallback();
8363            removeTapCallback();
8364            onFocusLost();
8365        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8366            imm.focusIn(this);
8367        }
8368        refreshDrawableState();
8369    }
8370
8371    /**
8372     * Returns true if this view is in a window that currently has window focus.
8373     * Note that this is not the same as the view itself having focus.
8374     *
8375     * @return True if this view is in a window that currently has window focus.
8376     */
8377    public boolean hasWindowFocus() {
8378        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
8379    }
8380
8381    /**
8382     * Dispatch a view visibility change down the view hierarchy.
8383     * ViewGroups should override to route to their children.
8384     * @param changedView The view whose visibility changed. Could be 'this' or
8385     * an ancestor view.
8386     * @param visibility The new visibility of changedView: {@link #VISIBLE},
8387     * {@link #INVISIBLE} or {@link #GONE}.
8388     */
8389    protected void dispatchVisibilityChanged(@NonNull View changedView,
8390            @Visibility int visibility) {
8391        onVisibilityChanged(changedView, visibility);
8392    }
8393
8394    /**
8395     * Called when the visibility of the view or an ancestor of the view is changed.
8396     * @param changedView The view whose visibility changed. Could be 'this' or
8397     * an ancestor view.
8398     * @param visibility The new visibility of changedView: {@link #VISIBLE},
8399     * {@link #INVISIBLE} or {@link #GONE}.
8400     */
8401    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
8402        if (visibility == VISIBLE) {
8403            if (mAttachInfo != null) {
8404                initialAwakenScrollBars();
8405            } else {
8406                mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
8407            }
8408        }
8409    }
8410
8411    /**
8412     * Dispatch a hint about whether this view is displayed. For instance, when
8413     * a View moves out of the screen, it might receives a display hint indicating
8414     * the view is not displayed. Applications should not <em>rely</em> on this hint
8415     * as there is no guarantee that they will receive one.
8416     *
8417     * @param hint A hint about whether or not this view is displayed:
8418     * {@link #VISIBLE} or {@link #INVISIBLE}.
8419     */
8420    public void dispatchDisplayHint(@Visibility int hint) {
8421        onDisplayHint(hint);
8422    }
8423
8424    /**
8425     * Gives this view a hint about whether is displayed or not. For instance, when
8426     * a View moves out of the screen, it might receives a display hint indicating
8427     * the view is not displayed. Applications should not <em>rely</em> on this hint
8428     * as there is no guarantee that they will receive one.
8429     *
8430     * @param hint A hint about whether or not this view is displayed:
8431     * {@link #VISIBLE} or {@link #INVISIBLE}.
8432     */
8433    protected void onDisplayHint(@Visibility int hint) {
8434    }
8435
8436    /**
8437     * Dispatch a window visibility change down the view hierarchy.
8438     * ViewGroups should override to route to their children.
8439     *
8440     * @param visibility The new visibility of the window.
8441     *
8442     * @see #onWindowVisibilityChanged(int)
8443     */
8444    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
8445        onWindowVisibilityChanged(visibility);
8446    }
8447
8448    /**
8449     * Called when the window containing has change its visibility
8450     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
8451     * that this tells you whether or not your window is being made visible
8452     * to the window manager; this does <em>not</em> tell you whether or not
8453     * your window is obscured by other windows on the screen, even if it
8454     * is itself visible.
8455     *
8456     * @param visibility The new visibility of the window.
8457     */
8458    protected void onWindowVisibilityChanged(@Visibility int visibility) {
8459        if (visibility == VISIBLE) {
8460            initialAwakenScrollBars();
8461        }
8462    }
8463
8464    /**
8465     * Returns the current visibility of the window this view is attached to
8466     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
8467     *
8468     * @return Returns the current visibility of the view's window.
8469     */
8470    @Visibility
8471    public int getWindowVisibility() {
8472        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
8473    }
8474
8475    /**
8476     * Retrieve the overall visible display size in which the window this view is
8477     * attached to has been positioned in.  This takes into account screen
8478     * decorations above the window, for both cases where the window itself
8479     * is being position inside of them or the window is being placed under
8480     * then and covered insets are used for the window to position its content
8481     * inside.  In effect, this tells you the available area where content can
8482     * be placed and remain visible to users.
8483     *
8484     * <p>This function requires an IPC back to the window manager to retrieve
8485     * the requested information, so should not be used in performance critical
8486     * code like drawing.
8487     *
8488     * @param outRect Filled in with the visible display frame.  If the view
8489     * is not attached to a window, this is simply the raw display size.
8490     */
8491    public void getWindowVisibleDisplayFrame(Rect outRect) {
8492        if (mAttachInfo != null) {
8493            try {
8494                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
8495            } catch (RemoteException e) {
8496                return;
8497            }
8498            // XXX This is really broken, and probably all needs to be done
8499            // in the window manager, and we need to know more about whether
8500            // we want the area behind or in front of the IME.
8501            final Rect insets = mAttachInfo.mVisibleInsets;
8502            outRect.left += insets.left;
8503            outRect.top += insets.top;
8504            outRect.right -= insets.right;
8505            outRect.bottom -= insets.bottom;
8506            return;
8507        }
8508        // The view is not attached to a display so we don't have a context.
8509        // Make a best guess about the display size.
8510        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
8511        d.getRectSize(outRect);
8512    }
8513
8514    /**
8515     * Dispatch a notification about a resource configuration change down
8516     * the view hierarchy.
8517     * ViewGroups should override to route to their children.
8518     *
8519     * @param newConfig The new resource configuration.
8520     *
8521     * @see #onConfigurationChanged(android.content.res.Configuration)
8522     */
8523    public void dispatchConfigurationChanged(Configuration newConfig) {
8524        onConfigurationChanged(newConfig);
8525    }
8526
8527    /**
8528     * Called when the current configuration of the resources being used
8529     * by the application have changed.  You can use this to decide when
8530     * to reload resources that can changed based on orientation and other
8531     * configuration characterstics.  You only need to use this if you are
8532     * not relying on the normal {@link android.app.Activity} mechanism of
8533     * recreating the activity instance upon a configuration change.
8534     *
8535     * @param newConfig The new resource configuration.
8536     */
8537    protected void onConfigurationChanged(Configuration newConfig) {
8538    }
8539
8540    /**
8541     * Private function to aggregate all per-view attributes in to the view
8542     * root.
8543     */
8544    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8545        performCollectViewAttributes(attachInfo, visibility);
8546    }
8547
8548    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8549        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
8550            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
8551                attachInfo.mKeepScreenOn = true;
8552            }
8553            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
8554            ListenerInfo li = mListenerInfo;
8555            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
8556                attachInfo.mHasSystemUiListeners = true;
8557            }
8558        }
8559    }
8560
8561    void needGlobalAttributesUpdate(boolean force) {
8562        final AttachInfo ai = mAttachInfo;
8563        if (ai != null && !ai.mRecomputeGlobalAttributes) {
8564            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
8565                    || ai.mHasSystemUiListeners) {
8566                ai.mRecomputeGlobalAttributes = true;
8567            }
8568        }
8569    }
8570
8571    /**
8572     * Returns whether the device is currently in touch mode.  Touch mode is entered
8573     * once the user begins interacting with the device by touch, and affects various
8574     * things like whether focus is always visible to the user.
8575     *
8576     * @return Whether the device is in touch mode.
8577     */
8578    @ViewDebug.ExportedProperty
8579    public boolean isInTouchMode() {
8580        if (mAttachInfo != null) {
8581            return mAttachInfo.mInTouchMode;
8582        } else {
8583            return ViewRootImpl.isInTouchMode();
8584        }
8585    }
8586
8587    /**
8588     * Returns the context the view is running in, through which it can
8589     * access the current theme, resources, etc.
8590     *
8591     * @return The view's Context.
8592     */
8593    @ViewDebug.CapturedViewProperty
8594    public final Context getContext() {
8595        return mContext;
8596    }
8597
8598    /**
8599     * Handle a key event before it is processed by any input method
8600     * associated with the view hierarchy.  This can be used to intercept
8601     * key events in special situations before the IME consumes them; a
8602     * typical example would be handling the BACK key to update the application's
8603     * UI instead of allowing the IME to see it and close itself.
8604     *
8605     * @param keyCode The value in event.getKeyCode().
8606     * @param event Description of the key event.
8607     * @return If you handled the event, return true. If you want to allow the
8608     *         event to be handled by the next receiver, return false.
8609     */
8610    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
8611        return false;
8612    }
8613
8614    /**
8615     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
8616     * KeyEvent.Callback.onKeyDown()}: perform press of the view
8617     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
8618     * is released, if the view is enabled and clickable.
8619     *
8620     * <p>Key presses in software keyboards will generally NOT trigger this listener,
8621     * although some may elect to do so in some situations. Do not rely on this to
8622     * catch software key presses.
8623     *
8624     * @param keyCode A key code that represents the button pressed, from
8625     *                {@link android.view.KeyEvent}.
8626     * @param event   The KeyEvent object that defines the button action.
8627     */
8628    public boolean onKeyDown(int keyCode, KeyEvent event) {
8629        boolean result = false;
8630
8631        if (KeyEvent.isConfirmKey(keyCode)) {
8632            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8633                return true;
8634            }
8635            // Long clickable items don't necessarily have to be clickable
8636            if (((mViewFlags & CLICKABLE) == CLICKABLE ||
8637                    (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
8638                    (event.getRepeatCount() == 0)) {
8639                setPressed(true);
8640                checkForLongClick(0);
8641                return true;
8642            }
8643        }
8644        return result;
8645    }
8646
8647    /**
8648     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
8649     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
8650     * the event).
8651     * <p>Key presses in software keyboards will generally NOT trigger this listener,
8652     * although some may elect to do so in some situations. Do not rely on this to
8653     * catch software key presses.
8654     */
8655    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
8656        return false;
8657    }
8658
8659    /**
8660     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
8661     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
8662     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
8663     * {@link KeyEvent#KEYCODE_ENTER} is released.
8664     * <p>Key presses in software keyboards will generally NOT trigger this listener,
8665     * although some may elect to do so in some situations. Do not rely on this to
8666     * catch software key presses.
8667     *
8668     * @param keyCode A key code that represents the button pressed, from
8669     *                {@link android.view.KeyEvent}.
8670     * @param event   The KeyEvent object that defines the button action.
8671     */
8672    public boolean onKeyUp(int keyCode, KeyEvent event) {
8673        if (KeyEvent.isConfirmKey(keyCode)) {
8674            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8675                return true;
8676            }
8677            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
8678                setPressed(false);
8679
8680                if (!mHasPerformedLongPress) {
8681                    // This is a tap, so remove the longpress check
8682                    removeLongPressCallback();
8683                    return performClick();
8684                }
8685            }
8686        }
8687        return false;
8688    }
8689
8690    /**
8691     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
8692     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
8693     * the event).
8694     * <p>Key presses in software keyboards will generally NOT trigger this listener,
8695     * although some may elect to do so in some situations. Do not rely on this to
8696     * catch software key presses.
8697     *
8698     * @param keyCode     A key code that represents the button pressed, from
8699     *                    {@link android.view.KeyEvent}.
8700     * @param repeatCount The number of times the action was made.
8701     * @param event       The KeyEvent object that defines the button action.
8702     */
8703    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
8704        return false;
8705    }
8706
8707    /**
8708     * Called on the focused view when a key shortcut event is not handled.
8709     * Override this method to implement local key shortcuts for the View.
8710     * Key shortcuts can also be implemented by setting the
8711     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
8712     *
8713     * @param keyCode The value in event.getKeyCode().
8714     * @param event Description of the key event.
8715     * @return If you handled the event, return true. If you want to allow the
8716     *         event to be handled by the next receiver, return false.
8717     */
8718    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
8719        return false;
8720    }
8721
8722    /**
8723     * Check whether the called view is a text editor, in which case it
8724     * would make sense to automatically display a soft input window for
8725     * it.  Subclasses should override this if they implement
8726     * {@link #onCreateInputConnection(EditorInfo)} to return true if
8727     * a call on that method would return a non-null InputConnection, and
8728     * they are really a first-class editor that the user would normally
8729     * start typing on when the go into a window containing your view.
8730     *
8731     * <p>The default implementation always returns false.  This does
8732     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
8733     * will not be called or the user can not otherwise perform edits on your
8734     * view; it is just a hint to the system that this is not the primary
8735     * purpose of this view.
8736     *
8737     * @return Returns true if this view is a text editor, else false.
8738     */
8739    public boolean onCheckIsTextEditor() {
8740        return false;
8741    }
8742
8743    /**
8744     * Create a new InputConnection for an InputMethod to interact
8745     * with the view.  The default implementation returns null, since it doesn't
8746     * support input methods.  You can override this to implement such support.
8747     * This is only needed for views that take focus and text input.
8748     *
8749     * <p>When implementing this, you probably also want to implement
8750     * {@link #onCheckIsTextEditor()} to indicate you will return a
8751     * non-null InputConnection.</p>
8752     *
8753     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
8754     * object correctly and in its entirety, so that the connected IME can rely
8755     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
8756     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
8757     * must be filled in with the correct cursor position for IMEs to work correctly
8758     * with your application.</p>
8759     *
8760     * @param outAttrs Fill in with attribute information about the connection.
8761     */
8762    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
8763        return null;
8764    }
8765
8766    /**
8767     * Called by the {@link android.view.inputmethod.InputMethodManager}
8768     * when a view who is not the current
8769     * input connection target is trying to make a call on the manager.  The
8770     * default implementation returns false; you can override this to return
8771     * true for certain views if you are performing InputConnection proxying
8772     * to them.
8773     * @param view The View that is making the InputMethodManager call.
8774     * @return Return true to allow the call, false to reject.
8775     */
8776    public boolean checkInputConnectionProxy(View view) {
8777        return false;
8778    }
8779
8780    /**
8781     * Show the context menu for this view. It is not safe to hold on to the
8782     * menu after returning from this method.
8783     *
8784     * You should normally not overload this method. Overload
8785     * {@link #onCreateContextMenu(ContextMenu)} or define an
8786     * {@link OnCreateContextMenuListener} to add items to the context menu.
8787     *
8788     * @param menu The context menu to populate
8789     */
8790    public void createContextMenu(ContextMenu menu) {
8791        ContextMenuInfo menuInfo = getContextMenuInfo();
8792
8793        // Sets the current menu info so all items added to menu will have
8794        // my extra info set.
8795        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
8796
8797        onCreateContextMenu(menu);
8798        ListenerInfo li = mListenerInfo;
8799        if (li != null && li.mOnCreateContextMenuListener != null) {
8800            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
8801        }
8802
8803        // Clear the extra information so subsequent items that aren't mine don't
8804        // have my extra info.
8805        ((MenuBuilder)menu).setCurrentMenuInfo(null);
8806
8807        if (mParent != null) {
8808            mParent.createContextMenu(menu);
8809        }
8810    }
8811
8812    /**
8813     * Views should implement this if they have extra information to associate
8814     * with the context menu. The return result is supplied as a parameter to
8815     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
8816     * callback.
8817     *
8818     * @return Extra information about the item for which the context menu
8819     *         should be shown. This information will vary across different
8820     *         subclasses of View.
8821     */
8822    protected ContextMenuInfo getContextMenuInfo() {
8823        return null;
8824    }
8825
8826    /**
8827     * Views should implement this if the view itself is going to add items to
8828     * the context menu.
8829     *
8830     * @param menu the context menu to populate
8831     */
8832    protected void onCreateContextMenu(ContextMenu menu) {
8833    }
8834
8835    /**
8836     * Implement this method to handle trackball motion events.  The
8837     * <em>relative</em> movement of the trackball since the last event
8838     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
8839     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
8840     * that a movement of 1 corresponds to the user pressing one DPAD key (so
8841     * they will often be fractional values, representing the more fine-grained
8842     * movement information available from a trackball).
8843     *
8844     * @param event The motion event.
8845     * @return True if the event was handled, false otherwise.
8846     */
8847    public boolean onTrackballEvent(MotionEvent event) {
8848        return false;
8849    }
8850
8851    /**
8852     * Implement this method to handle generic motion events.
8853     * <p>
8854     * Generic motion events describe joystick movements, mouse hovers, track pad
8855     * touches, scroll wheel movements and other input events.  The
8856     * {@link MotionEvent#getSource() source} of the motion event specifies
8857     * the class of input that was received.  Implementations of this method
8858     * must examine the bits in the source before processing the event.
8859     * The following code example shows how this is done.
8860     * </p><p>
8861     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8862     * are delivered to the view under the pointer.  All other generic motion events are
8863     * delivered to the focused view.
8864     * </p>
8865     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
8866     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
8867     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
8868     *             // process the joystick movement...
8869     *             return true;
8870     *         }
8871     *     }
8872     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
8873     *         switch (event.getAction()) {
8874     *             case MotionEvent.ACTION_HOVER_MOVE:
8875     *                 // process the mouse hover movement...
8876     *                 return true;
8877     *             case MotionEvent.ACTION_SCROLL:
8878     *                 // process the scroll wheel movement...
8879     *                 return true;
8880     *         }
8881     *     }
8882     *     return super.onGenericMotionEvent(event);
8883     * }</pre>
8884     *
8885     * @param event The generic motion event being processed.
8886     * @return True if the event was handled, false otherwise.
8887     */
8888    public boolean onGenericMotionEvent(MotionEvent event) {
8889        return false;
8890    }
8891
8892    /**
8893     * Implement this method to handle hover events.
8894     * <p>
8895     * This method is called whenever a pointer is hovering into, over, or out of the
8896     * bounds of a view and the view is not currently being touched.
8897     * Hover events are represented as pointer events with action
8898     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
8899     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
8900     * </p>
8901     * <ul>
8902     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
8903     * when the pointer enters the bounds of the view.</li>
8904     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
8905     * when the pointer has already entered the bounds of the view and has moved.</li>
8906     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
8907     * when the pointer has exited the bounds of the view or when the pointer is
8908     * about to go down due to a button click, tap, or similar user action that
8909     * causes the view to be touched.</li>
8910     * </ul>
8911     * <p>
8912     * The view should implement this method to return true to indicate that it is
8913     * handling the hover event, such as by changing its drawable state.
8914     * </p><p>
8915     * The default implementation calls {@link #setHovered} to update the hovered state
8916     * of the view when a hover enter or hover exit event is received, if the view
8917     * is enabled and is clickable.  The default implementation also sends hover
8918     * accessibility events.
8919     * </p>
8920     *
8921     * @param event The motion event that describes the hover.
8922     * @return True if the view handled the hover event.
8923     *
8924     * @see #isHovered
8925     * @see #setHovered
8926     * @see #onHoverChanged
8927     */
8928    public boolean onHoverEvent(MotionEvent event) {
8929        // The root view may receive hover (or touch) events that are outside the bounds of
8930        // the window.  This code ensures that we only send accessibility events for
8931        // hovers that are actually within the bounds of the root view.
8932        final int action = event.getActionMasked();
8933        if (!mSendingHoverAccessibilityEvents) {
8934            if ((action == MotionEvent.ACTION_HOVER_ENTER
8935                    || action == MotionEvent.ACTION_HOVER_MOVE)
8936                    && !hasHoveredChild()
8937                    && pointInView(event.getX(), event.getY())) {
8938                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
8939                mSendingHoverAccessibilityEvents = true;
8940            }
8941        } else {
8942            if (action == MotionEvent.ACTION_HOVER_EXIT
8943                    || (action == MotionEvent.ACTION_MOVE
8944                            && !pointInView(event.getX(), event.getY()))) {
8945                mSendingHoverAccessibilityEvents = false;
8946                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
8947            }
8948        }
8949
8950        if (isHoverable()) {
8951            switch (action) {
8952                case MotionEvent.ACTION_HOVER_ENTER:
8953                    setHovered(true);
8954                    break;
8955                case MotionEvent.ACTION_HOVER_EXIT:
8956                    setHovered(false);
8957                    break;
8958            }
8959
8960            // Dispatch the event to onGenericMotionEvent before returning true.
8961            // This is to provide compatibility with existing applications that
8962            // handled HOVER_MOVE events in onGenericMotionEvent and that would
8963            // break because of the new default handling for hoverable views
8964            // in onHoverEvent.
8965            // Note that onGenericMotionEvent will be called by default when
8966            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
8967            dispatchGenericMotionEventInternal(event);
8968            // The event was already handled by calling setHovered(), so always
8969            // return true.
8970            return true;
8971        }
8972
8973        return false;
8974    }
8975
8976    /**
8977     * Returns true if the view should handle {@link #onHoverEvent}
8978     * by calling {@link #setHovered} to change its hovered state.
8979     *
8980     * @return True if the view is hoverable.
8981     */
8982    private boolean isHoverable() {
8983        final int viewFlags = mViewFlags;
8984        if ((viewFlags & ENABLED_MASK) == DISABLED) {
8985            return false;
8986        }
8987
8988        return (viewFlags & CLICKABLE) == CLICKABLE
8989                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8990    }
8991
8992    /**
8993     * Returns true if the view is currently hovered.
8994     *
8995     * @return True if the view is currently hovered.
8996     *
8997     * @see #setHovered
8998     * @see #onHoverChanged
8999     */
9000    @ViewDebug.ExportedProperty
9001    public boolean isHovered() {
9002        return (mPrivateFlags & PFLAG_HOVERED) != 0;
9003    }
9004
9005    /**
9006     * Sets whether the view is currently hovered.
9007     * <p>
9008     * Calling this method also changes the drawable state of the view.  This
9009     * enables the view to react to hover by using different drawable resources
9010     * to change its appearance.
9011     * </p><p>
9012     * The {@link #onHoverChanged} method is called when the hovered state changes.
9013     * </p>
9014     *
9015     * @param hovered True if the view is hovered.
9016     *
9017     * @see #isHovered
9018     * @see #onHoverChanged
9019     */
9020    public void setHovered(boolean hovered) {
9021        if (hovered) {
9022            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
9023                mPrivateFlags |= PFLAG_HOVERED;
9024                refreshDrawableState();
9025                onHoverChanged(true);
9026            }
9027        } else {
9028            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
9029                mPrivateFlags &= ~PFLAG_HOVERED;
9030                refreshDrawableState();
9031                onHoverChanged(false);
9032            }
9033        }
9034    }
9035
9036    /**
9037     * Implement this method to handle hover state changes.
9038     * <p>
9039     * This method is called whenever the hover state changes as a result of a
9040     * call to {@link #setHovered}.
9041     * </p>
9042     *
9043     * @param hovered The current hover state, as returned by {@link #isHovered}.
9044     *
9045     * @see #isHovered
9046     * @see #setHovered
9047     */
9048    public void onHoverChanged(boolean hovered) {
9049    }
9050
9051    /**
9052     * Implement this method to handle touch screen motion events.
9053     * <p>
9054     * If this method is used to detect click actions, it is recommended that
9055     * the actions be performed by implementing and calling
9056     * {@link #performClick()}. This will ensure consistent system behavior,
9057     * including:
9058     * <ul>
9059     * <li>obeying click sound preferences
9060     * <li>dispatching OnClickListener calls
9061     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
9062     * accessibility features are enabled
9063     * </ul>
9064     *
9065     * @param event The motion event.
9066     * @return True if the event was handled, false otherwise.
9067     */
9068    public boolean onTouchEvent(MotionEvent event) {
9069        final float x = event.getX();
9070        final float y = event.getY();
9071        final int viewFlags = mViewFlags;
9072
9073        if ((viewFlags & ENABLED_MASK) == DISABLED) {
9074            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
9075                setPressed(false);
9076            }
9077            // A disabled view that is clickable still consumes the touch
9078            // events, it just doesn't respond to them.
9079            return (((viewFlags & CLICKABLE) == CLICKABLE ||
9080                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
9081        }
9082
9083        if (mTouchDelegate != null) {
9084            if (mTouchDelegate.onTouchEvent(event)) {
9085                return true;
9086            }
9087        }
9088
9089        if (((viewFlags & CLICKABLE) == CLICKABLE ||
9090                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
9091            switch (event.getAction()) {
9092                case MotionEvent.ACTION_UP:
9093                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
9094                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
9095                        // take focus if we don't have it already and we should in
9096                        // touch mode.
9097                        boolean focusTaken = false;
9098                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
9099                            focusTaken = requestFocus();
9100                        }
9101
9102                        if (prepressed) {
9103                            // The button is being released before we actually
9104                            // showed it as pressed.  Make it show the pressed
9105                            // state now (before scheduling the click) to ensure
9106                            // the user sees it.
9107                            setPressed(true, x, y);
9108                       }
9109
9110                        if (!mHasPerformedLongPress) {
9111                            // This is a tap, so remove the longpress check
9112                            removeLongPressCallback();
9113
9114                            // Only perform take click actions if we were in the pressed state
9115                            if (!focusTaken) {
9116                                // Use a Runnable and post this rather than calling
9117                                // performClick directly. This lets other visual state
9118                                // of the view update before click actions start.
9119                                if (mPerformClick == null) {
9120                                    mPerformClick = new PerformClick();
9121                                }
9122                                if (!post(mPerformClick)) {
9123                                    performClick();
9124                                }
9125                            }
9126                        }
9127
9128                        if (mUnsetPressedState == null) {
9129                            mUnsetPressedState = new UnsetPressedState();
9130                        }
9131
9132                        if (prepressed) {
9133                            postDelayed(mUnsetPressedState,
9134                                    ViewConfiguration.getPressedStateDuration());
9135                        } else if (!post(mUnsetPressedState)) {
9136                            // If the post failed, unpress right now
9137                            mUnsetPressedState.run();
9138                        }
9139
9140                        removeTapCallback();
9141                    }
9142                    break;
9143
9144                case MotionEvent.ACTION_DOWN:
9145                    mHasPerformedLongPress = false;
9146
9147                    if (performButtonActionOnTouchDown(event)) {
9148                        break;
9149                    }
9150
9151                    // Walk up the hierarchy to determine if we're inside a scrolling container.
9152                    boolean isInScrollingContainer = isInScrollingContainer();
9153
9154                    // For views inside a scrolling container, delay the pressed feedback for
9155                    // a short period in case this is a scroll.
9156                    if (isInScrollingContainer) {
9157                        mPrivateFlags |= PFLAG_PREPRESSED;
9158                        if (mPendingCheckForTap == null) {
9159                            mPendingCheckForTap = new CheckForTap();
9160                        }
9161                        mPendingCheckForTap.x = event.getX();
9162                        mPendingCheckForTap.y = event.getY();
9163                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
9164                    } else {
9165                        // Not inside a scrolling container, so show the feedback right away
9166                        setPressed(true, x, y);
9167                        checkForLongClick(0);
9168                    }
9169                    break;
9170
9171                case MotionEvent.ACTION_CANCEL:
9172                    setPressed(false);
9173                    removeTapCallback();
9174                    removeLongPressCallback();
9175                    break;
9176
9177                case MotionEvent.ACTION_MOVE:
9178                    drawableHotspotChanged(x, y);
9179
9180                    // Be lenient about moving outside of buttons
9181                    if (!pointInView(x, y, mTouchSlop)) {
9182                        // Outside button
9183                        removeTapCallback();
9184                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
9185                            // Remove any future long press/tap checks
9186                            removeLongPressCallback();
9187
9188                            setPressed(false);
9189                        }
9190                    }
9191                    break;
9192            }
9193
9194            return true;
9195        }
9196
9197        return false;
9198    }
9199
9200    /**
9201     * @hide
9202     */
9203    public boolean isInScrollingContainer() {
9204        ViewParent p = getParent();
9205        while (p != null && p instanceof ViewGroup) {
9206            if (((ViewGroup) p).shouldDelayChildPressedState()) {
9207                return true;
9208            }
9209            p = p.getParent();
9210        }
9211        return false;
9212    }
9213
9214    /**
9215     * Remove the longpress detection timer.
9216     */
9217    private void removeLongPressCallback() {
9218        if (mPendingCheckForLongPress != null) {
9219          removeCallbacks(mPendingCheckForLongPress);
9220        }
9221    }
9222
9223    /**
9224     * Remove the pending click action
9225     */
9226    private void removePerformClickCallback() {
9227        if (mPerformClick != null) {
9228            removeCallbacks(mPerformClick);
9229        }
9230    }
9231
9232    /**
9233     * Remove the prepress detection timer.
9234     */
9235    private void removeUnsetPressCallback() {
9236        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
9237            setPressed(false);
9238            removeCallbacks(mUnsetPressedState);
9239        }
9240    }
9241
9242    /**
9243     * Remove the tap detection timer.
9244     */
9245    private void removeTapCallback() {
9246        if (mPendingCheckForTap != null) {
9247            mPrivateFlags &= ~PFLAG_PREPRESSED;
9248            removeCallbacks(mPendingCheckForTap);
9249        }
9250    }
9251
9252    /**
9253     * Cancels a pending long press.  Your subclass can use this if you
9254     * want the context menu to come up if the user presses and holds
9255     * at the same place, but you don't want it to come up if they press
9256     * and then move around enough to cause scrolling.
9257     */
9258    public void cancelLongPress() {
9259        removeLongPressCallback();
9260
9261        /*
9262         * The prepressed state handled by the tap callback is a display
9263         * construct, but the tap callback will post a long press callback
9264         * less its own timeout. Remove it here.
9265         */
9266        removeTapCallback();
9267    }
9268
9269    /**
9270     * Remove the pending callback for sending a
9271     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
9272     */
9273    private void removeSendViewScrolledAccessibilityEventCallback() {
9274        if (mSendViewScrolledAccessibilityEvent != null) {
9275            removeCallbacks(mSendViewScrolledAccessibilityEvent);
9276            mSendViewScrolledAccessibilityEvent.mIsPending = false;
9277        }
9278    }
9279
9280    /**
9281     * Sets the TouchDelegate for this View.
9282     */
9283    public void setTouchDelegate(TouchDelegate delegate) {
9284        mTouchDelegate = delegate;
9285    }
9286
9287    /**
9288     * Gets the TouchDelegate for this View.
9289     */
9290    public TouchDelegate getTouchDelegate() {
9291        return mTouchDelegate;
9292    }
9293
9294    /**
9295     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
9296     *
9297     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
9298     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
9299     * available. This method should only be called for touch events.
9300     *
9301     * <p class="note">This api is not intended for most applications. Buffered dispatch
9302     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
9303     * streams will not improve your input latency. Side effects include: increased latency,
9304     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
9305     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
9306     * you.</p>
9307     */
9308    public final void requestUnbufferedDispatch(MotionEvent event) {
9309        final int action = event.getAction();
9310        if (mAttachInfo == null
9311                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
9312                || !event.isTouchEvent()) {
9313            return;
9314        }
9315        mAttachInfo.mUnbufferedDispatchRequested = true;
9316    }
9317
9318    /**
9319     * Set flags controlling behavior of this view.
9320     *
9321     * @param flags Constant indicating the value which should be set
9322     * @param mask Constant indicating the bit range that should be changed
9323     */
9324    void setFlags(int flags, int mask) {
9325        final boolean accessibilityEnabled =
9326                AccessibilityManager.getInstance(mContext).isEnabled();
9327        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
9328
9329        int old = mViewFlags;
9330        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
9331
9332        int changed = mViewFlags ^ old;
9333        if (changed == 0) {
9334            return;
9335        }
9336        int privateFlags = mPrivateFlags;
9337
9338        /* Check if the FOCUSABLE bit has changed */
9339        if (((changed & FOCUSABLE_MASK) != 0) &&
9340                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
9341            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
9342                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
9343                /* Give up focus if we are no longer focusable */
9344                clearFocus();
9345            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
9346                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
9347                /*
9348                 * Tell the view system that we are now available to take focus
9349                 * if no one else already has it.
9350                 */
9351                if (mParent != null) mParent.focusableViewAvailable(this);
9352            }
9353        }
9354
9355        final int newVisibility = flags & VISIBILITY_MASK;
9356        if (newVisibility == VISIBLE) {
9357            if ((changed & VISIBILITY_MASK) != 0) {
9358                /*
9359                 * If this view is becoming visible, invalidate it in case it changed while
9360                 * it was not visible. Marking it drawn ensures that the invalidation will
9361                 * go through.
9362                 */
9363                mPrivateFlags |= PFLAG_DRAWN;
9364                invalidate(true);
9365
9366                needGlobalAttributesUpdate(true);
9367
9368                // a view becoming visible is worth notifying the parent
9369                // about in case nothing has focus.  even if this specific view
9370                // isn't focusable, it may contain something that is, so let
9371                // the root view try to give this focus if nothing else does.
9372                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
9373                    mParent.focusableViewAvailable(this);
9374                }
9375            }
9376        }
9377
9378        /* Check if the GONE bit has changed */
9379        if ((changed & GONE) != 0) {
9380            needGlobalAttributesUpdate(false);
9381            requestLayout();
9382
9383            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
9384                if (hasFocus()) clearFocus();
9385                clearAccessibilityFocus();
9386                destroyDrawingCache();
9387                if (mParent instanceof View) {
9388                    // GONE views noop invalidation, so invalidate the parent
9389                    ((View) mParent).invalidate(true);
9390                }
9391                // Mark the view drawn to ensure that it gets invalidated properly the next
9392                // time it is visible and gets invalidated
9393                mPrivateFlags |= PFLAG_DRAWN;
9394            }
9395            if (mAttachInfo != null) {
9396                mAttachInfo.mViewVisibilityChanged = true;
9397            }
9398        }
9399
9400        /* Check if the VISIBLE bit has changed */
9401        if ((changed & INVISIBLE) != 0) {
9402            needGlobalAttributesUpdate(false);
9403            /*
9404             * If this view is becoming invisible, set the DRAWN flag so that
9405             * the next invalidate() will not be skipped.
9406             */
9407            mPrivateFlags |= PFLAG_DRAWN;
9408
9409            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
9410                // root view becoming invisible shouldn't clear focus and accessibility focus
9411                if (getRootView() != this) {
9412                    if (hasFocus()) clearFocus();
9413                    clearAccessibilityFocus();
9414                }
9415            }
9416            if (mAttachInfo != null) {
9417                mAttachInfo.mViewVisibilityChanged = true;
9418            }
9419        }
9420
9421        if ((changed & VISIBILITY_MASK) != 0) {
9422            // If the view is invisible, cleanup its display list to free up resources
9423            if (newVisibility != VISIBLE && mAttachInfo != null) {
9424                cleanupDraw();
9425            }
9426
9427            if (mParent instanceof ViewGroup) {
9428                ((ViewGroup) mParent).onChildVisibilityChanged(this,
9429                        (changed & VISIBILITY_MASK), newVisibility);
9430                ((View) mParent).invalidate(true);
9431            } else if (mParent != null) {
9432                mParent.invalidateChild(this, null);
9433            }
9434            dispatchVisibilityChanged(this, newVisibility);
9435
9436            notifySubtreeAccessibilityStateChangedIfNeeded();
9437        }
9438
9439        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
9440            destroyDrawingCache();
9441        }
9442
9443        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
9444            destroyDrawingCache();
9445            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9446            invalidateParentCaches();
9447        }
9448
9449        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
9450            destroyDrawingCache();
9451            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9452        }
9453
9454        if ((changed & DRAW_MASK) != 0) {
9455            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
9456                if (mBackground != null) {
9457                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9458                    mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
9459                } else {
9460                    mPrivateFlags |= PFLAG_SKIP_DRAW;
9461                }
9462            } else {
9463                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9464            }
9465            requestLayout();
9466            invalidate(true);
9467        }
9468
9469        if ((changed & KEEP_SCREEN_ON) != 0) {
9470            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
9471                mParent.recomputeViewAttributes(this);
9472            }
9473        }
9474
9475        if (accessibilityEnabled) {
9476            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
9477                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
9478                if (oldIncludeForAccessibility != includeForAccessibility()) {
9479                    notifySubtreeAccessibilityStateChangedIfNeeded();
9480                } else {
9481                    notifyViewAccessibilityStateChangedIfNeeded(
9482                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9483                }
9484            } else if ((changed & ENABLED_MASK) != 0) {
9485                notifyViewAccessibilityStateChangedIfNeeded(
9486                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9487            }
9488        }
9489    }
9490
9491    /**
9492     * Change the view's z order in the tree, so it's on top of other sibling
9493     * views. This ordering change may affect layout, if the parent container
9494     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
9495     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
9496     * method should be followed by calls to {@link #requestLayout()} and
9497     * {@link View#invalidate()} on the view's parent to force the parent to redraw
9498     * with the new child ordering.
9499     *
9500     * @see ViewGroup#bringChildToFront(View)
9501     */
9502    public void bringToFront() {
9503        if (mParent != null) {
9504            mParent.bringChildToFront(this);
9505        }
9506    }
9507
9508    /**
9509     * This is called in response to an internal scroll in this view (i.e., the
9510     * view scrolled its own contents). This is typically as a result of
9511     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
9512     * called.
9513     *
9514     * @param l Current horizontal scroll origin.
9515     * @param t Current vertical scroll origin.
9516     * @param oldl Previous horizontal scroll origin.
9517     * @param oldt Previous vertical scroll origin.
9518     */
9519    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
9520        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9521            postSendViewScrolledAccessibilityEventCallback();
9522        }
9523
9524        mBackgroundSizeChanged = true;
9525
9526        final AttachInfo ai = mAttachInfo;
9527        if (ai != null) {
9528            ai.mViewScrollChanged = true;
9529        }
9530    }
9531
9532    /**
9533     * Interface definition for a callback to be invoked when the layout bounds of a view
9534     * changes due to layout processing.
9535     */
9536    public interface OnLayoutChangeListener {
9537        /**
9538         * Called when the layout bounds of a view changes due to layout processing.
9539         *
9540         * @param v The view whose bounds have changed.
9541         * @param left The new value of the view's left property.
9542         * @param top The new value of the view's top property.
9543         * @param right The new value of the view's right property.
9544         * @param bottom The new value of the view's bottom property.
9545         * @param oldLeft The previous value of the view's left property.
9546         * @param oldTop The previous value of the view's top property.
9547         * @param oldRight The previous value of the view's right property.
9548         * @param oldBottom The previous value of the view's bottom property.
9549         */
9550        void onLayoutChange(View v, int left, int top, int right, int bottom,
9551            int oldLeft, int oldTop, int oldRight, int oldBottom);
9552    }
9553
9554    /**
9555     * This is called during layout when the size of this view has changed. If
9556     * you were just added to the view hierarchy, you're called with the old
9557     * values of 0.
9558     *
9559     * @param w Current width of this view.
9560     * @param h Current height of this view.
9561     * @param oldw Old width of this view.
9562     * @param oldh Old height of this view.
9563     */
9564    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
9565    }
9566
9567    /**
9568     * Called by draw to draw the child views. This may be overridden
9569     * by derived classes to gain control just before its children are drawn
9570     * (but after its own view has been drawn).
9571     * @param canvas the canvas on which to draw the view
9572     */
9573    protected void dispatchDraw(Canvas canvas) {
9574
9575    }
9576
9577    /**
9578     * Gets the parent of this view. Note that the parent is a
9579     * ViewParent and not necessarily a View.
9580     *
9581     * @return Parent of this view.
9582     */
9583    public final ViewParent getParent() {
9584        return mParent;
9585    }
9586
9587    /**
9588     * Set the horizontal scrolled position of your view. This will cause a call to
9589     * {@link #onScrollChanged(int, int, int, int)} and the view will be
9590     * invalidated.
9591     * @param value the x position to scroll to
9592     */
9593    public void setScrollX(int value) {
9594        scrollTo(value, mScrollY);
9595    }
9596
9597    /**
9598     * Set the vertical scrolled position of your view. This will cause a call to
9599     * {@link #onScrollChanged(int, int, int, int)} and the view will be
9600     * invalidated.
9601     * @param value the y position to scroll to
9602     */
9603    public void setScrollY(int value) {
9604        scrollTo(mScrollX, value);
9605    }
9606
9607    /**
9608     * Return the scrolled left position of this view. This is the left edge of
9609     * the displayed part of your view. You do not need to draw any pixels
9610     * farther left, since those are outside of the frame of your view on
9611     * screen.
9612     *
9613     * @return The left edge of the displayed part of your view, in pixels.
9614     */
9615    public final int getScrollX() {
9616        return mScrollX;
9617    }
9618
9619    /**
9620     * Return the scrolled top position of this view. This is the top edge of
9621     * the displayed part of your view. You do not need to draw any pixels above
9622     * it, since those are outside of the frame of your view on screen.
9623     *
9624     * @return The top edge of the displayed part of your view, in pixels.
9625     */
9626    public final int getScrollY() {
9627        return mScrollY;
9628    }
9629
9630    /**
9631     * Return the width of the your view.
9632     *
9633     * @return The width of your view, in pixels.
9634     */
9635    @ViewDebug.ExportedProperty(category = "layout")
9636    public final int getWidth() {
9637        return mRight - mLeft;
9638    }
9639
9640    /**
9641     * Return the height of your view.
9642     *
9643     * @return The height of your view, in pixels.
9644     */
9645    @ViewDebug.ExportedProperty(category = "layout")
9646    public final int getHeight() {
9647        return mBottom - mTop;
9648    }
9649
9650    /**
9651     * Return the visible drawing bounds of your view. Fills in the output
9652     * rectangle with the values from getScrollX(), getScrollY(),
9653     * getWidth(), and getHeight(). These bounds do not account for any
9654     * transformation properties currently set on the view, such as
9655     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
9656     *
9657     * @param outRect The (scrolled) drawing bounds of the view.
9658     */
9659    public void getDrawingRect(Rect outRect) {
9660        outRect.left = mScrollX;
9661        outRect.top = mScrollY;
9662        outRect.right = mScrollX + (mRight - mLeft);
9663        outRect.bottom = mScrollY + (mBottom - mTop);
9664    }
9665
9666    /**
9667     * Like {@link #getMeasuredWidthAndState()}, but only returns the
9668     * raw width component (that is the result is masked by
9669     * {@link #MEASURED_SIZE_MASK}).
9670     *
9671     * @return The raw measured width of this view.
9672     */
9673    public final int getMeasuredWidth() {
9674        return mMeasuredWidth & MEASURED_SIZE_MASK;
9675    }
9676
9677    /**
9678     * Return the full width measurement information for this view as computed
9679     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
9680     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
9681     * This should be used during measurement and layout calculations only. Use
9682     * {@link #getWidth()} to see how wide a view is after layout.
9683     *
9684     * @return The measured width of this view as a bit mask.
9685     */
9686    public final int getMeasuredWidthAndState() {
9687        return mMeasuredWidth;
9688    }
9689
9690    /**
9691     * Like {@link #getMeasuredHeightAndState()}, but only returns the
9692     * raw width component (that is the result is masked by
9693     * {@link #MEASURED_SIZE_MASK}).
9694     *
9695     * @return The raw measured height of this view.
9696     */
9697    public final int getMeasuredHeight() {
9698        return mMeasuredHeight & MEASURED_SIZE_MASK;
9699    }
9700
9701    /**
9702     * Return the full height measurement information for this view as computed
9703     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
9704     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
9705     * This should be used during measurement and layout calculations only. Use
9706     * {@link #getHeight()} to see how wide a view is after layout.
9707     *
9708     * @return The measured width of this view as a bit mask.
9709     */
9710    public final int getMeasuredHeightAndState() {
9711        return mMeasuredHeight;
9712    }
9713
9714    /**
9715     * Return only the state bits of {@link #getMeasuredWidthAndState()}
9716     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
9717     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
9718     * and the height component is at the shifted bits
9719     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
9720     */
9721    public final int getMeasuredState() {
9722        return (mMeasuredWidth&MEASURED_STATE_MASK)
9723                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
9724                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
9725    }
9726
9727    /**
9728     * The transform matrix of this view, which is calculated based on the current
9729     * rotation, scale, and pivot properties.
9730     *
9731     * @see #getRotation()
9732     * @see #getScaleX()
9733     * @see #getScaleY()
9734     * @see #getPivotX()
9735     * @see #getPivotY()
9736     * @return The current transform matrix for the view
9737     */
9738    public Matrix getMatrix() {
9739        ensureTransformationInfo();
9740        final Matrix matrix = mTransformationInfo.mMatrix;
9741        mRenderNode.getMatrix(matrix);
9742        return matrix;
9743    }
9744
9745    /**
9746     * Returns true if the transform matrix is the identity matrix.
9747     * Recomputes the matrix if necessary.
9748     *
9749     * @return True if the transform matrix is the identity matrix, false otherwise.
9750     */
9751    final boolean hasIdentityMatrix() {
9752        return mRenderNode.hasIdentityMatrix();
9753    }
9754
9755    void ensureTransformationInfo() {
9756        if (mTransformationInfo == null) {
9757            mTransformationInfo = new TransformationInfo();
9758        }
9759    }
9760
9761   /**
9762     * Utility method to retrieve the inverse of the current mMatrix property.
9763     * We cache the matrix to avoid recalculating it when transform properties
9764     * have not changed.
9765     *
9766     * @return The inverse of the current matrix of this view.
9767     */
9768    final Matrix getInverseMatrix() {
9769        ensureTransformationInfo();
9770        if (mTransformationInfo.mInverseMatrix == null) {
9771            mTransformationInfo.mInverseMatrix = new Matrix();
9772        }
9773        final Matrix matrix = mTransformationInfo.mInverseMatrix;
9774        mRenderNode.getInverseMatrix(matrix);
9775        return matrix;
9776    }
9777
9778    /**
9779     * Gets the distance along the Z axis from the camera to this view.
9780     *
9781     * @see #setCameraDistance(float)
9782     *
9783     * @return The distance along the Z axis.
9784     */
9785    public float getCameraDistance() {
9786        final float dpi = mResources.getDisplayMetrics().densityDpi;
9787        return -(mRenderNode.getCameraDistance() * dpi);
9788    }
9789
9790    /**
9791     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
9792     * views are drawn) from the camera to this view. The camera's distance
9793     * affects 3D transformations, for instance rotations around the X and Y
9794     * axis. If the rotationX or rotationY properties are changed and this view is
9795     * large (more than half the size of the screen), it is recommended to always
9796     * use a camera distance that's greater than the height (X axis rotation) or
9797     * the width (Y axis rotation) of this view.</p>
9798     *
9799     * <p>The distance of the camera from the view plane can have an affect on the
9800     * perspective distortion of the view when it is rotated around the x or y axis.
9801     * For example, a large distance will result in a large viewing angle, and there
9802     * will not be much perspective distortion of the view as it rotates. A short
9803     * distance may cause much more perspective distortion upon rotation, and can
9804     * also result in some drawing artifacts if the rotated view ends up partially
9805     * behind the camera (which is why the recommendation is to use a distance at
9806     * least as far as the size of the view, if the view is to be rotated.)</p>
9807     *
9808     * <p>The distance is expressed in "depth pixels." The default distance depends
9809     * on the screen density. For instance, on a medium density display, the
9810     * default distance is 1280. On a high density display, the default distance
9811     * is 1920.</p>
9812     *
9813     * <p>If you want to specify a distance that leads to visually consistent
9814     * results across various densities, use the following formula:</p>
9815     * <pre>
9816     * float scale = context.getResources().getDisplayMetrics().density;
9817     * view.setCameraDistance(distance * scale);
9818     * </pre>
9819     *
9820     * <p>The density scale factor of a high density display is 1.5,
9821     * and 1920 = 1280 * 1.5.</p>
9822     *
9823     * @param distance The distance in "depth pixels", if negative the opposite
9824     *        value is used
9825     *
9826     * @see #setRotationX(float)
9827     * @see #setRotationY(float)
9828     */
9829    public void setCameraDistance(float distance) {
9830        final float dpi = mResources.getDisplayMetrics().densityDpi;
9831
9832        invalidateViewProperty(true, false);
9833        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
9834        invalidateViewProperty(false, false);
9835
9836        invalidateParentIfNeededAndWasQuickRejected();
9837    }
9838
9839    /**
9840     * The degrees that the view is rotated around the pivot point.
9841     *
9842     * @see #setRotation(float)
9843     * @see #getPivotX()
9844     * @see #getPivotY()
9845     *
9846     * @return The degrees of rotation.
9847     */
9848    @ViewDebug.ExportedProperty(category = "drawing")
9849    public float getRotation() {
9850        return mRenderNode.getRotation();
9851    }
9852
9853    /**
9854     * Sets the degrees that the view is rotated around the pivot point. Increasing values
9855     * result in clockwise rotation.
9856     *
9857     * @param rotation The degrees of rotation.
9858     *
9859     * @see #getRotation()
9860     * @see #getPivotX()
9861     * @see #getPivotY()
9862     * @see #setRotationX(float)
9863     * @see #setRotationY(float)
9864     *
9865     * @attr ref android.R.styleable#View_rotation
9866     */
9867    public void setRotation(float rotation) {
9868        if (rotation != getRotation()) {
9869            // Double-invalidation is necessary to capture view's old and new areas
9870            invalidateViewProperty(true, false);
9871            mRenderNode.setRotation(rotation);
9872            invalidateViewProperty(false, true);
9873
9874            invalidateParentIfNeededAndWasQuickRejected();
9875            notifySubtreeAccessibilityStateChangedIfNeeded();
9876        }
9877    }
9878
9879    /**
9880     * The degrees that the view is rotated around the vertical axis through the pivot point.
9881     *
9882     * @see #getPivotX()
9883     * @see #getPivotY()
9884     * @see #setRotationY(float)
9885     *
9886     * @return The degrees of Y rotation.
9887     */
9888    @ViewDebug.ExportedProperty(category = "drawing")
9889    public float getRotationY() {
9890        return mRenderNode.getRotationY();
9891    }
9892
9893    /**
9894     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
9895     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
9896     * down the y axis.
9897     *
9898     * When rotating large views, it is recommended to adjust the camera distance
9899     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
9900     *
9901     * @param rotationY The degrees of Y rotation.
9902     *
9903     * @see #getRotationY()
9904     * @see #getPivotX()
9905     * @see #getPivotY()
9906     * @see #setRotation(float)
9907     * @see #setRotationX(float)
9908     * @see #setCameraDistance(float)
9909     *
9910     * @attr ref android.R.styleable#View_rotationY
9911     */
9912    public void setRotationY(float rotationY) {
9913        if (rotationY != getRotationY()) {
9914            invalidateViewProperty(true, false);
9915            mRenderNode.setRotationY(rotationY);
9916            invalidateViewProperty(false, true);
9917
9918            invalidateParentIfNeededAndWasQuickRejected();
9919            notifySubtreeAccessibilityStateChangedIfNeeded();
9920        }
9921    }
9922
9923    /**
9924     * The degrees that the view is rotated around the horizontal axis through the pivot point.
9925     *
9926     * @see #getPivotX()
9927     * @see #getPivotY()
9928     * @see #setRotationX(float)
9929     *
9930     * @return The degrees of X rotation.
9931     */
9932    @ViewDebug.ExportedProperty(category = "drawing")
9933    public float getRotationX() {
9934        return mRenderNode.getRotationX();
9935    }
9936
9937    /**
9938     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
9939     * Increasing values result in clockwise rotation from the viewpoint of looking down the
9940     * x axis.
9941     *
9942     * When rotating large views, it is recommended to adjust the camera distance
9943     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
9944     *
9945     * @param rotationX The degrees of X rotation.
9946     *
9947     * @see #getRotationX()
9948     * @see #getPivotX()
9949     * @see #getPivotY()
9950     * @see #setRotation(float)
9951     * @see #setRotationY(float)
9952     * @see #setCameraDistance(float)
9953     *
9954     * @attr ref android.R.styleable#View_rotationX
9955     */
9956    public void setRotationX(float rotationX) {
9957        if (rotationX != getRotationX()) {
9958            invalidateViewProperty(true, false);
9959            mRenderNode.setRotationX(rotationX);
9960            invalidateViewProperty(false, true);
9961
9962            invalidateParentIfNeededAndWasQuickRejected();
9963            notifySubtreeAccessibilityStateChangedIfNeeded();
9964        }
9965    }
9966
9967    /**
9968     * The amount that the view is scaled in x around the pivot point, as a proportion of
9969     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
9970     *
9971     * <p>By default, this is 1.0f.
9972     *
9973     * @see #getPivotX()
9974     * @see #getPivotY()
9975     * @return The scaling factor.
9976     */
9977    @ViewDebug.ExportedProperty(category = "drawing")
9978    public float getScaleX() {
9979        return mRenderNode.getScaleX();
9980    }
9981
9982    /**
9983     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
9984     * the view's unscaled width. A value of 1 means that no scaling is applied.
9985     *
9986     * @param scaleX The scaling factor.
9987     * @see #getPivotX()
9988     * @see #getPivotY()
9989     *
9990     * @attr ref android.R.styleable#View_scaleX
9991     */
9992    public void setScaleX(float scaleX) {
9993        if (scaleX != getScaleX()) {
9994            invalidateViewProperty(true, false);
9995            mRenderNode.setScaleX(scaleX);
9996            invalidateViewProperty(false, true);
9997
9998            invalidateParentIfNeededAndWasQuickRejected();
9999            notifySubtreeAccessibilityStateChangedIfNeeded();
10000        }
10001    }
10002
10003    /**
10004     * The amount that the view is scaled in y around the pivot point, as a proportion of
10005     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
10006     *
10007     * <p>By default, this is 1.0f.
10008     *
10009     * @see #getPivotX()
10010     * @see #getPivotY()
10011     * @return The scaling factor.
10012     */
10013    @ViewDebug.ExportedProperty(category = "drawing")
10014    public float getScaleY() {
10015        return mRenderNode.getScaleY();
10016    }
10017
10018    /**
10019     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
10020     * the view's unscaled width. A value of 1 means that no scaling is applied.
10021     *
10022     * @param scaleY The scaling factor.
10023     * @see #getPivotX()
10024     * @see #getPivotY()
10025     *
10026     * @attr ref android.R.styleable#View_scaleY
10027     */
10028    public void setScaleY(float scaleY) {
10029        if (scaleY != getScaleY()) {
10030            invalidateViewProperty(true, false);
10031            mRenderNode.setScaleY(scaleY);
10032            invalidateViewProperty(false, true);
10033
10034            invalidateParentIfNeededAndWasQuickRejected();
10035            notifySubtreeAccessibilityStateChangedIfNeeded();
10036        }
10037    }
10038
10039    /**
10040     * The x location of the point around which the view is {@link #setRotation(float) rotated}
10041     * and {@link #setScaleX(float) scaled}.
10042     *
10043     * @see #getRotation()
10044     * @see #getScaleX()
10045     * @see #getScaleY()
10046     * @see #getPivotY()
10047     * @return The x location of the pivot point.
10048     *
10049     * @attr ref android.R.styleable#View_transformPivotX
10050     */
10051    @ViewDebug.ExportedProperty(category = "drawing")
10052    public float getPivotX() {
10053        return mRenderNode.getPivotX();
10054    }
10055
10056    /**
10057     * Sets the x location of the point around which the view is
10058     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
10059     * By default, the pivot point is centered on the object.
10060     * Setting this property disables this behavior and causes the view to use only the
10061     * explicitly set pivotX and pivotY values.
10062     *
10063     * @param pivotX The x location of the pivot point.
10064     * @see #getRotation()
10065     * @see #getScaleX()
10066     * @see #getScaleY()
10067     * @see #getPivotY()
10068     *
10069     * @attr ref android.R.styleable#View_transformPivotX
10070     */
10071    public void setPivotX(float pivotX) {
10072        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
10073            invalidateViewProperty(true, false);
10074            mRenderNode.setPivotX(pivotX);
10075            invalidateViewProperty(false, true);
10076
10077            invalidateParentIfNeededAndWasQuickRejected();
10078        }
10079    }
10080
10081    /**
10082     * The y location of the point around which the view is {@link #setRotation(float) rotated}
10083     * and {@link #setScaleY(float) scaled}.
10084     *
10085     * @see #getRotation()
10086     * @see #getScaleX()
10087     * @see #getScaleY()
10088     * @see #getPivotY()
10089     * @return The y location of the pivot point.
10090     *
10091     * @attr ref android.R.styleable#View_transformPivotY
10092     */
10093    @ViewDebug.ExportedProperty(category = "drawing")
10094    public float getPivotY() {
10095        return mRenderNode.getPivotY();
10096    }
10097
10098    /**
10099     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
10100     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
10101     * Setting this property disables this behavior and causes the view to use only the
10102     * explicitly set pivotX and pivotY values.
10103     *
10104     * @param pivotY The y location of the pivot point.
10105     * @see #getRotation()
10106     * @see #getScaleX()
10107     * @see #getScaleY()
10108     * @see #getPivotY()
10109     *
10110     * @attr ref android.R.styleable#View_transformPivotY
10111     */
10112    public void setPivotY(float pivotY) {
10113        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
10114            invalidateViewProperty(true, false);
10115            mRenderNode.setPivotY(pivotY);
10116            invalidateViewProperty(false, true);
10117
10118            invalidateParentIfNeededAndWasQuickRejected();
10119        }
10120    }
10121
10122    /**
10123     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
10124     * completely transparent and 1 means the view is completely opaque.
10125     *
10126     * <p>By default this is 1.0f.
10127     * @return The opacity of the view.
10128     */
10129    @ViewDebug.ExportedProperty(category = "drawing")
10130    public float getAlpha() {
10131        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
10132    }
10133
10134    /**
10135     * Returns whether this View has content which overlaps.
10136     *
10137     * <p>This function, intended to be overridden by specific View types, is an optimization when
10138     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
10139     * an offscreen buffer and then composited into place, which can be expensive. If the view has
10140     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
10141     * directly. An example of overlapping rendering is a TextView with a background image, such as
10142     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
10143     * ImageView with only the foreground image. The default implementation returns true; subclasses
10144     * should override if they have cases which can be optimized.</p>
10145     *
10146     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
10147     * necessitates that a View return true if it uses the methods internally without passing the
10148     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
10149     *
10150     * @return true if the content in this view might overlap, false otherwise.
10151     */
10152    public boolean hasOverlappingRendering() {
10153        return true;
10154    }
10155
10156    /**
10157     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
10158     * completely transparent and 1 means the view is completely opaque.</p>
10159     *
10160     * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
10161     * performance implications, especially for large views. It is best to use the alpha property
10162     * sparingly and transiently, as in the case of fading animations.</p>
10163     *
10164     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
10165     * strongly recommended for performance reasons to either override
10166     * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
10167     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
10168     *
10169     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
10170     * responsible for applying the opacity itself.</p>
10171     *
10172     * <p>Note that if the view is backed by a
10173     * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
10174     * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
10175     * 1.0 will supercede the alpha of the layer paint.</p>
10176     *
10177     * @param alpha The opacity of the view.
10178     *
10179     * @see #hasOverlappingRendering()
10180     * @see #setLayerType(int, android.graphics.Paint)
10181     *
10182     * @attr ref android.R.styleable#View_alpha
10183     */
10184    public void setAlpha(float alpha) {
10185        ensureTransformationInfo();
10186        if (mTransformationInfo.mAlpha != alpha) {
10187            mTransformationInfo.mAlpha = alpha;
10188            if (onSetAlpha((int) (alpha * 255))) {
10189                mPrivateFlags |= PFLAG_ALPHA_SET;
10190                // subclass is handling alpha - don't optimize rendering cache invalidation
10191                invalidateParentCaches();
10192                invalidate(true);
10193            } else {
10194                mPrivateFlags &= ~PFLAG_ALPHA_SET;
10195                invalidateViewProperty(true, false);
10196                mRenderNode.setAlpha(getFinalAlpha());
10197                notifyViewAccessibilityStateChangedIfNeeded(
10198                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10199            }
10200        }
10201    }
10202
10203    /**
10204     * Faster version of setAlpha() which performs the same steps except there are
10205     * no calls to invalidate(). The caller of this function should perform proper invalidation
10206     * on the parent and this object. The return value indicates whether the subclass handles
10207     * alpha (the return value for onSetAlpha()).
10208     *
10209     * @param alpha The new value for the alpha property
10210     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
10211     *         the new value for the alpha property is different from the old value
10212     */
10213    boolean setAlphaNoInvalidation(float alpha) {
10214        ensureTransformationInfo();
10215        if (mTransformationInfo.mAlpha != alpha) {
10216            mTransformationInfo.mAlpha = alpha;
10217            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
10218            if (subclassHandlesAlpha) {
10219                mPrivateFlags |= PFLAG_ALPHA_SET;
10220                return true;
10221            } else {
10222                mPrivateFlags &= ~PFLAG_ALPHA_SET;
10223                mRenderNode.setAlpha(getFinalAlpha());
10224            }
10225        }
10226        return false;
10227    }
10228
10229    /**
10230     * This property is hidden and intended only for use by the Fade transition, which
10231     * animates it to produce a visual translucency that does not side-effect (or get
10232     * affected by) the real alpha property. This value is composited with the other
10233     * alpha value (and the AlphaAnimation value, when that is present) to produce
10234     * a final visual translucency result, which is what is passed into the DisplayList.
10235     *
10236     * @hide
10237     */
10238    public void setTransitionAlpha(float alpha) {
10239        ensureTransformationInfo();
10240        if (mTransformationInfo.mTransitionAlpha != alpha) {
10241            mTransformationInfo.mTransitionAlpha = alpha;
10242            mPrivateFlags &= ~PFLAG_ALPHA_SET;
10243            invalidateViewProperty(true, false);
10244            mRenderNode.setAlpha(getFinalAlpha());
10245        }
10246    }
10247
10248    /**
10249     * Calculates the visual alpha of this view, which is a combination of the actual
10250     * alpha value and the transitionAlpha value (if set).
10251     */
10252    private float getFinalAlpha() {
10253        if (mTransformationInfo != null) {
10254            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
10255        }
10256        return 1;
10257    }
10258
10259    /**
10260     * This property is hidden and intended only for use by the Fade transition, which
10261     * animates it to produce a visual translucency that does not side-effect (or get
10262     * affected by) the real alpha property. This value is composited with the other
10263     * alpha value (and the AlphaAnimation value, when that is present) to produce
10264     * a final visual translucency result, which is what is passed into the DisplayList.
10265     *
10266     * @hide
10267     */
10268    public float getTransitionAlpha() {
10269        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
10270    }
10271
10272    /**
10273     * Top position of this view relative to its parent.
10274     *
10275     * @return The top of this view, in pixels.
10276     */
10277    @ViewDebug.CapturedViewProperty
10278    public final int getTop() {
10279        return mTop;
10280    }
10281
10282    /**
10283     * Sets the top position of this view relative to its parent. This method is meant to be called
10284     * by the layout system and should not generally be called otherwise, because the property
10285     * may be changed at any time by the layout.
10286     *
10287     * @param top The top of this view, in pixels.
10288     */
10289    public final void setTop(int top) {
10290        if (top != mTop) {
10291            final boolean matrixIsIdentity = hasIdentityMatrix();
10292            if (matrixIsIdentity) {
10293                if (mAttachInfo != null) {
10294                    int minTop;
10295                    int yLoc;
10296                    if (top < mTop) {
10297                        minTop = top;
10298                        yLoc = top - mTop;
10299                    } else {
10300                        minTop = mTop;
10301                        yLoc = 0;
10302                    }
10303                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
10304                }
10305            } else {
10306                // Double-invalidation is necessary to capture view's old and new areas
10307                invalidate(true);
10308            }
10309
10310            int width = mRight - mLeft;
10311            int oldHeight = mBottom - mTop;
10312
10313            mTop = top;
10314            mRenderNode.setTop(mTop);
10315
10316            sizeChange(width, mBottom - mTop, width, oldHeight);
10317
10318            if (!matrixIsIdentity) {
10319                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10320                invalidate(true);
10321            }
10322            mBackgroundSizeChanged = true;
10323            invalidateParentIfNeeded();
10324            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10325                // View was rejected last time it was drawn by its parent; this may have changed
10326                invalidateParentIfNeeded();
10327            }
10328        }
10329    }
10330
10331    /**
10332     * Bottom position of this view relative to its parent.
10333     *
10334     * @return The bottom of this view, in pixels.
10335     */
10336    @ViewDebug.CapturedViewProperty
10337    public final int getBottom() {
10338        return mBottom;
10339    }
10340
10341    /**
10342     * True if this view has changed since the last time being drawn.
10343     *
10344     * @return The dirty state of this view.
10345     */
10346    public boolean isDirty() {
10347        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
10348    }
10349
10350    /**
10351     * Sets the bottom position of this view relative to its parent. This method is meant to be
10352     * called by the layout system and should not generally be called otherwise, because the
10353     * property may be changed at any time by the layout.
10354     *
10355     * @param bottom The bottom of this view, in pixels.
10356     */
10357    public final void setBottom(int bottom) {
10358        if (bottom != mBottom) {
10359            final boolean matrixIsIdentity = hasIdentityMatrix();
10360            if (matrixIsIdentity) {
10361                if (mAttachInfo != null) {
10362                    int maxBottom;
10363                    if (bottom < mBottom) {
10364                        maxBottom = mBottom;
10365                    } else {
10366                        maxBottom = bottom;
10367                    }
10368                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
10369                }
10370            } else {
10371                // Double-invalidation is necessary to capture view's old and new areas
10372                invalidate(true);
10373            }
10374
10375            int width = mRight - mLeft;
10376            int oldHeight = mBottom - mTop;
10377
10378            mBottom = bottom;
10379            mRenderNode.setBottom(mBottom);
10380
10381            sizeChange(width, mBottom - mTop, width, oldHeight);
10382
10383            if (!matrixIsIdentity) {
10384                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10385                invalidate(true);
10386            }
10387            mBackgroundSizeChanged = true;
10388            invalidateParentIfNeeded();
10389            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10390                // View was rejected last time it was drawn by its parent; this may have changed
10391                invalidateParentIfNeeded();
10392            }
10393        }
10394    }
10395
10396    /**
10397     * Left position of this view relative to its parent.
10398     *
10399     * @return The left edge of this view, in pixels.
10400     */
10401    @ViewDebug.CapturedViewProperty
10402    public final int getLeft() {
10403        return mLeft;
10404    }
10405
10406    /**
10407     * Sets the left position of this view relative to its parent. This method is meant to be called
10408     * by the layout system and should not generally be called otherwise, because the property
10409     * may be changed at any time by the layout.
10410     *
10411     * @param left The left of this view, in pixels.
10412     */
10413    public final void setLeft(int left) {
10414        if (left != mLeft) {
10415            final boolean matrixIsIdentity = hasIdentityMatrix();
10416            if (matrixIsIdentity) {
10417                if (mAttachInfo != null) {
10418                    int minLeft;
10419                    int xLoc;
10420                    if (left < mLeft) {
10421                        minLeft = left;
10422                        xLoc = left - mLeft;
10423                    } else {
10424                        minLeft = mLeft;
10425                        xLoc = 0;
10426                    }
10427                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
10428                }
10429            } else {
10430                // Double-invalidation is necessary to capture view's old and new areas
10431                invalidate(true);
10432            }
10433
10434            int oldWidth = mRight - mLeft;
10435            int height = mBottom - mTop;
10436
10437            mLeft = left;
10438            mRenderNode.setLeft(left);
10439
10440            sizeChange(mRight - mLeft, height, oldWidth, height);
10441
10442            if (!matrixIsIdentity) {
10443                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10444                invalidate(true);
10445            }
10446            mBackgroundSizeChanged = true;
10447            invalidateParentIfNeeded();
10448            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10449                // View was rejected last time it was drawn by its parent; this may have changed
10450                invalidateParentIfNeeded();
10451            }
10452        }
10453    }
10454
10455    /**
10456     * Right position of this view relative to its parent.
10457     *
10458     * @return The right edge of this view, in pixels.
10459     */
10460    @ViewDebug.CapturedViewProperty
10461    public final int getRight() {
10462        return mRight;
10463    }
10464
10465    /**
10466     * Sets the right position of this view relative to its parent. This method is meant to be called
10467     * by the layout system and should not generally be called otherwise, because the property
10468     * may be changed at any time by the layout.
10469     *
10470     * @param right The right of this view, in pixels.
10471     */
10472    public final void setRight(int right) {
10473        if (right != mRight) {
10474            final boolean matrixIsIdentity = hasIdentityMatrix();
10475            if (matrixIsIdentity) {
10476                if (mAttachInfo != null) {
10477                    int maxRight;
10478                    if (right < mRight) {
10479                        maxRight = mRight;
10480                    } else {
10481                        maxRight = right;
10482                    }
10483                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
10484                }
10485            } else {
10486                // Double-invalidation is necessary to capture view's old and new areas
10487                invalidate(true);
10488            }
10489
10490            int oldWidth = mRight - mLeft;
10491            int height = mBottom - mTop;
10492
10493            mRight = right;
10494            mRenderNode.setRight(mRight);
10495
10496            sizeChange(mRight - mLeft, height, oldWidth, height);
10497
10498            if (!matrixIsIdentity) {
10499                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10500                invalidate(true);
10501            }
10502            mBackgroundSizeChanged = true;
10503            invalidateParentIfNeeded();
10504            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10505                // View was rejected last time it was drawn by its parent; this may have changed
10506                invalidateParentIfNeeded();
10507            }
10508        }
10509    }
10510
10511    /**
10512     * The visual x position of this view, in pixels. This is equivalent to the
10513     * {@link #setTranslationX(float) translationX} property plus the current
10514     * {@link #getLeft() left} property.
10515     *
10516     * @return The visual x position of this view, in pixels.
10517     */
10518    @ViewDebug.ExportedProperty(category = "drawing")
10519    public float getX() {
10520        return mLeft + getTranslationX();
10521    }
10522
10523    /**
10524     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
10525     * {@link #setTranslationX(float) translationX} property to be the difference between
10526     * the x value passed in and the current {@link #getLeft() left} property.
10527     *
10528     * @param x The visual x position of this view, in pixels.
10529     */
10530    public void setX(float x) {
10531        setTranslationX(x - mLeft);
10532    }
10533
10534    /**
10535     * The visual y position of this view, in pixels. This is equivalent to the
10536     * {@link #setTranslationY(float) translationY} property plus the current
10537     * {@link #getTop() top} property.
10538     *
10539     * @return The visual y position of this view, in pixels.
10540     */
10541    @ViewDebug.ExportedProperty(category = "drawing")
10542    public float getY() {
10543        return mTop + getTranslationY();
10544    }
10545
10546    /**
10547     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
10548     * {@link #setTranslationY(float) translationY} property to be the difference between
10549     * the y value passed in and the current {@link #getTop() top} property.
10550     *
10551     * @param y The visual y position of this view, in pixels.
10552     */
10553    public void setY(float y) {
10554        setTranslationY(y - mTop);
10555    }
10556
10557    /**
10558     * The visual z position of this view, in pixels. This is equivalent to the
10559     * {@link #setTranslationZ(float) translationZ} property plus the current
10560     * {@link #getElevation() elevation} property.
10561     *
10562     * @return The visual z position of this view, in pixels.
10563     */
10564    @ViewDebug.ExportedProperty(category = "drawing")
10565    public float getZ() {
10566        return getElevation() + getTranslationZ();
10567    }
10568
10569    /**
10570     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
10571     * {@link #setTranslationZ(float) translationZ} property to be the difference between
10572     * the x value passed in and the current {@link #getElevation() elevation} property.
10573     *
10574     * @param z The visual z position of this view, in pixels.
10575     */
10576    public void setZ(float z) {
10577        setTranslationZ(z - getElevation());
10578    }
10579
10580    /**
10581     * The base elevation of this view relative to its parent, in pixels.
10582     *
10583     * @return The base depth position of the view, in pixels.
10584     */
10585    @ViewDebug.ExportedProperty(category = "drawing")
10586    public float getElevation() {
10587        return mRenderNode.getElevation();
10588    }
10589
10590    /**
10591     * Sets the base elevation of this view, in pixels.
10592     *
10593     * @attr ref android.R.styleable#View_elevation
10594     */
10595    public void setElevation(float elevation) {
10596        if (elevation != getElevation()) {
10597            invalidateViewProperty(true, false);
10598            mRenderNode.setElevation(elevation);
10599            invalidateViewProperty(false, true);
10600
10601            invalidateParentIfNeededAndWasQuickRejected();
10602        }
10603    }
10604
10605    /**
10606     * The horizontal location of this view relative to its {@link #getLeft() left} position.
10607     * This position is post-layout, in addition to wherever the object's
10608     * layout placed it.
10609     *
10610     * @return The horizontal position of this view relative to its left position, in pixels.
10611     */
10612    @ViewDebug.ExportedProperty(category = "drawing")
10613    public float getTranslationX() {
10614        return mRenderNode.getTranslationX();
10615    }
10616
10617    /**
10618     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
10619     * This effectively positions the object post-layout, in addition to wherever the object's
10620     * layout placed it.
10621     *
10622     * @param translationX The horizontal position of this view relative to its left position,
10623     * in pixels.
10624     *
10625     * @attr ref android.R.styleable#View_translationX
10626     */
10627    public void setTranslationX(float translationX) {
10628        if (translationX != getTranslationX()) {
10629            invalidateViewProperty(true, false);
10630            mRenderNode.setTranslationX(translationX);
10631            invalidateViewProperty(false, true);
10632
10633            invalidateParentIfNeededAndWasQuickRejected();
10634            notifySubtreeAccessibilityStateChangedIfNeeded();
10635        }
10636    }
10637
10638    /**
10639     * The vertical location of this view relative to its {@link #getTop() top} position.
10640     * This position is post-layout, in addition to wherever the object's
10641     * layout placed it.
10642     *
10643     * @return The vertical position of this view relative to its top position,
10644     * in pixels.
10645     */
10646    @ViewDebug.ExportedProperty(category = "drawing")
10647    public float getTranslationY() {
10648        return mRenderNode.getTranslationY();
10649    }
10650
10651    /**
10652     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
10653     * This effectively positions the object post-layout, in addition to wherever the object's
10654     * layout placed it.
10655     *
10656     * @param translationY The vertical position of this view relative to its top position,
10657     * in pixels.
10658     *
10659     * @attr ref android.R.styleable#View_translationY
10660     */
10661    public void setTranslationY(float translationY) {
10662        if (translationY != getTranslationY()) {
10663            invalidateViewProperty(true, false);
10664            mRenderNode.setTranslationY(translationY);
10665            invalidateViewProperty(false, true);
10666
10667            invalidateParentIfNeededAndWasQuickRejected();
10668        }
10669    }
10670
10671    /**
10672     * The depth location of this view relative to its {@link #getElevation() elevation}.
10673     *
10674     * @return The depth of this view relative to its elevation.
10675     */
10676    @ViewDebug.ExportedProperty(category = "drawing")
10677    public float getTranslationZ() {
10678        return mRenderNode.getTranslationZ();
10679    }
10680
10681    /**
10682     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
10683     *
10684     * @attr ref android.R.styleable#View_translationZ
10685     */
10686    public void setTranslationZ(float translationZ) {
10687        if (translationZ != getTranslationZ()) {
10688            invalidateViewProperty(true, false);
10689            mRenderNode.setTranslationZ(translationZ);
10690            invalidateViewProperty(false, true);
10691
10692            invalidateParentIfNeededAndWasQuickRejected();
10693        }
10694    }
10695
10696    /**
10697     * Returns a ValueAnimator which can animate a clearing circle.
10698     * <p>
10699     * The View is prevented from drawing within the circle, so the content
10700     * behind the View shows through.
10701     *
10702     * @param centerX The x coordinate of the center of the animating circle.
10703     * @param centerY The y coordinate of the center of the animating circle.
10704     * @param startRadius The starting radius of the animating circle.
10705     * @param endRadius The ending radius of the animating circle.
10706     *
10707     * @hide
10708     */
10709    public final ValueAnimator createClearCircleAnimator(int centerX,  int centerY,
10710            float startRadius, float endRadius) {
10711        return RevealAnimator.ofRevealCircle(this, centerX, centerY,
10712                startRadius, endRadius, true);
10713    }
10714
10715    /**
10716     * Returns the current StateListAnimator if exists.
10717     *
10718     * @return StateListAnimator or null if it does not exists
10719     * @see    #setStateListAnimator(android.animation.StateListAnimator)
10720     */
10721    public StateListAnimator getStateListAnimator() {
10722        return mStateListAnimator;
10723    }
10724
10725    /**
10726     * Attaches the provided StateListAnimator to this View.
10727     * <p>
10728     * Any previously attached StateListAnimator will be detached.
10729     *
10730     * @param stateListAnimator The StateListAnimator to update the view
10731     * @see {@link android.animation.StateListAnimator}
10732     */
10733    public void setStateListAnimator(StateListAnimator stateListAnimator) {
10734        if (mStateListAnimator == stateListAnimator) {
10735            return;
10736        }
10737        if (mStateListAnimator != null) {
10738            mStateListAnimator.setTarget(null);
10739        }
10740        mStateListAnimator = stateListAnimator;
10741        if (stateListAnimator != null) {
10742            stateListAnimator.setTarget(this);
10743            if (isAttachedToWindow()) {
10744                stateListAnimator.setState(getDrawableState());
10745            }
10746        }
10747    }
10748
10749    /** Deprecated, pending removal */
10750    @Deprecated
10751    public void setOutline(@Nullable Outline outline) {}
10752
10753    /**
10754     * Returns whether the Outline should be used to clip the contents of the View.
10755     * <p>
10756     * Note that this flag will only be respected if the View's Outline returns true from
10757     * {@link Outline#canClip()}.
10758     *
10759     * @see #setOutlineProvider(ViewOutlineProvider)
10760     * @see #setClipToOutline(boolean)
10761     */
10762    public final boolean getClipToOutline() {
10763        return mRenderNode.getClipToOutline();
10764    }
10765
10766    /**
10767     * Sets whether the View's Outline should be used to clip the contents of the View.
10768     * <p>
10769     * Note that this flag will only be respected if the View's Outline returns true from
10770     * {@link Outline#canClip()}.
10771     *
10772     * @see #setOutlineProvider(ViewOutlineProvider)
10773     * @see #getClipToOutline()
10774     */
10775    public void setClipToOutline(boolean clipToOutline) {
10776        damageInParent();
10777        if (getClipToOutline() != clipToOutline) {
10778            mRenderNode.setClipToOutline(clipToOutline);
10779        }
10780    }
10781
10782    /**
10783     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
10784     * the shape of the shadow it casts, and enables outline clipping.
10785     * <p>
10786     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
10787     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
10788     * outline provider with this method allows this behavior to be overridden.
10789     * <p>
10790     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
10791     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
10792     * <p>
10793     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
10794     *
10795     * @see #setClipToOutline(boolean)
10796     * @see #getClipToOutline()
10797     * @see #getOutlineProvider()
10798     */
10799    public void setOutlineProvider(ViewOutlineProvider provider) {
10800        mOutlineProvider = provider;
10801        invalidateOutline();
10802    }
10803
10804    /**
10805     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
10806     * that defines the shape of the shadow it casts, and enables outline clipping.
10807     *
10808     * @see #setOutlineProvider(ViewOutlineProvider)
10809     */
10810    public ViewOutlineProvider getOutlineProvider() {
10811        return mOutlineProvider;
10812    }
10813
10814    /**
10815     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
10816     *
10817     * @see #setOutlineProvider(ViewOutlineProvider)
10818     */
10819    public void invalidateOutline() {
10820        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
10821        if (mAttachInfo == null) return;
10822
10823        final Outline outline = mAttachInfo.mTmpOutline;
10824        outline.setEmpty();
10825
10826        if (mOutlineProvider == null) {
10827            // no provider, remove outline
10828            mRenderNode.setOutline(null);
10829        } else {
10830            if (mOutlineProvider.getOutline(this, outline)) {
10831                if (outline.isEmpty()) {
10832                    throw new IllegalStateException("Outline provider failed to build outline");
10833                }
10834                // provider has provided
10835                mRenderNode.setOutline(outline);
10836            } else {
10837                // provider failed to provide
10838                mRenderNode.setOutline(null);
10839            }
10840        }
10841
10842        notifySubtreeAccessibilityStateChangedIfNeeded();
10843        invalidateViewProperty(false, false);
10844    }
10845
10846    /**
10847     * Private API to be used for reveal animation
10848     *
10849     * @hide
10850     */
10851    public void setRevealClip(boolean shouldClip, boolean inverseClip,
10852            float x, float y, float radius) {
10853        mRenderNode.setRevealClip(shouldClip, inverseClip, x, y, radius);
10854        // TODO: Handle this invalidate in a better way, or purely in native.
10855        invalidate();
10856    }
10857
10858    /**
10859     * Hit rectangle in parent's coordinates
10860     *
10861     * @param outRect The hit rectangle of the view.
10862     */
10863    public void getHitRect(Rect outRect) {
10864        if (hasIdentityMatrix() || mAttachInfo == null) {
10865            outRect.set(mLeft, mTop, mRight, mBottom);
10866        } else {
10867            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
10868            tmpRect.set(0, 0, getWidth(), getHeight());
10869            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
10870            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
10871                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
10872        }
10873    }
10874
10875    /**
10876     * Determines whether the given point, in local coordinates is inside the view.
10877     */
10878    /*package*/ final boolean pointInView(float localX, float localY) {
10879        return localX >= 0 && localX < (mRight - mLeft)
10880                && localY >= 0 && localY < (mBottom - mTop);
10881    }
10882
10883    /**
10884     * Utility method to determine whether the given point, in local coordinates,
10885     * is inside the view, where the area of the view is expanded by the slop factor.
10886     * This method is called while processing touch-move events to determine if the event
10887     * is still within the view.
10888     *
10889     * @hide
10890     */
10891    public boolean pointInView(float localX, float localY, float slop) {
10892        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
10893                localY < ((mBottom - mTop) + slop);
10894    }
10895
10896    /**
10897     * When a view has focus and the user navigates away from it, the next view is searched for
10898     * starting from the rectangle filled in by this method.
10899     *
10900     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
10901     * of the view.  However, if your view maintains some idea of internal selection,
10902     * such as a cursor, or a selected row or column, you should override this method and
10903     * fill in a more specific rectangle.
10904     *
10905     * @param r The rectangle to fill in, in this view's coordinates.
10906     */
10907    public void getFocusedRect(Rect r) {
10908        getDrawingRect(r);
10909    }
10910
10911    /**
10912     * If some part of this view is not clipped by any of its parents, then
10913     * return that area in r in global (root) coordinates. To convert r to local
10914     * coordinates (without taking possible View rotations into account), offset
10915     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
10916     * If the view is completely clipped or translated out, return false.
10917     *
10918     * @param r If true is returned, r holds the global coordinates of the
10919     *        visible portion of this view.
10920     * @param globalOffset If true is returned, globalOffset holds the dx,dy
10921     *        between this view and its root. globalOffet may be null.
10922     * @return true if r is non-empty (i.e. part of the view is visible at the
10923     *         root level.
10924     */
10925    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
10926        int width = mRight - mLeft;
10927        int height = mBottom - mTop;
10928        if (width > 0 && height > 0) {
10929            r.set(0, 0, width, height);
10930            if (globalOffset != null) {
10931                globalOffset.set(-mScrollX, -mScrollY);
10932            }
10933            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
10934        }
10935        return false;
10936    }
10937
10938    public final boolean getGlobalVisibleRect(Rect r) {
10939        return getGlobalVisibleRect(r, null);
10940    }
10941
10942    public final boolean getLocalVisibleRect(Rect r) {
10943        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
10944        if (getGlobalVisibleRect(r, offset)) {
10945            r.offset(-offset.x, -offset.y); // make r local
10946            return true;
10947        }
10948        return false;
10949    }
10950
10951    /**
10952     * Offset this view's vertical location by the specified number of pixels.
10953     *
10954     * @param offset the number of pixels to offset the view by
10955     */
10956    public void offsetTopAndBottom(int offset) {
10957        if (offset != 0) {
10958            final boolean matrixIsIdentity = hasIdentityMatrix();
10959            if (matrixIsIdentity) {
10960                if (isHardwareAccelerated()) {
10961                    invalidateViewProperty(false, false);
10962                } else {
10963                    final ViewParent p = mParent;
10964                    if (p != null && mAttachInfo != null) {
10965                        final Rect r = mAttachInfo.mTmpInvalRect;
10966                        int minTop;
10967                        int maxBottom;
10968                        int yLoc;
10969                        if (offset < 0) {
10970                            minTop = mTop + offset;
10971                            maxBottom = mBottom;
10972                            yLoc = offset;
10973                        } else {
10974                            minTop = mTop;
10975                            maxBottom = mBottom + offset;
10976                            yLoc = 0;
10977                        }
10978                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
10979                        p.invalidateChild(this, r);
10980                    }
10981                }
10982            } else {
10983                invalidateViewProperty(false, false);
10984            }
10985
10986            mTop += offset;
10987            mBottom += offset;
10988            mRenderNode.offsetTopAndBottom(offset);
10989            if (isHardwareAccelerated()) {
10990                invalidateViewProperty(false, false);
10991            } else {
10992                if (!matrixIsIdentity) {
10993                    invalidateViewProperty(false, true);
10994                }
10995                invalidateParentIfNeeded();
10996            }
10997            notifySubtreeAccessibilityStateChangedIfNeeded();
10998        }
10999    }
11000
11001    /**
11002     * Offset this view's horizontal location by the specified amount of pixels.
11003     *
11004     * @param offset the number of pixels to offset the view by
11005     */
11006    public void offsetLeftAndRight(int offset) {
11007        if (offset != 0) {
11008            final boolean matrixIsIdentity = hasIdentityMatrix();
11009            if (matrixIsIdentity) {
11010                if (isHardwareAccelerated()) {
11011                    invalidateViewProperty(false, false);
11012                } else {
11013                    final ViewParent p = mParent;
11014                    if (p != null && mAttachInfo != null) {
11015                        final Rect r = mAttachInfo.mTmpInvalRect;
11016                        int minLeft;
11017                        int maxRight;
11018                        if (offset < 0) {
11019                            minLeft = mLeft + offset;
11020                            maxRight = mRight;
11021                        } else {
11022                            minLeft = mLeft;
11023                            maxRight = mRight + offset;
11024                        }
11025                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
11026                        p.invalidateChild(this, r);
11027                    }
11028                }
11029            } else {
11030                invalidateViewProperty(false, false);
11031            }
11032
11033            mLeft += offset;
11034            mRight += offset;
11035            mRenderNode.offsetLeftAndRight(offset);
11036            if (isHardwareAccelerated()) {
11037                invalidateViewProperty(false, false);
11038            } else {
11039                if (!matrixIsIdentity) {
11040                    invalidateViewProperty(false, true);
11041                }
11042                invalidateParentIfNeeded();
11043            }
11044            notifySubtreeAccessibilityStateChangedIfNeeded();
11045        }
11046    }
11047
11048    /**
11049     * Get the LayoutParams associated with this view. All views should have
11050     * layout parameters. These supply parameters to the <i>parent</i> of this
11051     * view specifying how it should be arranged. There are many subclasses of
11052     * ViewGroup.LayoutParams, and these correspond to the different subclasses
11053     * of ViewGroup that are responsible for arranging their children.
11054     *
11055     * This method may return null if this View is not attached to a parent
11056     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
11057     * was not invoked successfully. When a View is attached to a parent
11058     * ViewGroup, this method must not return null.
11059     *
11060     * @return The LayoutParams associated with this view, or null if no
11061     *         parameters have been set yet
11062     */
11063    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
11064    public ViewGroup.LayoutParams getLayoutParams() {
11065        return mLayoutParams;
11066    }
11067
11068    /**
11069     * Set the layout parameters associated with this view. These supply
11070     * parameters to the <i>parent</i> of this view specifying how it should be
11071     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
11072     * correspond to the different subclasses of ViewGroup that are responsible
11073     * for arranging their children.
11074     *
11075     * @param params The layout parameters for this view, cannot be null
11076     */
11077    public void setLayoutParams(ViewGroup.LayoutParams params) {
11078        if (params == null) {
11079            throw new NullPointerException("Layout parameters cannot be null");
11080        }
11081        mLayoutParams = params;
11082        resolveLayoutParams();
11083        if (mParent instanceof ViewGroup) {
11084            ((ViewGroup) mParent).onSetLayoutParams(this, params);
11085        }
11086        requestLayout();
11087    }
11088
11089    /**
11090     * Resolve the layout parameters depending on the resolved layout direction
11091     *
11092     * @hide
11093     */
11094    public void resolveLayoutParams() {
11095        if (mLayoutParams != null) {
11096            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
11097        }
11098    }
11099
11100    /**
11101     * Set the scrolled position of your view. This will cause a call to
11102     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11103     * invalidated.
11104     * @param x the x position to scroll to
11105     * @param y the y position to scroll to
11106     */
11107    public void scrollTo(int x, int y) {
11108        if (mScrollX != x || mScrollY != y) {
11109            int oldX = mScrollX;
11110            int oldY = mScrollY;
11111            mScrollX = x;
11112            mScrollY = y;
11113            invalidateParentCaches();
11114            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
11115            if (!awakenScrollBars()) {
11116                postInvalidateOnAnimation();
11117            }
11118        }
11119    }
11120
11121    /**
11122     * Move the scrolled position of your view. This will cause a call to
11123     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11124     * invalidated.
11125     * @param x the amount of pixels to scroll by horizontally
11126     * @param y the amount of pixels to scroll by vertically
11127     */
11128    public void scrollBy(int x, int y) {
11129        scrollTo(mScrollX + x, mScrollY + y);
11130    }
11131
11132    /**
11133     * <p>Trigger the scrollbars to draw. When invoked this method starts an
11134     * animation to fade the scrollbars out after a default delay. If a subclass
11135     * provides animated scrolling, the start delay should equal the duration
11136     * of the scrolling animation.</p>
11137     *
11138     * <p>The animation starts only if at least one of the scrollbars is
11139     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
11140     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11141     * this method returns true, and false otherwise. If the animation is
11142     * started, this method calls {@link #invalidate()}; in that case the
11143     * caller should not call {@link #invalidate()}.</p>
11144     *
11145     * <p>This method should be invoked every time a subclass directly updates
11146     * the scroll parameters.</p>
11147     *
11148     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
11149     * and {@link #scrollTo(int, int)}.</p>
11150     *
11151     * @return true if the animation is played, false otherwise
11152     *
11153     * @see #awakenScrollBars(int)
11154     * @see #scrollBy(int, int)
11155     * @see #scrollTo(int, int)
11156     * @see #isHorizontalScrollBarEnabled()
11157     * @see #isVerticalScrollBarEnabled()
11158     * @see #setHorizontalScrollBarEnabled(boolean)
11159     * @see #setVerticalScrollBarEnabled(boolean)
11160     */
11161    protected boolean awakenScrollBars() {
11162        return mScrollCache != null &&
11163                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
11164    }
11165
11166    /**
11167     * Trigger the scrollbars to draw.
11168     * This method differs from awakenScrollBars() only in its default duration.
11169     * initialAwakenScrollBars() will show the scroll bars for longer than
11170     * usual to give the user more of a chance to notice them.
11171     *
11172     * @return true if the animation is played, false otherwise.
11173     */
11174    private boolean initialAwakenScrollBars() {
11175        return mScrollCache != null &&
11176                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
11177    }
11178
11179    /**
11180     * <p>
11181     * Trigger the scrollbars to draw. When invoked this method starts an
11182     * animation to fade the scrollbars out after a fixed delay. If a subclass
11183     * provides animated scrolling, the start delay should equal the duration of
11184     * the scrolling animation.
11185     * </p>
11186     *
11187     * <p>
11188     * The animation starts only if at least one of the scrollbars is enabled,
11189     * as specified by {@link #isHorizontalScrollBarEnabled()} and
11190     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11191     * this method returns true, and false otherwise. If the animation is
11192     * started, this method calls {@link #invalidate()}; in that case the caller
11193     * should not call {@link #invalidate()}.
11194     * </p>
11195     *
11196     * <p>
11197     * This method should be invoked everytime a subclass directly updates the
11198     * scroll parameters.
11199     * </p>
11200     *
11201     * @param startDelay the delay, in milliseconds, after which the animation
11202     *        should start; when the delay is 0, the animation starts
11203     *        immediately
11204     * @return true if the animation is played, false otherwise
11205     *
11206     * @see #scrollBy(int, int)
11207     * @see #scrollTo(int, int)
11208     * @see #isHorizontalScrollBarEnabled()
11209     * @see #isVerticalScrollBarEnabled()
11210     * @see #setHorizontalScrollBarEnabled(boolean)
11211     * @see #setVerticalScrollBarEnabled(boolean)
11212     */
11213    protected boolean awakenScrollBars(int startDelay) {
11214        return awakenScrollBars(startDelay, true);
11215    }
11216
11217    /**
11218     * <p>
11219     * Trigger the scrollbars to draw. When invoked this method starts an
11220     * animation to fade the scrollbars out after a fixed delay. If a subclass
11221     * provides animated scrolling, the start delay should equal the duration of
11222     * the scrolling animation.
11223     * </p>
11224     *
11225     * <p>
11226     * The animation starts only if at least one of the scrollbars is enabled,
11227     * as specified by {@link #isHorizontalScrollBarEnabled()} and
11228     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11229     * this method returns true, and false otherwise. If the animation is
11230     * started, this method calls {@link #invalidate()} if the invalidate parameter
11231     * is set to true; in that case the caller
11232     * should not call {@link #invalidate()}.
11233     * </p>
11234     *
11235     * <p>
11236     * This method should be invoked everytime a subclass directly updates the
11237     * scroll parameters.
11238     * </p>
11239     *
11240     * @param startDelay the delay, in milliseconds, after which the animation
11241     *        should start; when the delay is 0, the animation starts
11242     *        immediately
11243     *
11244     * @param invalidate Wheter this method should call invalidate
11245     *
11246     * @return true if the animation is played, false otherwise
11247     *
11248     * @see #scrollBy(int, int)
11249     * @see #scrollTo(int, int)
11250     * @see #isHorizontalScrollBarEnabled()
11251     * @see #isVerticalScrollBarEnabled()
11252     * @see #setHorizontalScrollBarEnabled(boolean)
11253     * @see #setVerticalScrollBarEnabled(boolean)
11254     */
11255    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
11256        final ScrollabilityCache scrollCache = mScrollCache;
11257
11258        if (scrollCache == null || !scrollCache.fadeScrollBars) {
11259            return false;
11260        }
11261
11262        if (scrollCache.scrollBar == null) {
11263            scrollCache.scrollBar = new ScrollBarDrawable();
11264        }
11265
11266        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
11267
11268            if (invalidate) {
11269                // Invalidate to show the scrollbars
11270                postInvalidateOnAnimation();
11271            }
11272
11273            if (scrollCache.state == ScrollabilityCache.OFF) {
11274                // FIXME: this is copied from WindowManagerService.
11275                // We should get this value from the system when it
11276                // is possible to do so.
11277                final int KEY_REPEAT_FIRST_DELAY = 750;
11278                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
11279            }
11280
11281            // Tell mScrollCache when we should start fading. This may
11282            // extend the fade start time if one was already scheduled
11283            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
11284            scrollCache.fadeStartTime = fadeStartTime;
11285            scrollCache.state = ScrollabilityCache.ON;
11286
11287            // Schedule our fader to run, unscheduling any old ones first
11288            if (mAttachInfo != null) {
11289                mAttachInfo.mHandler.removeCallbacks(scrollCache);
11290                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
11291            }
11292
11293            return true;
11294        }
11295
11296        return false;
11297    }
11298
11299    /**
11300     * Do not invalidate views which are not visible and which are not running an animation. They
11301     * will not get drawn and they should not set dirty flags as if they will be drawn
11302     */
11303    private boolean skipInvalidate() {
11304        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
11305                (!(mParent instanceof ViewGroup) ||
11306                        !((ViewGroup) mParent).isViewTransitioning(this));
11307    }
11308
11309    /**
11310     * Mark the area defined by dirty as needing to be drawn. If the view is
11311     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11312     * point in the future.
11313     * <p>
11314     * This must be called from a UI thread. To call from a non-UI thread, call
11315     * {@link #postInvalidate()}.
11316     * <p>
11317     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
11318     * {@code dirty}.
11319     *
11320     * @param dirty the rectangle representing the bounds of the dirty region
11321     */
11322    public void invalidate(Rect dirty) {
11323        final int scrollX = mScrollX;
11324        final int scrollY = mScrollY;
11325        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
11326                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
11327    }
11328
11329    /**
11330     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
11331     * coordinates of the dirty rect are relative to the view. If the view is
11332     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11333     * point in the future.
11334     * <p>
11335     * This must be called from a UI thread. To call from a non-UI thread, call
11336     * {@link #postInvalidate()}.
11337     *
11338     * @param l the left position of the dirty region
11339     * @param t the top position of the dirty region
11340     * @param r the right position of the dirty region
11341     * @param b the bottom position of the dirty region
11342     */
11343    public void invalidate(int l, int t, int r, int b) {
11344        final int scrollX = mScrollX;
11345        final int scrollY = mScrollY;
11346        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
11347    }
11348
11349    /**
11350     * Invalidate the whole view. If the view is visible,
11351     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
11352     * the future.
11353     * <p>
11354     * This must be called from a UI thread. To call from a non-UI thread, call
11355     * {@link #postInvalidate()}.
11356     */
11357    public void invalidate() {
11358        invalidate(true);
11359    }
11360
11361    /**
11362     * This is where the invalidate() work actually happens. A full invalidate()
11363     * causes the drawing cache to be invalidated, but this function can be
11364     * called with invalidateCache set to false to skip that invalidation step
11365     * for cases that do not need it (for example, a component that remains at
11366     * the same dimensions with the same content).
11367     *
11368     * @param invalidateCache Whether the drawing cache for this view should be
11369     *            invalidated as well. This is usually true for a full
11370     *            invalidate, but may be set to false if the View's contents or
11371     *            dimensions have not changed.
11372     */
11373    void invalidate(boolean invalidateCache) {
11374        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
11375    }
11376
11377    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
11378            boolean fullInvalidate) {
11379        if (skipInvalidate()) {
11380            return;
11381        }
11382
11383        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
11384                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
11385                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
11386                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
11387            if (fullInvalidate) {
11388                mLastIsOpaque = isOpaque();
11389                mPrivateFlags &= ~PFLAG_DRAWN;
11390            }
11391
11392            mPrivateFlags |= PFLAG_DIRTY;
11393
11394            if (invalidateCache) {
11395                mPrivateFlags |= PFLAG_INVALIDATED;
11396                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11397            }
11398
11399            // Propagate the damage rectangle to the parent view.
11400            final AttachInfo ai = mAttachInfo;
11401            final ViewParent p = mParent;
11402            if (p != null && ai != null && l < r && t < b) {
11403                final Rect damage = ai.mTmpInvalRect;
11404                damage.set(l, t, r, b);
11405                p.invalidateChild(this, damage);
11406            }
11407
11408            // Damage the entire projection receiver, if necessary.
11409            if (mBackground != null && mBackground.isProjected()) {
11410                final View receiver = getProjectionReceiver();
11411                if (receiver != null) {
11412                    receiver.damageInParent();
11413                }
11414            }
11415
11416            // Damage the entire IsolatedZVolume recieving this view's shadow.
11417            if (isHardwareAccelerated() && getZ() != 0) {
11418                damageShadowReceiver();
11419            }
11420        }
11421    }
11422
11423    /**
11424     * @return this view's projection receiver, or {@code null} if none exists
11425     */
11426    private View getProjectionReceiver() {
11427        ViewParent p = getParent();
11428        while (p != null && p instanceof View) {
11429            final View v = (View) p;
11430            if (v.isProjectionReceiver()) {
11431                return v;
11432            }
11433            p = p.getParent();
11434        }
11435
11436        return null;
11437    }
11438
11439    /**
11440     * @return whether the view is a projection receiver
11441     */
11442    private boolean isProjectionReceiver() {
11443        return mBackground != null;
11444    }
11445
11446    /**
11447     * Damage area of the screen that can be covered by this View's shadow.
11448     *
11449     * This method will guarantee that any changes to shadows cast by a View
11450     * are damaged on the screen for future redraw.
11451     */
11452    private void damageShadowReceiver() {
11453        final AttachInfo ai = mAttachInfo;
11454        if (ai != null) {
11455            ViewParent p = getParent();
11456            if (p != null && p instanceof ViewGroup) {
11457                final ViewGroup vg = (ViewGroup) p;
11458                vg.damageInParent();
11459            }
11460        }
11461    }
11462
11463    /**
11464     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
11465     * set any flags or handle all of the cases handled by the default invalidation methods.
11466     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
11467     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
11468     * walk up the hierarchy, transforming the dirty rect as necessary.
11469     *
11470     * The method also handles normal invalidation logic if display list properties are not
11471     * being used in this view. The invalidateParent and forceRedraw flags are used by that
11472     * backup approach, to handle these cases used in the various property-setting methods.
11473     *
11474     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
11475     * are not being used in this view
11476     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
11477     * list properties are not being used in this view
11478     */
11479    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
11480        if (!isHardwareAccelerated()
11481                || !mRenderNode.isValid()
11482                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
11483            if (invalidateParent) {
11484                invalidateParentCaches();
11485            }
11486            if (forceRedraw) {
11487                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11488            }
11489            invalidate(false);
11490        } else {
11491            damageInParent();
11492        }
11493        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
11494            damageShadowReceiver();
11495        }
11496    }
11497
11498    /**
11499     * Tells the parent view to damage this view's bounds.
11500     *
11501     * @hide
11502     */
11503    protected void damageInParent() {
11504        final AttachInfo ai = mAttachInfo;
11505        final ViewParent p = mParent;
11506        if (p != null && ai != null) {
11507            final Rect r = ai.mTmpInvalRect;
11508            r.set(0, 0, mRight - mLeft, mBottom - mTop);
11509            if (mParent instanceof ViewGroup) {
11510                ((ViewGroup) mParent).damageChild(this, r);
11511            } else {
11512                mParent.invalidateChild(this, r);
11513            }
11514        }
11515    }
11516
11517    /**
11518     * Utility method to transform a given Rect by the current matrix of this view.
11519     */
11520    void transformRect(final Rect rect) {
11521        if (!getMatrix().isIdentity()) {
11522            RectF boundingRect = mAttachInfo.mTmpTransformRect;
11523            boundingRect.set(rect);
11524            getMatrix().mapRect(boundingRect);
11525            rect.set((int) Math.floor(boundingRect.left),
11526                    (int) Math.floor(boundingRect.top),
11527                    (int) Math.ceil(boundingRect.right),
11528                    (int) Math.ceil(boundingRect.bottom));
11529        }
11530    }
11531
11532    /**
11533     * Used to indicate that the parent of this view should clear its caches. This functionality
11534     * is used to force the parent to rebuild its display list (when hardware-accelerated),
11535     * which is necessary when various parent-managed properties of the view change, such as
11536     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
11537     * clears the parent caches and does not causes an invalidate event.
11538     *
11539     * @hide
11540     */
11541    protected void invalidateParentCaches() {
11542        if (mParent instanceof View) {
11543            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
11544        }
11545    }
11546
11547    /**
11548     * Used to indicate that the parent of this view should be invalidated. This functionality
11549     * is used to force the parent to rebuild its display list (when hardware-accelerated),
11550     * which is necessary when various parent-managed properties of the view change, such as
11551     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
11552     * an invalidation event to the parent.
11553     *
11554     * @hide
11555     */
11556    protected void invalidateParentIfNeeded() {
11557        if (isHardwareAccelerated() && mParent instanceof View) {
11558            ((View) mParent).invalidate(true);
11559        }
11560    }
11561
11562    /**
11563     * @hide
11564     */
11565    protected void invalidateParentIfNeededAndWasQuickRejected() {
11566        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
11567            // View was rejected last time it was drawn by its parent; this may have changed
11568            invalidateParentIfNeeded();
11569        }
11570    }
11571
11572    /**
11573     * Indicates whether this View is opaque. An opaque View guarantees that it will
11574     * draw all the pixels overlapping its bounds using a fully opaque color.
11575     *
11576     * Subclasses of View should override this method whenever possible to indicate
11577     * whether an instance is opaque. Opaque Views are treated in a special way by
11578     * the View hierarchy, possibly allowing it to perform optimizations during
11579     * invalidate/draw passes.
11580     *
11581     * @return True if this View is guaranteed to be fully opaque, false otherwise.
11582     */
11583    @ViewDebug.ExportedProperty(category = "drawing")
11584    public boolean isOpaque() {
11585        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
11586                getFinalAlpha() >= 1.0f;
11587    }
11588
11589    /**
11590     * @hide
11591     */
11592    protected void computeOpaqueFlags() {
11593        // Opaque if:
11594        //   - Has a background
11595        //   - Background is opaque
11596        //   - Doesn't have scrollbars or scrollbars overlay
11597
11598        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
11599            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
11600        } else {
11601            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
11602        }
11603
11604        final int flags = mViewFlags;
11605        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
11606                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
11607                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
11608            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
11609        } else {
11610            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
11611        }
11612    }
11613
11614    /**
11615     * @hide
11616     */
11617    protected boolean hasOpaqueScrollbars() {
11618        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
11619    }
11620
11621    /**
11622     * @return A handler associated with the thread running the View. This
11623     * handler can be used to pump events in the UI events queue.
11624     */
11625    public Handler getHandler() {
11626        final AttachInfo attachInfo = mAttachInfo;
11627        if (attachInfo != null) {
11628            return attachInfo.mHandler;
11629        }
11630        return null;
11631    }
11632
11633    /**
11634     * Gets the view root associated with the View.
11635     * @return The view root, or null if none.
11636     * @hide
11637     */
11638    public ViewRootImpl getViewRootImpl() {
11639        if (mAttachInfo != null) {
11640            return mAttachInfo.mViewRootImpl;
11641        }
11642        return null;
11643    }
11644
11645    /**
11646     * @hide
11647     */
11648    public HardwareRenderer getHardwareRenderer() {
11649        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
11650    }
11651
11652    /**
11653     * <p>Causes the Runnable to be added to the message queue.
11654     * The runnable will be run on the user interface thread.</p>
11655     *
11656     * @param action The Runnable that will be executed.
11657     *
11658     * @return Returns true if the Runnable was successfully placed in to the
11659     *         message queue.  Returns false on failure, usually because the
11660     *         looper processing the message queue is exiting.
11661     *
11662     * @see #postDelayed
11663     * @see #removeCallbacks
11664     */
11665    public boolean post(Runnable action) {
11666        final AttachInfo attachInfo = mAttachInfo;
11667        if (attachInfo != null) {
11668            return attachInfo.mHandler.post(action);
11669        }
11670        // Assume that post will succeed later
11671        ViewRootImpl.getRunQueue().post(action);
11672        return true;
11673    }
11674
11675    /**
11676     * <p>Causes the Runnable to be added to the message queue, to be run
11677     * after the specified amount of time elapses.
11678     * The runnable will be run on the user interface thread.</p>
11679     *
11680     * @param action The Runnable that will be executed.
11681     * @param delayMillis The delay (in milliseconds) until the Runnable
11682     *        will be executed.
11683     *
11684     * @return true if the Runnable was successfully placed in to the
11685     *         message queue.  Returns false on failure, usually because the
11686     *         looper processing the message queue is exiting.  Note that a
11687     *         result of true does not mean the Runnable will be processed --
11688     *         if the looper is quit before the delivery time of the message
11689     *         occurs then the message will be dropped.
11690     *
11691     * @see #post
11692     * @see #removeCallbacks
11693     */
11694    public boolean postDelayed(Runnable action, long delayMillis) {
11695        final AttachInfo attachInfo = mAttachInfo;
11696        if (attachInfo != null) {
11697            return attachInfo.mHandler.postDelayed(action, delayMillis);
11698        }
11699        // Assume that post will succeed later
11700        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
11701        return true;
11702    }
11703
11704    /**
11705     * <p>Causes the Runnable to execute on the next animation time step.
11706     * The runnable will be run on the user interface thread.</p>
11707     *
11708     * @param action The Runnable that will be executed.
11709     *
11710     * @see #postOnAnimationDelayed
11711     * @see #removeCallbacks
11712     */
11713    public void postOnAnimation(Runnable action) {
11714        final AttachInfo attachInfo = mAttachInfo;
11715        if (attachInfo != null) {
11716            attachInfo.mViewRootImpl.mChoreographer.postCallback(
11717                    Choreographer.CALLBACK_ANIMATION, action, null);
11718        } else {
11719            // Assume that post will succeed later
11720            ViewRootImpl.getRunQueue().post(action);
11721        }
11722    }
11723
11724    /**
11725     * <p>Causes the Runnable to execute on the next animation time step,
11726     * after the specified amount of time elapses.
11727     * The runnable will be run on the user interface thread.</p>
11728     *
11729     * @param action The Runnable that will be executed.
11730     * @param delayMillis The delay (in milliseconds) until the Runnable
11731     *        will be executed.
11732     *
11733     * @see #postOnAnimation
11734     * @see #removeCallbacks
11735     */
11736    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
11737        final AttachInfo attachInfo = mAttachInfo;
11738        if (attachInfo != null) {
11739            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
11740                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
11741        } else {
11742            // Assume that post will succeed later
11743            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
11744        }
11745    }
11746
11747    /**
11748     * <p>Removes the specified Runnable from the message queue.</p>
11749     *
11750     * @param action The Runnable to remove from the message handling queue
11751     *
11752     * @return true if this view could ask the Handler to remove the Runnable,
11753     *         false otherwise. When the returned value is true, the Runnable
11754     *         may or may not have been actually removed from the message queue
11755     *         (for instance, if the Runnable was not in the queue already.)
11756     *
11757     * @see #post
11758     * @see #postDelayed
11759     * @see #postOnAnimation
11760     * @see #postOnAnimationDelayed
11761     */
11762    public boolean removeCallbacks(Runnable action) {
11763        if (action != null) {
11764            final AttachInfo attachInfo = mAttachInfo;
11765            if (attachInfo != null) {
11766                attachInfo.mHandler.removeCallbacks(action);
11767                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
11768                        Choreographer.CALLBACK_ANIMATION, action, null);
11769            }
11770            // Assume that post will succeed later
11771            ViewRootImpl.getRunQueue().removeCallbacks(action);
11772        }
11773        return true;
11774    }
11775
11776    /**
11777     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
11778     * Use this to invalidate the View from a non-UI thread.</p>
11779     *
11780     * <p>This method can be invoked from outside of the UI thread
11781     * only when this View is attached to a window.</p>
11782     *
11783     * @see #invalidate()
11784     * @see #postInvalidateDelayed(long)
11785     */
11786    public void postInvalidate() {
11787        postInvalidateDelayed(0);
11788    }
11789
11790    /**
11791     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
11792     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
11793     *
11794     * <p>This method can be invoked from outside of the UI thread
11795     * only when this View is attached to a window.</p>
11796     *
11797     * @param left The left coordinate of the rectangle to invalidate.
11798     * @param top The top coordinate of the rectangle to invalidate.
11799     * @param right The right coordinate of the rectangle to invalidate.
11800     * @param bottom The bottom coordinate of the rectangle to invalidate.
11801     *
11802     * @see #invalidate(int, int, int, int)
11803     * @see #invalidate(Rect)
11804     * @see #postInvalidateDelayed(long, int, int, int, int)
11805     */
11806    public void postInvalidate(int left, int top, int right, int bottom) {
11807        postInvalidateDelayed(0, left, top, right, bottom);
11808    }
11809
11810    /**
11811     * <p>Cause an invalidate to happen on a subsequent cycle through the event
11812     * loop. Waits for the specified amount of time.</p>
11813     *
11814     * <p>This method can be invoked from outside of the UI thread
11815     * only when this View is attached to a window.</p>
11816     *
11817     * @param delayMilliseconds the duration in milliseconds to delay the
11818     *         invalidation by
11819     *
11820     * @see #invalidate()
11821     * @see #postInvalidate()
11822     */
11823    public void postInvalidateDelayed(long delayMilliseconds) {
11824        // We try only with the AttachInfo because there's no point in invalidating
11825        // if we are not attached to our window
11826        final AttachInfo attachInfo = mAttachInfo;
11827        if (attachInfo != null) {
11828            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
11829        }
11830    }
11831
11832    /**
11833     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
11834     * through the event loop. Waits for the specified amount of time.</p>
11835     *
11836     * <p>This method can be invoked from outside of the UI thread
11837     * only when this View is attached to a window.</p>
11838     *
11839     * @param delayMilliseconds the duration in milliseconds to delay the
11840     *         invalidation by
11841     * @param left The left coordinate of the rectangle to invalidate.
11842     * @param top The top coordinate of the rectangle to invalidate.
11843     * @param right The right coordinate of the rectangle to invalidate.
11844     * @param bottom The bottom coordinate of the rectangle to invalidate.
11845     *
11846     * @see #invalidate(int, int, int, int)
11847     * @see #invalidate(Rect)
11848     * @see #postInvalidate(int, int, int, int)
11849     */
11850    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
11851            int right, int bottom) {
11852
11853        // We try only with the AttachInfo because there's no point in invalidating
11854        // if we are not attached to our window
11855        final AttachInfo attachInfo = mAttachInfo;
11856        if (attachInfo != null) {
11857            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
11858            info.target = this;
11859            info.left = left;
11860            info.top = top;
11861            info.right = right;
11862            info.bottom = bottom;
11863
11864            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
11865        }
11866    }
11867
11868    /**
11869     * <p>Cause an invalidate to happen on the next animation time step, typically the
11870     * next display frame.</p>
11871     *
11872     * <p>This method can be invoked from outside of the UI thread
11873     * only when this View is attached to a window.</p>
11874     *
11875     * @see #invalidate()
11876     */
11877    public void postInvalidateOnAnimation() {
11878        // We try only with the AttachInfo because there's no point in invalidating
11879        // if we are not attached to our window
11880        final AttachInfo attachInfo = mAttachInfo;
11881        if (attachInfo != null) {
11882            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
11883        }
11884    }
11885
11886    /**
11887     * <p>Cause an invalidate of the specified area to happen on the next animation
11888     * time step, typically the next display frame.</p>
11889     *
11890     * <p>This method can be invoked from outside of the UI thread
11891     * only when this View is attached to a window.</p>
11892     *
11893     * @param left The left coordinate of the rectangle to invalidate.
11894     * @param top The top coordinate of the rectangle to invalidate.
11895     * @param right The right coordinate of the rectangle to invalidate.
11896     * @param bottom The bottom coordinate of the rectangle to invalidate.
11897     *
11898     * @see #invalidate(int, int, int, int)
11899     * @see #invalidate(Rect)
11900     */
11901    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
11902        // We try only with the AttachInfo because there's no point in invalidating
11903        // if we are not attached to our window
11904        final AttachInfo attachInfo = mAttachInfo;
11905        if (attachInfo != null) {
11906            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
11907            info.target = this;
11908            info.left = left;
11909            info.top = top;
11910            info.right = right;
11911            info.bottom = bottom;
11912
11913            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
11914        }
11915    }
11916
11917    /**
11918     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
11919     * This event is sent at most once every
11920     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
11921     */
11922    private void postSendViewScrolledAccessibilityEventCallback() {
11923        if (mSendViewScrolledAccessibilityEvent == null) {
11924            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
11925        }
11926        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
11927            mSendViewScrolledAccessibilityEvent.mIsPending = true;
11928            postDelayed(mSendViewScrolledAccessibilityEvent,
11929                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
11930        }
11931    }
11932
11933    /**
11934     * Called by a parent to request that a child update its values for mScrollX
11935     * and mScrollY if necessary. This will typically be done if the child is
11936     * animating a scroll using a {@link android.widget.Scroller Scroller}
11937     * object.
11938     */
11939    public void computeScroll() {
11940    }
11941
11942    /**
11943     * <p>Indicate whether the horizontal edges are faded when the view is
11944     * scrolled horizontally.</p>
11945     *
11946     * @return true if the horizontal edges should are faded on scroll, false
11947     *         otherwise
11948     *
11949     * @see #setHorizontalFadingEdgeEnabled(boolean)
11950     *
11951     * @attr ref android.R.styleable#View_requiresFadingEdge
11952     */
11953    public boolean isHorizontalFadingEdgeEnabled() {
11954        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
11955    }
11956
11957    /**
11958     * <p>Define whether the horizontal edges should be faded when this view
11959     * is scrolled horizontally.</p>
11960     *
11961     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
11962     *                                    be faded when the view is scrolled
11963     *                                    horizontally
11964     *
11965     * @see #isHorizontalFadingEdgeEnabled()
11966     *
11967     * @attr ref android.R.styleable#View_requiresFadingEdge
11968     */
11969    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
11970        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
11971            if (horizontalFadingEdgeEnabled) {
11972                initScrollCache();
11973            }
11974
11975            mViewFlags ^= FADING_EDGE_HORIZONTAL;
11976        }
11977    }
11978
11979    /**
11980     * <p>Indicate whether the vertical edges are faded when the view is
11981     * scrolled horizontally.</p>
11982     *
11983     * @return true if the vertical edges should are faded on scroll, false
11984     *         otherwise
11985     *
11986     * @see #setVerticalFadingEdgeEnabled(boolean)
11987     *
11988     * @attr ref android.R.styleable#View_requiresFadingEdge
11989     */
11990    public boolean isVerticalFadingEdgeEnabled() {
11991        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
11992    }
11993
11994    /**
11995     * <p>Define whether the vertical edges should be faded when this view
11996     * is scrolled vertically.</p>
11997     *
11998     * @param verticalFadingEdgeEnabled true if the vertical edges should
11999     *                                  be faded when the view is scrolled
12000     *                                  vertically
12001     *
12002     * @see #isVerticalFadingEdgeEnabled()
12003     *
12004     * @attr ref android.R.styleable#View_requiresFadingEdge
12005     */
12006    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
12007        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
12008            if (verticalFadingEdgeEnabled) {
12009                initScrollCache();
12010            }
12011
12012            mViewFlags ^= FADING_EDGE_VERTICAL;
12013        }
12014    }
12015
12016    /**
12017     * Returns the strength, or intensity, of the top faded edge. The strength is
12018     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12019     * returns 0.0 or 1.0 but no value in between.
12020     *
12021     * Subclasses should override this method to provide a smoother fade transition
12022     * when scrolling occurs.
12023     *
12024     * @return the intensity of the top fade as a float between 0.0f and 1.0f
12025     */
12026    protected float getTopFadingEdgeStrength() {
12027        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
12028    }
12029
12030    /**
12031     * Returns the strength, or intensity, of the bottom faded edge. The strength is
12032     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12033     * returns 0.0 or 1.0 but no value in between.
12034     *
12035     * Subclasses should override this method to provide a smoother fade transition
12036     * when scrolling occurs.
12037     *
12038     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
12039     */
12040    protected float getBottomFadingEdgeStrength() {
12041        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
12042                computeVerticalScrollRange() ? 1.0f : 0.0f;
12043    }
12044
12045    /**
12046     * Returns the strength, or intensity, of the left faded edge. The strength is
12047     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12048     * returns 0.0 or 1.0 but no value in between.
12049     *
12050     * Subclasses should override this method to provide a smoother fade transition
12051     * when scrolling occurs.
12052     *
12053     * @return the intensity of the left fade as a float between 0.0f and 1.0f
12054     */
12055    protected float getLeftFadingEdgeStrength() {
12056        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
12057    }
12058
12059    /**
12060     * Returns the strength, or intensity, of the right faded edge. The strength is
12061     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12062     * returns 0.0 or 1.0 but no value in between.
12063     *
12064     * Subclasses should override this method to provide a smoother fade transition
12065     * when scrolling occurs.
12066     *
12067     * @return the intensity of the right fade as a float between 0.0f and 1.0f
12068     */
12069    protected float getRightFadingEdgeStrength() {
12070        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
12071                computeHorizontalScrollRange() ? 1.0f : 0.0f;
12072    }
12073
12074    /**
12075     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
12076     * scrollbar is not drawn by default.</p>
12077     *
12078     * @return true if the horizontal scrollbar should be painted, false
12079     *         otherwise
12080     *
12081     * @see #setHorizontalScrollBarEnabled(boolean)
12082     */
12083    public boolean isHorizontalScrollBarEnabled() {
12084        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12085    }
12086
12087    /**
12088     * <p>Define whether the horizontal scrollbar should be drawn or not. The
12089     * scrollbar is not drawn by default.</p>
12090     *
12091     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
12092     *                                   be painted
12093     *
12094     * @see #isHorizontalScrollBarEnabled()
12095     */
12096    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
12097        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
12098            mViewFlags ^= SCROLLBARS_HORIZONTAL;
12099            computeOpaqueFlags();
12100            resolvePadding();
12101        }
12102    }
12103
12104    /**
12105     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
12106     * scrollbar is not drawn by default.</p>
12107     *
12108     * @return true if the vertical scrollbar should be painted, false
12109     *         otherwise
12110     *
12111     * @see #setVerticalScrollBarEnabled(boolean)
12112     */
12113    public boolean isVerticalScrollBarEnabled() {
12114        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
12115    }
12116
12117    /**
12118     * <p>Define whether the vertical scrollbar should be drawn or not. The
12119     * scrollbar is not drawn by default.</p>
12120     *
12121     * @param verticalScrollBarEnabled true if the vertical scrollbar should
12122     *                                 be painted
12123     *
12124     * @see #isVerticalScrollBarEnabled()
12125     */
12126    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
12127        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
12128            mViewFlags ^= SCROLLBARS_VERTICAL;
12129            computeOpaqueFlags();
12130            resolvePadding();
12131        }
12132    }
12133
12134    /**
12135     * @hide
12136     */
12137    protected void recomputePadding() {
12138        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
12139    }
12140
12141    /**
12142     * Define whether scrollbars will fade when the view is not scrolling.
12143     *
12144     * @param fadeScrollbars wheter to enable fading
12145     *
12146     * @attr ref android.R.styleable#View_fadeScrollbars
12147     */
12148    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
12149        initScrollCache();
12150        final ScrollabilityCache scrollabilityCache = mScrollCache;
12151        scrollabilityCache.fadeScrollBars = fadeScrollbars;
12152        if (fadeScrollbars) {
12153            scrollabilityCache.state = ScrollabilityCache.OFF;
12154        } else {
12155            scrollabilityCache.state = ScrollabilityCache.ON;
12156        }
12157    }
12158
12159    /**
12160     *
12161     * Returns true if scrollbars will fade when this view is not scrolling
12162     *
12163     * @return true if scrollbar fading is enabled
12164     *
12165     * @attr ref android.R.styleable#View_fadeScrollbars
12166     */
12167    public boolean isScrollbarFadingEnabled() {
12168        return mScrollCache != null && mScrollCache.fadeScrollBars;
12169    }
12170
12171    /**
12172     *
12173     * Returns the delay before scrollbars fade.
12174     *
12175     * @return the delay before scrollbars fade
12176     *
12177     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12178     */
12179    public int getScrollBarDefaultDelayBeforeFade() {
12180        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
12181                mScrollCache.scrollBarDefaultDelayBeforeFade;
12182    }
12183
12184    /**
12185     * Define the delay before scrollbars fade.
12186     *
12187     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
12188     *
12189     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12190     */
12191    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
12192        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
12193    }
12194
12195    /**
12196     *
12197     * Returns the scrollbar fade duration.
12198     *
12199     * @return the scrollbar fade duration
12200     *
12201     * @attr ref android.R.styleable#View_scrollbarFadeDuration
12202     */
12203    public int getScrollBarFadeDuration() {
12204        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
12205                mScrollCache.scrollBarFadeDuration;
12206    }
12207
12208    /**
12209     * Define the scrollbar fade duration.
12210     *
12211     * @param scrollBarFadeDuration - the scrollbar fade duration
12212     *
12213     * @attr ref android.R.styleable#View_scrollbarFadeDuration
12214     */
12215    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
12216        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
12217    }
12218
12219    /**
12220     *
12221     * Returns the scrollbar size.
12222     *
12223     * @return the scrollbar size
12224     *
12225     * @attr ref android.R.styleable#View_scrollbarSize
12226     */
12227    public int getScrollBarSize() {
12228        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
12229                mScrollCache.scrollBarSize;
12230    }
12231
12232    /**
12233     * Define the scrollbar size.
12234     *
12235     * @param scrollBarSize - the scrollbar size
12236     *
12237     * @attr ref android.R.styleable#View_scrollbarSize
12238     */
12239    public void setScrollBarSize(int scrollBarSize) {
12240        getScrollCache().scrollBarSize = scrollBarSize;
12241    }
12242
12243    /**
12244     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
12245     * inset. When inset, they add to the padding of the view. And the scrollbars
12246     * can be drawn inside the padding area or on the edge of the view. For example,
12247     * if a view has a background drawable and you want to draw the scrollbars
12248     * inside the padding specified by the drawable, you can use
12249     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
12250     * appear at the edge of the view, ignoring the padding, then you can use
12251     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
12252     * @param style the style of the scrollbars. Should be one of
12253     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
12254     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
12255     * @see #SCROLLBARS_INSIDE_OVERLAY
12256     * @see #SCROLLBARS_INSIDE_INSET
12257     * @see #SCROLLBARS_OUTSIDE_OVERLAY
12258     * @see #SCROLLBARS_OUTSIDE_INSET
12259     *
12260     * @attr ref android.R.styleable#View_scrollbarStyle
12261     */
12262    public void setScrollBarStyle(@ScrollBarStyle int style) {
12263        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
12264            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
12265            computeOpaqueFlags();
12266            resolvePadding();
12267        }
12268    }
12269
12270    /**
12271     * <p>Returns the current scrollbar style.</p>
12272     * @return the current scrollbar style
12273     * @see #SCROLLBARS_INSIDE_OVERLAY
12274     * @see #SCROLLBARS_INSIDE_INSET
12275     * @see #SCROLLBARS_OUTSIDE_OVERLAY
12276     * @see #SCROLLBARS_OUTSIDE_INSET
12277     *
12278     * @attr ref android.R.styleable#View_scrollbarStyle
12279     */
12280    @ViewDebug.ExportedProperty(mapping = {
12281            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
12282            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
12283            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
12284            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
12285    })
12286    @ScrollBarStyle
12287    public int getScrollBarStyle() {
12288        return mViewFlags & SCROLLBARS_STYLE_MASK;
12289    }
12290
12291    /**
12292     * <p>Compute the horizontal range that the horizontal scrollbar
12293     * represents.</p>
12294     *
12295     * <p>The range is expressed in arbitrary units that must be the same as the
12296     * units used by {@link #computeHorizontalScrollExtent()} and
12297     * {@link #computeHorizontalScrollOffset()}.</p>
12298     *
12299     * <p>The default range is the drawing width of this view.</p>
12300     *
12301     * @return the total horizontal range represented by the horizontal
12302     *         scrollbar
12303     *
12304     * @see #computeHorizontalScrollExtent()
12305     * @see #computeHorizontalScrollOffset()
12306     * @see android.widget.ScrollBarDrawable
12307     */
12308    protected int computeHorizontalScrollRange() {
12309        return getWidth();
12310    }
12311
12312    /**
12313     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
12314     * within the horizontal range. This value is used to compute the position
12315     * of the thumb within the scrollbar's track.</p>
12316     *
12317     * <p>The range is expressed in arbitrary units that must be the same as the
12318     * units used by {@link #computeHorizontalScrollRange()} and
12319     * {@link #computeHorizontalScrollExtent()}.</p>
12320     *
12321     * <p>The default offset is the scroll offset of this view.</p>
12322     *
12323     * @return the horizontal offset of the scrollbar's thumb
12324     *
12325     * @see #computeHorizontalScrollRange()
12326     * @see #computeHorizontalScrollExtent()
12327     * @see android.widget.ScrollBarDrawable
12328     */
12329    protected int computeHorizontalScrollOffset() {
12330        return mScrollX;
12331    }
12332
12333    /**
12334     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
12335     * within the horizontal range. This value is used to compute the length
12336     * of the thumb within the scrollbar's track.</p>
12337     *
12338     * <p>The range is expressed in arbitrary units that must be the same as the
12339     * units used by {@link #computeHorizontalScrollRange()} and
12340     * {@link #computeHorizontalScrollOffset()}.</p>
12341     *
12342     * <p>The default extent is the drawing width of this view.</p>
12343     *
12344     * @return the horizontal extent of the scrollbar's thumb
12345     *
12346     * @see #computeHorizontalScrollRange()
12347     * @see #computeHorizontalScrollOffset()
12348     * @see android.widget.ScrollBarDrawable
12349     */
12350    protected int computeHorizontalScrollExtent() {
12351        return getWidth();
12352    }
12353
12354    /**
12355     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
12356     *
12357     * <p>The range is expressed in arbitrary units that must be the same as the
12358     * units used by {@link #computeVerticalScrollExtent()} and
12359     * {@link #computeVerticalScrollOffset()}.</p>
12360     *
12361     * @return the total vertical range represented by the vertical scrollbar
12362     *
12363     * <p>The default range is the drawing height of this view.</p>
12364     *
12365     * @see #computeVerticalScrollExtent()
12366     * @see #computeVerticalScrollOffset()
12367     * @see android.widget.ScrollBarDrawable
12368     */
12369    protected int computeVerticalScrollRange() {
12370        return getHeight();
12371    }
12372
12373    /**
12374     * <p>Compute the vertical offset of the vertical scrollbar's thumb
12375     * within the horizontal range. This value is used to compute the position
12376     * of the thumb within the scrollbar's track.</p>
12377     *
12378     * <p>The range is expressed in arbitrary units that must be the same as the
12379     * units used by {@link #computeVerticalScrollRange()} and
12380     * {@link #computeVerticalScrollExtent()}.</p>
12381     *
12382     * <p>The default offset is the scroll offset of this view.</p>
12383     *
12384     * @return the vertical offset of the scrollbar's thumb
12385     *
12386     * @see #computeVerticalScrollRange()
12387     * @see #computeVerticalScrollExtent()
12388     * @see android.widget.ScrollBarDrawable
12389     */
12390    protected int computeVerticalScrollOffset() {
12391        return mScrollY;
12392    }
12393
12394    /**
12395     * <p>Compute the vertical extent of the vertical scrollbar's thumb
12396     * within the vertical range. This value is used to compute the length
12397     * of the thumb within the scrollbar's track.</p>
12398     *
12399     * <p>The range is expressed in arbitrary units that must be the same as the
12400     * units used by {@link #computeVerticalScrollRange()} and
12401     * {@link #computeVerticalScrollOffset()}.</p>
12402     *
12403     * <p>The default extent is the drawing height of this view.</p>
12404     *
12405     * @return the vertical extent of the scrollbar's thumb
12406     *
12407     * @see #computeVerticalScrollRange()
12408     * @see #computeVerticalScrollOffset()
12409     * @see android.widget.ScrollBarDrawable
12410     */
12411    protected int computeVerticalScrollExtent() {
12412        return getHeight();
12413    }
12414
12415    /**
12416     * Check if this view can be scrolled horizontally in a certain direction.
12417     *
12418     * @param direction Negative to check scrolling left, positive to check scrolling right.
12419     * @return true if this view can be scrolled in the specified direction, false otherwise.
12420     */
12421    public boolean canScrollHorizontally(int direction) {
12422        final int offset = computeHorizontalScrollOffset();
12423        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
12424        if (range == 0) return false;
12425        if (direction < 0) {
12426            return offset > 0;
12427        } else {
12428            return offset < range - 1;
12429        }
12430    }
12431
12432    /**
12433     * Check if this view can be scrolled vertically in a certain direction.
12434     *
12435     * @param direction Negative to check scrolling up, positive to check scrolling down.
12436     * @return true if this view can be scrolled in the specified direction, false otherwise.
12437     */
12438    public boolean canScrollVertically(int direction) {
12439        final int offset = computeVerticalScrollOffset();
12440        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
12441        if (range == 0) return false;
12442        if (direction < 0) {
12443            return offset > 0;
12444        } else {
12445            return offset < range - 1;
12446        }
12447    }
12448
12449    /**
12450     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
12451     * scrollbars are painted only if they have been awakened first.</p>
12452     *
12453     * @param canvas the canvas on which to draw the scrollbars
12454     *
12455     * @see #awakenScrollBars(int)
12456     */
12457    protected final void onDrawScrollBars(Canvas canvas) {
12458        // scrollbars are drawn only when the animation is running
12459        final ScrollabilityCache cache = mScrollCache;
12460        if (cache != null) {
12461
12462            int state = cache.state;
12463
12464            if (state == ScrollabilityCache.OFF) {
12465                return;
12466            }
12467
12468            boolean invalidate = false;
12469
12470            if (state == ScrollabilityCache.FADING) {
12471                // We're fading -- get our fade interpolation
12472                if (cache.interpolatorValues == null) {
12473                    cache.interpolatorValues = new float[1];
12474                }
12475
12476                float[] values = cache.interpolatorValues;
12477
12478                // Stops the animation if we're done
12479                if (cache.scrollBarInterpolator.timeToValues(values) ==
12480                        Interpolator.Result.FREEZE_END) {
12481                    cache.state = ScrollabilityCache.OFF;
12482                } else {
12483                    cache.scrollBar.setAlpha(Math.round(values[0]));
12484                }
12485
12486                // This will make the scroll bars inval themselves after
12487                // drawing. We only want this when we're fading so that
12488                // we prevent excessive redraws
12489                invalidate = true;
12490            } else {
12491                // We're just on -- but we may have been fading before so
12492                // reset alpha
12493                cache.scrollBar.setAlpha(255);
12494            }
12495
12496
12497            final int viewFlags = mViewFlags;
12498
12499            final boolean drawHorizontalScrollBar =
12500                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12501            final boolean drawVerticalScrollBar =
12502                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
12503                && !isVerticalScrollBarHidden();
12504
12505            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
12506                final int width = mRight - mLeft;
12507                final int height = mBottom - mTop;
12508
12509                final ScrollBarDrawable scrollBar = cache.scrollBar;
12510
12511                final int scrollX = mScrollX;
12512                final int scrollY = mScrollY;
12513                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
12514
12515                int left;
12516                int top;
12517                int right;
12518                int bottom;
12519
12520                if (drawHorizontalScrollBar) {
12521                    int size = scrollBar.getSize(false);
12522                    if (size <= 0) {
12523                        size = cache.scrollBarSize;
12524                    }
12525
12526                    scrollBar.setParameters(computeHorizontalScrollRange(),
12527                                            computeHorizontalScrollOffset(),
12528                                            computeHorizontalScrollExtent(), false);
12529                    final int verticalScrollBarGap = drawVerticalScrollBar ?
12530                            getVerticalScrollbarWidth() : 0;
12531                    top = scrollY + height - size - (mUserPaddingBottom & inside);
12532                    left = scrollX + (mPaddingLeft & inside);
12533                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
12534                    bottom = top + size;
12535                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
12536                    if (invalidate) {
12537                        invalidate(left, top, right, bottom);
12538                    }
12539                }
12540
12541                if (drawVerticalScrollBar) {
12542                    int size = scrollBar.getSize(true);
12543                    if (size <= 0) {
12544                        size = cache.scrollBarSize;
12545                    }
12546
12547                    scrollBar.setParameters(computeVerticalScrollRange(),
12548                                            computeVerticalScrollOffset(),
12549                                            computeVerticalScrollExtent(), true);
12550                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
12551                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
12552                        verticalScrollbarPosition = isLayoutRtl() ?
12553                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
12554                    }
12555                    switch (verticalScrollbarPosition) {
12556                        default:
12557                        case SCROLLBAR_POSITION_RIGHT:
12558                            left = scrollX + width - size - (mUserPaddingRight & inside);
12559                            break;
12560                        case SCROLLBAR_POSITION_LEFT:
12561                            left = scrollX + (mUserPaddingLeft & inside);
12562                            break;
12563                    }
12564                    top = scrollY + (mPaddingTop & inside);
12565                    right = left + size;
12566                    bottom = scrollY + height - (mUserPaddingBottom & inside);
12567                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
12568                    if (invalidate) {
12569                        invalidate(left, top, right, bottom);
12570                    }
12571                }
12572            }
12573        }
12574    }
12575
12576    /**
12577     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
12578     * FastScroller is visible.
12579     * @return whether to temporarily hide the vertical scrollbar
12580     * @hide
12581     */
12582    protected boolean isVerticalScrollBarHidden() {
12583        return false;
12584    }
12585
12586    /**
12587     * <p>Draw the horizontal scrollbar if
12588     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
12589     *
12590     * @param canvas the canvas on which to draw the scrollbar
12591     * @param scrollBar the scrollbar's drawable
12592     *
12593     * @see #isHorizontalScrollBarEnabled()
12594     * @see #computeHorizontalScrollRange()
12595     * @see #computeHorizontalScrollExtent()
12596     * @see #computeHorizontalScrollOffset()
12597     * @see android.widget.ScrollBarDrawable
12598     * @hide
12599     */
12600    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
12601            int l, int t, int r, int b) {
12602        scrollBar.setBounds(l, t, r, b);
12603        scrollBar.draw(canvas);
12604    }
12605
12606    /**
12607     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
12608     * returns true.</p>
12609     *
12610     * @param canvas the canvas on which to draw the scrollbar
12611     * @param scrollBar the scrollbar's drawable
12612     *
12613     * @see #isVerticalScrollBarEnabled()
12614     * @see #computeVerticalScrollRange()
12615     * @see #computeVerticalScrollExtent()
12616     * @see #computeVerticalScrollOffset()
12617     * @see android.widget.ScrollBarDrawable
12618     * @hide
12619     */
12620    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
12621            int l, int t, int r, int b) {
12622        scrollBar.setBounds(l, t, r, b);
12623        scrollBar.draw(canvas);
12624    }
12625
12626    /**
12627     * Implement this to do your drawing.
12628     *
12629     * @param canvas the canvas on which the background will be drawn
12630     */
12631    protected void onDraw(Canvas canvas) {
12632    }
12633
12634    /*
12635     * Caller is responsible for calling requestLayout if necessary.
12636     * (This allows addViewInLayout to not request a new layout.)
12637     */
12638    void assignParent(ViewParent parent) {
12639        if (mParent == null) {
12640            mParent = parent;
12641        } else if (parent == null) {
12642            mParent = null;
12643        } else {
12644            throw new RuntimeException("view " + this + " being added, but"
12645                    + " it already has a parent");
12646        }
12647    }
12648
12649    /**
12650     * This is called when the view is attached to a window.  At this point it
12651     * has a Surface and will start drawing.  Note that this function is
12652     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
12653     * however it may be called any time before the first onDraw -- including
12654     * before or after {@link #onMeasure(int, int)}.
12655     *
12656     * @see #onDetachedFromWindow()
12657     */
12658    protected void onAttachedToWindow() {
12659        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
12660            mParent.requestTransparentRegion(this);
12661        }
12662
12663        if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
12664            initialAwakenScrollBars();
12665            mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
12666        }
12667
12668        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
12669
12670        jumpDrawablesToCurrentState();
12671
12672        resetSubtreeAccessibilityStateChanged();
12673
12674        invalidateOutline();
12675
12676        if (isFocused()) {
12677            InputMethodManager imm = InputMethodManager.peekInstance();
12678            imm.focusIn(this);
12679        }
12680    }
12681
12682    /**
12683     * Resolve all RTL related properties.
12684     *
12685     * @return true if resolution of RTL properties has been done
12686     *
12687     * @hide
12688     */
12689    public boolean resolveRtlPropertiesIfNeeded() {
12690        if (!needRtlPropertiesResolution()) return false;
12691
12692        // Order is important here: LayoutDirection MUST be resolved first
12693        if (!isLayoutDirectionResolved()) {
12694            resolveLayoutDirection();
12695            resolveLayoutParams();
12696        }
12697        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
12698        if (!isTextDirectionResolved()) {
12699            resolveTextDirection();
12700        }
12701        if (!isTextAlignmentResolved()) {
12702            resolveTextAlignment();
12703        }
12704        // Should resolve Drawables before Padding because we need the layout direction of the
12705        // Drawable to correctly resolve Padding.
12706        if (!isDrawablesResolved()) {
12707            resolveDrawables();
12708        }
12709        if (!isPaddingResolved()) {
12710            resolvePadding();
12711        }
12712        onRtlPropertiesChanged(getLayoutDirection());
12713        return true;
12714    }
12715
12716    /**
12717     * Reset resolution of all RTL related properties.
12718     *
12719     * @hide
12720     */
12721    public void resetRtlProperties() {
12722        resetResolvedLayoutDirection();
12723        resetResolvedTextDirection();
12724        resetResolvedTextAlignment();
12725        resetResolvedPadding();
12726        resetResolvedDrawables();
12727    }
12728
12729    /**
12730     * @see #onScreenStateChanged(int)
12731     */
12732    void dispatchScreenStateChanged(int screenState) {
12733        onScreenStateChanged(screenState);
12734    }
12735
12736    /**
12737     * This method is called whenever the state of the screen this view is
12738     * attached to changes. A state change will usually occurs when the screen
12739     * turns on or off (whether it happens automatically or the user does it
12740     * manually.)
12741     *
12742     * @param screenState The new state of the screen. Can be either
12743     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
12744     */
12745    public void onScreenStateChanged(int screenState) {
12746    }
12747
12748    /**
12749     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
12750     */
12751    private boolean hasRtlSupport() {
12752        return mContext.getApplicationInfo().hasRtlSupport();
12753    }
12754
12755    /**
12756     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
12757     * RTL not supported)
12758     */
12759    private boolean isRtlCompatibilityMode() {
12760        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
12761        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
12762    }
12763
12764    /**
12765     * @return true if RTL properties need resolution.
12766     *
12767     */
12768    private boolean needRtlPropertiesResolution() {
12769        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
12770    }
12771
12772    /**
12773     * Called when any RTL property (layout direction or text direction or text alignment) has
12774     * been changed.
12775     *
12776     * Subclasses need to override this method to take care of cached information that depends on the
12777     * resolved layout direction, or to inform child views that inherit their layout direction.
12778     *
12779     * The default implementation does nothing.
12780     *
12781     * @param layoutDirection the direction of the layout
12782     *
12783     * @see #LAYOUT_DIRECTION_LTR
12784     * @see #LAYOUT_DIRECTION_RTL
12785     */
12786    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
12787    }
12788
12789    /**
12790     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
12791     * that the parent directionality can and will be resolved before its children.
12792     *
12793     * @return true if resolution has been done, false otherwise.
12794     *
12795     * @hide
12796     */
12797    public boolean resolveLayoutDirection() {
12798        // Clear any previous layout direction resolution
12799        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
12800
12801        if (hasRtlSupport()) {
12802            // Set resolved depending on layout direction
12803            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
12804                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
12805                case LAYOUT_DIRECTION_INHERIT:
12806                    // We cannot resolve yet. LTR is by default and let the resolution happen again
12807                    // later to get the correct resolved value
12808                    if (!canResolveLayoutDirection()) return false;
12809
12810                    // Parent has not yet resolved, LTR is still the default
12811                    try {
12812                        if (!mParent.isLayoutDirectionResolved()) return false;
12813
12814                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
12815                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
12816                        }
12817                    } catch (AbstractMethodError e) {
12818                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
12819                                " does not fully implement ViewParent", e);
12820                    }
12821                    break;
12822                case LAYOUT_DIRECTION_RTL:
12823                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
12824                    break;
12825                case LAYOUT_DIRECTION_LOCALE:
12826                    if((LAYOUT_DIRECTION_RTL ==
12827                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
12828                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
12829                    }
12830                    break;
12831                default:
12832                    // Nothing to do, LTR by default
12833            }
12834        }
12835
12836        // Set to resolved
12837        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
12838        return true;
12839    }
12840
12841    /**
12842     * Check if layout direction resolution can be done.
12843     *
12844     * @return true if layout direction resolution can be done otherwise return false.
12845     */
12846    public boolean canResolveLayoutDirection() {
12847        switch (getRawLayoutDirection()) {
12848            case LAYOUT_DIRECTION_INHERIT:
12849                if (mParent != null) {
12850                    try {
12851                        return mParent.canResolveLayoutDirection();
12852                    } catch (AbstractMethodError e) {
12853                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
12854                                " does not fully implement ViewParent", e);
12855                    }
12856                }
12857                return false;
12858
12859            default:
12860                return true;
12861        }
12862    }
12863
12864    /**
12865     * Reset the resolved layout direction. Layout direction will be resolved during a call to
12866     * {@link #onMeasure(int, int)}.
12867     *
12868     * @hide
12869     */
12870    public void resetResolvedLayoutDirection() {
12871        // Reset the current resolved bits
12872        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
12873    }
12874
12875    /**
12876     * @return true if the layout direction is inherited.
12877     *
12878     * @hide
12879     */
12880    public boolean isLayoutDirectionInherited() {
12881        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
12882    }
12883
12884    /**
12885     * @return true if layout direction has been resolved.
12886     */
12887    public boolean isLayoutDirectionResolved() {
12888        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
12889    }
12890
12891    /**
12892     * Return if padding has been resolved
12893     *
12894     * @hide
12895     */
12896    boolean isPaddingResolved() {
12897        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
12898    }
12899
12900    /**
12901     * Resolves padding depending on layout direction, if applicable, and
12902     * recomputes internal padding values to adjust for scroll bars.
12903     *
12904     * @hide
12905     */
12906    public void resolvePadding() {
12907        final int resolvedLayoutDirection = getLayoutDirection();
12908
12909        if (!isRtlCompatibilityMode()) {
12910            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
12911            // If start / end padding are defined, they will be resolved (hence overriding) to
12912            // left / right or right / left depending on the resolved layout direction.
12913            // If start / end padding are not defined, use the left / right ones.
12914            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
12915                Rect padding = sThreadLocal.get();
12916                if (padding == null) {
12917                    padding = new Rect();
12918                    sThreadLocal.set(padding);
12919                }
12920                mBackground.getPadding(padding);
12921                if (!mLeftPaddingDefined) {
12922                    mUserPaddingLeftInitial = padding.left;
12923                }
12924                if (!mRightPaddingDefined) {
12925                    mUserPaddingRightInitial = padding.right;
12926                }
12927            }
12928            switch (resolvedLayoutDirection) {
12929                case LAYOUT_DIRECTION_RTL:
12930                    if (mUserPaddingStart != UNDEFINED_PADDING) {
12931                        mUserPaddingRight = mUserPaddingStart;
12932                    } else {
12933                        mUserPaddingRight = mUserPaddingRightInitial;
12934                    }
12935                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
12936                        mUserPaddingLeft = mUserPaddingEnd;
12937                    } else {
12938                        mUserPaddingLeft = mUserPaddingLeftInitial;
12939                    }
12940                    break;
12941                case LAYOUT_DIRECTION_LTR:
12942                default:
12943                    if (mUserPaddingStart != UNDEFINED_PADDING) {
12944                        mUserPaddingLeft = mUserPaddingStart;
12945                    } else {
12946                        mUserPaddingLeft = mUserPaddingLeftInitial;
12947                    }
12948                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
12949                        mUserPaddingRight = mUserPaddingEnd;
12950                    } else {
12951                        mUserPaddingRight = mUserPaddingRightInitial;
12952                    }
12953            }
12954
12955            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
12956        }
12957
12958        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
12959        onRtlPropertiesChanged(resolvedLayoutDirection);
12960
12961        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
12962    }
12963
12964    /**
12965     * Reset the resolved layout direction.
12966     *
12967     * @hide
12968     */
12969    public void resetResolvedPadding() {
12970        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
12971    }
12972
12973    /**
12974     * This is called when the view is detached from a window.  At this point it
12975     * no longer has a surface for drawing.
12976     *
12977     * @see #onAttachedToWindow()
12978     */
12979    protected void onDetachedFromWindow() {
12980    }
12981
12982    /**
12983     * This is a framework-internal mirror of onDetachedFromWindow() that's called
12984     * after onDetachedFromWindow().
12985     *
12986     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
12987     * The super method should be called at the end of the overriden method to ensure
12988     * subclasses are destroyed first
12989     *
12990     * @hide
12991     */
12992    protected void onDetachedFromWindowInternal() {
12993        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
12994        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
12995
12996        removeUnsetPressCallback();
12997        removeLongPressCallback();
12998        removePerformClickCallback();
12999        removeSendViewScrolledAccessibilityEventCallback();
13000        stopNestedScroll();
13001
13002        destroyDrawingCache();
13003
13004        cleanupDraw();
13005        mCurrentAnimation = null;
13006    }
13007
13008    private void cleanupDraw() {
13009        resetDisplayList();
13010        if (mAttachInfo != null) {
13011            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
13012        }
13013    }
13014
13015    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
13016    }
13017
13018    /**
13019     * @return The number of times this view has been attached to a window
13020     */
13021    protected int getWindowAttachCount() {
13022        return mWindowAttachCount;
13023    }
13024
13025    /**
13026     * Retrieve a unique token identifying the window this view is attached to.
13027     * @return Return the window's token for use in
13028     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
13029     */
13030    public IBinder getWindowToken() {
13031        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
13032    }
13033
13034    /**
13035     * Retrieve the {@link WindowId} for the window this view is
13036     * currently attached to.
13037     */
13038    public WindowId getWindowId() {
13039        if (mAttachInfo == null) {
13040            return null;
13041        }
13042        if (mAttachInfo.mWindowId == null) {
13043            try {
13044                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
13045                        mAttachInfo.mWindowToken);
13046                mAttachInfo.mWindowId = new WindowId(
13047                        mAttachInfo.mIWindowId);
13048            } catch (RemoteException e) {
13049            }
13050        }
13051        return mAttachInfo.mWindowId;
13052    }
13053
13054    /**
13055     * Retrieve a unique token identifying the top-level "real" window of
13056     * the window that this view is attached to.  That is, this is like
13057     * {@link #getWindowToken}, except if the window this view in is a panel
13058     * window (attached to another containing window), then the token of
13059     * the containing window is returned instead.
13060     *
13061     * @return Returns the associated window token, either
13062     * {@link #getWindowToken()} or the containing window's token.
13063     */
13064    public IBinder getApplicationWindowToken() {
13065        AttachInfo ai = mAttachInfo;
13066        if (ai != null) {
13067            IBinder appWindowToken = ai.mPanelParentWindowToken;
13068            if (appWindowToken == null) {
13069                appWindowToken = ai.mWindowToken;
13070            }
13071            return appWindowToken;
13072        }
13073        return null;
13074    }
13075
13076    /**
13077     * Gets the logical display to which the view's window has been attached.
13078     *
13079     * @return The logical display, or null if the view is not currently attached to a window.
13080     */
13081    public Display getDisplay() {
13082        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
13083    }
13084
13085    /**
13086     * Retrieve private session object this view hierarchy is using to
13087     * communicate with the window manager.
13088     * @return the session object to communicate with the window manager
13089     */
13090    /*package*/ IWindowSession getWindowSession() {
13091        return mAttachInfo != null ? mAttachInfo.mSession : null;
13092    }
13093
13094    /**
13095     * @param info the {@link android.view.View.AttachInfo} to associated with
13096     *        this view
13097     */
13098    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
13099        //System.out.println("Attached! " + this);
13100        mAttachInfo = info;
13101        if (mOverlay != null) {
13102            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
13103        }
13104        mWindowAttachCount++;
13105        // We will need to evaluate the drawable state at least once.
13106        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
13107        if (mFloatingTreeObserver != null) {
13108            info.mTreeObserver.merge(mFloatingTreeObserver);
13109            mFloatingTreeObserver = null;
13110        }
13111        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
13112            mAttachInfo.mScrollContainers.add(this);
13113            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
13114        }
13115        performCollectViewAttributes(mAttachInfo, visibility);
13116        onAttachedToWindow();
13117
13118        ListenerInfo li = mListenerInfo;
13119        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13120                li != null ? li.mOnAttachStateChangeListeners : null;
13121        if (listeners != null && listeners.size() > 0) {
13122            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13123            // perform the dispatching. The iterator is a safe guard against listeners that
13124            // could mutate the list by calling the various add/remove methods. This prevents
13125            // the array from being modified while we iterate it.
13126            for (OnAttachStateChangeListener listener : listeners) {
13127                listener.onViewAttachedToWindow(this);
13128            }
13129        }
13130
13131        int vis = info.mWindowVisibility;
13132        if (vis != GONE) {
13133            onWindowVisibilityChanged(vis);
13134        }
13135        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
13136            // If nobody has evaluated the drawable state yet, then do it now.
13137            refreshDrawableState();
13138        }
13139        needGlobalAttributesUpdate(false);
13140    }
13141
13142    void dispatchDetachedFromWindow() {
13143        AttachInfo info = mAttachInfo;
13144        if (info != null) {
13145            int vis = info.mWindowVisibility;
13146            if (vis != GONE) {
13147                onWindowVisibilityChanged(GONE);
13148            }
13149        }
13150
13151        onDetachedFromWindow();
13152        onDetachedFromWindowInternal();
13153
13154        ListenerInfo li = mListenerInfo;
13155        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13156                li != null ? li.mOnAttachStateChangeListeners : null;
13157        if (listeners != null && listeners.size() > 0) {
13158            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13159            // perform the dispatching. The iterator is a safe guard against listeners that
13160            // could mutate the list by calling the various add/remove methods. This prevents
13161            // the array from being modified while we iterate it.
13162            for (OnAttachStateChangeListener listener : listeners) {
13163                listener.onViewDetachedFromWindow(this);
13164            }
13165        }
13166
13167        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
13168            mAttachInfo.mScrollContainers.remove(this);
13169            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
13170        }
13171
13172        mAttachInfo = null;
13173        if (mOverlay != null) {
13174            mOverlay.getOverlayView().dispatchDetachedFromWindow();
13175        }
13176    }
13177
13178    /**
13179     * Cancel any deferred high-level input events that were previously posted to the event queue.
13180     *
13181     * <p>Many views post high-level events such as click handlers to the event queue
13182     * to run deferred in order to preserve a desired user experience - clearing visible
13183     * pressed states before executing, etc. This method will abort any events of this nature
13184     * that are currently in flight.</p>
13185     *
13186     * <p>Custom views that generate their own high-level deferred input events should override
13187     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
13188     *
13189     * <p>This will also cancel pending input events for any child views.</p>
13190     *
13191     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
13192     * This will not impact newer events posted after this call that may occur as a result of
13193     * lower-level input events still waiting in the queue. If you are trying to prevent
13194     * double-submitted  events for the duration of some sort of asynchronous transaction
13195     * you should also take other steps to protect against unexpected double inputs e.g. calling
13196     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
13197     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
13198     */
13199    public final void cancelPendingInputEvents() {
13200        dispatchCancelPendingInputEvents();
13201    }
13202
13203    /**
13204     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
13205     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
13206     */
13207    void dispatchCancelPendingInputEvents() {
13208        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
13209        onCancelPendingInputEvents();
13210        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
13211            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
13212                    " did not call through to super.onCancelPendingInputEvents()");
13213        }
13214    }
13215
13216    /**
13217     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
13218     * a parent view.
13219     *
13220     * <p>This method is responsible for removing any pending high-level input events that were
13221     * posted to the event queue to run later. Custom view classes that post their own deferred
13222     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
13223     * {@link android.os.Handler} should override this method, call
13224     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
13225     * </p>
13226     */
13227    public void onCancelPendingInputEvents() {
13228        removePerformClickCallback();
13229        cancelLongPress();
13230        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
13231    }
13232
13233    /**
13234     * Store this view hierarchy's frozen state into the given container.
13235     *
13236     * @param container The SparseArray in which to save the view's state.
13237     *
13238     * @see #restoreHierarchyState(android.util.SparseArray)
13239     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13240     * @see #onSaveInstanceState()
13241     */
13242    public void saveHierarchyState(SparseArray<Parcelable> container) {
13243        dispatchSaveInstanceState(container);
13244    }
13245
13246    /**
13247     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
13248     * this view and its children. May be overridden to modify how freezing happens to a
13249     * view's children; for example, some views may want to not store state for their children.
13250     *
13251     * @param container The SparseArray in which to save the view's state.
13252     *
13253     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13254     * @see #saveHierarchyState(android.util.SparseArray)
13255     * @see #onSaveInstanceState()
13256     */
13257    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
13258        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
13259            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13260            Parcelable state = onSaveInstanceState();
13261            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13262                throw new IllegalStateException(
13263                        "Derived class did not call super.onSaveInstanceState()");
13264            }
13265            if (state != null) {
13266                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
13267                // + ": " + state);
13268                container.put(mID, state);
13269            }
13270        }
13271    }
13272
13273    /**
13274     * Hook allowing a view to generate a representation of its internal state
13275     * that can later be used to create a new instance with that same state.
13276     * This state should only contain information that is not persistent or can
13277     * not be reconstructed later. For example, you will never store your
13278     * current position on screen because that will be computed again when a
13279     * new instance of the view is placed in its view hierarchy.
13280     * <p>
13281     * Some examples of things you may store here: the current cursor position
13282     * in a text view (but usually not the text itself since that is stored in a
13283     * content provider or other persistent storage), the currently selected
13284     * item in a list view.
13285     *
13286     * @return Returns a Parcelable object containing the view's current dynamic
13287     *         state, or null if there is nothing interesting to save. The
13288     *         default implementation returns null.
13289     * @see #onRestoreInstanceState(android.os.Parcelable)
13290     * @see #saveHierarchyState(android.util.SparseArray)
13291     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13292     * @see #setSaveEnabled(boolean)
13293     */
13294    protected Parcelable onSaveInstanceState() {
13295        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13296        return BaseSavedState.EMPTY_STATE;
13297    }
13298
13299    /**
13300     * Restore this view hierarchy's frozen state from the given container.
13301     *
13302     * @param container The SparseArray which holds previously frozen states.
13303     *
13304     * @see #saveHierarchyState(android.util.SparseArray)
13305     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13306     * @see #onRestoreInstanceState(android.os.Parcelable)
13307     */
13308    public void restoreHierarchyState(SparseArray<Parcelable> container) {
13309        dispatchRestoreInstanceState(container);
13310    }
13311
13312    /**
13313     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
13314     * state for this view and its children. May be overridden to modify how restoring
13315     * happens to a view's children; for example, some views may want to not store state
13316     * for their children.
13317     *
13318     * @param container The SparseArray which holds previously saved state.
13319     *
13320     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13321     * @see #restoreHierarchyState(android.util.SparseArray)
13322     * @see #onRestoreInstanceState(android.os.Parcelable)
13323     */
13324    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
13325        if (mID != NO_ID) {
13326            Parcelable state = container.get(mID);
13327            if (state != null) {
13328                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
13329                // + ": " + state);
13330                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13331                onRestoreInstanceState(state);
13332                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13333                    throw new IllegalStateException(
13334                            "Derived class did not call super.onRestoreInstanceState()");
13335                }
13336            }
13337        }
13338    }
13339
13340    /**
13341     * Hook allowing a view to re-apply a representation of its internal state that had previously
13342     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
13343     * null state.
13344     *
13345     * @param state The frozen state that had previously been returned by
13346     *        {@link #onSaveInstanceState}.
13347     *
13348     * @see #onSaveInstanceState()
13349     * @see #restoreHierarchyState(android.util.SparseArray)
13350     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13351     */
13352    protected void onRestoreInstanceState(Parcelable state) {
13353        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13354        if (state != BaseSavedState.EMPTY_STATE && state != null) {
13355            throw new IllegalArgumentException("Wrong state class, expecting View State but "
13356                    + "received " + state.getClass().toString() + " instead. This usually happens "
13357                    + "when two views of different type have the same id in the same hierarchy. "
13358                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
13359                    + "other views do not use the same id.");
13360        }
13361    }
13362
13363    /**
13364     * <p>Return the time at which the drawing of the view hierarchy started.</p>
13365     *
13366     * @return the drawing start time in milliseconds
13367     */
13368    public long getDrawingTime() {
13369        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
13370    }
13371
13372    /**
13373     * <p>Enables or disables the duplication of the parent's state into this view. When
13374     * duplication is enabled, this view gets its drawable state from its parent rather
13375     * than from its own internal properties.</p>
13376     *
13377     * <p>Note: in the current implementation, setting this property to true after the
13378     * view was added to a ViewGroup might have no effect at all. This property should
13379     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
13380     *
13381     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
13382     * property is enabled, an exception will be thrown.</p>
13383     *
13384     * <p>Note: if the child view uses and updates additionnal states which are unknown to the
13385     * parent, these states should not be affected by this method.</p>
13386     *
13387     * @param enabled True to enable duplication of the parent's drawable state, false
13388     *                to disable it.
13389     *
13390     * @see #getDrawableState()
13391     * @see #isDuplicateParentStateEnabled()
13392     */
13393    public void setDuplicateParentStateEnabled(boolean enabled) {
13394        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
13395    }
13396
13397    /**
13398     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
13399     *
13400     * @return True if this view's drawable state is duplicated from the parent,
13401     *         false otherwise
13402     *
13403     * @see #getDrawableState()
13404     * @see #setDuplicateParentStateEnabled(boolean)
13405     */
13406    public boolean isDuplicateParentStateEnabled() {
13407        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
13408    }
13409
13410    /**
13411     * <p>Specifies the type of layer backing this view. The layer can be
13412     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13413     * {@link #LAYER_TYPE_HARDWARE}.</p>
13414     *
13415     * <p>A layer is associated with an optional {@link android.graphics.Paint}
13416     * instance that controls how the layer is composed on screen. The following
13417     * properties of the paint are taken into account when composing the layer:</p>
13418     * <ul>
13419     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13420     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13421     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13422     * </ul>
13423     *
13424     * <p>If this view has an alpha value set to < 1.0 by calling
13425     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superceded
13426     * by this view's alpha value.</p>
13427     *
13428     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
13429     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
13430     * for more information on when and how to use layers.</p>
13431     *
13432     * @param layerType The type of layer to use with this view, must be one of
13433     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13434     *        {@link #LAYER_TYPE_HARDWARE}
13435     * @param paint The paint used to compose the layer. This argument is optional
13436     *        and can be null. It is ignored when the layer type is
13437     *        {@link #LAYER_TYPE_NONE}
13438     *
13439     * @see #getLayerType()
13440     * @see #LAYER_TYPE_NONE
13441     * @see #LAYER_TYPE_SOFTWARE
13442     * @see #LAYER_TYPE_HARDWARE
13443     * @see #setAlpha(float)
13444     *
13445     * @attr ref android.R.styleable#View_layerType
13446     */
13447    public void setLayerType(int layerType, Paint paint) {
13448        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
13449            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
13450                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
13451        }
13452
13453        boolean typeChanged = mRenderNode.setLayerType(layerType);
13454
13455        if (!typeChanged) {
13456            setLayerPaint(paint);
13457            return;
13458        }
13459
13460        // Destroy any previous software drawing cache if needed
13461        if (mLayerType == LAYER_TYPE_SOFTWARE) {
13462            destroyDrawingCache();
13463        }
13464
13465        mLayerType = layerType;
13466        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
13467        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
13468        mRenderNode.setLayerPaint(mLayerPaint);
13469
13470        // draw() behaves differently if we are on a layer, so we need to
13471        // invalidate() here
13472        invalidateParentCaches();
13473        invalidate(true);
13474    }
13475
13476    /**
13477     * Updates the {@link Paint} object used with the current layer (used only if the current
13478     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
13479     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
13480     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
13481     * ensure that the view gets redrawn immediately.
13482     *
13483     * <p>A layer is associated with an optional {@link android.graphics.Paint}
13484     * instance that controls how the layer is composed on screen. The following
13485     * properties of the paint are taken into account when composing the layer:</p>
13486     * <ul>
13487     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13488     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13489     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13490     * </ul>
13491     *
13492     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
13493     * alpha value of the layer's paint is superceded by this view's alpha value.</p>
13494     *
13495     * @param paint The paint used to compose the layer. This argument is optional
13496     *        and can be null. It is ignored when the layer type is
13497     *        {@link #LAYER_TYPE_NONE}
13498     *
13499     * @see #setLayerType(int, android.graphics.Paint)
13500     */
13501    public void setLayerPaint(Paint paint) {
13502        int layerType = getLayerType();
13503        if (layerType != LAYER_TYPE_NONE) {
13504            mLayerPaint = paint == null ? new Paint() : paint;
13505            if (layerType == LAYER_TYPE_HARDWARE) {
13506                if (mRenderNode.setLayerPaint(mLayerPaint)) {
13507                    invalidateViewProperty(false, false);
13508                }
13509            } else {
13510                invalidate();
13511            }
13512        }
13513    }
13514
13515    /**
13516     * Indicates whether this view has a static layer. A view with layer type
13517     * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
13518     * dynamic.
13519     */
13520    boolean hasStaticLayer() {
13521        return true;
13522    }
13523
13524    /**
13525     * Indicates what type of layer is currently associated with this view. By default
13526     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
13527     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
13528     * for more information on the different types of layers.
13529     *
13530     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13531     *         {@link #LAYER_TYPE_HARDWARE}
13532     *
13533     * @see #setLayerType(int, android.graphics.Paint)
13534     * @see #buildLayer()
13535     * @see #LAYER_TYPE_NONE
13536     * @see #LAYER_TYPE_SOFTWARE
13537     * @see #LAYER_TYPE_HARDWARE
13538     */
13539    public int getLayerType() {
13540        return mLayerType;
13541    }
13542
13543    /**
13544     * Forces this view's layer to be created and this view to be rendered
13545     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
13546     * invoking this method will have no effect.
13547     *
13548     * This method can for instance be used to render a view into its layer before
13549     * starting an animation. If this view is complex, rendering into the layer
13550     * before starting the animation will avoid skipping frames.
13551     *
13552     * @throws IllegalStateException If this view is not attached to a window
13553     *
13554     * @see #setLayerType(int, android.graphics.Paint)
13555     */
13556    public void buildLayer() {
13557        if (mLayerType == LAYER_TYPE_NONE) return;
13558
13559        final AttachInfo attachInfo = mAttachInfo;
13560        if (attachInfo == null) {
13561            throw new IllegalStateException("This view must be attached to a window first");
13562        }
13563
13564        if (getWidth() == 0 || getHeight() == 0) {
13565            return;
13566        }
13567
13568        switch (mLayerType) {
13569            case LAYER_TYPE_HARDWARE:
13570                // The only part of a hardware layer we can build in response to
13571                // this call is to ensure the display list is up to date.
13572                // The actual rendering of the display list into the layer must
13573                // be done at playback time
13574                updateDisplayListIfDirty();
13575                break;
13576            case LAYER_TYPE_SOFTWARE:
13577                buildDrawingCache(true);
13578                break;
13579        }
13580    }
13581
13582    /**
13583     * If this View draws with a HardwareLayer, returns it.
13584     * Otherwise returns null
13585     *
13586     * TODO: Only TextureView uses this, can we eliminate it?
13587     */
13588    HardwareLayer getHardwareLayer() {
13589        return null;
13590    }
13591
13592    /**
13593     * Destroys all hardware rendering resources. This method is invoked
13594     * when the system needs to reclaim resources. Upon execution of this
13595     * method, you should free any OpenGL resources created by the view.
13596     *
13597     * Note: you <strong>must</strong> call
13598     * <code>super.destroyHardwareResources()</code> when overriding
13599     * this method.
13600     *
13601     * @hide
13602     */
13603    protected void destroyHardwareResources() {
13604        // Although the Layer will be destroyed by RenderNode, we want to release
13605        // the staging display list, which is also a signal to RenderNode that it's
13606        // safe to free its copy of the display list as it knows that we will
13607        // push an updated DisplayList if we try to draw again
13608        resetDisplayList();
13609    }
13610
13611    /**
13612     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
13613     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
13614     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
13615     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
13616     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
13617     * null.</p>
13618     *
13619     * <p>Enabling the drawing cache is similar to
13620     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
13621     * acceleration is turned off. When hardware acceleration is turned on, enabling the
13622     * drawing cache has no effect on rendering because the system uses a different mechanism
13623     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
13624     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
13625     * for information on how to enable software and hardware layers.</p>
13626     *
13627     * <p>This API can be used to manually generate
13628     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
13629     * {@link #getDrawingCache()}.</p>
13630     *
13631     * @param enabled true to enable the drawing cache, false otherwise
13632     *
13633     * @see #isDrawingCacheEnabled()
13634     * @see #getDrawingCache()
13635     * @see #buildDrawingCache()
13636     * @see #setLayerType(int, android.graphics.Paint)
13637     */
13638    public void setDrawingCacheEnabled(boolean enabled) {
13639        mCachingFailed = false;
13640        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
13641    }
13642
13643    /**
13644     * <p>Indicates whether the drawing cache is enabled for this view.</p>
13645     *
13646     * @return true if the drawing cache is enabled
13647     *
13648     * @see #setDrawingCacheEnabled(boolean)
13649     * @see #getDrawingCache()
13650     */
13651    @ViewDebug.ExportedProperty(category = "drawing")
13652    public boolean isDrawingCacheEnabled() {
13653        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
13654    }
13655
13656    /**
13657     * Debugging utility which recursively outputs the dirty state of a view and its
13658     * descendants.
13659     *
13660     * @hide
13661     */
13662    @SuppressWarnings({"UnusedDeclaration"})
13663    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
13664        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
13665                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
13666                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
13667                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
13668        if (clear) {
13669            mPrivateFlags &= clearMask;
13670        }
13671        if (this instanceof ViewGroup) {
13672            ViewGroup parent = (ViewGroup) this;
13673            final int count = parent.getChildCount();
13674            for (int i = 0; i < count; i++) {
13675                final View child = parent.getChildAt(i);
13676                child.outputDirtyFlags(indent + "  ", clear, clearMask);
13677            }
13678        }
13679    }
13680
13681    /**
13682     * This method is used by ViewGroup to cause its children to restore or recreate their
13683     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
13684     * to recreate its own display list, which would happen if it went through the normal
13685     * draw/dispatchDraw mechanisms.
13686     *
13687     * @hide
13688     */
13689    protected void dispatchGetDisplayList() {}
13690
13691    /**
13692     * A view that is not attached or hardware accelerated cannot create a display list.
13693     * This method checks these conditions and returns the appropriate result.
13694     *
13695     * @return true if view has the ability to create a display list, false otherwise.
13696     *
13697     * @hide
13698     */
13699    public boolean canHaveDisplayList() {
13700        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
13701    }
13702
13703    private void updateDisplayListIfDirty() {
13704        final RenderNode renderNode = mRenderNode;
13705        if (!canHaveDisplayList()) {
13706            // can't populate RenderNode, don't try
13707            return;
13708        }
13709
13710        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
13711                || !renderNode.isValid()
13712                || (mRecreateDisplayList)) {
13713            // Don't need to recreate the display list, just need to tell our
13714            // children to restore/recreate theirs
13715            if (renderNode.isValid()
13716                    && !mRecreateDisplayList) {
13717                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
13718                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13719                dispatchGetDisplayList();
13720
13721                return; // no work needed
13722            }
13723
13724            // If we got here, we're recreating it. Mark it as such to ensure that
13725            // we copy in child display lists into ours in drawChild()
13726            mRecreateDisplayList = true;
13727
13728            int width = mRight - mLeft;
13729            int height = mBottom - mTop;
13730            int layerType = getLayerType();
13731
13732            final HardwareCanvas canvas = renderNode.start(width, height);
13733
13734            try {
13735                final HardwareLayer layer = getHardwareLayer();
13736                if (layer != null && layer.isValid()) {
13737                    canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
13738                } else if (layerType == LAYER_TYPE_SOFTWARE) {
13739                    buildDrawingCache(true);
13740                    Bitmap cache = getDrawingCache(true);
13741                    if (cache != null) {
13742                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
13743                    }
13744                } else {
13745                    computeScroll();
13746
13747                    canvas.translate(-mScrollX, -mScrollY);
13748                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
13749                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13750
13751                    // Fast path for layouts with no backgrounds
13752                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13753                        dispatchDraw(canvas);
13754                        if (mOverlay != null && !mOverlay.isEmpty()) {
13755                            mOverlay.getOverlayView().draw(canvas);
13756                        }
13757                    } else {
13758                        draw(canvas);
13759                    }
13760                }
13761            } finally {
13762                renderNode.end(canvas);
13763                setDisplayListProperties(renderNode);
13764            }
13765        } else {
13766            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
13767            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
13768        }
13769    }
13770
13771    /**
13772     * Returns a RenderNode with View draw content recorded, which can be
13773     * used to draw this view again without executing its draw method.
13774     *
13775     * @return A RenderNode ready to replay, or null if caching is not enabled.
13776     *
13777     * @hide
13778     */
13779    public RenderNode getDisplayList() {
13780        updateDisplayListIfDirty();
13781        return mRenderNode;
13782    }
13783
13784    private void resetDisplayList() {
13785        if (mRenderNode.isValid()) {
13786            mRenderNode.destroyDisplayListData();
13787        }
13788
13789        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
13790            mBackgroundRenderNode.destroyDisplayListData();
13791        }
13792    }
13793
13794    /**
13795     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
13796     *
13797     * @return A non-scaled bitmap representing this view or null if cache is disabled.
13798     *
13799     * @see #getDrawingCache(boolean)
13800     */
13801    public Bitmap getDrawingCache() {
13802        return getDrawingCache(false);
13803    }
13804
13805    /**
13806     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
13807     * is null when caching is disabled. If caching is enabled and the cache is not ready,
13808     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
13809     * draw from the cache when the cache is enabled. To benefit from the cache, you must
13810     * request the drawing cache by calling this method and draw it on screen if the
13811     * returned bitmap is not null.</p>
13812     *
13813     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
13814     * this method will create a bitmap of the same size as this view. Because this bitmap
13815     * will be drawn scaled by the parent ViewGroup, the result on screen might show
13816     * scaling artifacts. To avoid such artifacts, you should call this method by setting
13817     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
13818     * size than the view. This implies that your application must be able to handle this
13819     * size.</p>
13820     *
13821     * @param autoScale Indicates whether the generated bitmap should be scaled based on
13822     *        the current density of the screen when the application is in compatibility
13823     *        mode.
13824     *
13825     * @return A bitmap representing this view or null if cache is disabled.
13826     *
13827     * @see #setDrawingCacheEnabled(boolean)
13828     * @see #isDrawingCacheEnabled()
13829     * @see #buildDrawingCache(boolean)
13830     * @see #destroyDrawingCache()
13831     */
13832    public Bitmap getDrawingCache(boolean autoScale) {
13833        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
13834            return null;
13835        }
13836        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
13837            buildDrawingCache(autoScale);
13838        }
13839        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
13840    }
13841
13842    /**
13843     * <p>Frees the resources used by the drawing cache. If you call
13844     * {@link #buildDrawingCache()} manually without calling
13845     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
13846     * should cleanup the cache with this method afterwards.</p>
13847     *
13848     * @see #setDrawingCacheEnabled(boolean)
13849     * @see #buildDrawingCache()
13850     * @see #getDrawingCache()
13851     */
13852    public void destroyDrawingCache() {
13853        if (mDrawingCache != null) {
13854            mDrawingCache.recycle();
13855            mDrawingCache = null;
13856        }
13857        if (mUnscaledDrawingCache != null) {
13858            mUnscaledDrawingCache.recycle();
13859            mUnscaledDrawingCache = null;
13860        }
13861    }
13862
13863    /**
13864     * Setting a solid background color for the drawing cache's bitmaps will improve
13865     * performance and memory usage. Note, though that this should only be used if this
13866     * view will always be drawn on top of a solid color.
13867     *
13868     * @param color The background color to use for the drawing cache's bitmap
13869     *
13870     * @see #setDrawingCacheEnabled(boolean)
13871     * @see #buildDrawingCache()
13872     * @see #getDrawingCache()
13873     */
13874    public void setDrawingCacheBackgroundColor(int color) {
13875        if (color != mDrawingCacheBackgroundColor) {
13876            mDrawingCacheBackgroundColor = color;
13877            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
13878        }
13879    }
13880
13881    /**
13882     * @see #setDrawingCacheBackgroundColor(int)
13883     *
13884     * @return The background color to used for the drawing cache's bitmap
13885     */
13886    public int getDrawingCacheBackgroundColor() {
13887        return mDrawingCacheBackgroundColor;
13888    }
13889
13890    /**
13891     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
13892     *
13893     * @see #buildDrawingCache(boolean)
13894     */
13895    public void buildDrawingCache() {
13896        buildDrawingCache(false);
13897    }
13898
13899    /**
13900     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
13901     *
13902     * <p>If you call {@link #buildDrawingCache()} manually without calling
13903     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
13904     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
13905     *
13906     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
13907     * this method will create a bitmap of the same size as this view. Because this bitmap
13908     * will be drawn scaled by the parent ViewGroup, the result on screen might show
13909     * scaling artifacts. To avoid such artifacts, you should call this method by setting
13910     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
13911     * size than the view. This implies that your application must be able to handle this
13912     * size.</p>
13913     *
13914     * <p>You should avoid calling this method when hardware acceleration is enabled. If
13915     * you do not need the drawing cache bitmap, calling this method will increase memory
13916     * usage and cause the view to be rendered in software once, thus negatively impacting
13917     * performance.</p>
13918     *
13919     * @see #getDrawingCache()
13920     * @see #destroyDrawingCache()
13921     */
13922    public void buildDrawingCache(boolean autoScale) {
13923        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
13924                mDrawingCache == null : mUnscaledDrawingCache == null)) {
13925            mCachingFailed = false;
13926
13927            int width = mRight - mLeft;
13928            int height = mBottom - mTop;
13929
13930            final AttachInfo attachInfo = mAttachInfo;
13931            final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
13932
13933            if (autoScale && scalingRequired) {
13934                width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
13935                height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
13936            }
13937
13938            final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
13939            final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
13940            final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
13941
13942            final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
13943            final long drawingCacheSize =
13944                    ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
13945            if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
13946                if (width > 0 && height > 0) {
13947                    Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
13948                            + projectedBitmapSize + " bytes, only "
13949                            + drawingCacheSize + " available");
13950                }
13951                destroyDrawingCache();
13952                mCachingFailed = true;
13953                return;
13954            }
13955
13956            boolean clear = true;
13957            Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
13958
13959            if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
13960                Bitmap.Config quality;
13961                if (!opaque) {
13962                    // Never pick ARGB_4444 because it looks awful
13963                    // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
13964                    switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
13965                        case DRAWING_CACHE_QUALITY_AUTO:
13966                        case DRAWING_CACHE_QUALITY_LOW:
13967                        case DRAWING_CACHE_QUALITY_HIGH:
13968                        default:
13969                            quality = Bitmap.Config.ARGB_8888;
13970                            break;
13971                    }
13972                } else {
13973                    // Optimization for translucent windows
13974                    // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
13975                    quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
13976                }
13977
13978                // Try to cleanup memory
13979                if (bitmap != null) bitmap.recycle();
13980
13981                try {
13982                    bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
13983                            width, height, quality);
13984                    bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
13985                    if (autoScale) {
13986                        mDrawingCache = bitmap;
13987                    } else {
13988                        mUnscaledDrawingCache = bitmap;
13989                    }
13990                    if (opaque && use32BitCache) bitmap.setHasAlpha(false);
13991                } catch (OutOfMemoryError e) {
13992                    // If there is not enough memory to create the bitmap cache, just
13993                    // ignore the issue as bitmap caches are not required to draw the
13994                    // view hierarchy
13995                    if (autoScale) {
13996                        mDrawingCache = null;
13997                    } else {
13998                        mUnscaledDrawingCache = null;
13999                    }
14000                    mCachingFailed = true;
14001                    return;
14002                }
14003
14004                clear = drawingCacheBackgroundColor != 0;
14005            }
14006
14007            Canvas canvas;
14008            if (attachInfo != null) {
14009                canvas = attachInfo.mCanvas;
14010                if (canvas == null) {
14011                    canvas = new Canvas();
14012                }
14013                canvas.setBitmap(bitmap);
14014                // Temporarily clobber the cached Canvas in case one of our children
14015                // is also using a drawing cache. Without this, the children would
14016                // steal the canvas by attaching their own bitmap to it and bad, bad
14017                // thing would happen (invisible views, corrupted drawings, etc.)
14018                attachInfo.mCanvas = null;
14019            } else {
14020                // This case should hopefully never or seldom happen
14021                canvas = new Canvas(bitmap);
14022            }
14023
14024            if (clear) {
14025                bitmap.eraseColor(drawingCacheBackgroundColor);
14026            }
14027
14028            computeScroll();
14029            final int restoreCount = canvas.save();
14030
14031            if (autoScale && scalingRequired) {
14032                final float scale = attachInfo.mApplicationScale;
14033                canvas.scale(scale, scale);
14034            }
14035
14036            canvas.translate(-mScrollX, -mScrollY);
14037
14038            mPrivateFlags |= PFLAG_DRAWN;
14039            if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
14040                    mLayerType != LAYER_TYPE_NONE) {
14041                mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
14042            }
14043
14044            // Fast path for layouts with no backgrounds
14045            if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14046                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14047                dispatchDraw(canvas);
14048                if (mOverlay != null && !mOverlay.isEmpty()) {
14049                    mOverlay.getOverlayView().draw(canvas);
14050                }
14051            } else {
14052                draw(canvas);
14053            }
14054
14055            canvas.restoreToCount(restoreCount);
14056            canvas.setBitmap(null);
14057
14058            if (attachInfo != null) {
14059                // Restore the cached Canvas for our siblings
14060                attachInfo.mCanvas = canvas;
14061            }
14062        }
14063    }
14064
14065    /**
14066     * Create a snapshot of the view into a bitmap.  We should probably make
14067     * some form of this public, but should think about the API.
14068     */
14069    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
14070        int width = mRight - mLeft;
14071        int height = mBottom - mTop;
14072
14073        final AttachInfo attachInfo = mAttachInfo;
14074        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
14075        width = (int) ((width * scale) + 0.5f);
14076        height = (int) ((height * scale) + 0.5f);
14077
14078        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14079                width > 0 ? width : 1, height > 0 ? height : 1, quality);
14080        if (bitmap == null) {
14081            throw new OutOfMemoryError();
14082        }
14083
14084        Resources resources = getResources();
14085        if (resources != null) {
14086            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
14087        }
14088
14089        Canvas canvas;
14090        if (attachInfo != null) {
14091            canvas = attachInfo.mCanvas;
14092            if (canvas == null) {
14093                canvas = new Canvas();
14094            }
14095            canvas.setBitmap(bitmap);
14096            // Temporarily clobber the cached Canvas in case one of our children
14097            // is also using a drawing cache. Without this, the children would
14098            // steal the canvas by attaching their own bitmap to it and bad, bad
14099            // things would happen (invisible views, corrupted drawings, etc.)
14100            attachInfo.mCanvas = null;
14101        } else {
14102            // This case should hopefully never or seldom happen
14103            canvas = new Canvas(bitmap);
14104        }
14105
14106        if ((backgroundColor & 0xff000000) != 0) {
14107            bitmap.eraseColor(backgroundColor);
14108        }
14109
14110        computeScroll();
14111        final int restoreCount = canvas.save();
14112        canvas.scale(scale, scale);
14113        canvas.translate(-mScrollX, -mScrollY);
14114
14115        // Temporarily remove the dirty mask
14116        int flags = mPrivateFlags;
14117        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14118
14119        // Fast path for layouts with no backgrounds
14120        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14121            dispatchDraw(canvas);
14122            if (mOverlay != null && !mOverlay.isEmpty()) {
14123                mOverlay.getOverlayView().draw(canvas);
14124            }
14125        } else {
14126            draw(canvas);
14127        }
14128
14129        mPrivateFlags = flags;
14130
14131        canvas.restoreToCount(restoreCount);
14132        canvas.setBitmap(null);
14133
14134        if (attachInfo != null) {
14135            // Restore the cached Canvas for our siblings
14136            attachInfo.mCanvas = canvas;
14137        }
14138
14139        return bitmap;
14140    }
14141
14142    /**
14143     * Indicates whether this View is currently in edit mode. A View is usually
14144     * in edit mode when displayed within a developer tool. For instance, if
14145     * this View is being drawn by a visual user interface builder, this method
14146     * should return true.
14147     *
14148     * Subclasses should check the return value of this method to provide
14149     * different behaviors if their normal behavior might interfere with the
14150     * host environment. For instance: the class spawns a thread in its
14151     * constructor, the drawing code relies on device-specific features, etc.
14152     *
14153     * This method is usually checked in the drawing code of custom widgets.
14154     *
14155     * @return True if this View is in edit mode, false otherwise.
14156     */
14157    public boolean isInEditMode() {
14158        return false;
14159    }
14160
14161    /**
14162     * If the View draws content inside its padding and enables fading edges,
14163     * it needs to support padding offsets. Padding offsets are added to the
14164     * fading edges to extend the length of the fade so that it covers pixels
14165     * drawn inside the padding.
14166     *
14167     * Subclasses of this class should override this method if they need
14168     * to draw content inside the padding.
14169     *
14170     * @return True if padding offset must be applied, false otherwise.
14171     *
14172     * @see #getLeftPaddingOffset()
14173     * @see #getRightPaddingOffset()
14174     * @see #getTopPaddingOffset()
14175     * @see #getBottomPaddingOffset()
14176     *
14177     * @since CURRENT
14178     */
14179    protected boolean isPaddingOffsetRequired() {
14180        return false;
14181    }
14182
14183    /**
14184     * Amount by which to extend the left fading region. Called only when
14185     * {@link #isPaddingOffsetRequired()} returns true.
14186     *
14187     * @return The left padding offset in pixels.
14188     *
14189     * @see #isPaddingOffsetRequired()
14190     *
14191     * @since CURRENT
14192     */
14193    protected int getLeftPaddingOffset() {
14194        return 0;
14195    }
14196
14197    /**
14198     * Amount by which to extend the right fading region. Called only when
14199     * {@link #isPaddingOffsetRequired()} returns true.
14200     *
14201     * @return The right padding offset in pixels.
14202     *
14203     * @see #isPaddingOffsetRequired()
14204     *
14205     * @since CURRENT
14206     */
14207    protected int getRightPaddingOffset() {
14208        return 0;
14209    }
14210
14211    /**
14212     * Amount by which to extend the top fading region. Called only when
14213     * {@link #isPaddingOffsetRequired()} returns true.
14214     *
14215     * @return The top padding offset in pixels.
14216     *
14217     * @see #isPaddingOffsetRequired()
14218     *
14219     * @since CURRENT
14220     */
14221    protected int getTopPaddingOffset() {
14222        return 0;
14223    }
14224
14225    /**
14226     * Amount by which to extend the bottom fading region. Called only when
14227     * {@link #isPaddingOffsetRequired()} returns true.
14228     *
14229     * @return The bottom padding offset in pixels.
14230     *
14231     * @see #isPaddingOffsetRequired()
14232     *
14233     * @since CURRENT
14234     */
14235    protected int getBottomPaddingOffset() {
14236        return 0;
14237    }
14238
14239    /**
14240     * @hide
14241     * @param offsetRequired
14242     */
14243    protected int getFadeTop(boolean offsetRequired) {
14244        int top = mPaddingTop;
14245        if (offsetRequired) top += getTopPaddingOffset();
14246        return top;
14247    }
14248
14249    /**
14250     * @hide
14251     * @param offsetRequired
14252     */
14253    protected int getFadeHeight(boolean offsetRequired) {
14254        int padding = mPaddingTop;
14255        if (offsetRequired) padding += getTopPaddingOffset();
14256        return mBottom - mTop - mPaddingBottom - padding;
14257    }
14258
14259    /**
14260     * <p>Indicates whether this view is attached to a hardware accelerated
14261     * window or not.</p>
14262     *
14263     * <p>Even if this method returns true, it does not mean that every call
14264     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
14265     * accelerated {@link android.graphics.Canvas}. For instance, if this view
14266     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
14267     * window is hardware accelerated,
14268     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
14269     * return false, and this method will return true.</p>
14270     *
14271     * @return True if the view is attached to a window and the window is
14272     *         hardware accelerated; false in any other case.
14273     */
14274    @ViewDebug.ExportedProperty(category = "drawing")
14275    public boolean isHardwareAccelerated() {
14276        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14277    }
14278
14279    /**
14280     * Sets a rectangular area on this view to which the view will be clipped
14281     * when it is drawn. Setting the value to null will remove the clip bounds
14282     * and the view will draw normally, using its full bounds.
14283     *
14284     * @param clipBounds The rectangular area, in the local coordinates of
14285     * this view, to which future drawing operations will be clipped.
14286     */
14287    public void setClipBounds(Rect clipBounds) {
14288        if (clipBounds != null) {
14289            if (clipBounds.equals(mClipBounds)) {
14290                return;
14291            }
14292            if (mClipBounds == null) {
14293                invalidate();
14294                mClipBounds = new Rect(clipBounds);
14295            } else {
14296                invalidate(Math.min(mClipBounds.left, clipBounds.left),
14297                        Math.min(mClipBounds.top, clipBounds.top),
14298                        Math.max(mClipBounds.right, clipBounds.right),
14299                        Math.max(mClipBounds.bottom, clipBounds.bottom));
14300                mClipBounds.set(clipBounds);
14301            }
14302        } else {
14303            if (mClipBounds != null) {
14304                invalidate();
14305                mClipBounds = null;
14306            }
14307        }
14308    }
14309
14310    /**
14311     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
14312     *
14313     * @return A copy of the current clip bounds if clip bounds are set,
14314     * otherwise null.
14315     */
14316    public Rect getClipBounds() {
14317        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
14318    }
14319
14320    /**
14321     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
14322     * case of an active Animation being run on the view.
14323     */
14324    private boolean drawAnimation(ViewGroup parent, long drawingTime,
14325            Animation a, boolean scalingRequired) {
14326        Transformation invalidationTransform;
14327        final int flags = parent.mGroupFlags;
14328        final boolean initialized = a.isInitialized();
14329        if (!initialized) {
14330            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
14331            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
14332            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
14333            onAnimationStart();
14334        }
14335
14336        final Transformation t = parent.getChildTransformation();
14337        boolean more = a.getTransformation(drawingTime, t, 1f);
14338        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
14339            if (parent.mInvalidationTransformation == null) {
14340                parent.mInvalidationTransformation = new Transformation();
14341            }
14342            invalidationTransform = parent.mInvalidationTransformation;
14343            a.getTransformation(drawingTime, invalidationTransform, 1f);
14344        } else {
14345            invalidationTransform = t;
14346        }
14347
14348        if (more) {
14349            if (!a.willChangeBounds()) {
14350                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
14351                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
14352                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
14353                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
14354                    // The child need to draw an animation, potentially offscreen, so
14355                    // make sure we do not cancel invalidate requests
14356                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14357                    parent.invalidate(mLeft, mTop, mRight, mBottom);
14358                }
14359            } else {
14360                if (parent.mInvalidateRegion == null) {
14361                    parent.mInvalidateRegion = new RectF();
14362                }
14363                final RectF region = parent.mInvalidateRegion;
14364                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
14365                        invalidationTransform);
14366
14367                // The child need to draw an animation, potentially offscreen, so
14368                // make sure we do not cancel invalidate requests
14369                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14370
14371                final int left = mLeft + (int) region.left;
14372                final int top = mTop + (int) region.top;
14373                parent.invalidate(left, top, left + (int) (region.width() + .5f),
14374                        top + (int) (region.height() + .5f));
14375            }
14376        }
14377        return more;
14378    }
14379
14380    /**
14381     * This method is called by getDisplayList() when a display list is recorded for a View.
14382     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
14383     */
14384    void setDisplayListProperties(RenderNode renderNode) {
14385        if (renderNode != null) {
14386            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
14387            if (mParent instanceof ViewGroup) {
14388                renderNode.setClipToBounds(
14389                        (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
14390            }
14391            float alpha = 1;
14392            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
14393                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14394                ViewGroup parentVG = (ViewGroup) mParent;
14395                final Transformation t = parentVG.getChildTransformation();
14396                if (parentVG.getChildStaticTransformation(this, t)) {
14397                    final int transformType = t.getTransformationType();
14398                    if (transformType != Transformation.TYPE_IDENTITY) {
14399                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
14400                            alpha = t.getAlpha();
14401                        }
14402                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
14403                            renderNode.setStaticMatrix(t.getMatrix());
14404                        }
14405                    }
14406                }
14407            }
14408            if (mTransformationInfo != null) {
14409                alpha *= getFinalAlpha();
14410                if (alpha < 1) {
14411                    final int multipliedAlpha = (int) (255 * alpha);
14412                    if (onSetAlpha(multipliedAlpha)) {
14413                        alpha = 1;
14414                    }
14415                }
14416                renderNode.setAlpha(alpha);
14417            } else if (alpha < 1) {
14418                renderNode.setAlpha(alpha);
14419            }
14420        }
14421    }
14422
14423    /**
14424     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
14425     * This draw() method is an implementation detail and is not intended to be overridden or
14426     * to be called from anywhere else other than ViewGroup.drawChild().
14427     */
14428    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
14429        boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14430        boolean more = false;
14431        final boolean childHasIdentityMatrix = hasIdentityMatrix();
14432        final int flags = parent.mGroupFlags;
14433
14434        if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
14435            parent.getChildTransformation().clear();
14436            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14437        }
14438
14439        Transformation transformToApply = null;
14440        boolean concatMatrix = false;
14441
14442        boolean scalingRequired = false;
14443        boolean caching;
14444        int layerType = getLayerType();
14445
14446        final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
14447        if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
14448                (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
14449            caching = true;
14450            // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
14451            if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
14452        } else {
14453            caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
14454        }
14455
14456        final Animation a = getAnimation();
14457        if (a != null) {
14458            more = drawAnimation(parent, drawingTime, a, scalingRequired);
14459            concatMatrix = a.willChangeTransformationMatrix();
14460            if (concatMatrix) {
14461                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14462            }
14463            transformToApply = parent.getChildTransformation();
14464        } else {
14465            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
14466                // No longer animating: clear out old animation matrix
14467                mRenderNode.setAnimationMatrix(null);
14468                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14469            }
14470            if (!useDisplayListProperties &&
14471                    (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14472                final Transformation t = parent.getChildTransformation();
14473                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
14474                if (hasTransform) {
14475                    final int transformType = t.getTransformationType();
14476                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
14477                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
14478                }
14479            }
14480        }
14481
14482        concatMatrix |= !childHasIdentityMatrix;
14483
14484        // Sets the flag as early as possible to allow draw() implementations
14485        // to call invalidate() successfully when doing animations
14486        mPrivateFlags |= PFLAG_DRAWN;
14487
14488        if (!concatMatrix &&
14489                (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
14490                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
14491                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
14492                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
14493            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
14494            return more;
14495        }
14496        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
14497
14498        if (hardwareAccelerated) {
14499            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
14500            // retain the flag's value temporarily in the mRecreateDisplayList flag
14501            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
14502            mPrivateFlags &= ~PFLAG_INVALIDATED;
14503        }
14504
14505        RenderNode renderNode = null;
14506        Bitmap cache = null;
14507        boolean hasDisplayList = false;
14508        if (caching) {
14509            if (!hardwareAccelerated) {
14510                if (layerType != LAYER_TYPE_NONE) {
14511                    layerType = LAYER_TYPE_SOFTWARE;
14512                    buildDrawingCache(true);
14513                }
14514                cache = getDrawingCache(true);
14515            } else {
14516                switch (layerType) {
14517                    case LAYER_TYPE_SOFTWARE:
14518                        if (useDisplayListProperties) {
14519                            hasDisplayList = canHaveDisplayList();
14520                        } else {
14521                            buildDrawingCache(true);
14522                            cache = getDrawingCache(true);
14523                        }
14524                        break;
14525                    case LAYER_TYPE_HARDWARE:
14526                        if (useDisplayListProperties) {
14527                            hasDisplayList = canHaveDisplayList();
14528                        }
14529                        break;
14530                    case LAYER_TYPE_NONE:
14531                        // Delay getting the display list until animation-driven alpha values are
14532                        // set up and possibly passed on to the view
14533                        hasDisplayList = canHaveDisplayList();
14534                        break;
14535                }
14536            }
14537        }
14538        useDisplayListProperties &= hasDisplayList;
14539        if (useDisplayListProperties) {
14540            renderNode = getDisplayList();
14541            if (!renderNode.isValid()) {
14542                // Uncommon, but possible. If a view is removed from the hierarchy during the call
14543                // to getDisplayList(), the display list will be marked invalid and we should not
14544                // try to use it again.
14545                renderNode = null;
14546                hasDisplayList = false;
14547                useDisplayListProperties = false;
14548            }
14549        }
14550
14551        int sx = 0;
14552        int sy = 0;
14553        if (!hasDisplayList) {
14554            computeScroll();
14555            sx = mScrollX;
14556            sy = mScrollY;
14557        }
14558
14559        final boolean hasNoCache = cache == null || hasDisplayList;
14560        final boolean offsetForScroll = cache == null && !hasDisplayList &&
14561                layerType != LAYER_TYPE_HARDWARE;
14562
14563        int restoreTo = -1;
14564        if (!useDisplayListProperties || transformToApply != null) {
14565            restoreTo = canvas.save();
14566        }
14567        if (offsetForScroll) {
14568            canvas.translate(mLeft - sx, mTop - sy);
14569        } else {
14570            if (!useDisplayListProperties) {
14571                canvas.translate(mLeft, mTop);
14572            }
14573            if (scalingRequired) {
14574                if (useDisplayListProperties) {
14575                    // TODO: Might not need this if we put everything inside the DL
14576                    restoreTo = canvas.save();
14577                }
14578                // mAttachInfo cannot be null, otherwise scalingRequired == false
14579                final float scale = 1.0f / mAttachInfo.mApplicationScale;
14580                canvas.scale(scale, scale);
14581            }
14582        }
14583
14584        float alpha = useDisplayListProperties ? 1 : (getAlpha() * getTransitionAlpha());
14585        if (transformToApply != null || alpha < 1 ||  !hasIdentityMatrix() ||
14586                (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
14587            if (transformToApply != null || !childHasIdentityMatrix) {
14588                int transX = 0;
14589                int transY = 0;
14590
14591                if (offsetForScroll) {
14592                    transX = -sx;
14593                    transY = -sy;
14594                }
14595
14596                if (transformToApply != null) {
14597                    if (concatMatrix) {
14598                        if (useDisplayListProperties) {
14599                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
14600                        } else {
14601                            // Undo the scroll translation, apply the transformation matrix,
14602                            // then redo the scroll translate to get the correct result.
14603                            canvas.translate(-transX, -transY);
14604                            canvas.concat(transformToApply.getMatrix());
14605                            canvas.translate(transX, transY);
14606                        }
14607                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14608                    }
14609
14610                    float transformAlpha = transformToApply.getAlpha();
14611                    if (transformAlpha < 1) {
14612                        alpha *= transformAlpha;
14613                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14614                    }
14615                }
14616
14617                if (!childHasIdentityMatrix && !useDisplayListProperties) {
14618                    canvas.translate(-transX, -transY);
14619                    canvas.concat(getMatrix());
14620                    canvas.translate(transX, transY);
14621                }
14622            }
14623
14624            // Deal with alpha if it is or used to be <1
14625            if (alpha < 1 ||
14626                    (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
14627                if (alpha < 1) {
14628                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
14629                } else {
14630                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
14631                }
14632                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14633                if (hasNoCache) {
14634                    final int multipliedAlpha = (int) (255 * alpha);
14635                    if (!onSetAlpha(multipliedAlpha)) {
14636                        int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
14637                        if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
14638                                layerType != LAYER_TYPE_NONE) {
14639                            layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
14640                        }
14641                        if (useDisplayListProperties) {
14642                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
14643                        } else  if (layerType == LAYER_TYPE_NONE) {
14644                            final int scrollX = hasDisplayList ? 0 : sx;
14645                            final int scrollY = hasDisplayList ? 0 : sy;
14646                            canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
14647                                    scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
14648                        }
14649                    } else {
14650                        // Alpha is handled by the child directly, clobber the layer's alpha
14651                        mPrivateFlags |= PFLAG_ALPHA_SET;
14652                    }
14653                }
14654            }
14655        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
14656            onSetAlpha(255);
14657            mPrivateFlags &= ~PFLAG_ALPHA_SET;
14658        }
14659
14660        if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
14661                !useDisplayListProperties && cache == null) {
14662            if (offsetForScroll) {
14663                canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
14664            } else {
14665                if (!scalingRequired || cache == null) {
14666                    canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
14667                } else {
14668                    canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
14669                }
14670            }
14671        }
14672
14673        if (!useDisplayListProperties && hasDisplayList) {
14674            renderNode = getDisplayList();
14675            if (!renderNode.isValid()) {
14676                // Uncommon, but possible. If a view is removed from the hierarchy during the call
14677                // to getDisplayList(), the display list will be marked invalid and we should not
14678                // try to use it again.
14679                renderNode = null;
14680                hasDisplayList = false;
14681            }
14682        }
14683
14684        if (hasNoCache) {
14685            boolean layerRendered = false;
14686            if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) {
14687                final HardwareLayer layer = getHardwareLayer();
14688                if (layer != null && layer.isValid()) {
14689                    mLayerPaint.setAlpha((int) (alpha * 255));
14690                    ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
14691                    layerRendered = true;
14692                } else {
14693                    final int scrollX = hasDisplayList ? 0 : sx;
14694                    final int scrollY = hasDisplayList ? 0 : sy;
14695                    canvas.saveLayer(scrollX, scrollY,
14696                            scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
14697                            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
14698                }
14699            }
14700
14701            if (!layerRendered) {
14702                if (!hasDisplayList) {
14703                    // Fast path for layouts with no backgrounds
14704                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14705                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14706                        dispatchDraw(canvas);
14707                    } else {
14708                        draw(canvas);
14709                    }
14710                } else {
14711                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14712                    ((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags);
14713                }
14714            }
14715        } else if (cache != null) {
14716            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14717            Paint cachePaint;
14718
14719            if (layerType == LAYER_TYPE_NONE) {
14720                cachePaint = parent.mCachePaint;
14721                if (cachePaint == null) {
14722                    cachePaint = new Paint();
14723                    cachePaint.setDither(false);
14724                    parent.mCachePaint = cachePaint;
14725                }
14726                if (alpha < 1) {
14727                    cachePaint.setAlpha((int) (alpha * 255));
14728                    parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
14729                } else if  ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) {
14730                    cachePaint.setAlpha(255);
14731                    parent.mGroupFlags &= ~ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
14732                }
14733            } else {
14734                cachePaint = mLayerPaint;
14735                cachePaint.setAlpha((int) (alpha * 255));
14736            }
14737            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
14738        }
14739
14740        if (restoreTo >= 0) {
14741            canvas.restoreToCount(restoreTo);
14742        }
14743
14744        if (a != null && !more) {
14745            if (!hardwareAccelerated && !a.getFillAfter()) {
14746                onSetAlpha(255);
14747            }
14748            parent.finishAnimatingView(this, a);
14749        }
14750
14751        if (more && hardwareAccelerated) {
14752            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
14753                // alpha animations should cause the child to recreate its display list
14754                invalidate(true);
14755            }
14756        }
14757
14758        mRecreateDisplayList = false;
14759
14760        return more;
14761    }
14762
14763    /**
14764     * Manually render this view (and all of its children) to the given Canvas.
14765     * The view must have already done a full layout before this function is
14766     * called.  When implementing a view, implement
14767     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
14768     * If you do need to override this method, call the superclass version.
14769     *
14770     * @param canvas The Canvas to which the View is rendered.
14771     */
14772    public void draw(Canvas canvas) {
14773        if (mClipBounds != null) {
14774            canvas.clipRect(mClipBounds);
14775        }
14776        final int privateFlags = mPrivateFlags;
14777        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
14778                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
14779        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
14780
14781        /*
14782         * Draw traversal performs several drawing steps which must be executed
14783         * in the appropriate order:
14784         *
14785         *      1. Draw the background
14786         *      2. If necessary, save the canvas' layers to prepare for fading
14787         *      3. Draw view's content
14788         *      4. Draw children
14789         *      5. If necessary, draw the fading edges and restore layers
14790         *      6. Draw decorations (scrollbars for instance)
14791         */
14792
14793        // Step 1, draw the background, if needed
14794        int saveCount;
14795
14796        if (!dirtyOpaque) {
14797            drawBackground(canvas);
14798        }
14799
14800        // skip step 2 & 5 if possible (common case)
14801        final int viewFlags = mViewFlags;
14802        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
14803        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
14804        if (!verticalEdges && !horizontalEdges) {
14805            // Step 3, draw the content
14806            if (!dirtyOpaque) onDraw(canvas);
14807
14808            // Step 4, draw the children
14809            dispatchDraw(canvas);
14810
14811            // Step 6, draw decorations (scrollbars)
14812            onDrawScrollBars(canvas);
14813
14814            if (mOverlay != null && !mOverlay.isEmpty()) {
14815                mOverlay.getOverlayView().dispatchDraw(canvas);
14816            }
14817
14818            // we're done...
14819            return;
14820        }
14821
14822        /*
14823         * Here we do the full fledged routine...
14824         * (this is an uncommon case where speed matters less,
14825         * this is why we repeat some of the tests that have been
14826         * done above)
14827         */
14828
14829        boolean drawTop = false;
14830        boolean drawBottom = false;
14831        boolean drawLeft = false;
14832        boolean drawRight = false;
14833
14834        float topFadeStrength = 0.0f;
14835        float bottomFadeStrength = 0.0f;
14836        float leftFadeStrength = 0.0f;
14837        float rightFadeStrength = 0.0f;
14838
14839        // Step 2, save the canvas' layers
14840        int paddingLeft = mPaddingLeft;
14841
14842        final boolean offsetRequired = isPaddingOffsetRequired();
14843        if (offsetRequired) {
14844            paddingLeft += getLeftPaddingOffset();
14845        }
14846
14847        int left = mScrollX + paddingLeft;
14848        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
14849        int top = mScrollY + getFadeTop(offsetRequired);
14850        int bottom = top + getFadeHeight(offsetRequired);
14851
14852        if (offsetRequired) {
14853            right += getRightPaddingOffset();
14854            bottom += getBottomPaddingOffset();
14855        }
14856
14857        final ScrollabilityCache scrollabilityCache = mScrollCache;
14858        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
14859        int length = (int) fadeHeight;
14860
14861        // clip the fade length if top and bottom fades overlap
14862        // overlapping fades produce odd-looking artifacts
14863        if (verticalEdges && (top + length > bottom - length)) {
14864            length = (bottom - top) / 2;
14865        }
14866
14867        // also clip horizontal fades if necessary
14868        if (horizontalEdges && (left + length > right - length)) {
14869            length = (right - left) / 2;
14870        }
14871
14872        if (verticalEdges) {
14873            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
14874            drawTop = topFadeStrength * fadeHeight > 1.0f;
14875            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
14876            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
14877        }
14878
14879        if (horizontalEdges) {
14880            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
14881            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
14882            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
14883            drawRight = rightFadeStrength * fadeHeight > 1.0f;
14884        }
14885
14886        saveCount = canvas.getSaveCount();
14887
14888        int solidColor = getSolidColor();
14889        if (solidColor == 0) {
14890            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
14891
14892            if (drawTop) {
14893                canvas.saveLayer(left, top, right, top + length, null, flags);
14894            }
14895
14896            if (drawBottom) {
14897                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
14898            }
14899
14900            if (drawLeft) {
14901                canvas.saveLayer(left, top, left + length, bottom, null, flags);
14902            }
14903
14904            if (drawRight) {
14905                canvas.saveLayer(right - length, top, right, bottom, null, flags);
14906            }
14907        } else {
14908            scrollabilityCache.setFadeColor(solidColor);
14909        }
14910
14911        // Step 3, draw the content
14912        if (!dirtyOpaque) onDraw(canvas);
14913
14914        // Step 4, draw the children
14915        dispatchDraw(canvas);
14916
14917        // Step 5, draw the fade effect and restore layers
14918        final Paint p = scrollabilityCache.paint;
14919        final Matrix matrix = scrollabilityCache.matrix;
14920        final Shader fade = scrollabilityCache.shader;
14921
14922        if (drawTop) {
14923            matrix.setScale(1, fadeHeight * topFadeStrength);
14924            matrix.postTranslate(left, top);
14925            fade.setLocalMatrix(matrix);
14926            p.setShader(fade);
14927            canvas.drawRect(left, top, right, top + length, p);
14928        }
14929
14930        if (drawBottom) {
14931            matrix.setScale(1, fadeHeight * bottomFadeStrength);
14932            matrix.postRotate(180);
14933            matrix.postTranslate(left, bottom);
14934            fade.setLocalMatrix(matrix);
14935            p.setShader(fade);
14936            canvas.drawRect(left, bottom - length, right, bottom, p);
14937        }
14938
14939        if (drawLeft) {
14940            matrix.setScale(1, fadeHeight * leftFadeStrength);
14941            matrix.postRotate(-90);
14942            matrix.postTranslate(left, top);
14943            fade.setLocalMatrix(matrix);
14944            p.setShader(fade);
14945            canvas.drawRect(left, top, left + length, bottom, p);
14946        }
14947
14948        if (drawRight) {
14949            matrix.setScale(1, fadeHeight * rightFadeStrength);
14950            matrix.postRotate(90);
14951            matrix.postTranslate(right, top);
14952            fade.setLocalMatrix(matrix);
14953            p.setShader(fade);
14954            canvas.drawRect(right - length, top, right, bottom, p);
14955        }
14956
14957        canvas.restoreToCount(saveCount);
14958
14959        // Step 6, draw decorations (scrollbars)
14960        onDrawScrollBars(canvas);
14961
14962        if (mOverlay != null && !mOverlay.isEmpty()) {
14963            mOverlay.getOverlayView().dispatchDraw(canvas);
14964        }
14965    }
14966
14967    /**
14968     * Draws the background onto the specified canvas.
14969     *
14970     * @param canvas Canvas on which to draw the background
14971     */
14972    private void drawBackground(Canvas canvas) {
14973        final Drawable background = mBackground;
14974        if (background == null) {
14975            return;
14976        }
14977
14978        if (mBackgroundSizeChanged) {
14979            background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
14980            mBackgroundSizeChanged = false;
14981            invalidateOutline();
14982        }
14983
14984        // Attempt to use a display list if requested.
14985        if (canvas.isHardwareAccelerated() && mAttachInfo != null
14986                && mAttachInfo.mHardwareRenderer != null) {
14987            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
14988
14989            final RenderNode displayList = mBackgroundRenderNode;
14990            if (displayList != null && displayList.isValid()) {
14991                setBackgroundDisplayListProperties(displayList);
14992                ((HardwareCanvas) canvas).drawRenderNode(displayList);
14993                return;
14994            }
14995        }
14996
14997        final int scrollX = mScrollX;
14998        final int scrollY = mScrollY;
14999        if ((scrollX | scrollY) == 0) {
15000            background.draw(canvas);
15001        } else {
15002            canvas.translate(scrollX, scrollY);
15003            background.draw(canvas);
15004            canvas.translate(-scrollX, -scrollY);
15005        }
15006    }
15007
15008    /**
15009     * Set up background drawable display list properties.
15010     *
15011     * @param displayList Valid display list for the background drawable
15012     */
15013    private void setBackgroundDisplayListProperties(RenderNode displayList) {
15014        displayList.setTranslationX(mScrollX);
15015        displayList.setTranslationY(mScrollY);
15016    }
15017
15018    /**
15019     * Creates a new display list or updates the existing display list for the
15020     * specified Drawable.
15021     *
15022     * @param drawable Drawable for which to create a display list
15023     * @param renderNode Existing RenderNode, or {@code null}
15024     * @return A valid display list for the specified drawable
15025     */
15026    private static RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
15027        if (renderNode == null) {
15028            renderNode = RenderNode.create(drawable.getClass().getName());
15029        }
15030
15031        final Rect bounds = drawable.getBounds();
15032        final int width = bounds.width();
15033        final int height = bounds.height();
15034        final HardwareCanvas canvas = renderNode.start(width, height);
15035        try {
15036            drawable.draw(canvas);
15037        } finally {
15038            renderNode.end(canvas);
15039        }
15040
15041        // Set up drawable properties that are view-independent.
15042        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
15043        renderNode.setProjectBackwards(drawable.isProjected());
15044        renderNode.setProjectionReceiver(true);
15045        renderNode.setClipToBounds(false);
15046        return renderNode;
15047    }
15048
15049    /**
15050     * Returns the overlay for this view, creating it if it does not yet exist.
15051     * Adding drawables to the overlay will cause them to be displayed whenever
15052     * the view itself is redrawn. Objects in the overlay should be actively
15053     * managed: remove them when they should not be displayed anymore. The
15054     * overlay will always have the same size as its host view.
15055     *
15056     * <p>Note: Overlays do not currently work correctly with {@link
15057     * SurfaceView} or {@link TextureView}; contents in overlays for these
15058     * types of views may not display correctly.</p>
15059     *
15060     * @return The ViewOverlay object for this view.
15061     * @see ViewOverlay
15062     */
15063    public ViewOverlay getOverlay() {
15064        if (mOverlay == null) {
15065            mOverlay = new ViewOverlay(mContext, this);
15066        }
15067        return mOverlay;
15068    }
15069
15070    /**
15071     * Override this if your view is known to always be drawn on top of a solid color background,
15072     * and needs to draw fading edges. Returning a non-zero color enables the view system to
15073     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
15074     * should be set to 0xFF.
15075     *
15076     * @see #setVerticalFadingEdgeEnabled(boolean)
15077     * @see #setHorizontalFadingEdgeEnabled(boolean)
15078     *
15079     * @return The known solid color background for this view, or 0 if the color may vary
15080     */
15081    @ViewDebug.ExportedProperty(category = "drawing")
15082    public int getSolidColor() {
15083        return 0;
15084    }
15085
15086    /**
15087     * Build a human readable string representation of the specified view flags.
15088     *
15089     * @param flags the view flags to convert to a string
15090     * @return a String representing the supplied flags
15091     */
15092    private static String printFlags(int flags) {
15093        String output = "";
15094        int numFlags = 0;
15095        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
15096            output += "TAKES_FOCUS";
15097            numFlags++;
15098        }
15099
15100        switch (flags & VISIBILITY_MASK) {
15101        case INVISIBLE:
15102            if (numFlags > 0) {
15103                output += " ";
15104            }
15105            output += "INVISIBLE";
15106            // USELESS HERE numFlags++;
15107            break;
15108        case GONE:
15109            if (numFlags > 0) {
15110                output += " ";
15111            }
15112            output += "GONE";
15113            // USELESS HERE numFlags++;
15114            break;
15115        default:
15116            break;
15117        }
15118        return output;
15119    }
15120
15121    /**
15122     * Build a human readable string representation of the specified private
15123     * view flags.
15124     *
15125     * @param privateFlags the private view flags to convert to a string
15126     * @return a String representing the supplied flags
15127     */
15128    private static String printPrivateFlags(int privateFlags) {
15129        String output = "";
15130        int numFlags = 0;
15131
15132        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
15133            output += "WANTS_FOCUS";
15134            numFlags++;
15135        }
15136
15137        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
15138            if (numFlags > 0) {
15139                output += " ";
15140            }
15141            output += "FOCUSED";
15142            numFlags++;
15143        }
15144
15145        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
15146            if (numFlags > 0) {
15147                output += " ";
15148            }
15149            output += "SELECTED";
15150            numFlags++;
15151        }
15152
15153        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
15154            if (numFlags > 0) {
15155                output += " ";
15156            }
15157            output += "IS_ROOT_NAMESPACE";
15158            numFlags++;
15159        }
15160
15161        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
15162            if (numFlags > 0) {
15163                output += " ";
15164            }
15165            output += "HAS_BOUNDS";
15166            numFlags++;
15167        }
15168
15169        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
15170            if (numFlags > 0) {
15171                output += " ";
15172            }
15173            output += "DRAWN";
15174            // USELESS HERE numFlags++;
15175        }
15176        return output;
15177    }
15178
15179    /**
15180     * <p>Indicates whether or not this view's layout will be requested during
15181     * the next hierarchy layout pass.</p>
15182     *
15183     * @return true if the layout will be forced during next layout pass
15184     */
15185    public boolean isLayoutRequested() {
15186        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
15187    }
15188
15189    /**
15190     * Return true if o is a ViewGroup that is laying out using optical bounds.
15191     * @hide
15192     */
15193    public static boolean isLayoutModeOptical(Object o) {
15194        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
15195    }
15196
15197    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
15198        Insets parentInsets = mParent instanceof View ?
15199                ((View) mParent).getOpticalInsets() : Insets.NONE;
15200        Insets childInsets = getOpticalInsets();
15201        return setFrame(
15202                left   + parentInsets.left - childInsets.left,
15203                top    + parentInsets.top  - childInsets.top,
15204                right  + parentInsets.left + childInsets.right,
15205                bottom + parentInsets.top  + childInsets.bottom);
15206    }
15207
15208    /**
15209     * Assign a size and position to a view and all of its
15210     * descendants
15211     *
15212     * <p>This is the second phase of the layout mechanism.
15213     * (The first is measuring). In this phase, each parent calls
15214     * layout on all of its children to position them.
15215     * This is typically done using the child measurements
15216     * that were stored in the measure pass().</p>
15217     *
15218     * <p>Derived classes should not override this method.
15219     * Derived classes with children should override
15220     * onLayout. In that method, they should
15221     * call layout on each of their children.</p>
15222     *
15223     * @param l Left position, relative to parent
15224     * @param t Top position, relative to parent
15225     * @param r Right position, relative to parent
15226     * @param b Bottom position, relative to parent
15227     */
15228    @SuppressWarnings({"unchecked"})
15229    public void layout(int l, int t, int r, int b) {
15230        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
15231            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
15232            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
15233        }
15234
15235        int oldL = mLeft;
15236        int oldT = mTop;
15237        int oldB = mBottom;
15238        int oldR = mRight;
15239
15240        boolean changed = isLayoutModeOptical(mParent) ?
15241                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
15242
15243        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
15244            onLayout(changed, l, t, r, b);
15245            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
15246
15247            ListenerInfo li = mListenerInfo;
15248            if (li != null && li.mOnLayoutChangeListeners != null) {
15249                ArrayList<OnLayoutChangeListener> listenersCopy =
15250                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
15251                int numListeners = listenersCopy.size();
15252                for (int i = 0; i < numListeners; ++i) {
15253                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
15254                }
15255            }
15256        }
15257
15258        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
15259        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
15260    }
15261
15262    /**
15263     * Called from layout when this view should
15264     * assign a size and position to each of its children.
15265     *
15266     * Derived classes with children should override
15267     * this method and call layout on each of
15268     * their children.
15269     * @param changed This is a new size or position for this view
15270     * @param left Left position, relative to parent
15271     * @param top Top position, relative to parent
15272     * @param right Right position, relative to parent
15273     * @param bottom Bottom position, relative to parent
15274     */
15275    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
15276    }
15277
15278    /**
15279     * Assign a size and position to this view.
15280     *
15281     * This is called from layout.
15282     *
15283     * @param left Left position, relative to parent
15284     * @param top Top position, relative to parent
15285     * @param right Right position, relative to parent
15286     * @param bottom Bottom position, relative to parent
15287     * @return true if the new size and position are different than the
15288     *         previous ones
15289     * {@hide}
15290     */
15291    protected boolean setFrame(int left, int top, int right, int bottom) {
15292        boolean changed = false;
15293
15294        if (DBG) {
15295            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
15296                    + right + "," + bottom + ")");
15297        }
15298
15299        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
15300            changed = true;
15301
15302            // Remember our drawn bit
15303            int drawn = mPrivateFlags & PFLAG_DRAWN;
15304
15305            int oldWidth = mRight - mLeft;
15306            int oldHeight = mBottom - mTop;
15307            int newWidth = right - left;
15308            int newHeight = bottom - top;
15309            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
15310
15311            // Invalidate our old position
15312            invalidate(sizeChanged);
15313
15314            mLeft = left;
15315            mTop = top;
15316            mRight = right;
15317            mBottom = bottom;
15318            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
15319
15320            mPrivateFlags |= PFLAG_HAS_BOUNDS;
15321
15322
15323            if (sizeChanged) {
15324                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
15325            }
15326
15327            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
15328                // If we are visible, force the DRAWN bit to on so that
15329                // this invalidate will go through (at least to our parent).
15330                // This is because someone may have invalidated this view
15331                // before this call to setFrame came in, thereby clearing
15332                // the DRAWN bit.
15333                mPrivateFlags |= PFLAG_DRAWN;
15334                invalidate(sizeChanged);
15335                // parent display list may need to be recreated based on a change in the bounds
15336                // of any child
15337                invalidateParentCaches();
15338            }
15339
15340            // Reset drawn bit to original value (invalidate turns it off)
15341            mPrivateFlags |= drawn;
15342
15343            mBackgroundSizeChanged = true;
15344
15345            notifySubtreeAccessibilityStateChangedIfNeeded();
15346        }
15347        return changed;
15348    }
15349
15350    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
15351        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
15352        if (mOverlay != null) {
15353            mOverlay.getOverlayView().setRight(newWidth);
15354            mOverlay.getOverlayView().setBottom(newHeight);
15355        }
15356        invalidateOutline();
15357    }
15358
15359    /**
15360     * Finalize inflating a view from XML.  This is called as the last phase
15361     * of inflation, after all child views have been added.
15362     *
15363     * <p>Even if the subclass overrides onFinishInflate, they should always be
15364     * sure to call the super method, so that we get called.
15365     */
15366    protected void onFinishInflate() {
15367    }
15368
15369    /**
15370     * Returns the resources associated with this view.
15371     *
15372     * @return Resources object.
15373     */
15374    public Resources getResources() {
15375        return mResources;
15376    }
15377
15378    /**
15379     * Invalidates the specified Drawable.
15380     *
15381     * @param drawable the drawable to invalidate
15382     */
15383    @Override
15384    public void invalidateDrawable(@NonNull Drawable drawable) {
15385        if (verifyDrawable(drawable)) {
15386            final Rect dirty = drawable.getDirtyBounds();
15387            final int scrollX = mScrollX;
15388            final int scrollY = mScrollY;
15389
15390            invalidate(dirty.left + scrollX, dirty.top + scrollY,
15391                    dirty.right + scrollX, dirty.bottom + scrollY);
15392
15393            invalidateOutline();
15394        }
15395    }
15396
15397    /**
15398     * Schedules an action on a drawable to occur at a specified time.
15399     *
15400     * @param who the recipient of the action
15401     * @param what the action to run on the drawable
15402     * @param when the time at which the action must occur. Uses the
15403     *        {@link SystemClock#uptimeMillis} timebase.
15404     */
15405    @Override
15406    public void scheduleDrawable(Drawable who, Runnable what, long when) {
15407        if (verifyDrawable(who) && what != null) {
15408            final long delay = when - SystemClock.uptimeMillis();
15409            if (mAttachInfo != null) {
15410                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15411                        Choreographer.CALLBACK_ANIMATION, what, who,
15412                        Choreographer.subtractFrameDelay(delay));
15413            } else {
15414                ViewRootImpl.getRunQueue().postDelayed(what, delay);
15415            }
15416        }
15417    }
15418
15419    /**
15420     * Cancels a scheduled action on a drawable.
15421     *
15422     * @param who the recipient of the action
15423     * @param what the action to cancel
15424     */
15425    @Override
15426    public void unscheduleDrawable(Drawable who, Runnable what) {
15427        if (verifyDrawable(who) && what != null) {
15428            if (mAttachInfo != null) {
15429                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15430                        Choreographer.CALLBACK_ANIMATION, what, who);
15431            }
15432            ViewRootImpl.getRunQueue().removeCallbacks(what);
15433        }
15434    }
15435
15436    /**
15437     * Unschedule any events associated with the given Drawable.  This can be
15438     * used when selecting a new Drawable into a view, so that the previous
15439     * one is completely unscheduled.
15440     *
15441     * @param who The Drawable to unschedule.
15442     *
15443     * @see #drawableStateChanged
15444     */
15445    public void unscheduleDrawable(Drawable who) {
15446        if (mAttachInfo != null && who != null) {
15447            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15448                    Choreographer.CALLBACK_ANIMATION, null, who);
15449        }
15450    }
15451
15452    /**
15453     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
15454     * that the View directionality can and will be resolved before its Drawables.
15455     *
15456     * Will call {@link View#onResolveDrawables} when resolution is done.
15457     *
15458     * @hide
15459     */
15460    protected void resolveDrawables() {
15461        // Drawables resolution may need to happen before resolving the layout direction (which is
15462        // done only during the measure() call).
15463        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
15464        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
15465        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
15466        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
15467        // direction to be resolved as its resolved value will be the same as its raw value.
15468        if (!isLayoutDirectionResolved() &&
15469                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
15470            return;
15471        }
15472
15473        final int layoutDirection = isLayoutDirectionResolved() ?
15474                getLayoutDirection() : getRawLayoutDirection();
15475
15476        if (mBackground != null) {
15477            mBackground.setLayoutDirection(layoutDirection);
15478        }
15479        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
15480        onResolveDrawables(layoutDirection);
15481    }
15482
15483    /**
15484     * Called when layout direction has been resolved.
15485     *
15486     * The default implementation does nothing.
15487     *
15488     * @param layoutDirection The resolved layout direction.
15489     *
15490     * @see #LAYOUT_DIRECTION_LTR
15491     * @see #LAYOUT_DIRECTION_RTL
15492     *
15493     * @hide
15494     */
15495    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
15496    }
15497
15498    /**
15499     * @hide
15500     */
15501    protected void resetResolvedDrawables() {
15502        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
15503    }
15504
15505    private boolean isDrawablesResolved() {
15506        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
15507    }
15508
15509    /**
15510     * If your view subclass is displaying its own Drawable objects, it should
15511     * override this function and return true for any Drawable it is
15512     * displaying.  This allows animations for those drawables to be
15513     * scheduled.
15514     *
15515     * <p>Be sure to call through to the super class when overriding this
15516     * function.
15517     *
15518     * @param who The Drawable to verify.  Return true if it is one you are
15519     *            displaying, else return the result of calling through to the
15520     *            super class.
15521     *
15522     * @return boolean If true than the Drawable is being displayed in the
15523     *         view; else false and it is not allowed to animate.
15524     *
15525     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
15526     * @see #drawableStateChanged()
15527     */
15528    protected boolean verifyDrawable(Drawable who) {
15529        return who == mBackground;
15530    }
15531
15532    /**
15533     * This function is called whenever the state of the view changes in such
15534     * a way that it impacts the state of drawables being shown.
15535     * <p>
15536     * If the View has a StateListAnimator, it will also be called to run necessary state
15537     * change animations.
15538     * <p>
15539     * Be sure to call through to the superclass when overriding this function.
15540     *
15541     * @see Drawable#setState(int[])
15542     */
15543    protected void drawableStateChanged() {
15544        final Drawable d = mBackground;
15545        if (d != null && d.isStateful()) {
15546            d.setState(getDrawableState());
15547        }
15548
15549        if (mStateListAnimator != null) {
15550            mStateListAnimator.setState(getDrawableState());
15551        }
15552    }
15553
15554    /**
15555     * This function is called whenever the drawable hotspot changes.
15556     * <p>
15557     * Be sure to call through to the superclass when overriding this function.
15558     *
15559     * @param x hotspot x coordinate
15560     * @param y hotspot y coordinate
15561     */
15562    public void drawableHotspotChanged(float x, float y) {
15563        if (mBackground != null) {
15564            mBackground.setHotspot(x, y);
15565        }
15566    }
15567
15568    /**
15569     * Call this to force a view to update its drawable state. This will cause
15570     * drawableStateChanged to be called on this view. Views that are interested
15571     * in the new state should call getDrawableState.
15572     *
15573     * @see #drawableStateChanged
15574     * @see #getDrawableState
15575     */
15576    public void refreshDrawableState() {
15577        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
15578        drawableStateChanged();
15579
15580        ViewParent parent = mParent;
15581        if (parent != null) {
15582            parent.childDrawableStateChanged(this);
15583        }
15584    }
15585
15586    /**
15587     * Return an array of resource IDs of the drawable states representing the
15588     * current state of the view.
15589     *
15590     * @return The current drawable state
15591     *
15592     * @see Drawable#setState(int[])
15593     * @see #drawableStateChanged()
15594     * @see #onCreateDrawableState(int)
15595     */
15596    public final int[] getDrawableState() {
15597        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
15598            return mDrawableState;
15599        } else {
15600            mDrawableState = onCreateDrawableState(0);
15601            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
15602            return mDrawableState;
15603        }
15604    }
15605
15606    /**
15607     * Generate the new {@link android.graphics.drawable.Drawable} state for
15608     * this view. This is called by the view
15609     * system when the cached Drawable state is determined to be invalid.  To
15610     * retrieve the current state, you should use {@link #getDrawableState}.
15611     *
15612     * @param extraSpace if non-zero, this is the number of extra entries you
15613     * would like in the returned array in which you can place your own
15614     * states.
15615     *
15616     * @return Returns an array holding the current {@link Drawable} state of
15617     * the view.
15618     *
15619     * @see #mergeDrawableStates(int[], int[])
15620     */
15621    protected int[] onCreateDrawableState(int extraSpace) {
15622        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
15623                mParent instanceof View) {
15624            return ((View) mParent).onCreateDrawableState(extraSpace);
15625        }
15626
15627        int[] drawableState;
15628
15629        int privateFlags = mPrivateFlags;
15630
15631        int viewStateIndex = 0;
15632        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
15633        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
15634        if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
15635        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
15636        if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
15637        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
15638        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
15639                HardwareRenderer.isAvailable()) {
15640            // This is set if HW acceleration is requested, even if the current
15641            // process doesn't allow it.  This is just to allow app preview
15642            // windows to better match their app.
15643            viewStateIndex |= VIEW_STATE_ACCELERATED;
15644        }
15645        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
15646
15647        final int privateFlags2 = mPrivateFlags2;
15648        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
15649        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
15650
15651        drawableState = VIEW_STATE_SETS[viewStateIndex];
15652
15653        //noinspection ConstantIfStatement
15654        if (false) {
15655            Log.i("View", "drawableStateIndex=" + viewStateIndex);
15656            Log.i("View", toString()
15657                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
15658                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
15659                    + " fo=" + hasFocus()
15660                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
15661                    + " wf=" + hasWindowFocus()
15662                    + ": " + Arrays.toString(drawableState));
15663        }
15664
15665        if (extraSpace == 0) {
15666            return drawableState;
15667        }
15668
15669        final int[] fullState;
15670        if (drawableState != null) {
15671            fullState = new int[drawableState.length + extraSpace];
15672            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
15673        } else {
15674            fullState = new int[extraSpace];
15675        }
15676
15677        return fullState;
15678    }
15679
15680    /**
15681     * Merge your own state values in <var>additionalState</var> into the base
15682     * state values <var>baseState</var> that were returned by
15683     * {@link #onCreateDrawableState(int)}.
15684     *
15685     * @param baseState The base state values returned by
15686     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
15687     * own additional state values.
15688     *
15689     * @param additionalState The additional state values you would like
15690     * added to <var>baseState</var>; this array is not modified.
15691     *
15692     * @return As a convenience, the <var>baseState</var> array you originally
15693     * passed into the function is returned.
15694     *
15695     * @see #onCreateDrawableState(int)
15696     */
15697    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
15698        final int N = baseState.length;
15699        int i = N - 1;
15700        while (i >= 0 && baseState[i] == 0) {
15701            i--;
15702        }
15703        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
15704        return baseState;
15705    }
15706
15707    /**
15708     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
15709     * on all Drawable objects associated with this view.
15710     * <p>
15711     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
15712     * attached to this view.
15713     */
15714    public void jumpDrawablesToCurrentState() {
15715        if (mBackground != null) {
15716            mBackground.jumpToCurrentState();
15717        }
15718        if (mStateListAnimator != null) {
15719            mStateListAnimator.jumpToCurrentState();
15720        }
15721    }
15722
15723    /**
15724     * Sets the background color for this view.
15725     * @param color the color of the background
15726     */
15727    @RemotableViewMethod
15728    public void setBackgroundColor(int color) {
15729        if (mBackground instanceof ColorDrawable) {
15730            ((ColorDrawable) mBackground.mutate()).setColor(color);
15731            computeOpaqueFlags();
15732            mBackgroundResource = 0;
15733        } else {
15734            setBackground(new ColorDrawable(color));
15735        }
15736    }
15737
15738    /**
15739     * Set the background to a given resource. The resource should refer to
15740     * a Drawable object or 0 to remove the background.
15741     * @param resid The identifier of the resource.
15742     *
15743     * @attr ref android.R.styleable#View_background
15744     */
15745    @RemotableViewMethod
15746    public void setBackgroundResource(int resid) {
15747        if (resid != 0 && resid == mBackgroundResource) {
15748            return;
15749        }
15750
15751        Drawable d = null;
15752        if (resid != 0) {
15753            d = mContext.getDrawable(resid);
15754        }
15755        setBackground(d);
15756
15757        mBackgroundResource = resid;
15758    }
15759
15760    /**
15761     * Set the background to a given Drawable, or remove the background. If the
15762     * background has padding, this View's padding is set to the background's
15763     * padding. However, when a background is removed, this View's padding isn't
15764     * touched. If setting the padding is desired, please use
15765     * {@link #setPadding(int, int, int, int)}.
15766     *
15767     * @param background The Drawable to use as the background, or null to remove the
15768     *        background
15769     */
15770    public void setBackground(Drawable background) {
15771        //noinspection deprecation
15772        setBackgroundDrawable(background);
15773    }
15774
15775    /**
15776     * @deprecated use {@link #setBackground(Drawable)} instead
15777     */
15778    @Deprecated
15779    public void setBackgroundDrawable(Drawable background) {
15780        computeOpaqueFlags();
15781
15782        if (background == mBackground) {
15783            return;
15784        }
15785
15786        boolean requestLayout = false;
15787
15788        mBackgroundResource = 0;
15789
15790        /*
15791         * Regardless of whether we're setting a new background or not, we want
15792         * to clear the previous drawable.
15793         */
15794        if (mBackground != null) {
15795            mBackground.setCallback(null);
15796            unscheduleDrawable(mBackground);
15797        }
15798
15799        if (background != null) {
15800            Rect padding = sThreadLocal.get();
15801            if (padding == null) {
15802                padding = new Rect();
15803                sThreadLocal.set(padding);
15804            }
15805            resetResolvedDrawables();
15806            background.setLayoutDirection(getLayoutDirection());
15807            if (background.getPadding(padding)) {
15808                resetResolvedPadding();
15809                switch (background.getLayoutDirection()) {
15810                    case LAYOUT_DIRECTION_RTL:
15811                        mUserPaddingLeftInitial = padding.right;
15812                        mUserPaddingRightInitial = padding.left;
15813                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
15814                        break;
15815                    case LAYOUT_DIRECTION_LTR:
15816                    default:
15817                        mUserPaddingLeftInitial = padding.left;
15818                        mUserPaddingRightInitial = padding.right;
15819                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
15820                }
15821                mLeftPaddingDefined = false;
15822                mRightPaddingDefined = false;
15823            }
15824
15825            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
15826            // if it has a different minimum size, we should layout again
15827            if (mBackground == null
15828                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
15829                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
15830                requestLayout = true;
15831            }
15832
15833            background.setCallback(this);
15834            if (background.isStateful()) {
15835                background.setState(getDrawableState());
15836            }
15837            background.setVisible(getVisibility() == VISIBLE, false);
15838            mBackground = background;
15839
15840            applyBackgroundTint();
15841
15842            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
15843                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
15844                mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
15845                requestLayout = true;
15846            }
15847        } else {
15848            /* Remove the background */
15849            mBackground = null;
15850
15851            if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
15852                /*
15853                 * This view ONLY drew the background before and we're removing
15854                 * the background, so now it won't draw anything
15855                 * (hence we SKIP_DRAW)
15856                 */
15857                mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
15858                mPrivateFlags |= PFLAG_SKIP_DRAW;
15859            }
15860
15861            /*
15862             * When the background is set, we try to apply its padding to this
15863             * View. When the background is removed, we don't touch this View's
15864             * padding. This is noted in the Javadocs. Hence, we don't need to
15865             * requestLayout(), the invalidate() below is sufficient.
15866             */
15867
15868            // The old background's minimum size could have affected this
15869            // View's layout, so let's requestLayout
15870            requestLayout = true;
15871        }
15872
15873        computeOpaqueFlags();
15874
15875        if (requestLayout) {
15876            requestLayout();
15877        }
15878
15879        mBackgroundSizeChanged = true;
15880        invalidate(true);
15881    }
15882
15883    /**
15884     * Gets the background drawable
15885     *
15886     * @return The drawable used as the background for this view, if any.
15887     *
15888     * @see #setBackground(Drawable)
15889     *
15890     * @attr ref android.R.styleable#View_background
15891     */
15892    public Drawable getBackground() {
15893        return mBackground;
15894    }
15895
15896    /**
15897     * Applies a tint to the background drawable.
15898     * <p>
15899     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
15900     * mutate the drawable and apply the specified tint and tint mode using
15901     * {@link Drawable#setTint(ColorStateList, PorterDuff.Mode)}.
15902     *
15903     * @param tint the tint to apply, may be {@code null} to clear tint
15904     * @param tintMode the blending mode used to apply the tint, may be
15905     *                 {@code null} to clear tint
15906     *
15907     * @attr ref android.R.styleable#View_backgroundTint
15908     * @attr ref android.R.styleable#View_backgroundTintMode
15909     * @see Drawable#setTint(ColorStateList, PorterDuff.Mode)
15910     */
15911    private void setBackgroundTint(@Nullable ColorStateList tint,
15912            @Nullable PorterDuff.Mode tintMode) {
15913        mBackgroundTint = tint;
15914        mBackgroundTintMode = tintMode;
15915        mHasBackgroundTint = true;
15916
15917        applyBackgroundTint();
15918    }
15919
15920    /**
15921     * Applies a tint to the background drawable. Does not modify the current tint
15922     * mode, which is {@link PorterDuff.Mode#SRC_ATOP} by default.
15923     * <p>
15924     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
15925     * mutate the drawable and apply the specified tint and tint mode using
15926     * {@link Drawable#setTint(ColorStateList, PorterDuff.Mode)}.
15927     *
15928     * @param tint the tint to apply, may be {@code null} to clear tint
15929     *
15930     * @attr ref android.R.styleable#View_backgroundTint
15931     * @see #setBackgroundTint(ColorStateList, PorterDuff.Mode)
15932     */
15933    public void setBackgroundTint(@Nullable ColorStateList tint) {
15934        setBackgroundTint(tint, mBackgroundTintMode);
15935    }
15936
15937    /**
15938     * @return the tint applied to the background drawable
15939     * @attr ref android.R.styleable#View_backgroundTint
15940     * @see #setBackgroundTint(ColorStateList, PorterDuff.Mode)
15941     */
15942    @Nullable
15943    public ColorStateList getBackgroundTint() {
15944        return mBackgroundTint;
15945    }
15946
15947    /**
15948     * Specifies the blending mode used to apply the tint specified by
15949     * {@link #setBackgroundTint(ColorStateList)}} to the background drawable.
15950     * The default mode is {@link PorterDuff.Mode#SRC_ATOP}.
15951     *
15952     * @param tintMode the blending mode used to apply the tint, may be
15953     *                 {@code null} to clear tint
15954     * @attr ref android.R.styleable#View_backgroundTintMode
15955     * @see #setBackgroundTint(ColorStateList)
15956     */
15957    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
15958        setBackgroundTint(mBackgroundTint, tintMode);
15959    }
15960
15961    /**
15962     * @return the blending mode used to apply the tint to the background drawable
15963     * @attr ref android.R.styleable#View_backgroundTintMode
15964     * @see #setBackgroundTint(ColorStateList, PorterDuff.Mode)
15965     */
15966    @Nullable
15967    public PorterDuff.Mode getBackgroundTintMode() {
15968        return mBackgroundTintMode;
15969    }
15970
15971    private void applyBackgroundTint() {
15972        if (mBackground != null && mHasBackgroundTint) {
15973            mBackground = mBackground.mutate();
15974            mBackground.setTint(mBackgroundTint, mBackgroundTintMode);
15975        }
15976    }
15977
15978    /**
15979     * Sets the padding. The view may add on the space required to display
15980     * the scrollbars, depending on the style and visibility of the scrollbars.
15981     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
15982     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
15983     * from the values set in this call.
15984     *
15985     * @attr ref android.R.styleable#View_padding
15986     * @attr ref android.R.styleable#View_paddingBottom
15987     * @attr ref android.R.styleable#View_paddingLeft
15988     * @attr ref android.R.styleable#View_paddingRight
15989     * @attr ref android.R.styleable#View_paddingTop
15990     * @param left the left padding in pixels
15991     * @param top the top padding in pixels
15992     * @param right the right padding in pixels
15993     * @param bottom the bottom padding in pixels
15994     */
15995    public void setPadding(int left, int top, int right, int bottom) {
15996        resetResolvedPadding();
15997
15998        mUserPaddingStart = UNDEFINED_PADDING;
15999        mUserPaddingEnd = UNDEFINED_PADDING;
16000
16001        mUserPaddingLeftInitial = left;
16002        mUserPaddingRightInitial = right;
16003
16004        mLeftPaddingDefined = true;
16005        mRightPaddingDefined = true;
16006
16007        internalSetPadding(left, top, right, bottom);
16008    }
16009
16010    /**
16011     * @hide
16012     */
16013    protected void internalSetPadding(int left, int top, int right, int bottom) {
16014        mUserPaddingLeft = left;
16015        mUserPaddingRight = right;
16016        mUserPaddingBottom = bottom;
16017
16018        final int viewFlags = mViewFlags;
16019        boolean changed = false;
16020
16021        // Common case is there are no scroll bars.
16022        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
16023            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
16024                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
16025                        ? 0 : getVerticalScrollbarWidth();
16026                switch (mVerticalScrollbarPosition) {
16027                    case SCROLLBAR_POSITION_DEFAULT:
16028                        if (isLayoutRtl()) {
16029                            left += offset;
16030                        } else {
16031                            right += offset;
16032                        }
16033                        break;
16034                    case SCROLLBAR_POSITION_RIGHT:
16035                        right += offset;
16036                        break;
16037                    case SCROLLBAR_POSITION_LEFT:
16038                        left += offset;
16039                        break;
16040                }
16041            }
16042            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
16043                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
16044                        ? 0 : getHorizontalScrollbarHeight();
16045            }
16046        }
16047
16048        if (mPaddingLeft != left) {
16049            changed = true;
16050            mPaddingLeft = left;
16051        }
16052        if (mPaddingTop != top) {
16053            changed = true;
16054            mPaddingTop = top;
16055        }
16056        if (mPaddingRight != right) {
16057            changed = true;
16058            mPaddingRight = right;
16059        }
16060        if (mPaddingBottom != bottom) {
16061            changed = true;
16062            mPaddingBottom = bottom;
16063        }
16064
16065        if (changed) {
16066            requestLayout();
16067        }
16068    }
16069
16070    /**
16071     * Sets the relative padding. The view may add on the space required to display
16072     * the scrollbars, depending on the style and visibility of the scrollbars.
16073     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
16074     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
16075     * from the values set in this call.
16076     *
16077     * @attr ref android.R.styleable#View_padding
16078     * @attr ref android.R.styleable#View_paddingBottom
16079     * @attr ref android.R.styleable#View_paddingStart
16080     * @attr ref android.R.styleable#View_paddingEnd
16081     * @attr ref android.R.styleable#View_paddingTop
16082     * @param start the start padding in pixels
16083     * @param top the top padding in pixels
16084     * @param end the end padding in pixels
16085     * @param bottom the bottom padding in pixels
16086     */
16087    public void setPaddingRelative(int start, int top, int end, int bottom) {
16088        resetResolvedPadding();
16089
16090        mUserPaddingStart = start;
16091        mUserPaddingEnd = end;
16092        mLeftPaddingDefined = true;
16093        mRightPaddingDefined = true;
16094
16095        switch(getLayoutDirection()) {
16096            case LAYOUT_DIRECTION_RTL:
16097                mUserPaddingLeftInitial = end;
16098                mUserPaddingRightInitial = start;
16099                internalSetPadding(end, top, start, bottom);
16100                break;
16101            case LAYOUT_DIRECTION_LTR:
16102            default:
16103                mUserPaddingLeftInitial = start;
16104                mUserPaddingRightInitial = end;
16105                internalSetPadding(start, top, end, bottom);
16106        }
16107    }
16108
16109    /**
16110     * Returns the top padding of this view.
16111     *
16112     * @return the top padding in pixels
16113     */
16114    public int getPaddingTop() {
16115        return mPaddingTop;
16116    }
16117
16118    /**
16119     * Returns the bottom padding of this view. If there are inset and enabled
16120     * scrollbars, this value may include the space required to display the
16121     * scrollbars as well.
16122     *
16123     * @return the bottom padding in pixels
16124     */
16125    public int getPaddingBottom() {
16126        return mPaddingBottom;
16127    }
16128
16129    /**
16130     * Returns the left padding of this view. If there are inset and enabled
16131     * scrollbars, this value may include the space required to display the
16132     * scrollbars as well.
16133     *
16134     * @return the left padding in pixels
16135     */
16136    public int getPaddingLeft() {
16137        if (!isPaddingResolved()) {
16138            resolvePadding();
16139        }
16140        return mPaddingLeft;
16141    }
16142
16143    /**
16144     * Returns the start padding of this view depending on its resolved layout direction.
16145     * If there are inset and enabled scrollbars, this value may include the space
16146     * required to display the scrollbars as well.
16147     *
16148     * @return the start padding in pixels
16149     */
16150    public int getPaddingStart() {
16151        if (!isPaddingResolved()) {
16152            resolvePadding();
16153        }
16154        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
16155                mPaddingRight : mPaddingLeft;
16156    }
16157
16158    /**
16159     * Returns the right padding of this view. If there are inset and enabled
16160     * scrollbars, this value may include the space required to display the
16161     * scrollbars as well.
16162     *
16163     * @return the right padding in pixels
16164     */
16165    public int getPaddingRight() {
16166        if (!isPaddingResolved()) {
16167            resolvePadding();
16168        }
16169        return mPaddingRight;
16170    }
16171
16172    /**
16173     * Returns the end padding of this view depending on its resolved layout direction.
16174     * If there are inset and enabled scrollbars, this value may include the space
16175     * required to display the scrollbars as well.
16176     *
16177     * @return the end padding in pixels
16178     */
16179    public int getPaddingEnd() {
16180        if (!isPaddingResolved()) {
16181            resolvePadding();
16182        }
16183        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
16184                mPaddingLeft : mPaddingRight;
16185    }
16186
16187    /**
16188     * Return if the padding as been set thru relative values
16189     * {@link #setPaddingRelative(int, int, int, int)} or thru
16190     * @attr ref android.R.styleable#View_paddingStart or
16191     * @attr ref android.R.styleable#View_paddingEnd
16192     *
16193     * @return true if the padding is relative or false if it is not.
16194     */
16195    public boolean isPaddingRelative() {
16196        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
16197    }
16198
16199    Insets computeOpticalInsets() {
16200        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
16201    }
16202
16203    /**
16204     * @hide
16205     */
16206    public void resetPaddingToInitialValues() {
16207        if (isRtlCompatibilityMode()) {
16208            mPaddingLeft = mUserPaddingLeftInitial;
16209            mPaddingRight = mUserPaddingRightInitial;
16210            return;
16211        }
16212        if (isLayoutRtl()) {
16213            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
16214            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
16215        } else {
16216            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
16217            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
16218        }
16219    }
16220
16221    /**
16222     * @hide
16223     */
16224    public Insets getOpticalInsets() {
16225        if (mLayoutInsets == null) {
16226            mLayoutInsets = computeOpticalInsets();
16227        }
16228        return mLayoutInsets;
16229    }
16230
16231    /**
16232     * Set this view's optical insets.
16233     *
16234     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
16235     * property. Views that compute their own optical insets should call it as part of measurement.
16236     * This method does not request layout. If you are setting optical insets outside of
16237     * measure/layout itself you will want to call requestLayout() yourself.
16238     * </p>
16239     * @hide
16240     */
16241    public void setOpticalInsets(Insets insets) {
16242        mLayoutInsets = insets;
16243    }
16244
16245    /**
16246     * Changes the selection state of this view. A view can be selected or not.
16247     * Note that selection is not the same as focus. Views are typically
16248     * selected in the context of an AdapterView like ListView or GridView;
16249     * the selected view is the view that is highlighted.
16250     *
16251     * @param selected true if the view must be selected, false otherwise
16252     */
16253    public void setSelected(boolean selected) {
16254        //noinspection DoubleNegation
16255        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
16256            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
16257            if (!selected) resetPressedState();
16258            invalidate(true);
16259            refreshDrawableState();
16260            dispatchSetSelected(selected);
16261            notifyViewAccessibilityStateChangedIfNeeded(
16262                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16263        }
16264    }
16265
16266    /**
16267     * Dispatch setSelected to all of this View's children.
16268     *
16269     * @see #setSelected(boolean)
16270     *
16271     * @param selected The new selected state
16272     */
16273    protected void dispatchSetSelected(boolean selected) {
16274    }
16275
16276    /**
16277     * Indicates the selection state of this view.
16278     *
16279     * @return true if the view is selected, false otherwise
16280     */
16281    @ViewDebug.ExportedProperty
16282    public boolean isSelected() {
16283        return (mPrivateFlags & PFLAG_SELECTED) != 0;
16284    }
16285
16286    /**
16287     * Changes the activated state of this view. A view can be activated or not.
16288     * Note that activation is not the same as selection.  Selection is
16289     * a transient property, representing the view (hierarchy) the user is
16290     * currently interacting with.  Activation is a longer-term state that the
16291     * user can move views in and out of.  For example, in a list view with
16292     * single or multiple selection enabled, the views in the current selection
16293     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
16294     * here.)  The activated state is propagated down to children of the view it
16295     * is set on.
16296     *
16297     * @param activated true if the view must be activated, false otherwise
16298     */
16299    public void setActivated(boolean activated) {
16300        //noinspection DoubleNegation
16301        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
16302            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
16303            invalidate(true);
16304            refreshDrawableState();
16305            dispatchSetActivated(activated);
16306        }
16307    }
16308
16309    /**
16310     * Dispatch setActivated to all of this View's children.
16311     *
16312     * @see #setActivated(boolean)
16313     *
16314     * @param activated The new activated state
16315     */
16316    protected void dispatchSetActivated(boolean activated) {
16317    }
16318
16319    /**
16320     * Indicates the activation state of this view.
16321     *
16322     * @return true if the view is activated, false otherwise
16323     */
16324    @ViewDebug.ExportedProperty
16325    public boolean isActivated() {
16326        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
16327    }
16328
16329    /**
16330     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
16331     * observer can be used to get notifications when global events, like
16332     * layout, happen.
16333     *
16334     * The returned ViewTreeObserver observer is not guaranteed to remain
16335     * valid for the lifetime of this View. If the caller of this method keeps
16336     * a long-lived reference to ViewTreeObserver, it should always check for
16337     * the return value of {@link ViewTreeObserver#isAlive()}.
16338     *
16339     * @return The ViewTreeObserver for this view's hierarchy.
16340     */
16341    public ViewTreeObserver getViewTreeObserver() {
16342        if (mAttachInfo != null) {
16343            return mAttachInfo.mTreeObserver;
16344        }
16345        if (mFloatingTreeObserver == null) {
16346            mFloatingTreeObserver = new ViewTreeObserver();
16347        }
16348        return mFloatingTreeObserver;
16349    }
16350
16351    /**
16352     * <p>Finds the topmost view in the current view hierarchy.</p>
16353     *
16354     * @return the topmost view containing this view
16355     */
16356    public View getRootView() {
16357        if (mAttachInfo != null) {
16358            final View v = mAttachInfo.mRootView;
16359            if (v != null) {
16360                return v;
16361            }
16362        }
16363
16364        View parent = this;
16365
16366        while (parent.mParent != null && parent.mParent instanceof View) {
16367            parent = (View) parent.mParent;
16368        }
16369
16370        return parent;
16371    }
16372
16373    /**
16374     * Transforms a motion event from view-local coordinates to on-screen
16375     * coordinates.
16376     *
16377     * @param ev the view-local motion event
16378     * @return false if the transformation could not be applied
16379     * @hide
16380     */
16381    public boolean toGlobalMotionEvent(MotionEvent ev) {
16382        final AttachInfo info = mAttachInfo;
16383        if (info == null) {
16384            return false;
16385        }
16386
16387        final Matrix m = info.mTmpMatrix;
16388        m.set(Matrix.IDENTITY_MATRIX);
16389        transformMatrixToGlobal(m);
16390        ev.transform(m);
16391        return true;
16392    }
16393
16394    /**
16395     * Transforms a motion event from on-screen coordinates to view-local
16396     * coordinates.
16397     *
16398     * @param ev the on-screen motion event
16399     * @return false if the transformation could not be applied
16400     * @hide
16401     */
16402    public boolean toLocalMotionEvent(MotionEvent ev) {
16403        final AttachInfo info = mAttachInfo;
16404        if (info == null) {
16405            return false;
16406        }
16407
16408        final Matrix m = info.mTmpMatrix;
16409        m.set(Matrix.IDENTITY_MATRIX);
16410        transformMatrixToLocal(m);
16411        ev.transform(m);
16412        return true;
16413    }
16414
16415    /**
16416     * Modifies the input matrix such that it maps view-local coordinates to
16417     * on-screen coordinates.
16418     *
16419     * @param m input matrix to modify
16420     */
16421    void transformMatrixToGlobal(Matrix m) {
16422        final ViewParent parent = mParent;
16423        if (parent instanceof View) {
16424            final View vp = (View) parent;
16425            vp.transformMatrixToGlobal(m);
16426            m.postTranslate(-vp.mScrollX, -vp.mScrollY);
16427        } else if (parent instanceof ViewRootImpl) {
16428            final ViewRootImpl vr = (ViewRootImpl) parent;
16429            vr.transformMatrixToGlobal(m);
16430            m.postTranslate(0, -vr.mCurScrollY);
16431        }
16432
16433        m.postTranslate(mLeft, mTop);
16434
16435        if (!hasIdentityMatrix()) {
16436            m.postConcat(getMatrix());
16437        }
16438    }
16439
16440    /**
16441     * Modifies the input matrix such that it maps on-screen coordinates to
16442     * view-local coordinates.
16443     *
16444     * @param m input matrix to modify
16445     */
16446    void transformMatrixToLocal(Matrix m) {
16447        final ViewParent parent = mParent;
16448        if (parent instanceof View) {
16449            final View vp = (View) parent;
16450            vp.transformMatrixToLocal(m);
16451            m.preTranslate(vp.mScrollX, vp.mScrollY);
16452        } else if (parent instanceof ViewRootImpl) {
16453            final ViewRootImpl vr = (ViewRootImpl) parent;
16454            vr.transformMatrixToLocal(m);
16455            m.preTranslate(0, vr.mCurScrollY);
16456        }
16457
16458        m.preTranslate(-mLeft, -mTop);
16459
16460        if (!hasIdentityMatrix()) {
16461            m.preConcat(getInverseMatrix());
16462        }
16463    }
16464
16465    /**
16466     * <p>Computes the coordinates of this view on the screen. The argument
16467     * must be an array of two integers. After the method returns, the array
16468     * contains the x and y location in that order.</p>
16469     *
16470     * @param location an array of two integers in which to hold the coordinates
16471     */
16472    public void getLocationOnScreen(int[] location) {
16473        getLocationInWindow(location);
16474
16475        final AttachInfo info = mAttachInfo;
16476        if (info != null) {
16477            location[0] += info.mWindowLeft;
16478            location[1] += info.mWindowTop;
16479        }
16480    }
16481
16482    /**
16483     * <p>Computes the coordinates of this view in its window. The argument
16484     * must be an array of two integers. After the method returns, the array
16485     * contains the x and y location in that order.</p>
16486     *
16487     * @param location an array of two integers in which to hold the coordinates
16488     */
16489    public void getLocationInWindow(int[] location) {
16490        if (location == null || location.length < 2) {
16491            throw new IllegalArgumentException("location must be an array of two integers");
16492        }
16493
16494        if (mAttachInfo == null) {
16495            // When the view is not attached to a window, this method does not make sense
16496            location[0] = location[1] = 0;
16497            return;
16498        }
16499
16500        float[] position = mAttachInfo.mTmpTransformLocation;
16501        position[0] = position[1] = 0.0f;
16502
16503        if (!hasIdentityMatrix()) {
16504            getMatrix().mapPoints(position);
16505        }
16506
16507        position[0] += mLeft;
16508        position[1] += mTop;
16509
16510        ViewParent viewParent = mParent;
16511        while (viewParent instanceof View) {
16512            final View view = (View) viewParent;
16513
16514            position[0] -= view.mScrollX;
16515            position[1] -= view.mScrollY;
16516
16517            if (!view.hasIdentityMatrix()) {
16518                view.getMatrix().mapPoints(position);
16519            }
16520
16521            position[0] += view.mLeft;
16522            position[1] += view.mTop;
16523
16524            viewParent = view.mParent;
16525         }
16526
16527        if (viewParent instanceof ViewRootImpl) {
16528            // *cough*
16529            final ViewRootImpl vr = (ViewRootImpl) viewParent;
16530            position[1] -= vr.mCurScrollY;
16531        }
16532
16533        location[0] = (int) (position[0] + 0.5f);
16534        location[1] = (int) (position[1] + 0.5f);
16535    }
16536
16537    /**
16538     * {@hide}
16539     * @param id the id of the view to be found
16540     * @return the view of the specified id, null if cannot be found
16541     */
16542    protected View findViewTraversal(int id) {
16543        if (id == mID) {
16544            return this;
16545        }
16546        return null;
16547    }
16548
16549    /**
16550     * {@hide}
16551     * @param tag the tag of the view to be found
16552     * @return the view of specified tag, null if cannot be found
16553     */
16554    protected View findViewWithTagTraversal(Object tag) {
16555        if (tag != null && tag.equals(mTag)) {
16556            return this;
16557        }
16558        return null;
16559    }
16560
16561    /**
16562     * {@hide}
16563     * @param predicate The predicate to evaluate.
16564     * @param childToSkip If not null, ignores this child during the recursive traversal.
16565     * @return The first view that matches the predicate or null.
16566     */
16567    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
16568        if (predicate.apply(this)) {
16569            return this;
16570        }
16571        return null;
16572    }
16573
16574    /**
16575     * Look for a child view with the given id.  If this view has the given
16576     * id, return this view.
16577     *
16578     * @param id The id to search for.
16579     * @return The view that has the given id in the hierarchy or null
16580     */
16581    public final View findViewById(int id) {
16582        if (id < 0) {
16583            return null;
16584        }
16585        return findViewTraversal(id);
16586    }
16587
16588    /**
16589     * Finds a view by its unuque and stable accessibility id.
16590     *
16591     * @param accessibilityId The searched accessibility id.
16592     * @return The found view.
16593     */
16594    final View findViewByAccessibilityId(int accessibilityId) {
16595        if (accessibilityId < 0) {
16596            return null;
16597        }
16598        return findViewByAccessibilityIdTraversal(accessibilityId);
16599    }
16600
16601    /**
16602     * Performs the traversal to find a view by its unuque and stable accessibility id.
16603     *
16604     * <strong>Note:</strong>This method does not stop at the root namespace
16605     * boundary since the user can touch the screen at an arbitrary location
16606     * potentially crossing the root namespace bounday which will send an
16607     * accessibility event to accessibility services and they should be able
16608     * to obtain the event source. Also accessibility ids are guaranteed to be
16609     * unique in the window.
16610     *
16611     * @param accessibilityId The accessibility id.
16612     * @return The found view.
16613     *
16614     * @hide
16615     */
16616    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
16617        if (getAccessibilityViewId() == accessibilityId) {
16618            return this;
16619        }
16620        return null;
16621    }
16622
16623    /**
16624     * Look for a child view with the given tag.  If this view has the given
16625     * tag, return this view.
16626     *
16627     * @param tag The tag to search for, using "tag.equals(getTag())".
16628     * @return The View that has the given tag in the hierarchy or null
16629     */
16630    public final View findViewWithTag(Object tag) {
16631        if (tag == null) {
16632            return null;
16633        }
16634        return findViewWithTagTraversal(tag);
16635    }
16636
16637    /**
16638     * {@hide}
16639     * Look for a child view that matches the specified predicate.
16640     * If this view matches the predicate, return this view.
16641     *
16642     * @param predicate The predicate to evaluate.
16643     * @return The first view that matches the predicate or null.
16644     */
16645    public final View findViewByPredicate(Predicate<View> predicate) {
16646        return findViewByPredicateTraversal(predicate, null);
16647    }
16648
16649    /**
16650     * {@hide}
16651     * Look for a child view that matches the specified predicate,
16652     * starting with the specified view and its descendents and then
16653     * recusively searching the ancestors and siblings of that view
16654     * until this view is reached.
16655     *
16656     * This method is useful in cases where the predicate does not match
16657     * a single unique view (perhaps multiple views use the same id)
16658     * and we are trying to find the view that is "closest" in scope to the
16659     * starting view.
16660     *
16661     * @param start The view to start from.
16662     * @param predicate The predicate to evaluate.
16663     * @return The first view that matches the predicate or null.
16664     */
16665    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
16666        View childToSkip = null;
16667        for (;;) {
16668            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
16669            if (view != null || start == this) {
16670                return view;
16671            }
16672
16673            ViewParent parent = start.getParent();
16674            if (parent == null || !(parent instanceof View)) {
16675                return null;
16676            }
16677
16678            childToSkip = start;
16679            start = (View) parent;
16680        }
16681    }
16682
16683    /**
16684     * Sets the identifier for this view. The identifier does not have to be
16685     * unique in this view's hierarchy. The identifier should be a positive
16686     * number.
16687     *
16688     * @see #NO_ID
16689     * @see #getId()
16690     * @see #findViewById(int)
16691     *
16692     * @param id a number used to identify the view
16693     *
16694     * @attr ref android.R.styleable#View_id
16695     */
16696    public void setId(int id) {
16697        mID = id;
16698        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
16699            mID = generateViewId();
16700        }
16701    }
16702
16703    /**
16704     * {@hide}
16705     *
16706     * @param isRoot true if the view belongs to the root namespace, false
16707     *        otherwise
16708     */
16709    public void setIsRootNamespace(boolean isRoot) {
16710        if (isRoot) {
16711            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
16712        } else {
16713            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
16714        }
16715    }
16716
16717    /**
16718     * {@hide}
16719     *
16720     * @return true if the view belongs to the root namespace, false otherwise
16721     */
16722    public boolean isRootNamespace() {
16723        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
16724    }
16725
16726    /**
16727     * Returns this view's identifier.
16728     *
16729     * @return a positive integer used to identify the view or {@link #NO_ID}
16730     *         if the view has no ID
16731     *
16732     * @see #setId(int)
16733     * @see #findViewById(int)
16734     * @attr ref android.R.styleable#View_id
16735     */
16736    @ViewDebug.CapturedViewProperty
16737    public int getId() {
16738        return mID;
16739    }
16740
16741    /**
16742     * Returns this view's tag.
16743     *
16744     * @return the Object stored in this view as a tag, or {@code null} if not
16745     *         set
16746     *
16747     * @see #setTag(Object)
16748     * @see #getTag(int)
16749     */
16750    @ViewDebug.ExportedProperty
16751    public Object getTag() {
16752        return mTag;
16753    }
16754
16755    /**
16756     * Sets the tag associated with this view. A tag can be used to mark
16757     * a view in its hierarchy and does not have to be unique within the
16758     * hierarchy. Tags can also be used to store data within a view without
16759     * resorting to another data structure.
16760     *
16761     * @param tag an Object to tag the view with
16762     *
16763     * @see #getTag()
16764     * @see #setTag(int, Object)
16765     */
16766    public void setTag(final Object tag) {
16767        mTag = tag;
16768    }
16769
16770    /**
16771     * Returns the tag associated with this view and the specified key.
16772     *
16773     * @param key The key identifying the tag
16774     *
16775     * @return the Object stored in this view as a tag, or {@code null} if not
16776     *         set
16777     *
16778     * @see #setTag(int, Object)
16779     * @see #getTag()
16780     */
16781    public Object getTag(int key) {
16782        if (mKeyedTags != null) return mKeyedTags.get(key);
16783        return null;
16784    }
16785
16786    /**
16787     * Sets a tag associated with this view and a key. A tag can be used
16788     * to mark a view in its hierarchy and does not have to be unique within
16789     * the hierarchy. Tags can also be used to store data within a view
16790     * without resorting to another data structure.
16791     *
16792     * The specified key should be an id declared in the resources of the
16793     * application to ensure it is unique (see the <a
16794     * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
16795     * Keys identified as belonging to
16796     * the Android framework or not associated with any package will cause
16797     * an {@link IllegalArgumentException} to be thrown.
16798     *
16799     * @param key The key identifying the tag
16800     * @param tag An Object to tag the view with
16801     *
16802     * @throws IllegalArgumentException If they specified key is not valid
16803     *
16804     * @see #setTag(Object)
16805     * @see #getTag(int)
16806     */
16807    public void setTag(int key, final Object tag) {
16808        // If the package id is 0x00 or 0x01, it's either an undefined package
16809        // or a framework id
16810        if ((key >>> 24) < 2) {
16811            throw new IllegalArgumentException("The key must be an application-specific "
16812                    + "resource id.");
16813        }
16814
16815        setKeyedTag(key, tag);
16816    }
16817
16818    /**
16819     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
16820     * framework id.
16821     *
16822     * @hide
16823     */
16824    public void setTagInternal(int key, Object tag) {
16825        if ((key >>> 24) != 0x1) {
16826            throw new IllegalArgumentException("The key must be a framework-specific "
16827                    + "resource id.");
16828        }
16829
16830        setKeyedTag(key, tag);
16831    }
16832
16833    private void setKeyedTag(int key, Object tag) {
16834        if (mKeyedTags == null) {
16835            mKeyedTags = new SparseArray<Object>(2);
16836        }
16837
16838        mKeyedTags.put(key, tag);
16839    }
16840
16841    /**
16842     * Prints information about this view in the log output, with the tag
16843     * {@link #VIEW_LOG_TAG}.
16844     *
16845     * @hide
16846     */
16847    public void debug() {
16848        debug(0);
16849    }
16850
16851    /**
16852     * Prints information about this view in the log output, with the tag
16853     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
16854     * indentation defined by the <code>depth</code>.
16855     *
16856     * @param depth the indentation level
16857     *
16858     * @hide
16859     */
16860    protected void debug(int depth) {
16861        String output = debugIndent(depth - 1);
16862
16863        output += "+ " + this;
16864        int id = getId();
16865        if (id != -1) {
16866            output += " (id=" + id + ")";
16867        }
16868        Object tag = getTag();
16869        if (tag != null) {
16870            output += " (tag=" + tag + ")";
16871        }
16872        Log.d(VIEW_LOG_TAG, output);
16873
16874        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
16875            output = debugIndent(depth) + " FOCUSED";
16876            Log.d(VIEW_LOG_TAG, output);
16877        }
16878
16879        output = debugIndent(depth);
16880        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
16881                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
16882                + "} ";
16883        Log.d(VIEW_LOG_TAG, output);
16884
16885        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
16886                || mPaddingBottom != 0) {
16887            output = debugIndent(depth);
16888            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
16889                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
16890            Log.d(VIEW_LOG_TAG, output);
16891        }
16892
16893        output = debugIndent(depth);
16894        output += "mMeasureWidth=" + mMeasuredWidth +
16895                " mMeasureHeight=" + mMeasuredHeight;
16896        Log.d(VIEW_LOG_TAG, output);
16897
16898        output = debugIndent(depth);
16899        if (mLayoutParams == null) {
16900            output += "BAD! no layout params";
16901        } else {
16902            output = mLayoutParams.debug(output);
16903        }
16904        Log.d(VIEW_LOG_TAG, output);
16905
16906        output = debugIndent(depth);
16907        output += "flags={";
16908        output += View.printFlags(mViewFlags);
16909        output += "}";
16910        Log.d(VIEW_LOG_TAG, output);
16911
16912        output = debugIndent(depth);
16913        output += "privateFlags={";
16914        output += View.printPrivateFlags(mPrivateFlags);
16915        output += "}";
16916        Log.d(VIEW_LOG_TAG, output);
16917    }
16918
16919    /**
16920     * Creates a string of whitespaces used for indentation.
16921     *
16922     * @param depth the indentation level
16923     * @return a String containing (depth * 2 + 3) * 2 white spaces
16924     *
16925     * @hide
16926     */
16927    protected static String debugIndent(int depth) {
16928        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
16929        for (int i = 0; i < (depth * 2) + 3; i++) {
16930            spaces.append(' ').append(' ');
16931        }
16932        return spaces.toString();
16933    }
16934
16935    /**
16936     * <p>Return the offset of the widget's text baseline from the widget's top
16937     * boundary. If this widget does not support baseline alignment, this
16938     * method returns -1. </p>
16939     *
16940     * @return the offset of the baseline within the widget's bounds or -1
16941     *         if baseline alignment is not supported
16942     */
16943    @ViewDebug.ExportedProperty(category = "layout")
16944    public int getBaseline() {
16945        return -1;
16946    }
16947
16948    /**
16949     * Returns whether the view hierarchy is currently undergoing a layout pass. This
16950     * information is useful to avoid situations such as calling {@link #requestLayout()} during
16951     * a layout pass.
16952     *
16953     * @return whether the view hierarchy is currently undergoing a layout pass
16954     */
16955    public boolean isInLayout() {
16956        ViewRootImpl viewRoot = getViewRootImpl();
16957        return (viewRoot != null && viewRoot.isInLayout());
16958    }
16959
16960    /**
16961     * Call this when something has changed which has invalidated the
16962     * layout of this view. This will schedule a layout pass of the view
16963     * tree. This should not be called while the view hierarchy is currently in a layout
16964     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
16965     * end of the current layout pass (and then layout will run again) or after the current
16966     * frame is drawn and the next layout occurs.
16967     *
16968     * <p>Subclasses which override this method should call the superclass method to
16969     * handle possible request-during-layout errors correctly.</p>
16970     */
16971    public void requestLayout() {
16972        if (mMeasureCache != null) mMeasureCache.clear();
16973
16974        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
16975            // Only trigger request-during-layout logic if this is the view requesting it,
16976            // not the views in its parent hierarchy
16977            ViewRootImpl viewRoot = getViewRootImpl();
16978            if (viewRoot != null && viewRoot.isInLayout()) {
16979                if (!viewRoot.requestLayoutDuringLayout(this)) {
16980                    return;
16981                }
16982            }
16983            mAttachInfo.mViewRequestingLayout = this;
16984        }
16985
16986        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
16987        mPrivateFlags |= PFLAG_INVALIDATED;
16988
16989        if (mParent != null && !mParent.isLayoutRequested()) {
16990            mParent.requestLayout();
16991        }
16992        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
16993            mAttachInfo.mViewRequestingLayout = null;
16994        }
16995    }
16996
16997    /**
16998     * Forces this view to be laid out during the next layout pass.
16999     * This method does not call requestLayout() or forceLayout()
17000     * on the parent.
17001     */
17002    public void forceLayout() {
17003        if (mMeasureCache != null) mMeasureCache.clear();
17004
17005        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
17006        mPrivateFlags |= PFLAG_INVALIDATED;
17007    }
17008
17009    /**
17010     * <p>
17011     * This is called to find out how big a view should be. The parent
17012     * supplies constraint information in the width and height parameters.
17013     * </p>
17014     *
17015     * <p>
17016     * The actual measurement work of a view is performed in
17017     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
17018     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
17019     * </p>
17020     *
17021     *
17022     * @param widthMeasureSpec Horizontal space requirements as imposed by the
17023     *        parent
17024     * @param heightMeasureSpec Vertical space requirements as imposed by the
17025     *        parent
17026     *
17027     * @see #onMeasure(int, int)
17028     */
17029    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
17030        boolean optical = isLayoutModeOptical(this);
17031        if (optical != isLayoutModeOptical(mParent)) {
17032            Insets insets = getOpticalInsets();
17033            int oWidth  = insets.left + insets.right;
17034            int oHeight = insets.top  + insets.bottom;
17035            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
17036            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
17037        }
17038
17039        // Suppress sign extension for the low bytes
17040        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
17041        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
17042
17043        if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
17044                widthMeasureSpec != mOldWidthMeasureSpec ||
17045                heightMeasureSpec != mOldHeightMeasureSpec) {
17046
17047            // first clears the measured dimension flag
17048            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
17049
17050            resolveRtlPropertiesIfNeeded();
17051
17052            int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
17053                    mMeasureCache.indexOfKey(key);
17054            if (cacheIndex < 0 || sIgnoreMeasureCache) {
17055                // measure ourselves, this should set the measured dimension flag back
17056                onMeasure(widthMeasureSpec, heightMeasureSpec);
17057                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17058            } else {
17059                long value = mMeasureCache.valueAt(cacheIndex);
17060                // Casting a long to int drops the high 32 bits, no mask needed
17061                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
17062                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17063            }
17064
17065            // flag not set, setMeasuredDimension() was not invoked, we raise
17066            // an exception to warn the developer
17067            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
17068                throw new IllegalStateException("onMeasure() did not set the"
17069                        + " measured dimension by calling"
17070                        + " setMeasuredDimension()");
17071            }
17072
17073            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
17074        }
17075
17076        mOldWidthMeasureSpec = widthMeasureSpec;
17077        mOldHeightMeasureSpec = heightMeasureSpec;
17078
17079        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
17080                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
17081    }
17082
17083    /**
17084     * <p>
17085     * Measure the view and its content to determine the measured width and the
17086     * measured height. This method is invoked by {@link #measure(int, int)} and
17087     * should be overriden by subclasses to provide accurate and efficient
17088     * measurement of their contents.
17089     * </p>
17090     *
17091     * <p>
17092     * <strong>CONTRACT:</strong> When overriding this method, you
17093     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
17094     * measured width and height of this view. Failure to do so will trigger an
17095     * <code>IllegalStateException</code>, thrown by
17096     * {@link #measure(int, int)}. Calling the superclass'
17097     * {@link #onMeasure(int, int)} is a valid use.
17098     * </p>
17099     *
17100     * <p>
17101     * The base class implementation of measure defaults to the background size,
17102     * unless a larger size is allowed by the MeasureSpec. Subclasses should
17103     * override {@link #onMeasure(int, int)} to provide better measurements of
17104     * their content.
17105     * </p>
17106     *
17107     * <p>
17108     * If this method is overridden, it is the subclass's responsibility to make
17109     * sure the measured height and width are at least the view's minimum height
17110     * and width ({@link #getSuggestedMinimumHeight()} and
17111     * {@link #getSuggestedMinimumWidth()}).
17112     * </p>
17113     *
17114     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
17115     *                         The requirements are encoded with
17116     *                         {@link android.view.View.MeasureSpec}.
17117     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
17118     *                         The requirements are encoded with
17119     *                         {@link android.view.View.MeasureSpec}.
17120     *
17121     * @see #getMeasuredWidth()
17122     * @see #getMeasuredHeight()
17123     * @see #setMeasuredDimension(int, int)
17124     * @see #getSuggestedMinimumHeight()
17125     * @see #getSuggestedMinimumWidth()
17126     * @see android.view.View.MeasureSpec#getMode(int)
17127     * @see android.view.View.MeasureSpec#getSize(int)
17128     */
17129    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
17130        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
17131                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
17132    }
17133
17134    /**
17135     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
17136     * measured width and measured height. Failing to do so will trigger an
17137     * exception at measurement time.</p>
17138     *
17139     * @param measuredWidth The measured width of this view.  May be a complex
17140     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17141     * {@link #MEASURED_STATE_TOO_SMALL}.
17142     * @param measuredHeight The measured height of this view.  May be a complex
17143     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17144     * {@link #MEASURED_STATE_TOO_SMALL}.
17145     */
17146    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
17147        boolean optical = isLayoutModeOptical(this);
17148        if (optical != isLayoutModeOptical(mParent)) {
17149            Insets insets = getOpticalInsets();
17150            int opticalWidth  = insets.left + insets.right;
17151            int opticalHeight = insets.top  + insets.bottom;
17152
17153            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
17154            measuredHeight += optical ? opticalHeight : -opticalHeight;
17155        }
17156        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
17157    }
17158
17159    /**
17160     * Sets the measured dimension without extra processing for things like optical bounds.
17161     * Useful for reapplying consistent values that have already been cooked with adjustments
17162     * for optical bounds, etc. such as those from the measurement cache.
17163     *
17164     * @param measuredWidth The measured width of this view.  May be a complex
17165     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17166     * {@link #MEASURED_STATE_TOO_SMALL}.
17167     * @param measuredHeight The measured height of this view.  May be a complex
17168     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17169     * {@link #MEASURED_STATE_TOO_SMALL}.
17170     */
17171    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
17172        mMeasuredWidth = measuredWidth;
17173        mMeasuredHeight = measuredHeight;
17174
17175        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
17176    }
17177
17178    /**
17179     * Merge two states as returned by {@link #getMeasuredState()}.
17180     * @param curState The current state as returned from a view or the result
17181     * of combining multiple views.
17182     * @param newState The new view state to combine.
17183     * @return Returns a new integer reflecting the combination of the two
17184     * states.
17185     */
17186    public static int combineMeasuredStates(int curState, int newState) {
17187        return curState | newState;
17188    }
17189
17190    /**
17191     * Version of {@link #resolveSizeAndState(int, int, int)}
17192     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
17193     */
17194    public static int resolveSize(int size, int measureSpec) {
17195        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
17196    }
17197
17198    /**
17199     * Utility to reconcile a desired size and state, with constraints imposed
17200     * by a MeasureSpec.  Will take the desired size, unless a different size
17201     * is imposed by the constraints.  The returned value is a compound integer,
17202     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
17203     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
17204     * size is smaller than the size the view wants to be.
17205     *
17206     * @param size How big the view wants to be
17207     * @param measureSpec Constraints imposed by the parent
17208     * @return Size information bit mask as defined by
17209     * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
17210     */
17211    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
17212        int result = size;
17213        int specMode = MeasureSpec.getMode(measureSpec);
17214        int specSize =  MeasureSpec.getSize(measureSpec);
17215        switch (specMode) {
17216        case MeasureSpec.UNSPECIFIED:
17217            result = size;
17218            break;
17219        case MeasureSpec.AT_MOST:
17220            if (specSize < size) {
17221                result = specSize | MEASURED_STATE_TOO_SMALL;
17222            } else {
17223                result = size;
17224            }
17225            break;
17226        case MeasureSpec.EXACTLY:
17227            result = specSize;
17228            break;
17229        }
17230        return result | (childMeasuredState&MEASURED_STATE_MASK);
17231    }
17232
17233    /**
17234     * Utility to return a default size. Uses the supplied size if the
17235     * MeasureSpec imposed no constraints. Will get larger if allowed
17236     * by the MeasureSpec.
17237     *
17238     * @param size Default size for this view
17239     * @param measureSpec Constraints imposed by the parent
17240     * @return The size this view should be.
17241     */
17242    public static int getDefaultSize(int size, int measureSpec) {
17243        int result = size;
17244        int specMode = MeasureSpec.getMode(measureSpec);
17245        int specSize = MeasureSpec.getSize(measureSpec);
17246
17247        switch (specMode) {
17248        case MeasureSpec.UNSPECIFIED:
17249            result = size;
17250            break;
17251        case MeasureSpec.AT_MOST:
17252        case MeasureSpec.EXACTLY:
17253            result = specSize;
17254            break;
17255        }
17256        return result;
17257    }
17258
17259    /**
17260     * Returns the suggested minimum height that the view should use. This
17261     * returns the maximum of the view's minimum height
17262     * and the background's minimum height
17263     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
17264     * <p>
17265     * When being used in {@link #onMeasure(int, int)}, the caller should still
17266     * ensure the returned height is within the requirements of the parent.
17267     *
17268     * @return The suggested minimum height of the view.
17269     */
17270    protected int getSuggestedMinimumHeight() {
17271        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
17272
17273    }
17274
17275    /**
17276     * Returns the suggested minimum width that the view should use. This
17277     * returns the maximum of the view's minimum width)
17278     * and the background's minimum width
17279     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
17280     * <p>
17281     * When being used in {@link #onMeasure(int, int)}, the caller should still
17282     * ensure the returned width is within the requirements of the parent.
17283     *
17284     * @return The suggested minimum width of the view.
17285     */
17286    protected int getSuggestedMinimumWidth() {
17287        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
17288    }
17289
17290    /**
17291     * Returns the minimum height of the view.
17292     *
17293     * @return the minimum height the view will try to be.
17294     *
17295     * @see #setMinimumHeight(int)
17296     *
17297     * @attr ref android.R.styleable#View_minHeight
17298     */
17299    public int getMinimumHeight() {
17300        return mMinHeight;
17301    }
17302
17303    /**
17304     * Sets the minimum height of the view. It is not guaranteed the view will
17305     * be able to achieve this minimum height (for example, if its parent layout
17306     * constrains it with less available height).
17307     *
17308     * @param minHeight The minimum height the view will try to be.
17309     *
17310     * @see #getMinimumHeight()
17311     *
17312     * @attr ref android.R.styleable#View_minHeight
17313     */
17314    public void setMinimumHeight(int minHeight) {
17315        mMinHeight = minHeight;
17316        requestLayout();
17317    }
17318
17319    /**
17320     * Returns the minimum width of the view.
17321     *
17322     * @return the minimum width the view will try to be.
17323     *
17324     * @see #setMinimumWidth(int)
17325     *
17326     * @attr ref android.R.styleable#View_minWidth
17327     */
17328    public int getMinimumWidth() {
17329        return mMinWidth;
17330    }
17331
17332    /**
17333     * Sets the minimum width of the view. It is not guaranteed the view will
17334     * be able to achieve this minimum width (for example, if its parent layout
17335     * constrains it with less available width).
17336     *
17337     * @param minWidth The minimum width the view will try to be.
17338     *
17339     * @see #getMinimumWidth()
17340     *
17341     * @attr ref android.R.styleable#View_minWidth
17342     */
17343    public void setMinimumWidth(int minWidth) {
17344        mMinWidth = minWidth;
17345        requestLayout();
17346
17347    }
17348
17349    /**
17350     * Get the animation currently associated with this view.
17351     *
17352     * @return The animation that is currently playing or
17353     *         scheduled to play for this view.
17354     */
17355    public Animation getAnimation() {
17356        return mCurrentAnimation;
17357    }
17358
17359    /**
17360     * Start the specified animation now.
17361     *
17362     * @param animation the animation to start now
17363     */
17364    public void startAnimation(Animation animation) {
17365        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
17366        setAnimation(animation);
17367        invalidateParentCaches();
17368        invalidate(true);
17369    }
17370
17371    /**
17372     * Cancels any animations for this view.
17373     */
17374    public void clearAnimation() {
17375        if (mCurrentAnimation != null) {
17376            mCurrentAnimation.detach();
17377        }
17378        mCurrentAnimation = null;
17379        invalidateParentIfNeeded();
17380    }
17381
17382    /**
17383     * Sets the next animation to play for this view.
17384     * If you want the animation to play immediately, use
17385     * {@link #startAnimation(android.view.animation.Animation)} instead.
17386     * This method provides allows fine-grained
17387     * control over the start time and invalidation, but you
17388     * must make sure that 1) the animation has a start time set, and
17389     * 2) the view's parent (which controls animations on its children)
17390     * will be invalidated when the animation is supposed to
17391     * start.
17392     *
17393     * @param animation The next animation, or null.
17394     */
17395    public void setAnimation(Animation animation) {
17396        mCurrentAnimation = animation;
17397
17398        if (animation != null) {
17399            // If the screen is off assume the animation start time is now instead of
17400            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
17401            // would cause the animation to start when the screen turns back on
17402            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
17403                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
17404                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
17405            }
17406            animation.reset();
17407        }
17408    }
17409
17410    /**
17411     * Invoked by a parent ViewGroup to notify the start of the animation
17412     * currently associated with this view. If you override this method,
17413     * always call super.onAnimationStart();
17414     *
17415     * @see #setAnimation(android.view.animation.Animation)
17416     * @see #getAnimation()
17417     */
17418    protected void onAnimationStart() {
17419        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
17420    }
17421
17422    /**
17423     * Invoked by a parent ViewGroup to notify the end of the animation
17424     * currently associated with this view. If you override this method,
17425     * always call super.onAnimationEnd();
17426     *
17427     * @see #setAnimation(android.view.animation.Animation)
17428     * @see #getAnimation()
17429     */
17430    protected void onAnimationEnd() {
17431        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
17432    }
17433
17434    /**
17435     * Invoked if there is a Transform that involves alpha. Subclass that can
17436     * draw themselves with the specified alpha should return true, and then
17437     * respect that alpha when their onDraw() is called. If this returns false
17438     * then the view may be redirected to draw into an offscreen buffer to
17439     * fulfill the request, which will look fine, but may be slower than if the
17440     * subclass handles it internally. The default implementation returns false.
17441     *
17442     * @param alpha The alpha (0..255) to apply to the view's drawing
17443     * @return true if the view can draw with the specified alpha.
17444     */
17445    protected boolean onSetAlpha(int alpha) {
17446        return false;
17447    }
17448
17449    /**
17450     * This is used by the RootView to perform an optimization when
17451     * the view hierarchy contains one or several SurfaceView.
17452     * SurfaceView is always considered transparent, but its children are not,
17453     * therefore all View objects remove themselves from the global transparent
17454     * region (passed as a parameter to this function).
17455     *
17456     * @param region The transparent region for this ViewAncestor (window).
17457     *
17458     * @return Returns true if the effective visibility of the view at this
17459     * point is opaque, regardless of the transparent region; returns false
17460     * if it is possible for underlying windows to be seen behind the view.
17461     *
17462     * {@hide}
17463     */
17464    public boolean gatherTransparentRegion(Region region) {
17465        final AttachInfo attachInfo = mAttachInfo;
17466        if (region != null && attachInfo != null) {
17467            final int pflags = mPrivateFlags;
17468            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
17469                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
17470                // remove it from the transparent region.
17471                final int[] location = attachInfo.mTransparentLocation;
17472                getLocationInWindow(location);
17473                region.op(location[0], location[1], location[0] + mRight - mLeft,
17474                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
17475            } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null &&
17476                    mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
17477                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
17478                // exists, so we remove the background drawable's non-transparent
17479                // parts from this transparent region.
17480                applyDrawableToTransparentRegion(mBackground, region);
17481            }
17482        }
17483        return true;
17484    }
17485
17486    /**
17487     * Play a sound effect for this view.
17488     *
17489     * <p>The framework will play sound effects for some built in actions, such as
17490     * clicking, but you may wish to play these effects in your widget,
17491     * for instance, for internal navigation.
17492     *
17493     * <p>The sound effect will only be played if sound effects are enabled by the user, and
17494     * {@link #isSoundEffectsEnabled()} is true.
17495     *
17496     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
17497     */
17498    public void playSoundEffect(int soundConstant) {
17499        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
17500            return;
17501        }
17502        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
17503    }
17504
17505    /**
17506     * BZZZTT!!1!
17507     *
17508     * <p>Provide haptic feedback to the user for this view.
17509     *
17510     * <p>The framework will provide haptic feedback for some built in actions,
17511     * such as long presses, but you may wish to provide feedback for your
17512     * own widget.
17513     *
17514     * <p>The feedback will only be performed if
17515     * {@link #isHapticFeedbackEnabled()} is true.
17516     *
17517     * @param feedbackConstant One of the constants defined in
17518     * {@link HapticFeedbackConstants}
17519     */
17520    public boolean performHapticFeedback(int feedbackConstant) {
17521        return performHapticFeedback(feedbackConstant, 0);
17522    }
17523
17524    /**
17525     * BZZZTT!!1!
17526     *
17527     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
17528     *
17529     * @param feedbackConstant One of the constants defined in
17530     * {@link HapticFeedbackConstants}
17531     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
17532     */
17533    public boolean performHapticFeedback(int feedbackConstant, int flags) {
17534        if (mAttachInfo == null) {
17535            return false;
17536        }
17537        //noinspection SimplifiableIfStatement
17538        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
17539                && !isHapticFeedbackEnabled()) {
17540            return false;
17541        }
17542        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
17543                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
17544    }
17545
17546    /**
17547     * Request that the visibility of the status bar or other screen/window
17548     * decorations be changed.
17549     *
17550     * <p>This method is used to put the over device UI into temporary modes
17551     * where the user's attention is focused more on the application content,
17552     * by dimming or hiding surrounding system affordances.  This is typically
17553     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
17554     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
17555     * to be placed behind the action bar (and with these flags other system
17556     * affordances) so that smooth transitions between hiding and showing them
17557     * can be done.
17558     *
17559     * <p>Two representative examples of the use of system UI visibility is
17560     * implementing a content browsing application (like a magazine reader)
17561     * and a video playing application.
17562     *
17563     * <p>The first code shows a typical implementation of a View in a content
17564     * browsing application.  In this implementation, the application goes
17565     * into a content-oriented mode by hiding the status bar and action bar,
17566     * and putting the navigation elements into lights out mode.  The user can
17567     * then interact with content while in this mode.  Such an application should
17568     * provide an easy way for the user to toggle out of the mode (such as to
17569     * check information in the status bar or access notifications).  In the
17570     * implementation here, this is done simply by tapping on the content.
17571     *
17572     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
17573     *      content}
17574     *
17575     * <p>This second code sample shows a typical implementation of a View
17576     * in a video playing application.  In this situation, while the video is
17577     * playing the application would like to go into a complete full-screen mode,
17578     * to use as much of the display as possible for the video.  When in this state
17579     * the user can not interact with the application; the system intercepts
17580     * touching on the screen to pop the UI out of full screen mode.  See
17581     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
17582     *
17583     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
17584     *      content}
17585     *
17586     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17587     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
17588     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
17589     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
17590     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
17591     */
17592    public void setSystemUiVisibility(int visibility) {
17593        if (visibility != mSystemUiVisibility) {
17594            mSystemUiVisibility = visibility;
17595            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
17596                mParent.recomputeViewAttributes(this);
17597            }
17598        }
17599    }
17600
17601    /**
17602     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
17603     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17604     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
17605     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
17606     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
17607     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
17608     */
17609    public int getSystemUiVisibility() {
17610        return mSystemUiVisibility;
17611    }
17612
17613    /**
17614     * Returns the current system UI visibility that is currently set for
17615     * the entire window.  This is the combination of the
17616     * {@link #setSystemUiVisibility(int)} values supplied by all of the
17617     * views in the window.
17618     */
17619    public int getWindowSystemUiVisibility() {
17620        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
17621    }
17622
17623    /**
17624     * Override to find out when the window's requested system UI visibility
17625     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
17626     * This is different from the callbacks received through
17627     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
17628     * in that this is only telling you about the local request of the window,
17629     * not the actual values applied by the system.
17630     */
17631    public void onWindowSystemUiVisibilityChanged(int visible) {
17632    }
17633
17634    /**
17635     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
17636     * the view hierarchy.
17637     */
17638    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
17639        onWindowSystemUiVisibilityChanged(visible);
17640    }
17641
17642    /**
17643     * Set a listener to receive callbacks when the visibility of the system bar changes.
17644     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
17645     */
17646    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
17647        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
17648        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
17649            mParent.recomputeViewAttributes(this);
17650        }
17651    }
17652
17653    /**
17654     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
17655     * the view hierarchy.
17656     */
17657    public void dispatchSystemUiVisibilityChanged(int visibility) {
17658        ListenerInfo li = mListenerInfo;
17659        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
17660            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
17661                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
17662        }
17663    }
17664
17665    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
17666        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
17667        if (val != mSystemUiVisibility) {
17668            setSystemUiVisibility(val);
17669            return true;
17670        }
17671        return false;
17672    }
17673
17674    /** @hide */
17675    public void setDisabledSystemUiVisibility(int flags) {
17676        if (mAttachInfo != null) {
17677            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
17678                mAttachInfo.mDisabledSystemUiVisibility = flags;
17679                if (mParent != null) {
17680                    mParent.recomputeViewAttributes(this);
17681                }
17682            }
17683        }
17684    }
17685
17686    /**
17687     * Creates an image that the system displays during the drag and drop
17688     * operation. This is called a &quot;drag shadow&quot;. The default implementation
17689     * for a DragShadowBuilder based on a View returns an image that has exactly the same
17690     * appearance as the given View. The default also positions the center of the drag shadow
17691     * directly under the touch point. If no View is provided (the constructor with no parameters
17692     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
17693     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
17694     * default is an invisible drag shadow.
17695     * <p>
17696     * You are not required to use the View you provide to the constructor as the basis of the
17697     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
17698     * anything you want as the drag shadow.
17699     * </p>
17700     * <p>
17701     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
17702     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
17703     *  size and position of the drag shadow. It uses this data to construct a
17704     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
17705     *  so that your application can draw the shadow image in the Canvas.
17706     * </p>
17707     *
17708     * <div class="special reference">
17709     * <h3>Developer Guides</h3>
17710     * <p>For a guide to implementing drag and drop features, read the
17711     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
17712     * </div>
17713     */
17714    public static class DragShadowBuilder {
17715        private final WeakReference<View> mView;
17716
17717        /**
17718         * Constructs a shadow image builder based on a View. By default, the resulting drag
17719         * shadow will have the same appearance and dimensions as the View, with the touch point
17720         * over the center of the View.
17721         * @param view A View. Any View in scope can be used.
17722         */
17723        public DragShadowBuilder(View view) {
17724            mView = new WeakReference<View>(view);
17725        }
17726
17727        /**
17728         * Construct a shadow builder object with no associated View.  This
17729         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
17730         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
17731         * to supply the drag shadow's dimensions and appearance without
17732         * reference to any View object. If they are not overridden, then the result is an
17733         * invisible drag shadow.
17734         */
17735        public DragShadowBuilder() {
17736            mView = new WeakReference<View>(null);
17737        }
17738
17739        /**
17740         * Returns the View object that had been passed to the
17741         * {@link #View.DragShadowBuilder(View)}
17742         * constructor.  If that View parameter was {@code null} or if the
17743         * {@link #View.DragShadowBuilder()}
17744         * constructor was used to instantiate the builder object, this method will return
17745         * null.
17746         *
17747         * @return The View object associate with this builder object.
17748         */
17749        @SuppressWarnings({"JavadocReference"})
17750        final public View getView() {
17751            return mView.get();
17752        }
17753
17754        /**
17755         * Provides the metrics for the shadow image. These include the dimensions of
17756         * the shadow image, and the point within that shadow that should
17757         * be centered under the touch location while dragging.
17758         * <p>
17759         * The default implementation sets the dimensions of the shadow to be the
17760         * same as the dimensions of the View itself and centers the shadow under
17761         * the touch point.
17762         * </p>
17763         *
17764         * @param shadowSize A {@link android.graphics.Point} containing the width and height
17765         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
17766         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
17767         * image.
17768         *
17769         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
17770         * shadow image that should be underneath the touch point during the drag and drop
17771         * operation. Your application must set {@link android.graphics.Point#x} to the
17772         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
17773         */
17774        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
17775            final View view = mView.get();
17776            if (view != null) {
17777                shadowSize.set(view.getWidth(), view.getHeight());
17778                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
17779            } else {
17780                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
17781            }
17782        }
17783
17784        /**
17785         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
17786         * based on the dimensions it received from the
17787         * {@link #onProvideShadowMetrics(Point, Point)} callback.
17788         *
17789         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
17790         */
17791        public void onDrawShadow(Canvas canvas) {
17792            final View view = mView.get();
17793            if (view != null) {
17794                view.draw(canvas);
17795            } else {
17796                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
17797            }
17798        }
17799    }
17800
17801    /**
17802     * Starts a drag and drop operation. When your application calls this method, it passes a
17803     * {@link android.view.View.DragShadowBuilder} object to the system. The
17804     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
17805     * to get metrics for the drag shadow, and then calls the object's
17806     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
17807     * <p>
17808     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
17809     *  drag events to all the View objects in your application that are currently visible. It does
17810     *  this either by calling the View object's drag listener (an implementation of
17811     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
17812     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
17813     *  Both are passed a {@link android.view.DragEvent} object that has a
17814     *  {@link android.view.DragEvent#getAction()} value of
17815     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
17816     * </p>
17817     * <p>
17818     * Your application can invoke startDrag() on any attached View object. The View object does not
17819     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
17820     * be related to the View the user selected for dragging.
17821     * </p>
17822     * @param data A {@link android.content.ClipData} object pointing to the data to be
17823     * transferred by the drag and drop operation.
17824     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
17825     * drag shadow.
17826     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
17827     * drop operation. This Object is put into every DragEvent object sent by the system during the
17828     * current drag.
17829     * <p>
17830     * myLocalState is a lightweight mechanism for the sending information from the dragged View
17831     * to the target Views. For example, it can contain flags that differentiate between a
17832     * a copy operation and a move operation.
17833     * </p>
17834     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
17835     * so the parameter should be set to 0.
17836     * @return {@code true} if the method completes successfully, or
17837     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
17838     * do a drag, and so no drag operation is in progress.
17839     */
17840    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
17841            Object myLocalState, int flags) {
17842        if (ViewDebug.DEBUG_DRAG) {
17843            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
17844        }
17845        boolean okay = false;
17846
17847        Point shadowSize = new Point();
17848        Point shadowTouchPoint = new Point();
17849        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
17850
17851        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
17852                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
17853            throw new IllegalStateException("Drag shadow dimensions must not be negative");
17854        }
17855
17856        if (ViewDebug.DEBUG_DRAG) {
17857            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
17858                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
17859        }
17860        Surface surface = new Surface();
17861        try {
17862            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
17863                    flags, shadowSize.x, shadowSize.y, surface);
17864            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
17865                    + " surface=" + surface);
17866            if (token != null) {
17867                Canvas canvas = surface.lockCanvas(null);
17868                try {
17869                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
17870                    shadowBuilder.onDrawShadow(canvas);
17871                } finally {
17872                    surface.unlockCanvasAndPost(canvas);
17873                }
17874
17875                final ViewRootImpl root = getViewRootImpl();
17876
17877                // Cache the local state object for delivery with DragEvents
17878                root.setLocalDragState(myLocalState);
17879
17880                // repurpose 'shadowSize' for the last touch point
17881                root.getLastTouchPoint(shadowSize);
17882
17883                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
17884                        shadowSize.x, shadowSize.y,
17885                        shadowTouchPoint.x, shadowTouchPoint.y, data);
17886                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
17887
17888                // Off and running!  Release our local surface instance; the drag
17889                // shadow surface is now managed by the system process.
17890                surface.release();
17891            }
17892        } catch (Exception e) {
17893            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
17894            surface.destroy();
17895        }
17896
17897        return okay;
17898    }
17899
17900    /**
17901     * Handles drag events sent by the system following a call to
17902     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
17903     *<p>
17904     * When the system calls this method, it passes a
17905     * {@link android.view.DragEvent} object. A call to
17906     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
17907     * in DragEvent. The method uses these to determine what is happening in the drag and drop
17908     * operation.
17909     * @param event The {@link android.view.DragEvent} sent by the system.
17910     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
17911     * in DragEvent, indicating the type of drag event represented by this object.
17912     * @return {@code true} if the method was successful, otherwise {@code false}.
17913     * <p>
17914     *  The method should return {@code true} in response to an action type of
17915     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
17916     *  operation.
17917     * </p>
17918     * <p>
17919     *  The method should also return {@code true} in response to an action type of
17920     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
17921     *  {@code false} if it didn't.
17922     * </p>
17923     */
17924    public boolean onDragEvent(DragEvent event) {
17925        return false;
17926    }
17927
17928    /**
17929     * Detects if this View is enabled and has a drag event listener.
17930     * If both are true, then it calls the drag event listener with the
17931     * {@link android.view.DragEvent} it received. If the drag event listener returns
17932     * {@code true}, then dispatchDragEvent() returns {@code true}.
17933     * <p>
17934     * For all other cases, the method calls the
17935     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
17936     * method and returns its result.
17937     * </p>
17938     * <p>
17939     * This ensures that a drag event is always consumed, even if the View does not have a drag
17940     * event listener. However, if the View has a listener and the listener returns true, then
17941     * onDragEvent() is not called.
17942     * </p>
17943     */
17944    public boolean dispatchDragEvent(DragEvent event) {
17945        ListenerInfo li = mListenerInfo;
17946        //noinspection SimplifiableIfStatement
17947        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
17948                && li.mOnDragListener.onDrag(this, event)) {
17949            return true;
17950        }
17951        return onDragEvent(event);
17952    }
17953
17954    boolean canAcceptDrag() {
17955        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
17956    }
17957
17958    /**
17959     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
17960     * it is ever exposed at all.
17961     * @hide
17962     */
17963    public void onCloseSystemDialogs(String reason) {
17964    }
17965
17966    /**
17967     * Given a Drawable whose bounds have been set to draw into this view,
17968     * update a Region being computed for
17969     * {@link #gatherTransparentRegion(android.graphics.Region)} so
17970     * that any non-transparent parts of the Drawable are removed from the
17971     * given transparent region.
17972     *
17973     * @param dr The Drawable whose transparency is to be applied to the region.
17974     * @param region A Region holding the current transparency information,
17975     * where any parts of the region that are set are considered to be
17976     * transparent.  On return, this region will be modified to have the
17977     * transparency information reduced by the corresponding parts of the
17978     * Drawable that are not transparent.
17979     * {@hide}
17980     */
17981    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
17982        if (DBG) {
17983            Log.i("View", "Getting transparent region for: " + this);
17984        }
17985        final Region r = dr.getTransparentRegion();
17986        final Rect db = dr.getBounds();
17987        final AttachInfo attachInfo = mAttachInfo;
17988        if (r != null && attachInfo != null) {
17989            final int w = getRight()-getLeft();
17990            final int h = getBottom()-getTop();
17991            if (db.left > 0) {
17992                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
17993                r.op(0, 0, db.left, h, Region.Op.UNION);
17994            }
17995            if (db.right < w) {
17996                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
17997                r.op(db.right, 0, w, h, Region.Op.UNION);
17998            }
17999            if (db.top > 0) {
18000                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
18001                r.op(0, 0, w, db.top, Region.Op.UNION);
18002            }
18003            if (db.bottom < h) {
18004                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
18005                r.op(0, db.bottom, w, h, Region.Op.UNION);
18006            }
18007            final int[] location = attachInfo.mTransparentLocation;
18008            getLocationInWindow(location);
18009            r.translate(location[0], location[1]);
18010            region.op(r, Region.Op.INTERSECT);
18011        } else {
18012            region.op(db, Region.Op.DIFFERENCE);
18013        }
18014    }
18015
18016    private void checkForLongClick(int delayOffset) {
18017        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
18018            mHasPerformedLongPress = false;
18019
18020            if (mPendingCheckForLongPress == null) {
18021                mPendingCheckForLongPress = new CheckForLongPress();
18022            }
18023            mPendingCheckForLongPress.rememberWindowAttachCount();
18024            postDelayed(mPendingCheckForLongPress,
18025                    ViewConfiguration.getLongPressTimeout() - delayOffset);
18026        }
18027    }
18028
18029    /**
18030     * Inflate a view from an XML resource.  This convenience method wraps the {@link
18031     * LayoutInflater} class, which provides a full range of options for view inflation.
18032     *
18033     * @param context The Context object for your activity or application.
18034     * @param resource The resource ID to inflate
18035     * @param root A view group that will be the parent.  Used to properly inflate the
18036     * layout_* parameters.
18037     * @see LayoutInflater
18038     */
18039    public static View inflate(Context context, int resource, ViewGroup root) {
18040        LayoutInflater factory = LayoutInflater.from(context);
18041        return factory.inflate(resource, root);
18042    }
18043
18044    /**
18045     * Scroll the view with standard behavior for scrolling beyond the normal
18046     * content boundaries. Views that call this method should override
18047     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
18048     * results of an over-scroll operation.
18049     *
18050     * Views can use this method to handle any touch or fling-based scrolling.
18051     *
18052     * @param deltaX Change in X in pixels
18053     * @param deltaY Change in Y in pixels
18054     * @param scrollX Current X scroll value in pixels before applying deltaX
18055     * @param scrollY Current Y scroll value in pixels before applying deltaY
18056     * @param scrollRangeX Maximum content scroll range along the X axis
18057     * @param scrollRangeY Maximum content scroll range along the Y axis
18058     * @param maxOverScrollX Number of pixels to overscroll by in either direction
18059     *          along the X axis.
18060     * @param maxOverScrollY Number of pixels to overscroll by in either direction
18061     *          along the Y axis.
18062     * @param isTouchEvent true if this scroll operation is the result of a touch event.
18063     * @return true if scrolling was clamped to an over-scroll boundary along either
18064     *          axis, false otherwise.
18065     */
18066    @SuppressWarnings({"UnusedParameters"})
18067    protected boolean overScrollBy(int deltaX, int deltaY,
18068            int scrollX, int scrollY,
18069            int scrollRangeX, int scrollRangeY,
18070            int maxOverScrollX, int maxOverScrollY,
18071            boolean isTouchEvent) {
18072        final int overScrollMode = mOverScrollMode;
18073        final boolean canScrollHorizontal =
18074                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
18075        final boolean canScrollVertical =
18076                computeVerticalScrollRange() > computeVerticalScrollExtent();
18077        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
18078                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
18079        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
18080                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
18081
18082        int newScrollX = scrollX + deltaX;
18083        if (!overScrollHorizontal) {
18084            maxOverScrollX = 0;
18085        }
18086
18087        int newScrollY = scrollY + deltaY;
18088        if (!overScrollVertical) {
18089            maxOverScrollY = 0;
18090        }
18091
18092        // Clamp values if at the limits and record
18093        final int left = -maxOverScrollX;
18094        final int right = maxOverScrollX + scrollRangeX;
18095        final int top = -maxOverScrollY;
18096        final int bottom = maxOverScrollY + scrollRangeY;
18097
18098        boolean clampedX = false;
18099        if (newScrollX > right) {
18100            newScrollX = right;
18101            clampedX = true;
18102        } else if (newScrollX < left) {
18103            newScrollX = left;
18104            clampedX = true;
18105        }
18106
18107        boolean clampedY = false;
18108        if (newScrollY > bottom) {
18109            newScrollY = bottom;
18110            clampedY = true;
18111        } else if (newScrollY < top) {
18112            newScrollY = top;
18113            clampedY = true;
18114        }
18115
18116        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
18117
18118        return clampedX || clampedY;
18119    }
18120
18121    /**
18122     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
18123     * respond to the results of an over-scroll operation.
18124     *
18125     * @param scrollX New X scroll value in pixels
18126     * @param scrollY New Y scroll value in pixels
18127     * @param clampedX True if scrollX was clamped to an over-scroll boundary
18128     * @param clampedY True if scrollY was clamped to an over-scroll boundary
18129     */
18130    protected void onOverScrolled(int scrollX, int scrollY,
18131            boolean clampedX, boolean clampedY) {
18132        // Intentionally empty.
18133    }
18134
18135    /**
18136     * Returns the over-scroll mode for this view. The result will be
18137     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
18138     * (allow over-scrolling only if the view content is larger than the container),
18139     * or {@link #OVER_SCROLL_NEVER}.
18140     *
18141     * @return This view's over-scroll mode.
18142     */
18143    public int getOverScrollMode() {
18144        return mOverScrollMode;
18145    }
18146
18147    /**
18148     * Set the over-scroll mode for this view. Valid over-scroll modes are
18149     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
18150     * (allow over-scrolling only if the view content is larger than the container),
18151     * or {@link #OVER_SCROLL_NEVER}.
18152     *
18153     * Setting the over-scroll mode of a view will have an effect only if the
18154     * view is capable of scrolling.
18155     *
18156     * @param overScrollMode The new over-scroll mode for this view.
18157     */
18158    public void setOverScrollMode(int overScrollMode) {
18159        if (overScrollMode != OVER_SCROLL_ALWAYS &&
18160                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
18161                overScrollMode != OVER_SCROLL_NEVER) {
18162            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
18163        }
18164        mOverScrollMode = overScrollMode;
18165    }
18166
18167    /**
18168     * Enable or disable nested scrolling for this view.
18169     *
18170     * <p>If this property is set to true the view will be permitted to initiate nested
18171     * scrolling operations with a compatible parent view in the current hierarchy. If this
18172     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
18173     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
18174     * the nested scroll.</p>
18175     *
18176     * @param enabled true to enable nested scrolling, false to disable
18177     *
18178     * @see #isNestedScrollingEnabled()
18179     */
18180    public void setNestedScrollingEnabled(boolean enabled) {
18181        if (enabled) {
18182            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
18183        } else {
18184            stopNestedScroll();
18185            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
18186        }
18187    }
18188
18189    /**
18190     * Returns true if nested scrolling is enabled for this view.
18191     *
18192     * <p>If nested scrolling is enabled and this View class implementation supports it,
18193     * this view will act as a nested scrolling child view when applicable, forwarding data
18194     * about the scroll operation in progress to a compatible and cooperating nested scrolling
18195     * parent.</p>
18196     *
18197     * @return true if nested scrolling is enabled
18198     *
18199     * @see #setNestedScrollingEnabled(boolean)
18200     */
18201    public boolean isNestedScrollingEnabled() {
18202        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
18203                PFLAG3_NESTED_SCROLLING_ENABLED;
18204    }
18205
18206    /**
18207     * Begin a nestable scroll operation along the given axes.
18208     *
18209     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
18210     *
18211     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
18212     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
18213     * In the case of touch scrolling the nested scroll will be terminated automatically in
18214     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
18215     * In the event of programmatic scrolling the caller must explicitly call
18216     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
18217     *
18218     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
18219     * If it returns false the caller may ignore the rest of this contract until the next scroll.
18220     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
18221     *
18222     * <p>At each incremental step of the scroll the caller should invoke
18223     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
18224     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
18225     * parent at least partially consumed the scroll and the caller should adjust the amount it
18226     * scrolls by.</p>
18227     *
18228     * <p>After applying the remainder of the scroll delta the caller should invoke
18229     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
18230     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
18231     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
18232     * </p>
18233     *
18234     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
18235     *             {@link #SCROLL_AXIS_VERTICAL}.
18236     * @return true if a cooperative parent was found and nested scrolling has been enabled for
18237     *         the current gesture.
18238     *
18239     * @see #stopNestedScroll()
18240     * @see #dispatchNestedPreScroll(int, int, int[], int[])
18241     * @see #dispatchNestedScroll(int, int, int, int, int[])
18242     */
18243    public boolean startNestedScroll(int axes) {
18244        if (hasNestedScrollingParent()) {
18245            // Already in progress
18246            return true;
18247        }
18248        if (isNestedScrollingEnabled()) {
18249            ViewParent p = getParent();
18250            View child = this;
18251            while (p != null) {
18252                try {
18253                    if (p.onStartNestedScroll(child, this, axes)) {
18254                        mNestedScrollingParent = p;
18255                        p.onNestedScrollAccepted(child, this, axes);
18256                        return true;
18257                    }
18258                } catch (AbstractMethodError e) {
18259                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
18260                            "method onStartNestedScroll", e);
18261                    // Allow the search upward to continue
18262                }
18263                if (p instanceof View) {
18264                    child = (View) p;
18265                }
18266                p = p.getParent();
18267            }
18268        }
18269        return false;
18270    }
18271
18272    /**
18273     * Stop a nested scroll in progress.
18274     *
18275     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
18276     *
18277     * @see #startNestedScroll(int)
18278     */
18279    public void stopNestedScroll() {
18280        if (mNestedScrollingParent != null) {
18281            mNestedScrollingParent.onStopNestedScroll(this);
18282            mNestedScrollingParent = null;
18283        }
18284    }
18285
18286    /**
18287     * Returns true if this view has a nested scrolling parent.
18288     *
18289     * <p>The presence of a nested scrolling parent indicates that this view has initiated
18290     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
18291     *
18292     * @return whether this view has a nested scrolling parent
18293     */
18294    public boolean hasNestedScrollingParent() {
18295        return mNestedScrollingParent != null;
18296    }
18297
18298    /**
18299     * Dispatch one step of a nested scroll in progress.
18300     *
18301     * <p>Implementations of views that support nested scrolling should call this to report
18302     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
18303     * is not currently in progress or nested scrolling is not
18304     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
18305     *
18306     * <p>Compatible View implementations should also call
18307     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
18308     * consuming a component of the scroll event themselves.</p>
18309     *
18310     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
18311     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
18312     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
18313     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
18314     * @param offsetInWindow Optional. If not null, on return this will contain the offset
18315     *                       in local view coordinates of this view from before this operation
18316     *                       to after it completes. View implementations may use this to adjust
18317     *                       expected input coordinate tracking.
18318     * @return true if the event was dispatched, false if it could not be dispatched.
18319     * @see #dispatchNestedPreScroll(int, int, int[], int[])
18320     */
18321    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
18322            int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
18323        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18324            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
18325                int startX = 0;
18326                int startY = 0;
18327                if (offsetInWindow != null) {
18328                    getLocationInWindow(offsetInWindow);
18329                    startX = offsetInWindow[0];
18330                    startY = offsetInWindow[1];
18331                }
18332
18333                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
18334                        dxUnconsumed, dyUnconsumed);
18335
18336                if (offsetInWindow != null) {
18337                    getLocationInWindow(offsetInWindow);
18338                    offsetInWindow[0] -= startX;
18339                    offsetInWindow[1] -= startY;
18340                }
18341                return true;
18342            } else if (offsetInWindow != null) {
18343                // No motion, no dispatch. Keep offsetInWindow up to date.
18344                offsetInWindow[0] = 0;
18345                offsetInWindow[1] = 0;
18346            }
18347        }
18348        return false;
18349    }
18350
18351    /**
18352     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
18353     *
18354     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
18355     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
18356     * scrolling operation to consume some or all of the scroll operation before the child view
18357     * consumes it.</p>
18358     *
18359     * @param dx Horizontal scroll distance in pixels
18360     * @param dy Vertical scroll distance in pixels
18361     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
18362     *                 and consumed[1] the consumed dy.
18363     * @param offsetInWindow Optional. If not null, on return this will contain the offset
18364     *                       in local view coordinates of this view from before this operation
18365     *                       to after it completes. View implementations may use this to adjust
18366     *                       expected input coordinate tracking.
18367     * @return true if the parent consumed some or all of the scroll delta
18368     * @see #dispatchNestedScroll(int, int, int, int, int[])
18369     */
18370    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
18371        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18372            if (dx != 0 || dy != 0) {
18373                int startX = 0;
18374                int startY = 0;
18375                if (offsetInWindow != null) {
18376                    getLocationInWindow(offsetInWindow);
18377                    startX = offsetInWindow[0];
18378                    startY = offsetInWindow[1];
18379                }
18380
18381                if (consumed == null) {
18382                    if (mTempNestedScrollConsumed == null) {
18383                        mTempNestedScrollConsumed = new int[2];
18384                    }
18385                    consumed = mTempNestedScrollConsumed;
18386                }
18387                consumed[0] = 0;
18388                consumed[1] = 0;
18389                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
18390
18391                if (offsetInWindow != null) {
18392                    getLocationInWindow(offsetInWindow);
18393                    offsetInWindow[0] -= startX;
18394                    offsetInWindow[1] -= startY;
18395                }
18396                return consumed[0] != 0 || consumed[1] != 0;
18397            } else if (offsetInWindow != null) {
18398                offsetInWindow[0] = 0;
18399                offsetInWindow[1] = 0;
18400            }
18401        }
18402        return false;
18403    }
18404
18405    /**
18406     * Dispatch a fling to a nested scrolling parent.
18407     *
18408     * <p>This method should be used to indicate that a nested scrolling child has detected
18409     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
18410     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
18411     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
18412     * along a scrollable axis.</p>
18413     *
18414     * <p>If a nested scrolling child view would normally fling but it is at the edge of
18415     * its own content, it can use this method to delegate the fling to its nested scrolling
18416     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
18417     *
18418     * @param velocityX Horizontal fling velocity in pixels per second
18419     * @param velocityY Vertical fling velocity in pixels per second
18420     * @param consumed true if the child consumed the fling, false otherwise
18421     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
18422     */
18423    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
18424        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18425            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
18426        }
18427        return false;
18428    }
18429
18430    /**
18431     * Gets a scale factor that determines the distance the view should scroll
18432     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
18433     * @return The vertical scroll scale factor.
18434     * @hide
18435     */
18436    protected float getVerticalScrollFactor() {
18437        if (mVerticalScrollFactor == 0) {
18438            TypedValue outValue = new TypedValue();
18439            if (!mContext.getTheme().resolveAttribute(
18440                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
18441                throw new IllegalStateException(
18442                        "Expected theme to define listPreferredItemHeight.");
18443            }
18444            mVerticalScrollFactor = outValue.getDimension(
18445                    mContext.getResources().getDisplayMetrics());
18446        }
18447        return mVerticalScrollFactor;
18448    }
18449
18450    /**
18451     * Gets a scale factor that determines the distance the view should scroll
18452     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
18453     * @return The horizontal scroll scale factor.
18454     * @hide
18455     */
18456    protected float getHorizontalScrollFactor() {
18457        // TODO: Should use something else.
18458        return getVerticalScrollFactor();
18459    }
18460
18461    /**
18462     * Return the value specifying the text direction or policy that was set with
18463     * {@link #setTextDirection(int)}.
18464     *
18465     * @return the defined text direction. It can be one of:
18466     *
18467     * {@link #TEXT_DIRECTION_INHERIT},
18468     * {@link #TEXT_DIRECTION_FIRST_STRONG}
18469     * {@link #TEXT_DIRECTION_ANY_RTL},
18470     * {@link #TEXT_DIRECTION_LTR},
18471     * {@link #TEXT_DIRECTION_RTL},
18472     * {@link #TEXT_DIRECTION_LOCALE}
18473     *
18474     * @attr ref android.R.styleable#View_textDirection
18475     *
18476     * @hide
18477     */
18478    @ViewDebug.ExportedProperty(category = "text", mapping = {
18479            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
18480            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
18481            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
18482            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
18483            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
18484            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
18485    })
18486    public int getRawTextDirection() {
18487        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
18488    }
18489
18490    /**
18491     * Set the text direction.
18492     *
18493     * @param textDirection the direction to set. Should be one of:
18494     *
18495     * {@link #TEXT_DIRECTION_INHERIT},
18496     * {@link #TEXT_DIRECTION_FIRST_STRONG}
18497     * {@link #TEXT_DIRECTION_ANY_RTL},
18498     * {@link #TEXT_DIRECTION_LTR},
18499     * {@link #TEXT_DIRECTION_RTL},
18500     * {@link #TEXT_DIRECTION_LOCALE}
18501     *
18502     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
18503     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
18504     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
18505     *
18506     * @attr ref android.R.styleable#View_textDirection
18507     */
18508    public void setTextDirection(int textDirection) {
18509        if (getRawTextDirection() != textDirection) {
18510            // Reset the current text direction and the resolved one
18511            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
18512            resetResolvedTextDirection();
18513            // Set the new text direction
18514            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
18515            // Do resolution
18516            resolveTextDirection();
18517            // Notify change
18518            onRtlPropertiesChanged(getLayoutDirection());
18519            // Refresh
18520            requestLayout();
18521            invalidate(true);
18522        }
18523    }
18524
18525    /**
18526     * Return the resolved text direction.
18527     *
18528     * @return the resolved text direction. Returns one of:
18529     *
18530     * {@link #TEXT_DIRECTION_FIRST_STRONG}
18531     * {@link #TEXT_DIRECTION_ANY_RTL},
18532     * {@link #TEXT_DIRECTION_LTR},
18533     * {@link #TEXT_DIRECTION_RTL},
18534     * {@link #TEXT_DIRECTION_LOCALE}
18535     *
18536     * @attr ref android.R.styleable#View_textDirection
18537     */
18538    @ViewDebug.ExportedProperty(category = "text", mapping = {
18539            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
18540            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
18541            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
18542            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
18543            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
18544            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
18545    })
18546    public int getTextDirection() {
18547        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
18548    }
18549
18550    /**
18551     * Resolve the text direction.
18552     *
18553     * @return true if resolution has been done, false otherwise.
18554     *
18555     * @hide
18556     */
18557    public boolean resolveTextDirection() {
18558        // Reset any previous text direction resolution
18559        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
18560
18561        if (hasRtlSupport()) {
18562            // Set resolved text direction flag depending on text direction flag
18563            final int textDirection = getRawTextDirection();
18564            switch(textDirection) {
18565                case TEXT_DIRECTION_INHERIT:
18566                    if (!canResolveTextDirection()) {
18567                        // We cannot do the resolution if there is no parent, so use the default one
18568                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18569                        // Resolution will need to happen again later
18570                        return false;
18571                    }
18572
18573                    // Parent has not yet resolved, so we still return the default
18574                    try {
18575                        if (!mParent.isTextDirectionResolved()) {
18576                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18577                            // Resolution will need to happen again later
18578                            return false;
18579                        }
18580                    } catch (AbstractMethodError e) {
18581                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18582                                " does not fully implement ViewParent", e);
18583                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
18584                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18585                        return true;
18586                    }
18587
18588                    // Set current resolved direction to the same value as the parent's one
18589                    int parentResolvedDirection;
18590                    try {
18591                        parentResolvedDirection = mParent.getTextDirection();
18592                    } catch (AbstractMethodError e) {
18593                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18594                                " does not fully implement ViewParent", e);
18595                        parentResolvedDirection = TEXT_DIRECTION_LTR;
18596                    }
18597                    switch (parentResolvedDirection) {
18598                        case TEXT_DIRECTION_FIRST_STRONG:
18599                        case TEXT_DIRECTION_ANY_RTL:
18600                        case TEXT_DIRECTION_LTR:
18601                        case TEXT_DIRECTION_RTL:
18602                        case TEXT_DIRECTION_LOCALE:
18603                            mPrivateFlags2 |=
18604                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
18605                            break;
18606                        default:
18607                            // Default resolved direction is "first strong" heuristic
18608                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18609                    }
18610                    break;
18611                case TEXT_DIRECTION_FIRST_STRONG:
18612                case TEXT_DIRECTION_ANY_RTL:
18613                case TEXT_DIRECTION_LTR:
18614                case TEXT_DIRECTION_RTL:
18615                case TEXT_DIRECTION_LOCALE:
18616                    // Resolved direction is the same as text direction
18617                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
18618                    break;
18619                default:
18620                    // Default resolved direction is "first strong" heuristic
18621                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18622            }
18623        } else {
18624            // Default resolved direction is "first strong" heuristic
18625            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18626        }
18627
18628        // Set to resolved
18629        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
18630        return true;
18631    }
18632
18633    /**
18634     * Check if text direction resolution can be done.
18635     *
18636     * @return true if text direction resolution can be done otherwise return false.
18637     */
18638    public boolean canResolveTextDirection() {
18639        switch (getRawTextDirection()) {
18640            case TEXT_DIRECTION_INHERIT:
18641                if (mParent != null) {
18642                    try {
18643                        return mParent.canResolveTextDirection();
18644                    } catch (AbstractMethodError e) {
18645                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18646                                " does not fully implement ViewParent", e);
18647                    }
18648                }
18649                return false;
18650
18651            default:
18652                return true;
18653        }
18654    }
18655
18656    /**
18657     * Reset resolved text direction. Text direction will be resolved during a call to
18658     * {@link #onMeasure(int, int)}.
18659     *
18660     * @hide
18661     */
18662    public void resetResolvedTextDirection() {
18663        // Reset any previous text direction resolution
18664        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
18665        // Set to default value
18666        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
18667    }
18668
18669    /**
18670     * @return true if text direction is inherited.
18671     *
18672     * @hide
18673     */
18674    public boolean isTextDirectionInherited() {
18675        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
18676    }
18677
18678    /**
18679     * @return true if text direction is resolved.
18680     */
18681    public boolean isTextDirectionResolved() {
18682        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
18683    }
18684
18685    /**
18686     * Return the value specifying the text alignment or policy that was set with
18687     * {@link #setTextAlignment(int)}.
18688     *
18689     * @return the defined text alignment. It can be one of:
18690     *
18691     * {@link #TEXT_ALIGNMENT_INHERIT},
18692     * {@link #TEXT_ALIGNMENT_GRAVITY},
18693     * {@link #TEXT_ALIGNMENT_CENTER},
18694     * {@link #TEXT_ALIGNMENT_TEXT_START},
18695     * {@link #TEXT_ALIGNMENT_TEXT_END},
18696     * {@link #TEXT_ALIGNMENT_VIEW_START},
18697     * {@link #TEXT_ALIGNMENT_VIEW_END}
18698     *
18699     * @attr ref android.R.styleable#View_textAlignment
18700     *
18701     * @hide
18702     */
18703    @ViewDebug.ExportedProperty(category = "text", mapping = {
18704            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
18705            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
18706            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
18707            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
18708            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
18709            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
18710            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
18711    })
18712    @TextAlignment
18713    public int getRawTextAlignment() {
18714        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
18715    }
18716
18717    /**
18718     * Set the text alignment.
18719     *
18720     * @param textAlignment The text alignment to set. Should be one of
18721     *
18722     * {@link #TEXT_ALIGNMENT_INHERIT},
18723     * {@link #TEXT_ALIGNMENT_GRAVITY},
18724     * {@link #TEXT_ALIGNMENT_CENTER},
18725     * {@link #TEXT_ALIGNMENT_TEXT_START},
18726     * {@link #TEXT_ALIGNMENT_TEXT_END},
18727     * {@link #TEXT_ALIGNMENT_VIEW_START},
18728     * {@link #TEXT_ALIGNMENT_VIEW_END}
18729     *
18730     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
18731     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
18732     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
18733     *
18734     * @attr ref android.R.styleable#View_textAlignment
18735     */
18736    public void setTextAlignment(@TextAlignment int textAlignment) {
18737        if (textAlignment != getRawTextAlignment()) {
18738            // Reset the current and resolved text alignment
18739            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
18740            resetResolvedTextAlignment();
18741            // Set the new text alignment
18742            mPrivateFlags2 |=
18743                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
18744            // Do resolution
18745            resolveTextAlignment();
18746            // Notify change
18747            onRtlPropertiesChanged(getLayoutDirection());
18748            // Refresh
18749            requestLayout();
18750            invalidate(true);
18751        }
18752    }
18753
18754    /**
18755     * Return the resolved text alignment.
18756     *
18757     * @return the resolved text alignment. Returns one of:
18758     *
18759     * {@link #TEXT_ALIGNMENT_GRAVITY},
18760     * {@link #TEXT_ALIGNMENT_CENTER},
18761     * {@link #TEXT_ALIGNMENT_TEXT_START},
18762     * {@link #TEXT_ALIGNMENT_TEXT_END},
18763     * {@link #TEXT_ALIGNMENT_VIEW_START},
18764     * {@link #TEXT_ALIGNMENT_VIEW_END}
18765     *
18766     * @attr ref android.R.styleable#View_textAlignment
18767     */
18768    @ViewDebug.ExportedProperty(category = "text", mapping = {
18769            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
18770            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
18771            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
18772            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
18773            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
18774            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
18775            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
18776    })
18777    @TextAlignment
18778    public int getTextAlignment() {
18779        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
18780                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
18781    }
18782
18783    /**
18784     * Resolve the text alignment.
18785     *
18786     * @return true if resolution has been done, false otherwise.
18787     *
18788     * @hide
18789     */
18790    public boolean resolveTextAlignment() {
18791        // Reset any previous text alignment resolution
18792        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
18793
18794        if (hasRtlSupport()) {
18795            // Set resolved text alignment flag depending on text alignment flag
18796            final int textAlignment = getRawTextAlignment();
18797            switch (textAlignment) {
18798                case TEXT_ALIGNMENT_INHERIT:
18799                    // Check if we can resolve the text alignment
18800                    if (!canResolveTextAlignment()) {
18801                        // We cannot do the resolution if there is no parent so use the default
18802                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18803                        // Resolution will need to happen again later
18804                        return false;
18805                    }
18806
18807                    // Parent has not yet resolved, so we still return the default
18808                    try {
18809                        if (!mParent.isTextAlignmentResolved()) {
18810                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18811                            // Resolution will need to happen again later
18812                            return false;
18813                        }
18814                    } catch (AbstractMethodError e) {
18815                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18816                                " does not fully implement ViewParent", e);
18817                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
18818                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18819                        return true;
18820                    }
18821
18822                    int parentResolvedTextAlignment;
18823                    try {
18824                        parentResolvedTextAlignment = mParent.getTextAlignment();
18825                    } catch (AbstractMethodError e) {
18826                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18827                                " does not fully implement ViewParent", e);
18828                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
18829                    }
18830                    switch (parentResolvedTextAlignment) {
18831                        case TEXT_ALIGNMENT_GRAVITY:
18832                        case TEXT_ALIGNMENT_TEXT_START:
18833                        case TEXT_ALIGNMENT_TEXT_END:
18834                        case TEXT_ALIGNMENT_CENTER:
18835                        case TEXT_ALIGNMENT_VIEW_START:
18836                        case TEXT_ALIGNMENT_VIEW_END:
18837                            // Resolved text alignment is the same as the parent resolved
18838                            // text alignment
18839                            mPrivateFlags2 |=
18840                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
18841                            break;
18842                        default:
18843                            // Use default resolved text alignment
18844                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18845                    }
18846                    break;
18847                case TEXT_ALIGNMENT_GRAVITY:
18848                case TEXT_ALIGNMENT_TEXT_START:
18849                case TEXT_ALIGNMENT_TEXT_END:
18850                case TEXT_ALIGNMENT_CENTER:
18851                case TEXT_ALIGNMENT_VIEW_START:
18852                case TEXT_ALIGNMENT_VIEW_END:
18853                    // Resolved text alignment is the same as text alignment
18854                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
18855                    break;
18856                default:
18857                    // Use default resolved text alignment
18858                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18859            }
18860        } else {
18861            // Use default resolved text alignment
18862            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18863        }
18864
18865        // Set the resolved
18866        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
18867        return true;
18868    }
18869
18870    /**
18871     * Check if text alignment resolution can be done.
18872     *
18873     * @return true if text alignment resolution can be done otherwise return false.
18874     */
18875    public boolean canResolveTextAlignment() {
18876        switch (getRawTextAlignment()) {
18877            case TEXT_DIRECTION_INHERIT:
18878                if (mParent != null) {
18879                    try {
18880                        return mParent.canResolveTextAlignment();
18881                    } catch (AbstractMethodError e) {
18882                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
18883                                " does not fully implement ViewParent", e);
18884                    }
18885                }
18886                return false;
18887
18888            default:
18889                return true;
18890        }
18891    }
18892
18893    /**
18894     * Reset resolved text alignment. Text alignment will be resolved during a call to
18895     * {@link #onMeasure(int, int)}.
18896     *
18897     * @hide
18898     */
18899    public void resetResolvedTextAlignment() {
18900        // Reset any previous text alignment resolution
18901        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
18902        // Set to default
18903        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
18904    }
18905
18906    /**
18907     * @return true if text alignment is inherited.
18908     *
18909     * @hide
18910     */
18911    public boolean isTextAlignmentInherited() {
18912        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
18913    }
18914
18915    /**
18916     * @return true if text alignment is resolved.
18917     */
18918    public boolean isTextAlignmentResolved() {
18919        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
18920    }
18921
18922    /**
18923     * Generate a value suitable for use in {@link #setId(int)}.
18924     * This value will not collide with ID values generated at build time by aapt for R.id.
18925     *
18926     * @return a generated ID value
18927     */
18928    public static int generateViewId() {
18929        for (;;) {
18930            final int result = sNextGeneratedId.get();
18931            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
18932            int newValue = result + 1;
18933            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
18934            if (sNextGeneratedId.compareAndSet(result, newValue)) {
18935                return result;
18936            }
18937        }
18938    }
18939
18940    /**
18941     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
18942     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
18943     *                           a normal View or a ViewGroup with
18944     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
18945     * @hide
18946     */
18947    public void captureTransitioningViews(List<View> transitioningViews) {
18948        if (getVisibility() == View.VISIBLE) {
18949            transitioningViews.add(this);
18950        }
18951    }
18952
18953    /**
18954     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
18955     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
18956     * @hide
18957     */
18958    public void findNamedViews(Map<String, View> namedElements) {
18959        if (getVisibility() == VISIBLE) {
18960            String transitionName = getTransitionName();
18961            if (transitionName != null) {
18962                namedElements.put(transitionName, this);
18963            }
18964        }
18965    }
18966
18967    //
18968    // Properties
18969    //
18970    /**
18971     * A Property wrapper around the <code>alpha</code> functionality handled by the
18972     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
18973     */
18974    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
18975        @Override
18976        public void setValue(View object, float value) {
18977            object.setAlpha(value);
18978        }
18979
18980        @Override
18981        public Float get(View object) {
18982            return object.getAlpha();
18983        }
18984    };
18985
18986    /**
18987     * A Property wrapper around the <code>translationX</code> functionality handled by the
18988     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
18989     */
18990    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
18991        @Override
18992        public void setValue(View object, float value) {
18993            object.setTranslationX(value);
18994        }
18995
18996                @Override
18997        public Float get(View object) {
18998            return object.getTranslationX();
18999        }
19000    };
19001
19002    /**
19003     * A Property wrapper around the <code>translationY</code> functionality handled by the
19004     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
19005     */
19006    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
19007        @Override
19008        public void setValue(View object, float value) {
19009            object.setTranslationY(value);
19010        }
19011
19012        @Override
19013        public Float get(View object) {
19014            return object.getTranslationY();
19015        }
19016    };
19017
19018    /**
19019     * A Property wrapper around the <code>translationZ</code> functionality handled by the
19020     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
19021     */
19022    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
19023        @Override
19024        public void setValue(View object, float value) {
19025            object.setTranslationZ(value);
19026        }
19027
19028        @Override
19029        public Float get(View object) {
19030            return object.getTranslationZ();
19031        }
19032    };
19033
19034    /**
19035     * A Property wrapper around the <code>x</code> functionality handled by the
19036     * {@link View#setX(float)} and {@link View#getX()} methods.
19037     */
19038    public static final Property<View, Float> X = new FloatProperty<View>("x") {
19039        @Override
19040        public void setValue(View object, float value) {
19041            object.setX(value);
19042        }
19043
19044        @Override
19045        public Float get(View object) {
19046            return object.getX();
19047        }
19048    };
19049
19050    /**
19051     * A Property wrapper around the <code>y</code> functionality handled by the
19052     * {@link View#setY(float)} and {@link View#getY()} methods.
19053     */
19054    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
19055        @Override
19056        public void setValue(View object, float value) {
19057            object.setY(value);
19058        }
19059
19060        @Override
19061        public Float get(View object) {
19062            return object.getY();
19063        }
19064    };
19065
19066    /**
19067     * A Property wrapper around the <code>z</code> functionality handled by the
19068     * {@link View#setZ(float)} and {@link View#getZ()} methods.
19069     */
19070    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
19071        @Override
19072        public void setValue(View object, float value) {
19073            object.setZ(value);
19074        }
19075
19076        @Override
19077        public Float get(View object) {
19078            return object.getZ();
19079        }
19080    };
19081
19082    /**
19083     * A Property wrapper around the <code>rotation</code> functionality handled by the
19084     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
19085     */
19086    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
19087        @Override
19088        public void setValue(View object, float value) {
19089            object.setRotation(value);
19090        }
19091
19092        @Override
19093        public Float get(View object) {
19094            return object.getRotation();
19095        }
19096    };
19097
19098    /**
19099     * A Property wrapper around the <code>rotationX</code> functionality handled by the
19100     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
19101     */
19102    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
19103        @Override
19104        public void setValue(View object, float value) {
19105            object.setRotationX(value);
19106        }
19107
19108        @Override
19109        public Float get(View object) {
19110            return object.getRotationX();
19111        }
19112    };
19113
19114    /**
19115     * A Property wrapper around the <code>rotationY</code> functionality handled by the
19116     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
19117     */
19118    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
19119        @Override
19120        public void setValue(View object, float value) {
19121            object.setRotationY(value);
19122        }
19123
19124        @Override
19125        public Float get(View object) {
19126            return object.getRotationY();
19127        }
19128    };
19129
19130    /**
19131     * A Property wrapper around the <code>scaleX</code> functionality handled by the
19132     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
19133     */
19134    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
19135        @Override
19136        public void setValue(View object, float value) {
19137            object.setScaleX(value);
19138        }
19139
19140        @Override
19141        public Float get(View object) {
19142            return object.getScaleX();
19143        }
19144    };
19145
19146    /**
19147     * A Property wrapper around the <code>scaleY</code> functionality handled by the
19148     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
19149     */
19150    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
19151        @Override
19152        public void setValue(View object, float value) {
19153            object.setScaleY(value);
19154        }
19155
19156        @Override
19157        public Float get(View object) {
19158            return object.getScaleY();
19159        }
19160    };
19161
19162    /**
19163     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
19164     * Each MeasureSpec represents a requirement for either the width or the height.
19165     * A MeasureSpec is comprised of a size and a mode. There are three possible
19166     * modes:
19167     * <dl>
19168     * <dt>UNSPECIFIED</dt>
19169     * <dd>
19170     * The parent has not imposed any constraint on the child. It can be whatever size
19171     * it wants.
19172     * </dd>
19173     *
19174     * <dt>EXACTLY</dt>
19175     * <dd>
19176     * The parent has determined an exact size for the child. The child is going to be
19177     * given those bounds regardless of how big it wants to be.
19178     * </dd>
19179     *
19180     * <dt>AT_MOST</dt>
19181     * <dd>
19182     * The child can be as large as it wants up to the specified size.
19183     * </dd>
19184     * </dl>
19185     *
19186     * MeasureSpecs are implemented as ints to reduce object allocation. This class
19187     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
19188     */
19189    public static class MeasureSpec {
19190        private static final int MODE_SHIFT = 30;
19191        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
19192
19193        /**
19194         * Measure specification mode: The parent has not imposed any constraint
19195         * on the child. It can be whatever size it wants.
19196         */
19197        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
19198
19199        /**
19200         * Measure specification mode: The parent has determined an exact size
19201         * for the child. The child is going to be given those bounds regardless
19202         * of how big it wants to be.
19203         */
19204        public static final int EXACTLY     = 1 << MODE_SHIFT;
19205
19206        /**
19207         * Measure specification mode: The child can be as large as it wants up
19208         * to the specified size.
19209         */
19210        public static final int AT_MOST     = 2 << MODE_SHIFT;
19211
19212        /**
19213         * Creates a measure specification based on the supplied size and mode.
19214         *
19215         * The mode must always be one of the following:
19216         * <ul>
19217         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
19218         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
19219         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
19220         * </ul>
19221         *
19222         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
19223         * implementation was such that the order of arguments did not matter
19224         * and overflow in either value could impact the resulting MeasureSpec.
19225         * {@link android.widget.RelativeLayout} was affected by this bug.
19226         * Apps targeting API levels greater than 17 will get the fixed, more strict
19227         * behavior.</p>
19228         *
19229         * @param size the size of the measure specification
19230         * @param mode the mode of the measure specification
19231         * @return the measure specification based on size and mode
19232         */
19233        public static int makeMeasureSpec(int size, int mode) {
19234            if (sUseBrokenMakeMeasureSpec) {
19235                return size + mode;
19236            } else {
19237                return (size & ~MODE_MASK) | (mode & MODE_MASK);
19238            }
19239        }
19240
19241        /**
19242         * Extracts the mode from the supplied measure specification.
19243         *
19244         * @param measureSpec the measure specification to extract the mode from
19245         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
19246         *         {@link android.view.View.MeasureSpec#AT_MOST} or
19247         *         {@link android.view.View.MeasureSpec#EXACTLY}
19248         */
19249        public static int getMode(int measureSpec) {
19250            return (measureSpec & MODE_MASK);
19251        }
19252
19253        /**
19254         * Extracts the size from the supplied measure specification.
19255         *
19256         * @param measureSpec the measure specification to extract the size from
19257         * @return the size in pixels defined in the supplied measure specification
19258         */
19259        public static int getSize(int measureSpec) {
19260            return (measureSpec & ~MODE_MASK);
19261        }
19262
19263        static int adjust(int measureSpec, int delta) {
19264            final int mode = getMode(measureSpec);
19265            if (mode == UNSPECIFIED) {
19266                // No need to adjust size for UNSPECIFIED mode.
19267                return makeMeasureSpec(0, UNSPECIFIED);
19268            }
19269            int size = getSize(measureSpec) + delta;
19270            if (size < 0) {
19271                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
19272                        ") spec: " + toString(measureSpec) + " delta: " + delta);
19273                size = 0;
19274            }
19275            return makeMeasureSpec(size, mode);
19276        }
19277
19278        /**
19279         * Returns a String representation of the specified measure
19280         * specification.
19281         *
19282         * @param measureSpec the measure specification to convert to a String
19283         * @return a String with the following format: "MeasureSpec: MODE SIZE"
19284         */
19285        public static String toString(int measureSpec) {
19286            int mode = getMode(measureSpec);
19287            int size = getSize(measureSpec);
19288
19289            StringBuilder sb = new StringBuilder("MeasureSpec: ");
19290
19291            if (mode == UNSPECIFIED)
19292                sb.append("UNSPECIFIED ");
19293            else if (mode == EXACTLY)
19294                sb.append("EXACTLY ");
19295            else if (mode == AT_MOST)
19296                sb.append("AT_MOST ");
19297            else
19298                sb.append(mode).append(" ");
19299
19300            sb.append(size);
19301            return sb.toString();
19302        }
19303    }
19304
19305    private final class CheckForLongPress implements Runnable {
19306        private int mOriginalWindowAttachCount;
19307
19308        @Override
19309        public void run() {
19310            if (isPressed() && (mParent != null)
19311                    && mOriginalWindowAttachCount == mWindowAttachCount) {
19312                if (performLongClick()) {
19313                    mHasPerformedLongPress = true;
19314                }
19315            }
19316        }
19317
19318        public void rememberWindowAttachCount() {
19319            mOriginalWindowAttachCount = mWindowAttachCount;
19320        }
19321    }
19322
19323    private final class CheckForTap implements Runnable {
19324        public float x;
19325        public float y;
19326
19327        @Override
19328        public void run() {
19329            mPrivateFlags &= ~PFLAG_PREPRESSED;
19330            setPressed(true, x, y);
19331            checkForLongClick(ViewConfiguration.getTapTimeout());
19332        }
19333    }
19334
19335    private final class PerformClick implements Runnable {
19336        @Override
19337        public void run() {
19338            performClick();
19339        }
19340    }
19341
19342    /** @hide */
19343    public void hackTurnOffWindowResizeAnim(boolean off) {
19344        mAttachInfo.mTurnOffWindowResizeAnim = off;
19345    }
19346
19347    /**
19348     * This method returns a ViewPropertyAnimator object, which can be used to animate
19349     * specific properties on this View.
19350     *
19351     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
19352     */
19353    public ViewPropertyAnimator animate() {
19354        if (mAnimator == null) {
19355            mAnimator = new ViewPropertyAnimator(this);
19356        }
19357        return mAnimator;
19358    }
19359
19360    /**
19361     * Sets the name of the View to be used to identify Views in Transitions.
19362     * Names should be unique in the View hierarchy.
19363     *
19364     * @param transitionName The name of the View to uniquely identify it for Transitions.
19365     */
19366    public final void setTransitionName(String transitionName) {
19367        mTransitionName = transitionName;
19368    }
19369
19370    /**
19371     * Returns the name of the View to be used to identify Views in Transitions.
19372     * Names should be unique in the View hierarchy.
19373     *
19374     * <p>This returns null if the View has not been given a name.</p>
19375     *
19376     * @return The name used of the View to be used to identify Views in Transitions or null
19377     * if no name has been given.
19378     */
19379    public String getTransitionName() {
19380        return mTransitionName;
19381    }
19382
19383    /**
19384     * Interface definition for a callback to be invoked when a hardware key event is
19385     * dispatched to this view. The callback will be invoked before the key event is
19386     * given to the view. This is only useful for hardware keyboards; a software input
19387     * method has no obligation to trigger this listener.
19388     */
19389    public interface OnKeyListener {
19390        /**
19391         * Called when a hardware key is dispatched to a view. This allows listeners to
19392         * get a chance to respond before the target view.
19393         * <p>Key presses in software keyboards will generally NOT trigger this method,
19394         * although some may elect to do so in some situations. Do not assume a
19395         * software input method has to be key-based; even if it is, it may use key presses
19396         * in a different way than you expect, so there is no way to reliably catch soft
19397         * input key presses.
19398         *
19399         * @param v The view the key has been dispatched to.
19400         * @param keyCode The code for the physical key that was pressed
19401         * @param event The KeyEvent object containing full information about
19402         *        the event.
19403         * @return True if the listener has consumed the event, false otherwise.
19404         */
19405        boolean onKey(View v, int keyCode, KeyEvent event);
19406    }
19407
19408    /**
19409     * Interface definition for a callback to be invoked when a touch event is
19410     * dispatched to this view. The callback will be invoked before the touch
19411     * event is given to the view.
19412     */
19413    public interface OnTouchListener {
19414        /**
19415         * Called when a touch event is dispatched to a view. This allows listeners to
19416         * get a chance to respond before the target view.
19417         *
19418         * @param v The view the touch event has been dispatched to.
19419         * @param event The MotionEvent object containing full information about
19420         *        the event.
19421         * @return True if the listener has consumed the event, false otherwise.
19422         */
19423        boolean onTouch(View v, MotionEvent event);
19424    }
19425
19426    /**
19427     * Interface definition for a callback to be invoked when a hover event is
19428     * dispatched to this view. The callback will be invoked before the hover
19429     * event is given to the view.
19430     */
19431    public interface OnHoverListener {
19432        /**
19433         * Called when a hover event is dispatched to a view. This allows listeners to
19434         * get a chance to respond before the target view.
19435         *
19436         * @param v The view the hover event has been dispatched to.
19437         * @param event The MotionEvent object containing full information about
19438         *        the event.
19439         * @return True if the listener has consumed the event, false otherwise.
19440         */
19441        boolean onHover(View v, MotionEvent event);
19442    }
19443
19444    /**
19445     * Interface definition for a callback to be invoked when a generic motion event is
19446     * dispatched to this view. The callback will be invoked before the generic motion
19447     * event is given to the view.
19448     */
19449    public interface OnGenericMotionListener {
19450        /**
19451         * Called when a generic motion event is dispatched to a view. This allows listeners to
19452         * get a chance to respond before the target view.
19453         *
19454         * @param v The view the generic motion event has been dispatched to.
19455         * @param event The MotionEvent object containing full information about
19456         *        the event.
19457         * @return True if the listener has consumed the event, false otherwise.
19458         */
19459        boolean onGenericMotion(View v, MotionEvent event);
19460    }
19461
19462    /**
19463     * Interface definition for a callback to be invoked when a view has been clicked and held.
19464     */
19465    public interface OnLongClickListener {
19466        /**
19467         * Called when a view has been clicked and held.
19468         *
19469         * @param v The view that was clicked and held.
19470         *
19471         * @return true if the callback consumed the long click, false otherwise.
19472         */
19473        boolean onLongClick(View v);
19474    }
19475
19476    /**
19477     * Interface definition for a callback to be invoked when a drag is being dispatched
19478     * to this view.  The callback will be invoked before the hosting view's own
19479     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
19480     * onDrag(event) behavior, it should return 'false' from this callback.
19481     *
19482     * <div class="special reference">
19483     * <h3>Developer Guides</h3>
19484     * <p>For a guide to implementing drag and drop features, read the
19485     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19486     * </div>
19487     */
19488    public interface OnDragListener {
19489        /**
19490         * Called when a drag event is dispatched to a view. This allows listeners
19491         * to get a chance to override base View behavior.
19492         *
19493         * @param v The View that received the drag event.
19494         * @param event The {@link android.view.DragEvent} object for the drag event.
19495         * @return {@code true} if the drag event was handled successfully, or {@code false}
19496         * if the drag event was not handled. Note that {@code false} will trigger the View
19497         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
19498         */
19499        boolean onDrag(View v, DragEvent event);
19500    }
19501
19502    /**
19503     * Interface definition for a callback to be invoked when the focus state of
19504     * a view changed.
19505     */
19506    public interface OnFocusChangeListener {
19507        /**
19508         * Called when the focus state of a view has changed.
19509         *
19510         * @param v The view whose state has changed.
19511         * @param hasFocus The new focus state of v.
19512         */
19513        void onFocusChange(View v, boolean hasFocus);
19514    }
19515
19516    /**
19517     * Interface definition for a callback to be invoked when a view is clicked.
19518     */
19519    public interface OnClickListener {
19520        /**
19521         * Called when a view has been clicked.
19522         *
19523         * @param v The view that was clicked.
19524         */
19525        void onClick(View v);
19526    }
19527
19528    /**
19529     * Interface definition for a callback to be invoked when the context menu
19530     * for this view is being built.
19531     */
19532    public interface OnCreateContextMenuListener {
19533        /**
19534         * Called when the context menu for this view is being built. It is not
19535         * safe to hold onto the menu after this method returns.
19536         *
19537         * @param menu The context menu that is being built
19538         * @param v The view for which the context menu is being built
19539         * @param menuInfo Extra information about the item for which the
19540         *            context menu should be shown. This information will vary
19541         *            depending on the class of v.
19542         */
19543        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
19544    }
19545
19546    /**
19547     * Interface definition for a callback to be invoked when the status bar changes
19548     * visibility.  This reports <strong>global</strong> changes to the system UI
19549     * state, not what the application is requesting.
19550     *
19551     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
19552     */
19553    public interface OnSystemUiVisibilityChangeListener {
19554        /**
19555         * Called when the status bar changes visibility because of a call to
19556         * {@link View#setSystemUiVisibility(int)}.
19557         *
19558         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19559         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
19560         * This tells you the <strong>global</strong> state of these UI visibility
19561         * flags, not what your app is currently applying.
19562         */
19563        public void onSystemUiVisibilityChange(int visibility);
19564    }
19565
19566    /**
19567     * Interface definition for a callback to be invoked when this view is attached
19568     * or detached from its window.
19569     */
19570    public interface OnAttachStateChangeListener {
19571        /**
19572         * Called when the view is attached to a window.
19573         * @param v The view that was attached
19574         */
19575        public void onViewAttachedToWindow(View v);
19576        /**
19577         * Called when the view is detached from a window.
19578         * @param v The view that was detached
19579         */
19580        public void onViewDetachedFromWindow(View v);
19581    }
19582
19583    /**
19584     * Listener for applying window insets on a view in a custom way.
19585     *
19586     * <p>Apps may choose to implement this interface if they want to apply custom policy
19587     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
19588     * is set, its
19589     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
19590     * method will be called instead of the View's own
19591     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
19592     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
19593     * the View's normal behavior as part of its own.</p>
19594     */
19595    public interface OnApplyWindowInsetsListener {
19596        /**
19597         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
19598         * on a View, this listener method will be called instead of the view's own
19599         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
19600         *
19601         * @param v The view applying window insets
19602         * @param insets The insets to apply
19603         * @return The insets supplied, minus any insets that were consumed
19604         */
19605        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
19606    }
19607
19608    private final class UnsetPressedState implements Runnable {
19609        @Override
19610        public void run() {
19611            setPressed(false);
19612        }
19613    }
19614
19615    /**
19616     * Base class for derived classes that want to save and restore their own
19617     * state in {@link android.view.View#onSaveInstanceState()}.
19618     */
19619    public static class BaseSavedState extends AbsSavedState {
19620        /**
19621         * Constructor used when reading from a parcel. Reads the state of the superclass.
19622         *
19623         * @param source
19624         */
19625        public BaseSavedState(Parcel source) {
19626            super(source);
19627        }
19628
19629        /**
19630         * Constructor called by derived classes when creating their SavedState objects
19631         *
19632         * @param superState The state of the superclass of this view
19633         */
19634        public BaseSavedState(Parcelable superState) {
19635            super(superState);
19636        }
19637
19638        public static final Parcelable.Creator<BaseSavedState> CREATOR =
19639                new Parcelable.Creator<BaseSavedState>() {
19640            public BaseSavedState createFromParcel(Parcel in) {
19641                return new BaseSavedState(in);
19642            }
19643
19644            public BaseSavedState[] newArray(int size) {
19645                return new BaseSavedState[size];
19646            }
19647        };
19648    }
19649
19650    /**
19651     * A set of information given to a view when it is attached to its parent
19652     * window.
19653     */
19654    final static class AttachInfo {
19655        interface Callbacks {
19656            void playSoundEffect(int effectId);
19657            boolean performHapticFeedback(int effectId, boolean always);
19658        }
19659
19660        /**
19661         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
19662         * to a Handler. This class contains the target (View) to invalidate and
19663         * the coordinates of the dirty rectangle.
19664         *
19665         * For performance purposes, this class also implements a pool of up to
19666         * POOL_LIMIT objects that get reused. This reduces memory allocations
19667         * whenever possible.
19668         */
19669        static class InvalidateInfo {
19670            private static final int POOL_LIMIT = 10;
19671
19672            private static final SynchronizedPool<InvalidateInfo> sPool =
19673                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
19674
19675            View target;
19676
19677            int left;
19678            int top;
19679            int right;
19680            int bottom;
19681
19682            public static InvalidateInfo obtain() {
19683                InvalidateInfo instance = sPool.acquire();
19684                return (instance != null) ? instance : new InvalidateInfo();
19685            }
19686
19687            public void recycle() {
19688                target = null;
19689                sPool.release(this);
19690            }
19691        }
19692
19693        final IWindowSession mSession;
19694
19695        final IWindow mWindow;
19696
19697        final IBinder mWindowToken;
19698
19699        final Display mDisplay;
19700
19701        final Callbacks mRootCallbacks;
19702
19703        IWindowId mIWindowId;
19704        WindowId mWindowId;
19705
19706        /**
19707         * The top view of the hierarchy.
19708         */
19709        View mRootView;
19710
19711        IBinder mPanelParentWindowToken;
19712
19713        boolean mHardwareAccelerated;
19714        boolean mHardwareAccelerationRequested;
19715        HardwareRenderer mHardwareRenderer;
19716
19717        /**
19718         * The state of the display to which the window is attached, as reported
19719         * by {@link Display#getState()}.  Note that the display state constants
19720         * declared by {@link Display} do not exactly line up with the screen state
19721         * constants declared by {@link View} (there are more display states than
19722         * screen states).
19723         */
19724        int mDisplayState = Display.STATE_UNKNOWN;
19725
19726        /**
19727         * Scale factor used by the compatibility mode
19728         */
19729        float mApplicationScale;
19730
19731        /**
19732         * Indicates whether the application is in compatibility mode
19733         */
19734        boolean mScalingRequired;
19735
19736        /**
19737         * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
19738         */
19739        boolean mTurnOffWindowResizeAnim;
19740
19741        /**
19742         * Left position of this view's window
19743         */
19744        int mWindowLeft;
19745
19746        /**
19747         * Top position of this view's window
19748         */
19749        int mWindowTop;
19750
19751        /**
19752         * Indicates whether views need to use 32-bit drawing caches
19753         */
19754        boolean mUse32BitDrawingCache;
19755
19756        /**
19757         * For windows that are full-screen but using insets to layout inside
19758         * of the screen areas, these are the current insets to appear inside
19759         * the overscan area of the display.
19760         */
19761        final Rect mOverscanInsets = new Rect();
19762
19763        /**
19764         * For windows that are full-screen but using insets to layout inside
19765         * of the screen decorations, these are the current insets for the
19766         * content of the window.
19767         */
19768        final Rect mContentInsets = new Rect();
19769
19770        /**
19771         * For windows that are full-screen but using insets to layout inside
19772         * of the screen decorations, these are the current insets for the
19773         * actual visible parts of the window.
19774         */
19775        final Rect mVisibleInsets = new Rect();
19776
19777        /**
19778         * For windows that are full-screen but using insets to layout inside
19779         * of the screen decorations, these are the current insets for the
19780         * stable system windows.
19781         */
19782        final Rect mStableInsets = new Rect();
19783
19784        /**
19785         * The internal insets given by this window.  This value is
19786         * supplied by the client (through
19787         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
19788         * be given to the window manager when changed to be used in laying
19789         * out windows behind it.
19790         */
19791        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
19792                = new ViewTreeObserver.InternalInsetsInfo();
19793
19794        /**
19795         * Set to true when mGivenInternalInsets is non-empty.
19796         */
19797        boolean mHasNonEmptyGivenInternalInsets;
19798
19799        /**
19800         * All views in the window's hierarchy that serve as scroll containers,
19801         * used to determine if the window can be resized or must be panned
19802         * to adjust for a soft input area.
19803         */
19804        final ArrayList<View> mScrollContainers = new ArrayList<View>();
19805
19806        final KeyEvent.DispatcherState mKeyDispatchState
19807                = new KeyEvent.DispatcherState();
19808
19809        /**
19810         * Indicates whether the view's window currently has the focus.
19811         */
19812        boolean mHasWindowFocus;
19813
19814        /**
19815         * The current visibility of the window.
19816         */
19817        int mWindowVisibility;
19818
19819        /**
19820         * Indicates the time at which drawing started to occur.
19821         */
19822        long mDrawingTime;
19823
19824        /**
19825         * Indicates whether or not ignoring the DIRTY_MASK flags.
19826         */
19827        boolean mIgnoreDirtyState;
19828
19829        /**
19830         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
19831         * to avoid clearing that flag prematurely.
19832         */
19833        boolean mSetIgnoreDirtyState = false;
19834
19835        /**
19836         * Indicates whether the view's window is currently in touch mode.
19837         */
19838        boolean mInTouchMode;
19839
19840        /**
19841         * Indicates whether the view has requested unbuffered input dispatching for the current
19842         * event stream.
19843         */
19844        boolean mUnbufferedDispatchRequested;
19845
19846        /**
19847         * Indicates that ViewAncestor should trigger a global layout change
19848         * the next time it performs a traversal
19849         */
19850        boolean mRecomputeGlobalAttributes;
19851
19852        /**
19853         * Always report new attributes at next traversal.
19854         */
19855        boolean mForceReportNewAttributes;
19856
19857        /**
19858         * Set during a traveral if any views want to keep the screen on.
19859         */
19860        boolean mKeepScreenOn;
19861
19862        /**
19863         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
19864         */
19865        int mSystemUiVisibility;
19866
19867        /**
19868         * Hack to force certain system UI visibility flags to be cleared.
19869         */
19870        int mDisabledSystemUiVisibility;
19871
19872        /**
19873         * Last global system UI visibility reported by the window manager.
19874         */
19875        int mGlobalSystemUiVisibility;
19876
19877        /**
19878         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
19879         * attached.
19880         */
19881        boolean mHasSystemUiListeners;
19882
19883        /**
19884         * Set if the window has requested to extend into the overscan region
19885         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
19886         */
19887        boolean mOverscanRequested;
19888
19889        /**
19890         * Set if the visibility of any views has changed.
19891         */
19892        boolean mViewVisibilityChanged;
19893
19894        /**
19895         * Set to true if a view has been scrolled.
19896         */
19897        boolean mViewScrollChanged;
19898
19899        /**
19900         * Global to the view hierarchy used as a temporary for dealing with
19901         * x/y points in the transparent region computations.
19902         */
19903        final int[] mTransparentLocation = new int[2];
19904
19905        /**
19906         * Global to the view hierarchy used as a temporary for dealing with
19907         * x/y points in the ViewGroup.invalidateChild implementation.
19908         */
19909        final int[] mInvalidateChildLocation = new int[2];
19910
19911        /**
19912         * Global to the view hierarchy used as a temporary for dealng with
19913         * computing absolute on-screen location.
19914         */
19915        final int[] mTmpLocation = new int[2];
19916
19917        /**
19918         * Global to the view hierarchy used as a temporary for dealing with
19919         * x/y location when view is transformed.
19920         */
19921        final float[] mTmpTransformLocation = new float[2];
19922
19923        /**
19924         * The view tree observer used to dispatch global events like
19925         * layout, pre-draw, touch mode change, etc.
19926         */
19927        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
19928
19929        /**
19930         * A Canvas used by the view hierarchy to perform bitmap caching.
19931         */
19932        Canvas mCanvas;
19933
19934        /**
19935         * The view root impl.
19936         */
19937        final ViewRootImpl mViewRootImpl;
19938
19939        /**
19940         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
19941         * handler can be used to pump events in the UI events queue.
19942         */
19943        final Handler mHandler;
19944
19945        /**
19946         * Temporary for use in computing invalidate rectangles while
19947         * calling up the hierarchy.
19948         */
19949        final Rect mTmpInvalRect = new Rect();
19950
19951        /**
19952         * Temporary for use in computing hit areas with transformed views
19953         */
19954        final RectF mTmpTransformRect = new RectF();
19955
19956        /**
19957         * Temporary for use in transforming invalidation rect
19958         */
19959        final Matrix mTmpMatrix = new Matrix();
19960
19961        /**
19962         * Temporary for use in transforming invalidation rect
19963         */
19964        final Transformation mTmpTransformation = new Transformation();
19965
19966        /**
19967         * Temporary for use in querying outlines from OutlineProviders
19968         */
19969        final Outline mTmpOutline = new Outline();
19970
19971        /**
19972         * Temporary list for use in collecting focusable descendents of a view.
19973         */
19974        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
19975
19976        /**
19977         * The id of the window for accessibility purposes.
19978         */
19979        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
19980
19981        /**
19982         * Flags related to accessibility processing.
19983         *
19984         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
19985         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
19986         */
19987        int mAccessibilityFetchFlags;
19988
19989        /**
19990         * The drawable for highlighting accessibility focus.
19991         */
19992        Drawable mAccessibilityFocusDrawable;
19993
19994        /**
19995         * Show where the margins, bounds and layout bounds are for each view.
19996         */
19997        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
19998
19999        /**
20000         * Point used to compute visible regions.
20001         */
20002        final Point mPoint = new Point();
20003
20004        /**
20005         * Used to track which View originated a requestLayout() call, used when
20006         * requestLayout() is called during layout.
20007         */
20008        View mViewRequestingLayout;
20009
20010        /**
20011         * Creates a new set of attachment information with the specified
20012         * events handler and thread.
20013         *
20014         * @param handler the events handler the view must use
20015         */
20016        AttachInfo(IWindowSession session, IWindow window, Display display,
20017                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
20018            mSession = session;
20019            mWindow = window;
20020            mWindowToken = window.asBinder();
20021            mDisplay = display;
20022            mViewRootImpl = viewRootImpl;
20023            mHandler = handler;
20024            mRootCallbacks = effectPlayer;
20025        }
20026    }
20027
20028    /**
20029     * <p>ScrollabilityCache holds various fields used by a View when scrolling
20030     * is supported. This avoids keeping too many unused fields in most
20031     * instances of View.</p>
20032     */
20033    private static class ScrollabilityCache implements Runnable {
20034
20035        /**
20036         * Scrollbars are not visible
20037         */
20038        public static final int OFF = 0;
20039
20040        /**
20041         * Scrollbars are visible
20042         */
20043        public static final int ON = 1;
20044
20045        /**
20046         * Scrollbars are fading away
20047         */
20048        public static final int FADING = 2;
20049
20050        public boolean fadeScrollBars;
20051
20052        public int fadingEdgeLength;
20053        public int scrollBarDefaultDelayBeforeFade;
20054        public int scrollBarFadeDuration;
20055
20056        public int scrollBarSize;
20057        public ScrollBarDrawable scrollBar;
20058        public float[] interpolatorValues;
20059        public View host;
20060
20061        public final Paint paint;
20062        public final Matrix matrix;
20063        public Shader shader;
20064
20065        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
20066
20067        private static final float[] OPAQUE = { 255 };
20068        private static final float[] TRANSPARENT = { 0.0f };
20069
20070        /**
20071         * When fading should start. This time moves into the future every time
20072         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
20073         */
20074        public long fadeStartTime;
20075
20076
20077        /**
20078         * The current state of the scrollbars: ON, OFF, or FADING
20079         */
20080        public int state = OFF;
20081
20082        private int mLastColor;
20083
20084        public ScrollabilityCache(ViewConfiguration configuration, View host) {
20085            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
20086            scrollBarSize = configuration.getScaledScrollBarSize();
20087            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
20088            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
20089
20090            paint = new Paint();
20091            matrix = new Matrix();
20092            // use use a height of 1, and then wack the matrix each time we
20093            // actually use it.
20094            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
20095            paint.setShader(shader);
20096            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
20097
20098            this.host = host;
20099        }
20100
20101        public void setFadeColor(int color) {
20102            if (color != mLastColor) {
20103                mLastColor = color;
20104
20105                if (color != 0) {
20106                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
20107                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
20108                    paint.setShader(shader);
20109                    // Restore the default transfer mode (src_over)
20110                    paint.setXfermode(null);
20111                } else {
20112                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
20113                    paint.setShader(shader);
20114                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
20115                }
20116            }
20117        }
20118
20119        public void run() {
20120            long now = AnimationUtils.currentAnimationTimeMillis();
20121            if (now >= fadeStartTime) {
20122
20123                // the animation fades the scrollbars out by changing
20124                // the opacity (alpha) from fully opaque to fully
20125                // transparent
20126                int nextFrame = (int) now;
20127                int framesCount = 0;
20128
20129                Interpolator interpolator = scrollBarInterpolator;
20130
20131                // Start opaque
20132                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
20133
20134                // End transparent
20135                nextFrame += scrollBarFadeDuration;
20136                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
20137
20138                state = FADING;
20139
20140                // Kick off the fade animation
20141                host.invalidate(true);
20142            }
20143        }
20144    }
20145
20146    /**
20147     * Resuable callback for sending
20148     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
20149     */
20150    private class SendViewScrolledAccessibilityEvent implements Runnable {
20151        public volatile boolean mIsPending;
20152
20153        public void run() {
20154            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
20155            mIsPending = false;
20156        }
20157    }
20158
20159    /**
20160     * <p>
20161     * This class represents a delegate that can be registered in a {@link View}
20162     * to enhance accessibility support via composition rather via inheritance.
20163     * It is specifically targeted to widget developers that extend basic View
20164     * classes i.e. classes in package android.view, that would like their
20165     * applications to be backwards compatible.
20166     * </p>
20167     * <div class="special reference">
20168     * <h3>Developer Guides</h3>
20169     * <p>For more information about making applications accessible, read the
20170     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
20171     * developer guide.</p>
20172     * </div>
20173     * <p>
20174     * A scenario in which a developer would like to use an accessibility delegate
20175     * is overriding a method introduced in a later API version then the minimal API
20176     * version supported by the application. For example, the method
20177     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
20178     * in API version 4 when the accessibility APIs were first introduced. If a
20179     * developer would like his application to run on API version 4 devices (assuming
20180     * all other APIs used by the application are version 4 or lower) and take advantage
20181     * of this method, instead of overriding the method which would break the application's
20182     * backwards compatibility, he can override the corresponding method in this
20183     * delegate and register the delegate in the target View if the API version of
20184     * the system is high enough i.e. the API version is same or higher to the API
20185     * version that introduced
20186     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
20187     * </p>
20188     * <p>
20189     * Here is an example implementation:
20190     * </p>
20191     * <code><pre><p>
20192     * if (Build.VERSION.SDK_INT >= 14) {
20193     *     // If the API version is equal of higher than the version in
20194     *     // which onInitializeAccessibilityNodeInfo was introduced we
20195     *     // register a delegate with a customized implementation.
20196     *     View view = findViewById(R.id.view_id);
20197     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
20198     *         public void onInitializeAccessibilityNodeInfo(View host,
20199     *                 AccessibilityNodeInfo info) {
20200     *             // Let the default implementation populate the info.
20201     *             super.onInitializeAccessibilityNodeInfo(host, info);
20202     *             // Set some other information.
20203     *             info.setEnabled(host.isEnabled());
20204     *         }
20205     *     });
20206     * }
20207     * </code></pre></p>
20208     * <p>
20209     * This delegate contains methods that correspond to the accessibility methods
20210     * in View. If a delegate has been specified the implementation in View hands
20211     * off handling to the corresponding method in this delegate. The default
20212     * implementation the delegate methods behaves exactly as the corresponding
20213     * method in View for the case of no accessibility delegate been set. Hence,
20214     * to customize the behavior of a View method, clients can override only the
20215     * corresponding delegate method without altering the behavior of the rest
20216     * accessibility related methods of the host view.
20217     * </p>
20218     */
20219    public static class AccessibilityDelegate {
20220
20221        /**
20222         * Sends an accessibility event of the given type. If accessibility is not
20223         * enabled this method has no effect.
20224         * <p>
20225         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
20226         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
20227         * been set.
20228         * </p>
20229         *
20230         * @param host The View hosting the delegate.
20231         * @param eventType The type of the event to send.
20232         *
20233         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
20234         */
20235        public void sendAccessibilityEvent(View host, int eventType) {
20236            host.sendAccessibilityEventInternal(eventType);
20237        }
20238
20239        /**
20240         * Performs the specified accessibility action on the view. For
20241         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
20242         * <p>
20243         * The default implementation behaves as
20244         * {@link View#performAccessibilityAction(int, Bundle)
20245         *  View#performAccessibilityAction(int, Bundle)} for the case of
20246         *  no accessibility delegate been set.
20247         * </p>
20248         *
20249         * @param action The action to perform.
20250         * @return Whether the action was performed.
20251         *
20252         * @see View#performAccessibilityAction(int, Bundle)
20253         *      View#performAccessibilityAction(int, Bundle)
20254         */
20255        public boolean performAccessibilityAction(View host, int action, Bundle args) {
20256            return host.performAccessibilityActionInternal(action, args);
20257        }
20258
20259        /**
20260         * Sends an accessibility event. This method behaves exactly as
20261         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
20262         * empty {@link AccessibilityEvent} and does not perform a check whether
20263         * accessibility is enabled.
20264         * <p>
20265         * The default implementation behaves as
20266         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20267         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
20268         * the case of no accessibility delegate been set.
20269         * </p>
20270         *
20271         * @param host The View hosting the delegate.
20272         * @param event The event to send.
20273         *
20274         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20275         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20276         */
20277        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
20278            host.sendAccessibilityEventUncheckedInternal(event);
20279        }
20280
20281        /**
20282         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
20283         * to its children for adding their text content to the event.
20284         * <p>
20285         * The default implementation behaves as
20286         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20287         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
20288         * the case of no accessibility delegate been set.
20289         * </p>
20290         *
20291         * @param host The View hosting the delegate.
20292         * @param event The event.
20293         * @return True if the event population was completed.
20294         *
20295         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20296         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20297         */
20298        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20299            return host.dispatchPopulateAccessibilityEventInternal(event);
20300        }
20301
20302        /**
20303         * Gives a chance to the host View to populate the accessibility event with its
20304         * text content.
20305         * <p>
20306         * The default implementation behaves as
20307         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
20308         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
20309         * the case of no accessibility delegate been set.
20310         * </p>
20311         *
20312         * @param host The View hosting the delegate.
20313         * @param event The accessibility event which to populate.
20314         *
20315         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
20316         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
20317         */
20318        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20319            host.onPopulateAccessibilityEventInternal(event);
20320        }
20321
20322        /**
20323         * Initializes an {@link AccessibilityEvent} with information about the
20324         * the host View which is the event source.
20325         * <p>
20326         * The default implementation behaves as
20327         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
20328         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
20329         * the case of no accessibility delegate been set.
20330         * </p>
20331         *
20332         * @param host The View hosting the delegate.
20333         * @param event The event to initialize.
20334         *
20335         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
20336         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
20337         */
20338        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
20339            host.onInitializeAccessibilityEventInternal(event);
20340        }
20341
20342        /**
20343         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
20344         * <p>
20345         * The default implementation behaves as
20346         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20347         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
20348         * the case of no accessibility delegate been set.
20349         * </p>
20350         *
20351         * @param host The View hosting the delegate.
20352         * @param info The instance to initialize.
20353         *
20354         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20355         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20356         */
20357        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
20358            host.onInitializeAccessibilityNodeInfoInternal(info);
20359        }
20360
20361        /**
20362         * Called when a child of the host View has requested sending an
20363         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
20364         * to augment the event.
20365         * <p>
20366         * The default implementation behaves as
20367         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20368         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
20369         * the case of no accessibility delegate been set.
20370         * </p>
20371         *
20372         * @param host The View hosting the delegate.
20373         * @param child The child which requests sending the event.
20374         * @param event The event to be sent.
20375         * @return True if the event should be sent
20376         *
20377         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20378         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20379         */
20380        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
20381                AccessibilityEvent event) {
20382            return host.onRequestSendAccessibilityEventInternal(child, event);
20383        }
20384
20385        /**
20386         * Gets the provider for managing a virtual view hierarchy rooted at this View
20387         * and reported to {@link android.accessibilityservice.AccessibilityService}s
20388         * that explore the window content.
20389         * <p>
20390         * The default implementation behaves as
20391         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
20392         * the case of no accessibility delegate been set.
20393         * </p>
20394         *
20395         * @return The provider.
20396         *
20397         * @see AccessibilityNodeProvider
20398         */
20399        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
20400            return null;
20401        }
20402
20403        /**
20404         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
20405         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
20406         * This method is responsible for obtaining an accessibility node info from a
20407         * pool of reusable instances and calling
20408         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
20409         * view to initialize the former.
20410         * <p>
20411         * <strong>Note:</strong> The client is responsible for recycling the obtained
20412         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
20413         * creation.
20414         * </p>
20415         * <p>
20416         * The default implementation behaves as
20417         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
20418         * the case of no accessibility delegate been set.
20419         * </p>
20420         * @return A populated {@link AccessibilityNodeInfo}.
20421         *
20422         * @see AccessibilityNodeInfo
20423         *
20424         * @hide
20425         */
20426        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
20427            return host.createAccessibilityNodeInfoInternal();
20428        }
20429    }
20430
20431    private class MatchIdPredicate implements Predicate<View> {
20432        public int mId;
20433
20434        @Override
20435        public boolean apply(View view) {
20436            return (view.mID == mId);
20437        }
20438    }
20439
20440    private class MatchLabelForPredicate implements Predicate<View> {
20441        private int mLabeledId;
20442
20443        @Override
20444        public boolean apply(View view) {
20445            return (view.mLabelForId == mLabeledId);
20446        }
20447    }
20448
20449    private class SendViewStateChangedAccessibilityEvent implements Runnable {
20450        private int mChangeTypes = 0;
20451        private boolean mPosted;
20452        private boolean mPostedWithDelay;
20453        private long mLastEventTimeMillis;
20454
20455        @Override
20456        public void run() {
20457            mPosted = false;
20458            mPostedWithDelay = false;
20459            mLastEventTimeMillis = SystemClock.uptimeMillis();
20460            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
20461                final AccessibilityEvent event = AccessibilityEvent.obtain();
20462                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
20463                event.setContentChangeTypes(mChangeTypes);
20464                sendAccessibilityEventUnchecked(event);
20465            }
20466            mChangeTypes = 0;
20467        }
20468
20469        public void runOrPost(int changeType) {
20470            mChangeTypes |= changeType;
20471
20472            // If this is a live region or the child of a live region, collect
20473            // all events from this frame and send them on the next frame.
20474            if (inLiveRegion()) {
20475                // If we're already posted with a delay, remove that.
20476                if (mPostedWithDelay) {
20477                    removeCallbacks(this);
20478                    mPostedWithDelay = false;
20479                }
20480                // Only post if we're not already posted.
20481                if (!mPosted) {
20482                    post(this);
20483                    mPosted = true;
20484                }
20485                return;
20486            }
20487
20488            if (mPosted) {
20489                return;
20490            }
20491            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
20492            final long minEventIntevalMillis =
20493                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
20494            if (timeSinceLastMillis >= minEventIntevalMillis) {
20495                removeCallbacks(this);
20496                run();
20497            } else {
20498                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
20499                mPosted = true;
20500                mPostedWithDelay = true;
20501            }
20502        }
20503    }
20504
20505    private boolean inLiveRegion() {
20506        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
20507            return true;
20508        }
20509
20510        ViewParent parent = getParent();
20511        while (parent instanceof View) {
20512            if (((View) parent).getAccessibilityLiveRegion()
20513                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
20514                return true;
20515            }
20516            parent = parent.getParent();
20517        }
20518
20519        return false;
20520    }
20521
20522    /**
20523     * Dump all private flags in readable format, useful for documentation and
20524     * sanity checking.
20525     */
20526    private static void dumpFlags() {
20527        final HashMap<String, String> found = Maps.newHashMap();
20528        try {
20529            for (Field field : View.class.getDeclaredFields()) {
20530                final int modifiers = field.getModifiers();
20531                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
20532                    if (field.getType().equals(int.class)) {
20533                        final int value = field.getInt(null);
20534                        dumpFlag(found, field.getName(), value);
20535                    } else if (field.getType().equals(int[].class)) {
20536                        final int[] values = (int[]) field.get(null);
20537                        for (int i = 0; i < values.length; i++) {
20538                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
20539                        }
20540                    }
20541                }
20542            }
20543        } catch (IllegalAccessException e) {
20544            throw new RuntimeException(e);
20545        }
20546
20547        final ArrayList<String> keys = Lists.newArrayList();
20548        keys.addAll(found.keySet());
20549        Collections.sort(keys);
20550        for (String key : keys) {
20551            Log.d(VIEW_LOG_TAG, found.get(key));
20552        }
20553    }
20554
20555    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
20556        // Sort flags by prefix, then by bits, always keeping unique keys
20557        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
20558        final int prefix = name.indexOf('_');
20559        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
20560        final String output = bits + " " + name;
20561        found.put(key, output);
20562    }
20563}
20564