View.java revision 2371276e7d2af6bc088e1ec628ee04d06f05d6cf
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.StateListAnimator;
21import android.annotation.CallSuper;
22import android.annotation.ColorInt;
23import android.annotation.DrawableRes;
24import android.annotation.FloatRange;
25import android.annotation.IdRes;
26import android.annotation.IntDef;
27import android.annotation.LayoutRes;
28import android.annotation.NonNull;
29import android.annotation.Nullable;
30import android.annotation.Size;
31import android.annotation.UiThread;
32import android.content.ClipData;
33import android.content.Context;
34import android.content.ContextWrapper;
35import android.content.Intent;
36import android.content.res.ColorStateList;
37import android.content.res.Configuration;
38import android.content.res.Resources;
39import android.content.res.TypedArray;
40import android.graphics.Bitmap;
41import android.graphics.Canvas;
42import android.graphics.Insets;
43import android.graphics.Interpolator;
44import android.graphics.LinearGradient;
45import android.graphics.Matrix;
46import android.graphics.Outline;
47import android.graphics.Paint;
48import android.graphics.PixelFormat;
49import android.graphics.Point;
50import android.graphics.PorterDuff;
51import android.graphics.PorterDuffXfermode;
52import android.graphics.Rect;
53import android.graphics.RectF;
54import android.graphics.Region;
55import android.graphics.Shader;
56import android.graphics.drawable.ColorDrawable;
57import android.graphics.drawable.Drawable;
58import android.hardware.display.DisplayManagerGlobal;
59import android.os.Build.VERSION_CODES;
60import android.os.Bundle;
61import android.os.Handler;
62import android.os.IBinder;
63import android.os.Parcel;
64import android.os.Parcelable;
65import android.os.RemoteException;
66import android.os.SystemClock;
67import android.os.SystemProperties;
68import android.os.Trace;
69import android.text.TextUtils;
70import android.util.AttributeSet;
71import android.util.FloatProperty;
72import android.util.LayoutDirection;
73import android.util.Log;
74import android.util.LongSparseLongArray;
75import android.util.Pools.SynchronizedPool;
76import android.util.Property;
77import android.util.SparseArray;
78import android.util.StateSet;
79import android.util.SuperNotCalledException;
80import android.util.TypedValue;
81import android.view.ContextMenu.ContextMenuInfo;
82import android.view.AccessibilityIterators.TextSegmentIterator;
83import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
84import android.view.AccessibilityIterators.WordTextSegmentIterator;
85import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
86import android.view.accessibility.AccessibilityEvent;
87import android.view.accessibility.AccessibilityEventSource;
88import android.view.accessibility.AccessibilityManager;
89import android.view.accessibility.AccessibilityNodeInfo;
90import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
91import android.view.accessibility.AccessibilityNodeProvider;
92import android.view.animation.Animation;
93import android.view.animation.AnimationUtils;
94import android.view.animation.Transformation;
95import android.view.inputmethod.EditorInfo;
96import android.view.inputmethod.InputConnection;
97import android.view.inputmethod.InputMethodManager;
98import android.widget.Checkable;
99import android.widget.FrameLayout;
100import android.widget.ScrollBarDrawable;
101
102import static android.os.Build.VERSION_CODES.*;
103import static java.lang.Math.max;
104
105import com.android.internal.R;
106import com.android.internal.util.Predicate;
107import com.android.internal.view.menu.MenuBuilder;
108import com.google.android.collect.Lists;
109import com.google.android.collect.Maps;
110
111import java.lang.annotation.Retention;
112import java.lang.annotation.RetentionPolicy;
113import java.lang.ref.WeakReference;
114import java.lang.reflect.Field;
115import java.lang.reflect.InvocationTargetException;
116import java.lang.reflect.Method;
117import java.lang.reflect.Modifier;
118import java.util.ArrayList;
119import java.util.Arrays;
120import java.util.Collections;
121import java.util.HashMap;
122import java.util.List;
123import java.util.Locale;
124import java.util.Map;
125import java.util.concurrent.CopyOnWriteArrayList;
126import java.util.concurrent.atomic.AtomicInteger;
127
128/**
129 * <p>
130 * This class represents the basic building block for user interface components. A View
131 * occupies a rectangular area on the screen and is responsible for drawing and
132 * event handling. View is the base class for <em>widgets</em>, which are
133 * used to create interactive UI components (buttons, text fields, etc.). The
134 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
135 * are invisible containers that hold other Views (or other ViewGroups) and define
136 * their layout properties.
137 * </p>
138 *
139 * <div class="special reference">
140 * <h3>Developer Guides</h3>
141 * <p>For information about using this class to develop your application's user interface,
142 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
143 * </div>
144 *
145 * <a name="Using"></a>
146 * <h3>Using Views</h3>
147 * <p>
148 * All of the views in a window are arranged in a single tree. You can add views
149 * either from code or by specifying a tree of views in one or more XML layout
150 * files. There are many specialized subclasses of views that act as controls or
151 * are capable of displaying text, images, or other content.
152 * </p>
153 * <p>
154 * Once you have created a tree of views, there are typically a few types of
155 * common operations you may wish to perform:
156 * <ul>
157 * <li><strong>Set properties:</strong> for example setting the text of a
158 * {@link android.widget.TextView}. The available properties and the methods
159 * that set them will vary among the different subclasses of views. Note that
160 * properties that are known at build time can be set in the XML layout
161 * files.</li>
162 * <li><strong>Set focus:</strong> The framework will handled moving focus in
163 * response to user input. To force focus to a specific view, call
164 * {@link #requestFocus}.</li>
165 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
166 * that will be notified when something interesting happens to the view. For
167 * example, all views will let you set a listener to be notified when the view
168 * gains or loses focus. You can register such a listener using
169 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
170 * Other view subclasses offer more specialized listeners. For example, a Button
171 * exposes a listener to notify clients when the button is clicked.</li>
172 * <li><strong>Set visibility:</strong> You can hide or show views using
173 * {@link #setVisibility(int)}.</li>
174 * </ul>
175 * </p>
176 * <p><em>
177 * Note: The Android framework is responsible for measuring, laying out and
178 * drawing views. You should not call methods that perform these actions on
179 * views yourself unless you are actually implementing a
180 * {@link android.view.ViewGroup}.
181 * </em></p>
182 *
183 * <a name="Lifecycle"></a>
184 * <h3>Implementing a Custom View</h3>
185 *
186 * <p>
187 * To implement a custom view, you will usually begin by providing overrides for
188 * some of the standard methods that the framework calls on all views. You do
189 * not need to override all of these methods. In fact, you can start by just
190 * overriding {@link #onDraw(android.graphics.Canvas)}.
191 * <table border="2" width="85%" align="center" cellpadding="5">
192 *     <thead>
193 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
194 *     </thead>
195 *
196 *     <tbody>
197 *     <tr>
198 *         <td rowspan="2">Creation</td>
199 *         <td>Constructors</td>
200 *         <td>There is a form of the constructor that are called when the view
201 *         is created from code and a form that is called when the view is
202 *         inflated from a layout file. The second form should parse and apply
203 *         any attributes defined in the layout file.
204 *         </td>
205 *     </tr>
206 *     <tr>
207 *         <td><code>{@link #onFinishInflate()}</code></td>
208 *         <td>Called after a view and all of its children has been inflated
209 *         from XML.</td>
210 *     </tr>
211 *
212 *     <tr>
213 *         <td rowspan="3">Layout</td>
214 *         <td><code>{@link #onMeasure(int, int)}</code></td>
215 *         <td>Called to determine the size requirements for this view and all
216 *         of its children.
217 *         </td>
218 *     </tr>
219 *     <tr>
220 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
221 *         <td>Called when this view should assign a size and position to all
222 *         of its children.
223 *         </td>
224 *     </tr>
225 *     <tr>
226 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
227 *         <td>Called when the size of this view has changed.
228 *         </td>
229 *     </tr>
230 *
231 *     <tr>
232 *         <td>Drawing</td>
233 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
234 *         <td>Called when the view should render its content.
235 *         </td>
236 *     </tr>
237 *
238 *     <tr>
239 *         <td rowspan="4">Event processing</td>
240 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
241 *         <td>Called when a new hardware key event occurs.
242 *         </td>
243 *     </tr>
244 *     <tr>
245 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
246 *         <td>Called when a hardware key up event occurs.
247 *         </td>
248 *     </tr>
249 *     <tr>
250 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
251 *         <td>Called when a trackball motion event occurs.
252 *         </td>
253 *     </tr>
254 *     <tr>
255 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
256 *         <td>Called when a touch screen motion event occurs.
257 *         </td>
258 *     </tr>
259 *
260 *     <tr>
261 *         <td rowspan="2">Focus</td>
262 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
263 *         <td>Called when the view gains or loses focus.
264 *         </td>
265 *     </tr>
266 *
267 *     <tr>
268 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
269 *         <td>Called when the window containing the view gains or loses focus.
270 *         </td>
271 *     </tr>
272 *
273 *     <tr>
274 *         <td rowspan="3">Attaching</td>
275 *         <td><code>{@link #onAttachedToWindow()}</code></td>
276 *         <td>Called when the view is attached to a window.
277 *         </td>
278 *     </tr>
279 *
280 *     <tr>
281 *         <td><code>{@link #onDetachedFromWindow}</code></td>
282 *         <td>Called when the view is detached from its window.
283 *         </td>
284 *     </tr>
285 *
286 *     <tr>
287 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
288 *         <td>Called when the visibility of the window containing the view
289 *         has changed.
290 *         </td>
291 *     </tr>
292 *     </tbody>
293 *
294 * </table>
295 * </p>
296 *
297 * <a name="IDs"></a>
298 * <h3>IDs</h3>
299 * Views may have an integer id associated with them. These ids are typically
300 * assigned in the layout XML files, and are used to find specific views within
301 * the view tree. A common pattern is to:
302 * <ul>
303 * <li>Define a Button in the layout file and assign it a unique ID.
304 * <pre>
305 * &lt;Button
306 *     android:id="@+id/my_button"
307 *     android:layout_width="wrap_content"
308 *     android:layout_height="wrap_content"
309 *     android:text="@string/my_button_text"/&gt;
310 * </pre></li>
311 * <li>From the onCreate method of an Activity, find the Button
312 * <pre class="prettyprint">
313 *      Button myButton = (Button) findViewById(R.id.my_button);
314 * </pre></li>
315 * </ul>
316 * <p>
317 * View IDs need not be unique throughout the tree, but it is good practice to
318 * ensure that they are at least unique within the part of the tree you are
319 * searching.
320 * </p>
321 *
322 * <a name="Position"></a>
323 * <h3>Position</h3>
324 * <p>
325 * The geometry of a view is that of a rectangle. A view has a location,
326 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
327 * two dimensions, expressed as a width and a height. The unit for location
328 * and dimensions is the pixel.
329 * </p>
330 *
331 * <p>
332 * It is possible to retrieve the location of a view by invoking the methods
333 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
334 * coordinate of the rectangle representing the view. The latter returns the
335 * top, or Y, coordinate of the rectangle representing the view. These methods
336 * both return the location of the view relative to its parent. For instance,
337 * when getLeft() returns 20, that means the view is located 20 pixels to the
338 * right of the left edge of its direct parent.
339 * </p>
340 *
341 * <p>
342 * In addition, several convenience methods are offered to avoid unnecessary
343 * computations, namely {@link #getRight()} and {@link #getBottom()}.
344 * These methods return the coordinates of the right and bottom edges of the
345 * rectangle representing the view. For instance, calling {@link #getRight()}
346 * is similar to the following computation: <code>getLeft() + getWidth()</code>
347 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
348 * </p>
349 *
350 * <a name="SizePaddingMargins"></a>
351 * <h3>Size, padding and margins</h3>
352 * <p>
353 * The size of a view is expressed with a width and a height. A view actually
354 * possess two pairs of width and height values.
355 * </p>
356 *
357 * <p>
358 * The first pair is known as <em>measured width</em> and
359 * <em>measured height</em>. These dimensions define how big a view wants to be
360 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
361 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
362 * and {@link #getMeasuredHeight()}.
363 * </p>
364 *
365 * <p>
366 * The second pair is simply known as <em>width</em> and <em>height</em>, or
367 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
368 * dimensions define the actual size of the view on screen, at drawing time and
369 * after layout. These values may, but do not have to, be different from the
370 * measured width and height. The width and height can be obtained by calling
371 * {@link #getWidth()} and {@link #getHeight()}.
372 * </p>
373 *
374 * <p>
375 * To measure its dimensions, a view takes into account its padding. The padding
376 * is expressed in pixels for the left, top, right and bottom parts of the view.
377 * Padding can be used to offset the content of the view by a specific amount of
378 * pixels. For instance, a left padding of 2 will push the view's content by
379 * 2 pixels to the right of the left edge. Padding can be set using the
380 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
381 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
382 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
383 * {@link #getPaddingEnd()}.
384 * </p>
385 *
386 * <p>
387 * Even though a view can define a padding, it does not provide any support for
388 * margins. However, view groups provide such a support. Refer to
389 * {@link android.view.ViewGroup} and
390 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
391 * </p>
392 *
393 * <a name="Layout"></a>
394 * <h3>Layout</h3>
395 * <p>
396 * Layout is a two pass process: a measure pass and a layout pass. The measuring
397 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
398 * of the view tree. Each view pushes dimension specifications down the tree
399 * during the recursion. At the end of the measure pass, every view has stored
400 * its measurements. The second pass happens in
401 * {@link #layout(int,int,int,int)} and is also top-down. During
402 * this pass each parent is responsible for positioning all of its children
403 * using the sizes computed in the measure pass.
404 * </p>
405 *
406 * <p>
407 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
408 * {@link #getMeasuredHeight()} values must be set, along with those for all of
409 * that view's descendants. A view's measured width and measured height values
410 * must respect the constraints imposed by the view's parents. This guarantees
411 * that at the end of the measure pass, all parents accept all of their
412 * children's measurements. A parent view may call measure() more than once on
413 * its children. For example, the parent may measure each child once with
414 * unspecified dimensions to find out how big they want to be, then call
415 * measure() on them again with actual numbers if the sum of all the children's
416 * unconstrained sizes is too big or too small.
417 * </p>
418 *
419 * <p>
420 * The measure pass uses two classes to communicate dimensions. The
421 * {@link MeasureSpec} class is used by views to tell their parents how they
422 * want to be measured and positioned. The base LayoutParams class just
423 * describes how big the view wants to be for both width and height. For each
424 * dimension, it can specify one of:
425 * <ul>
426 * <li> an exact number
427 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
428 * (minus padding)
429 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
430 * enclose its content (plus padding).
431 * </ul>
432 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
433 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
434 * an X and Y value.
435 * </p>
436 *
437 * <p>
438 * MeasureSpecs are used to push requirements down the tree from parent to
439 * child. A MeasureSpec can be in one of three modes:
440 * <ul>
441 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
442 * of a child view. For example, a LinearLayout may call measure() on its child
443 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
444 * tall the child view wants to be given a width of 240 pixels.
445 * <li>EXACTLY: This is used by the parent to impose an exact size on the
446 * child. The child must use this size, and guarantee that all of its
447 * descendants will fit within this size.
448 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
449 * child. The child must guarantee that it and all of its descendants will fit
450 * within this size.
451 * </ul>
452 * </p>
453 *
454 * <p>
455 * To initiate a layout, call {@link #requestLayout}. This method is typically
456 * called by a view on itself when it believes that is can no longer fit within
457 * its current bounds.
458 * </p>
459 *
460 * <a name="Drawing"></a>
461 * <h3>Drawing</h3>
462 * <p>
463 * Drawing is handled by walking the tree and recording the drawing commands of
464 * any View that needs to update. After this, the drawing commands of the
465 * entire tree are issued to screen, clipped to the newly damaged area.
466 * </p>
467 *
468 * <p>
469 * The tree is largely recorded and drawn in order, with parents drawn before
470 * (i.e., behind) their children, with siblings drawn in the order they appear
471 * in the tree. If you set a background drawable for a View, then the View will
472 * draw it before calling back to its <code>onDraw()</code> method. The child
473 * drawing order can be overridden with
474 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
475 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
476 * </p>
477 *
478 * <p>
479 * To force a view to draw, call {@link #invalidate()}.
480 * </p>
481 *
482 * <a name="EventHandlingThreading"></a>
483 * <h3>Event Handling and Threading</h3>
484 * <p>
485 * The basic cycle of a view is as follows:
486 * <ol>
487 * <li>An event comes in and is dispatched to the appropriate view. The view
488 * handles the event and notifies any listeners.</li>
489 * <li>If in the course of processing the event, the view's bounds may need
490 * to be changed, the view will call {@link #requestLayout()}.</li>
491 * <li>Similarly, if in the course of processing the event the view's appearance
492 * may need to be changed, the view will call {@link #invalidate()}.</li>
493 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
494 * the framework will take care of measuring, laying out, and drawing the tree
495 * as appropriate.</li>
496 * </ol>
497 * </p>
498 *
499 * <p><em>Note: The entire view tree is single threaded. You must always be on
500 * the UI thread when calling any method on any view.</em>
501 * If you are doing work on other threads and want to update the state of a view
502 * from that thread, you should use a {@link Handler}.
503 * </p>
504 *
505 * <a name="FocusHandling"></a>
506 * <h3>Focus Handling</h3>
507 * <p>
508 * The framework will handle routine focus movement in response to user input.
509 * This includes changing the focus as views are removed or hidden, or as new
510 * views become available. Views indicate their willingness to take focus
511 * through the {@link #isFocusable} method. To change whether a view can take
512 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
513 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
514 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
515 * </p>
516 * <p>
517 * Focus movement is based on an algorithm which finds the nearest neighbor in a
518 * given direction. In rare cases, the default algorithm may not match the
519 * intended behavior of the developer. In these situations, you can provide
520 * explicit overrides by using these XML attributes in the layout file:
521 * <pre>
522 * nextFocusDown
523 * nextFocusLeft
524 * nextFocusRight
525 * nextFocusUp
526 * </pre>
527 * </p>
528 *
529 *
530 * <p>
531 * To get a particular view to take focus, call {@link #requestFocus()}.
532 * </p>
533 *
534 * <a name="TouchMode"></a>
535 * <h3>Touch Mode</h3>
536 * <p>
537 * When a user is navigating a user interface via directional keys such as a D-pad, it is
538 * necessary to give focus to actionable items such as buttons so the user can see
539 * what will take input.  If the device has touch capabilities, however, and the user
540 * begins interacting with the interface by touching it, it is no longer necessary to
541 * always highlight, or give focus to, a particular view.  This motivates a mode
542 * for interaction named 'touch mode'.
543 * </p>
544 * <p>
545 * For a touch capable device, once the user touches the screen, the device
546 * will enter touch mode.  From this point onward, only views for which
547 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
548 * Other views that are touchable, like buttons, will not take focus when touched; they will
549 * only fire the on click listeners.
550 * </p>
551 * <p>
552 * Any time a user hits a directional key, such as a D-pad direction, the view device will
553 * exit touch mode, and find a view to take focus, so that the user may resume interacting
554 * with the user interface without touching the screen again.
555 * </p>
556 * <p>
557 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
558 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
559 * </p>
560 *
561 * <a name="Scrolling"></a>
562 * <h3>Scrolling</h3>
563 * <p>
564 * The framework provides basic support for views that wish to internally
565 * scroll their content. This includes keeping track of the X and Y scroll
566 * offset as well as mechanisms for drawing scrollbars. See
567 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
568 * {@link #awakenScrollBars()} for more details.
569 * </p>
570 *
571 * <a name="Tags"></a>
572 * <h3>Tags</h3>
573 * <p>
574 * Unlike IDs, tags are not used to identify views. Tags are essentially an
575 * extra piece of information that can be associated with a view. They are most
576 * often used as a convenience to store data related to views in the views
577 * themselves rather than by putting them in a separate structure.
578 * </p>
579 * <p>
580 * Tags may be specified with character sequence values in layout XML as either
581 * a single tag using the {@link android.R.styleable#View_tag android:tag}
582 * attribute or multiple tags using the {@code &lt;tag&gt;} child element:
583 * <pre>
584 *     &ltView ...
585 *           android:tag="@string/mytag_value" /&gt;
586 *     &ltView ...&gt;
587 *         &lttag android:id="@+id/mytag"
588 *              android:value="@string/mytag_value" /&gt;
589 *     &lt/View>
590 * </pre>
591 * </p>
592 * <p>
593 * Tags may also be specified with arbitrary objects from code using
594 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
595 * </p>
596 *
597 * <a name="Themes"></a>
598 * <h3>Themes</h3>
599 * <p>
600 * By default, Views are created using the theme of the Context object supplied
601 * to their constructor; however, a different theme may be specified by using
602 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
603 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
604 * code.
605 * </p>
606 * <p>
607 * When the {@link android.R.styleable#View_theme android:theme} attribute is
608 * used in XML, the specified theme is applied on top of the inflation
609 * context's theme (see {@link LayoutInflater}) and used for the view itself as
610 * well as any child elements.
611 * </p>
612 * <p>
613 * In the following example, both views will be created using the Material dark
614 * color scheme; however, because an overlay theme is used which only defines a
615 * subset of attributes, the value of
616 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
617 * the inflation context's theme (e.g. the Activity theme) will be preserved.
618 * <pre>
619 *     &ltLinearLayout
620 *             ...
621 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
622 *         &ltView ...&gt;
623 *     &lt/LinearLayout&gt;
624 * </pre>
625 * </p>
626 *
627 * <a name="Properties"></a>
628 * <h3>Properties</h3>
629 * <p>
630 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
631 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
632 * available both in the {@link Property} form as well as in similarly-named setter/getter
633 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
634 * be used to set persistent state associated with these rendering-related properties on the view.
635 * The properties and methods can also be used in conjunction with
636 * {@link android.animation.Animator Animator}-based animations, described more in the
637 * <a href="#Animation">Animation</a> section.
638 * </p>
639 *
640 * <a name="Animation"></a>
641 * <h3>Animation</h3>
642 * <p>
643 * Starting with Android 3.0, the preferred way of animating views is to use the
644 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
645 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
646 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
647 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
648 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
649 * makes animating these View properties particularly easy and efficient.
650 * </p>
651 * <p>
652 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
653 * You can attach an {@link Animation} object to a view using
654 * {@link #setAnimation(Animation)} or
655 * {@link #startAnimation(Animation)}. The animation can alter the scale,
656 * rotation, translation and alpha of a view over time. If the animation is
657 * attached to a view that has children, the animation will affect the entire
658 * subtree rooted by that node. When an animation is started, the framework will
659 * take care of redrawing the appropriate views until the animation completes.
660 * </p>
661 *
662 * <a name="Security"></a>
663 * <h3>Security</h3>
664 * <p>
665 * Sometimes it is essential that an application be able to verify that an action
666 * is being performed with the full knowledge and consent of the user, such as
667 * granting a permission request, making a purchase or clicking on an advertisement.
668 * Unfortunately, a malicious application could try to spoof the user into
669 * performing these actions, unaware, by concealing the intended purpose of the view.
670 * As a remedy, the framework offers a touch filtering mechanism that can be used to
671 * improve the security of views that provide access to sensitive functionality.
672 * </p><p>
673 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
674 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
675 * will discard touches that are received whenever the view's window is obscured by
676 * another visible window.  As a result, the view will not receive touches whenever a
677 * toast, dialog or other window appears above the view's window.
678 * </p><p>
679 * For more fine-grained control over security, consider overriding the
680 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
681 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
682 * </p>
683 *
684 * @attr ref android.R.styleable#View_alpha
685 * @attr ref android.R.styleable#View_background
686 * @attr ref android.R.styleable#View_clickable
687 * @attr ref android.R.styleable#View_contentDescription
688 * @attr ref android.R.styleable#View_drawingCacheQuality
689 * @attr ref android.R.styleable#View_duplicateParentState
690 * @attr ref android.R.styleable#View_id
691 * @attr ref android.R.styleable#View_requiresFadingEdge
692 * @attr ref android.R.styleable#View_fadeScrollbars
693 * @attr ref android.R.styleable#View_fadingEdgeLength
694 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
695 * @attr ref android.R.styleable#View_fitsSystemWindows
696 * @attr ref android.R.styleable#View_isScrollContainer
697 * @attr ref android.R.styleable#View_focusable
698 * @attr ref android.R.styleable#View_focusableInTouchMode
699 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
700 * @attr ref android.R.styleable#View_keepScreenOn
701 * @attr ref android.R.styleable#View_layerType
702 * @attr ref android.R.styleable#View_layoutDirection
703 * @attr ref android.R.styleable#View_longClickable
704 * @attr ref android.R.styleable#View_minHeight
705 * @attr ref android.R.styleable#View_minWidth
706 * @attr ref android.R.styleable#View_nextFocusDown
707 * @attr ref android.R.styleable#View_nextFocusLeft
708 * @attr ref android.R.styleable#View_nextFocusRight
709 * @attr ref android.R.styleable#View_nextFocusUp
710 * @attr ref android.R.styleable#View_onClick
711 * @attr ref android.R.styleable#View_padding
712 * @attr ref android.R.styleable#View_paddingBottom
713 * @attr ref android.R.styleable#View_paddingLeft
714 * @attr ref android.R.styleable#View_paddingRight
715 * @attr ref android.R.styleable#View_paddingTop
716 * @attr ref android.R.styleable#View_paddingStart
717 * @attr ref android.R.styleable#View_paddingEnd
718 * @attr ref android.R.styleable#View_saveEnabled
719 * @attr ref android.R.styleable#View_rotation
720 * @attr ref android.R.styleable#View_rotationX
721 * @attr ref android.R.styleable#View_rotationY
722 * @attr ref android.R.styleable#View_scaleX
723 * @attr ref android.R.styleable#View_scaleY
724 * @attr ref android.R.styleable#View_scrollX
725 * @attr ref android.R.styleable#View_scrollY
726 * @attr ref android.R.styleable#View_scrollbarSize
727 * @attr ref android.R.styleable#View_scrollbarStyle
728 * @attr ref android.R.styleable#View_scrollbars
729 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
730 * @attr ref android.R.styleable#View_scrollbarFadeDuration
731 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
732 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
733 * @attr ref android.R.styleable#View_scrollbarThumbVertical
734 * @attr ref android.R.styleable#View_scrollbarTrackVertical
735 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
736 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
737 * @attr ref android.R.styleable#View_stateListAnimator
738 * @attr ref android.R.styleable#View_transitionName
739 * @attr ref android.R.styleable#View_soundEffectsEnabled
740 * @attr ref android.R.styleable#View_tag
741 * @attr ref android.R.styleable#View_textAlignment
742 * @attr ref android.R.styleable#View_textDirection
743 * @attr ref android.R.styleable#View_transformPivotX
744 * @attr ref android.R.styleable#View_transformPivotY
745 * @attr ref android.R.styleable#View_translationX
746 * @attr ref android.R.styleable#View_translationY
747 * @attr ref android.R.styleable#View_translationZ
748 * @attr ref android.R.styleable#View_visibility
749 * @attr ref android.R.styleable#View_theme
750 *
751 * @see android.view.ViewGroup
752 */
753@UiThread
754public class View implements Drawable.Callback, KeyEvent.Callback,
755        AccessibilityEventSource {
756    private static final boolean DBG = false;
757
758    /**
759     * The logging tag used by this class with android.util.Log.
760     */
761    protected static final String VIEW_LOG_TAG = "View";
762
763    /**
764     * When set to true, apps will draw debugging information about their layouts.
765     *
766     * @hide
767     */
768    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
769
770    /**
771     * When set to true, this view will save its attribute data.
772     *
773     * @hide
774     */
775    public static boolean mDebugViewAttributes = false;
776
777    /**
778     * Used to mark a View that has no ID.
779     */
780    public static final int NO_ID = -1;
781
782    /**
783     * Signals that compatibility booleans have been initialized according to
784     * target SDK versions.
785     */
786    private static boolean sCompatibilityDone = false;
787
788    /**
789     * Use the old (broken) way of building MeasureSpecs.
790     */
791    private static boolean sUseBrokenMakeMeasureSpec = false;
792
793    /**
794     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
795     */
796    static boolean sUseZeroUnspecifiedMeasureSpec = false;
797
798    /**
799     * Ignore any optimizations using the measure cache.
800     */
801    private static boolean sIgnoreMeasureCache = false;
802
803    /**
804     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
805     */
806    private static boolean sAlwaysRemeasureExactly = false;
807
808    /**
809     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
810     * calling setFlags.
811     */
812    private static final int NOT_FOCUSABLE = 0x00000000;
813
814    /**
815     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
816     * setFlags.
817     */
818    private static final int FOCUSABLE = 0x00000001;
819
820    /**
821     * Mask for use with setFlags indicating bits used for focus.
822     */
823    private static final int FOCUSABLE_MASK = 0x00000001;
824
825    /**
826     * This view will adjust its padding to fit sytem windows (e.g. status bar)
827     */
828    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
829
830    /** @hide */
831    @IntDef({VISIBLE, INVISIBLE, GONE})
832    @Retention(RetentionPolicy.SOURCE)
833    public @interface Visibility {}
834
835    /**
836     * This view is visible.
837     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
838     * android:visibility}.
839     */
840    public static final int VISIBLE = 0x00000000;
841
842    /**
843     * This view is invisible, but it still takes up space for layout purposes.
844     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
845     * android:visibility}.
846     */
847    public static final int INVISIBLE = 0x00000004;
848
849    /**
850     * This view is invisible, and it doesn't take any space for layout
851     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
852     * android:visibility}.
853     */
854    public static final int GONE = 0x00000008;
855
856    /**
857     * Mask for use with setFlags indicating bits used for visibility.
858     * {@hide}
859     */
860    static final int VISIBILITY_MASK = 0x0000000C;
861
862    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
863
864    /**
865     * This view is enabled. Interpretation varies by subclass.
866     * Use with ENABLED_MASK when calling setFlags.
867     * {@hide}
868     */
869    static final int ENABLED = 0x00000000;
870
871    /**
872     * This view is disabled. Interpretation varies by subclass.
873     * Use with ENABLED_MASK when calling setFlags.
874     * {@hide}
875     */
876    static final int DISABLED = 0x00000020;
877
878   /**
879    * Mask for use with setFlags indicating bits used for indicating whether
880    * this view is enabled
881    * {@hide}
882    */
883    static final int ENABLED_MASK = 0x00000020;
884
885    /**
886     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
887     * called and further optimizations will be performed. It is okay to have
888     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
889     * {@hide}
890     */
891    static final int WILL_NOT_DRAW = 0x00000080;
892
893    /**
894     * Mask for use with setFlags indicating bits used for indicating whether
895     * this view is will draw
896     * {@hide}
897     */
898    static final int DRAW_MASK = 0x00000080;
899
900    /**
901     * <p>This view doesn't show scrollbars.</p>
902     * {@hide}
903     */
904    static final int SCROLLBARS_NONE = 0x00000000;
905
906    /**
907     * <p>This view shows horizontal scrollbars.</p>
908     * {@hide}
909     */
910    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
911
912    /**
913     * <p>This view shows vertical scrollbars.</p>
914     * {@hide}
915     */
916    static final int SCROLLBARS_VERTICAL = 0x00000200;
917
918    /**
919     * <p>Mask for use with setFlags indicating bits used for indicating which
920     * scrollbars are enabled.</p>
921     * {@hide}
922     */
923    static final int SCROLLBARS_MASK = 0x00000300;
924
925    /**
926     * Indicates that the view should filter touches when its window is obscured.
927     * Refer to the class comments for more information about this security feature.
928     * {@hide}
929     */
930    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
931
932    /**
933     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
934     * that they are optional and should be skipped if the window has
935     * requested system UI flags that ignore those insets for layout.
936     */
937    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
938
939    /**
940     * <p>This view doesn't show fading edges.</p>
941     * {@hide}
942     */
943    static final int FADING_EDGE_NONE = 0x00000000;
944
945    /**
946     * <p>This view shows horizontal fading edges.</p>
947     * {@hide}
948     */
949    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
950
951    /**
952     * <p>This view shows vertical fading edges.</p>
953     * {@hide}
954     */
955    static final int FADING_EDGE_VERTICAL = 0x00002000;
956
957    /**
958     * <p>Mask for use with setFlags indicating bits used for indicating which
959     * fading edges are enabled.</p>
960     * {@hide}
961     */
962    static final int FADING_EDGE_MASK = 0x00003000;
963
964    /**
965     * <p>Indicates this view can be clicked. When clickable, a View reacts
966     * to clicks by notifying the OnClickListener.<p>
967     * {@hide}
968     */
969    static final int CLICKABLE = 0x00004000;
970
971    /**
972     * <p>Indicates this view is caching its drawing into a bitmap.</p>
973     * {@hide}
974     */
975    static final int DRAWING_CACHE_ENABLED = 0x00008000;
976
977    /**
978     * <p>Indicates that no icicle should be saved for this view.<p>
979     * {@hide}
980     */
981    static final int SAVE_DISABLED = 0x000010000;
982
983    /**
984     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
985     * property.</p>
986     * {@hide}
987     */
988    static final int SAVE_DISABLED_MASK = 0x000010000;
989
990    /**
991     * <p>Indicates that no drawing cache should ever be created for this view.<p>
992     * {@hide}
993     */
994    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
995
996    /**
997     * <p>Indicates this view can take / keep focus when int touch mode.</p>
998     * {@hide}
999     */
1000    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1001
1002    /** @hide */
1003    @Retention(RetentionPolicy.SOURCE)
1004    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1005    public @interface DrawingCacheQuality {}
1006
1007    /**
1008     * <p>Enables low quality mode for the drawing cache.</p>
1009     */
1010    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1011
1012    /**
1013     * <p>Enables high quality mode for the drawing cache.</p>
1014     */
1015    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1016
1017    /**
1018     * <p>Enables automatic quality mode for the drawing cache.</p>
1019     */
1020    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1021
1022    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1023            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1024    };
1025
1026    /**
1027     * <p>Mask for use with setFlags indicating bits used for the cache
1028     * quality property.</p>
1029     * {@hide}
1030     */
1031    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1032
1033    /**
1034     * <p>
1035     * Indicates this view can be long clicked. When long clickable, a View
1036     * reacts to long clicks by notifying the OnLongClickListener or showing a
1037     * context menu.
1038     * </p>
1039     * {@hide}
1040     */
1041    static final int LONG_CLICKABLE = 0x00200000;
1042
1043    /**
1044     * <p>Indicates that this view gets its drawable states from its direct parent
1045     * and ignores its original internal states.</p>
1046     *
1047     * @hide
1048     */
1049    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1050
1051    /**
1052     * <p>
1053     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1054     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1055     * OnContextClickListener.
1056     * </p>
1057     * {@hide}
1058     */
1059    static final int CONTEXT_CLICKABLE = 0x00800000;
1060
1061
1062    /** @hide */
1063    @IntDef({
1064        SCROLLBARS_INSIDE_OVERLAY,
1065        SCROLLBARS_INSIDE_INSET,
1066        SCROLLBARS_OUTSIDE_OVERLAY,
1067        SCROLLBARS_OUTSIDE_INSET
1068    })
1069    @Retention(RetentionPolicy.SOURCE)
1070    public @interface ScrollBarStyle {}
1071
1072    /**
1073     * The scrollbar style to display the scrollbars inside the content area,
1074     * without increasing the padding. The scrollbars will be overlaid with
1075     * translucency on the view's content.
1076     */
1077    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1078
1079    /**
1080     * The scrollbar style to display the scrollbars inside the padded area,
1081     * increasing the padding of the view. The scrollbars will not overlap the
1082     * content area of the view.
1083     */
1084    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1085
1086    /**
1087     * The scrollbar style to display the scrollbars at the edge of the view,
1088     * without increasing the padding. The scrollbars will be overlaid with
1089     * translucency.
1090     */
1091    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1092
1093    /**
1094     * The scrollbar style to display the scrollbars at the edge of the view,
1095     * increasing the padding of the view. The scrollbars will only overlap the
1096     * background, if any.
1097     */
1098    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1099
1100    /**
1101     * Mask to check if the scrollbar style is overlay or inset.
1102     * {@hide}
1103     */
1104    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1105
1106    /**
1107     * Mask to check if the scrollbar style is inside or outside.
1108     * {@hide}
1109     */
1110    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1111
1112    /**
1113     * Mask for scrollbar style.
1114     * {@hide}
1115     */
1116    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1117
1118    /**
1119     * View flag indicating that the screen should remain on while the
1120     * window containing this view is visible to the user.  This effectively
1121     * takes care of automatically setting the WindowManager's
1122     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1123     */
1124    public static final int KEEP_SCREEN_ON = 0x04000000;
1125
1126    /**
1127     * View flag indicating whether this view should have sound effects enabled
1128     * for events such as clicking and touching.
1129     */
1130    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1131
1132    /**
1133     * View flag indicating whether this view should have haptic feedback
1134     * enabled for events such as long presses.
1135     */
1136    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1137
1138    /**
1139     * <p>Indicates that the view hierarchy should stop saving state when
1140     * it reaches this view.  If state saving is initiated immediately at
1141     * the view, it will be allowed.
1142     * {@hide}
1143     */
1144    static final int PARENT_SAVE_DISABLED = 0x20000000;
1145
1146    /**
1147     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1148     * {@hide}
1149     */
1150    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1151
1152    /** @hide */
1153    @IntDef(flag = true,
1154            value = {
1155                FOCUSABLES_ALL,
1156                FOCUSABLES_TOUCH_MODE
1157            })
1158    @Retention(RetentionPolicy.SOURCE)
1159    public @interface FocusableMode {}
1160
1161    /**
1162     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1163     * should add all focusable Views regardless if they are focusable in touch mode.
1164     */
1165    public static final int FOCUSABLES_ALL = 0x00000000;
1166
1167    /**
1168     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1169     * should add only Views focusable in touch mode.
1170     */
1171    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1172
1173    /** @hide */
1174    @IntDef({
1175            FOCUS_BACKWARD,
1176            FOCUS_FORWARD,
1177            FOCUS_LEFT,
1178            FOCUS_UP,
1179            FOCUS_RIGHT,
1180            FOCUS_DOWN
1181    })
1182    @Retention(RetentionPolicy.SOURCE)
1183    public @interface FocusDirection {}
1184
1185    /** @hide */
1186    @IntDef({
1187            FOCUS_LEFT,
1188            FOCUS_UP,
1189            FOCUS_RIGHT,
1190            FOCUS_DOWN
1191    })
1192    @Retention(RetentionPolicy.SOURCE)
1193    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1194
1195    /**
1196     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1197     * item.
1198     */
1199    public static final int FOCUS_BACKWARD = 0x00000001;
1200
1201    /**
1202     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1203     * item.
1204     */
1205    public static final int FOCUS_FORWARD = 0x00000002;
1206
1207    /**
1208     * Use with {@link #focusSearch(int)}. Move focus to the left.
1209     */
1210    public static final int FOCUS_LEFT = 0x00000011;
1211
1212    /**
1213     * Use with {@link #focusSearch(int)}. Move focus up.
1214     */
1215    public static final int FOCUS_UP = 0x00000021;
1216
1217    /**
1218     * Use with {@link #focusSearch(int)}. Move focus to the right.
1219     */
1220    public static final int FOCUS_RIGHT = 0x00000042;
1221
1222    /**
1223     * Use with {@link #focusSearch(int)}. Move focus down.
1224     */
1225    public static final int FOCUS_DOWN = 0x00000082;
1226
1227    /**
1228     * Bits of {@link #getMeasuredWidthAndState()} and
1229     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1230     */
1231    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1232
1233    /**
1234     * Bits of {@link #getMeasuredWidthAndState()} and
1235     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1236     */
1237    public static final int MEASURED_STATE_MASK = 0xff000000;
1238
1239    /**
1240     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1241     * for functions that combine both width and height into a single int,
1242     * such as {@link #getMeasuredState()} and the childState argument of
1243     * {@link #resolveSizeAndState(int, int, int)}.
1244     */
1245    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1246
1247    /**
1248     * Bit of {@link #getMeasuredWidthAndState()} and
1249     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1250     * is smaller that the space the view would like to have.
1251     */
1252    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1253
1254    /**
1255     * Base View state sets
1256     */
1257    // Singles
1258    /**
1259     * Indicates the view has no states set. States are used with
1260     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1261     * view depending on its state.
1262     *
1263     * @see android.graphics.drawable.Drawable
1264     * @see #getDrawableState()
1265     */
1266    protected static final int[] EMPTY_STATE_SET;
1267    /**
1268     * Indicates the view is enabled. States are used with
1269     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1270     * view depending on its state.
1271     *
1272     * @see android.graphics.drawable.Drawable
1273     * @see #getDrawableState()
1274     */
1275    protected static final int[] ENABLED_STATE_SET;
1276    /**
1277     * Indicates the view is focused. States are used with
1278     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1279     * view depending on its state.
1280     *
1281     * @see android.graphics.drawable.Drawable
1282     * @see #getDrawableState()
1283     */
1284    protected static final int[] FOCUSED_STATE_SET;
1285    /**
1286     * Indicates the view is selected. States are used with
1287     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1288     * view depending on its state.
1289     *
1290     * @see android.graphics.drawable.Drawable
1291     * @see #getDrawableState()
1292     */
1293    protected static final int[] SELECTED_STATE_SET;
1294    /**
1295     * Indicates the view is pressed. States are used with
1296     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1297     * view depending on its state.
1298     *
1299     * @see android.graphics.drawable.Drawable
1300     * @see #getDrawableState()
1301     */
1302    protected static final int[] PRESSED_STATE_SET;
1303    /**
1304     * Indicates the view's window has focus. States are used with
1305     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1306     * view depending on its state.
1307     *
1308     * @see android.graphics.drawable.Drawable
1309     * @see #getDrawableState()
1310     */
1311    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1312    // Doubles
1313    /**
1314     * Indicates the view is enabled and has the focus.
1315     *
1316     * @see #ENABLED_STATE_SET
1317     * @see #FOCUSED_STATE_SET
1318     */
1319    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1320    /**
1321     * Indicates the view is enabled and selected.
1322     *
1323     * @see #ENABLED_STATE_SET
1324     * @see #SELECTED_STATE_SET
1325     */
1326    protected static final int[] ENABLED_SELECTED_STATE_SET;
1327    /**
1328     * Indicates the view is enabled and that its window has focus.
1329     *
1330     * @see #ENABLED_STATE_SET
1331     * @see #WINDOW_FOCUSED_STATE_SET
1332     */
1333    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1334    /**
1335     * Indicates the view is focused and selected.
1336     *
1337     * @see #FOCUSED_STATE_SET
1338     * @see #SELECTED_STATE_SET
1339     */
1340    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1341    /**
1342     * Indicates the view has the focus and that its window has the focus.
1343     *
1344     * @see #FOCUSED_STATE_SET
1345     * @see #WINDOW_FOCUSED_STATE_SET
1346     */
1347    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1348    /**
1349     * Indicates the view is selected and that its window has the focus.
1350     *
1351     * @see #SELECTED_STATE_SET
1352     * @see #WINDOW_FOCUSED_STATE_SET
1353     */
1354    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1355    // Triples
1356    /**
1357     * Indicates the view is enabled, focused and selected.
1358     *
1359     * @see #ENABLED_STATE_SET
1360     * @see #FOCUSED_STATE_SET
1361     * @see #SELECTED_STATE_SET
1362     */
1363    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1364    /**
1365     * Indicates the view is enabled, focused and its window has the focus.
1366     *
1367     * @see #ENABLED_STATE_SET
1368     * @see #FOCUSED_STATE_SET
1369     * @see #WINDOW_FOCUSED_STATE_SET
1370     */
1371    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1372    /**
1373     * Indicates the view is enabled, selected and its window has the focus.
1374     *
1375     * @see #ENABLED_STATE_SET
1376     * @see #SELECTED_STATE_SET
1377     * @see #WINDOW_FOCUSED_STATE_SET
1378     */
1379    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1380    /**
1381     * Indicates the view is focused, selected and its window has the focus.
1382     *
1383     * @see #FOCUSED_STATE_SET
1384     * @see #SELECTED_STATE_SET
1385     * @see #WINDOW_FOCUSED_STATE_SET
1386     */
1387    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1388    /**
1389     * Indicates the view is enabled, focused, selected and its window
1390     * has the focus.
1391     *
1392     * @see #ENABLED_STATE_SET
1393     * @see #FOCUSED_STATE_SET
1394     * @see #SELECTED_STATE_SET
1395     * @see #WINDOW_FOCUSED_STATE_SET
1396     */
1397    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1398    /**
1399     * Indicates the view is pressed and its window has the focus.
1400     *
1401     * @see #PRESSED_STATE_SET
1402     * @see #WINDOW_FOCUSED_STATE_SET
1403     */
1404    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1405    /**
1406     * Indicates the view is pressed and selected.
1407     *
1408     * @see #PRESSED_STATE_SET
1409     * @see #SELECTED_STATE_SET
1410     */
1411    protected static final int[] PRESSED_SELECTED_STATE_SET;
1412    /**
1413     * Indicates the view is pressed, selected and its window has the focus.
1414     *
1415     * @see #PRESSED_STATE_SET
1416     * @see #SELECTED_STATE_SET
1417     * @see #WINDOW_FOCUSED_STATE_SET
1418     */
1419    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1420    /**
1421     * Indicates the view is pressed and focused.
1422     *
1423     * @see #PRESSED_STATE_SET
1424     * @see #FOCUSED_STATE_SET
1425     */
1426    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1427    /**
1428     * Indicates the view is pressed, focused and its window has the focus.
1429     *
1430     * @see #PRESSED_STATE_SET
1431     * @see #FOCUSED_STATE_SET
1432     * @see #WINDOW_FOCUSED_STATE_SET
1433     */
1434    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1435    /**
1436     * Indicates the view is pressed, focused and selected.
1437     *
1438     * @see #PRESSED_STATE_SET
1439     * @see #SELECTED_STATE_SET
1440     * @see #FOCUSED_STATE_SET
1441     */
1442    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1443    /**
1444     * Indicates the view is pressed, focused, selected and its window has the focus.
1445     *
1446     * @see #PRESSED_STATE_SET
1447     * @see #FOCUSED_STATE_SET
1448     * @see #SELECTED_STATE_SET
1449     * @see #WINDOW_FOCUSED_STATE_SET
1450     */
1451    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1452    /**
1453     * Indicates the view is pressed and enabled.
1454     *
1455     * @see #PRESSED_STATE_SET
1456     * @see #ENABLED_STATE_SET
1457     */
1458    protected static final int[] PRESSED_ENABLED_STATE_SET;
1459    /**
1460     * Indicates the view is pressed, enabled and its window has the focus.
1461     *
1462     * @see #PRESSED_STATE_SET
1463     * @see #ENABLED_STATE_SET
1464     * @see #WINDOW_FOCUSED_STATE_SET
1465     */
1466    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1467    /**
1468     * Indicates the view is pressed, enabled and selected.
1469     *
1470     * @see #PRESSED_STATE_SET
1471     * @see #ENABLED_STATE_SET
1472     * @see #SELECTED_STATE_SET
1473     */
1474    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1475    /**
1476     * Indicates the view is pressed, enabled, selected and its window has the
1477     * focus.
1478     *
1479     * @see #PRESSED_STATE_SET
1480     * @see #ENABLED_STATE_SET
1481     * @see #SELECTED_STATE_SET
1482     * @see #WINDOW_FOCUSED_STATE_SET
1483     */
1484    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1485    /**
1486     * Indicates the view is pressed, enabled and focused.
1487     *
1488     * @see #PRESSED_STATE_SET
1489     * @see #ENABLED_STATE_SET
1490     * @see #FOCUSED_STATE_SET
1491     */
1492    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1493    /**
1494     * Indicates the view is pressed, enabled, focused and its window has the
1495     * focus.
1496     *
1497     * @see #PRESSED_STATE_SET
1498     * @see #ENABLED_STATE_SET
1499     * @see #FOCUSED_STATE_SET
1500     * @see #WINDOW_FOCUSED_STATE_SET
1501     */
1502    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1503    /**
1504     * Indicates the view is pressed, enabled, focused and selected.
1505     *
1506     * @see #PRESSED_STATE_SET
1507     * @see #ENABLED_STATE_SET
1508     * @see #SELECTED_STATE_SET
1509     * @see #FOCUSED_STATE_SET
1510     */
1511    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1512    /**
1513     * Indicates the view is pressed, enabled, focused, selected and its window
1514     * has the focus.
1515     *
1516     * @see #PRESSED_STATE_SET
1517     * @see #ENABLED_STATE_SET
1518     * @see #SELECTED_STATE_SET
1519     * @see #FOCUSED_STATE_SET
1520     * @see #WINDOW_FOCUSED_STATE_SET
1521     */
1522    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1523
1524    static {
1525        EMPTY_STATE_SET = StateSet.get(0);
1526
1527        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1528
1529        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1530        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1531                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1532
1533        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1534        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1535                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1536        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1537                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1538        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1539                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1540                        | StateSet.VIEW_STATE_FOCUSED);
1541
1542        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1543        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1544                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1545        ENABLED_SELECTED_STATE_SET = StateSet.get(
1546                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1547        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1548                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1549                        | StateSet.VIEW_STATE_ENABLED);
1550        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1551                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1552        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1553                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1554                        | StateSet.VIEW_STATE_ENABLED);
1555        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1556                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1557                        | StateSet.VIEW_STATE_ENABLED);
1558        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1559                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1560                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1561
1562        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1563        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1564                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1565        PRESSED_SELECTED_STATE_SET = StateSet.get(
1566                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1567        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1568                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1569                        | StateSet.VIEW_STATE_PRESSED);
1570        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1571                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1572        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1573                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1574                        | StateSet.VIEW_STATE_PRESSED);
1575        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1576                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1577                        | StateSet.VIEW_STATE_PRESSED);
1578        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1579                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1580                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1581        PRESSED_ENABLED_STATE_SET = StateSet.get(
1582                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1583        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1584                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1585                        | StateSet.VIEW_STATE_PRESSED);
1586        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1587                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1588                        | StateSet.VIEW_STATE_PRESSED);
1589        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1590                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1591                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1592        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1593                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1594                        | StateSet.VIEW_STATE_PRESSED);
1595        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1596                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1597                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1598        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1599                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1600                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1601        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1602                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1603                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1604                        | StateSet.VIEW_STATE_PRESSED);
1605    }
1606
1607    /**
1608     * Accessibility event types that are dispatched for text population.
1609     */
1610    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1611            AccessibilityEvent.TYPE_VIEW_CLICKED
1612            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1613            | AccessibilityEvent.TYPE_VIEW_SELECTED
1614            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1615            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1616            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1617            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1618            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1619            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1620            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1621            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1622
1623    /**
1624     * Temporary Rect currently for use in setBackground().  This will probably
1625     * be extended in the future to hold our own class with more than just
1626     * a Rect. :)
1627     */
1628    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1629
1630    /**
1631     * Map used to store views' tags.
1632     */
1633    private SparseArray<Object> mKeyedTags;
1634
1635    /**
1636     * The next available accessibility id.
1637     */
1638    private static int sNextAccessibilityViewId;
1639
1640    /**
1641     * The animation currently associated with this view.
1642     * @hide
1643     */
1644    protected Animation mCurrentAnimation = null;
1645
1646    /**
1647     * Width as measured during measure pass.
1648     * {@hide}
1649     */
1650    @ViewDebug.ExportedProperty(category = "measurement")
1651    int mMeasuredWidth;
1652
1653    /**
1654     * Height as measured during measure pass.
1655     * {@hide}
1656     */
1657    @ViewDebug.ExportedProperty(category = "measurement")
1658    int mMeasuredHeight;
1659
1660    /**
1661     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1662     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1663     * its display list. This flag, used only when hw accelerated, allows us to clear the
1664     * flag while retaining this information until it's needed (at getDisplayList() time and
1665     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1666     *
1667     * {@hide}
1668     */
1669    boolean mRecreateDisplayList = false;
1670
1671    /**
1672     * The view's identifier.
1673     * {@hide}
1674     *
1675     * @see #setId(int)
1676     * @see #getId()
1677     */
1678    @IdRes
1679    @ViewDebug.ExportedProperty(resolveId = true)
1680    int mID = NO_ID;
1681
1682    /**
1683     * The stable ID of this view for accessibility purposes.
1684     */
1685    int mAccessibilityViewId = NO_ID;
1686
1687    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1688
1689    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1690
1691    /**
1692     * The view's tag.
1693     * {@hide}
1694     *
1695     * @see #setTag(Object)
1696     * @see #getTag()
1697     */
1698    protected Object mTag = null;
1699
1700    // for mPrivateFlags:
1701    /** {@hide} */
1702    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1703    /** {@hide} */
1704    static final int PFLAG_FOCUSED                     = 0x00000002;
1705    /** {@hide} */
1706    static final int PFLAG_SELECTED                    = 0x00000004;
1707    /** {@hide} */
1708    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1709    /** {@hide} */
1710    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1711    /** {@hide} */
1712    static final int PFLAG_DRAWN                       = 0x00000020;
1713    /**
1714     * When this flag is set, this view is running an animation on behalf of its
1715     * children and should therefore not cancel invalidate requests, even if they
1716     * lie outside of this view's bounds.
1717     *
1718     * {@hide}
1719     */
1720    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1721    /** {@hide} */
1722    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1723    /** {@hide} */
1724    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1725    /** {@hide} */
1726    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1727    /** {@hide} */
1728    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1729    /** {@hide} */
1730    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1731    /** {@hide} */
1732    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1733
1734    private static final int PFLAG_PRESSED             = 0x00004000;
1735
1736    /** {@hide} */
1737    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1738    /**
1739     * Flag used to indicate that this view should be drawn once more (and only once
1740     * more) after its animation has completed.
1741     * {@hide}
1742     */
1743    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1744
1745    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1746
1747    /**
1748     * Indicates that the View returned true when onSetAlpha() was called and that
1749     * the alpha must be restored.
1750     * {@hide}
1751     */
1752    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1753
1754    /**
1755     * Set by {@link #setScrollContainer(boolean)}.
1756     */
1757    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1758
1759    /**
1760     * Set by {@link #setScrollContainer(boolean)}.
1761     */
1762    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1763
1764    /**
1765     * View flag indicating whether this view was invalidated (fully or partially.)
1766     *
1767     * @hide
1768     */
1769    static final int PFLAG_DIRTY                       = 0x00200000;
1770
1771    /**
1772     * View flag indicating whether this view was invalidated by an opaque
1773     * invalidate request.
1774     *
1775     * @hide
1776     */
1777    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1778
1779    /**
1780     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1781     *
1782     * @hide
1783     */
1784    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1785
1786    /**
1787     * Indicates whether the background is opaque.
1788     *
1789     * @hide
1790     */
1791    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1792
1793    /**
1794     * Indicates whether the scrollbars are opaque.
1795     *
1796     * @hide
1797     */
1798    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1799
1800    /**
1801     * Indicates whether the view is opaque.
1802     *
1803     * @hide
1804     */
1805    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1806
1807    /**
1808     * Indicates a prepressed state;
1809     * the short time between ACTION_DOWN and recognizing
1810     * a 'real' press. Prepressed is used to recognize quick taps
1811     * even when they are shorter than ViewConfiguration.getTapTimeout().
1812     *
1813     * @hide
1814     */
1815    private static final int PFLAG_PREPRESSED          = 0x02000000;
1816
1817    /**
1818     * Indicates whether the view is temporarily detached.
1819     *
1820     * @hide
1821     */
1822    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1823
1824    /**
1825     * Indicates that we should awaken scroll bars once attached
1826     *
1827     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1828     * during window attachment and it is no longer needed. Feel free to repurpose it.
1829     *
1830     * @hide
1831     */
1832    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1833
1834    /**
1835     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1836     * @hide
1837     */
1838    private static final int PFLAG_HOVERED             = 0x10000000;
1839
1840    /**
1841     * no longer needed, should be reused
1842     */
1843    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1844
1845    /** {@hide} */
1846    static final int PFLAG_ACTIVATED                   = 0x40000000;
1847
1848    /**
1849     * Indicates that this view was specifically invalidated, not just dirtied because some
1850     * child view was invalidated. The flag is used to determine when we need to recreate
1851     * a view's display list (as opposed to just returning a reference to its existing
1852     * display list).
1853     *
1854     * @hide
1855     */
1856    static final int PFLAG_INVALIDATED                 = 0x80000000;
1857
1858    /**
1859     * Masks for mPrivateFlags2, as generated by dumpFlags():
1860     *
1861     * |-------|-------|-------|-------|
1862     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1863     *                                1  PFLAG2_DRAG_HOVERED
1864     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1865     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1866     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1867     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1868     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1869     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1870     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1871     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1872     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1873     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1874     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1875     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1876     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1877     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1878     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1879     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1880     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1881     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1882     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1883     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1884     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1885     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1886     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1887     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1888     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1889     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1890     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1891     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1892     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1893     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1894     *    1                              PFLAG2_PADDING_RESOLVED
1895     *   1                               PFLAG2_DRAWABLE_RESOLVED
1896     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1897     * |-------|-------|-------|-------|
1898     */
1899
1900    /**
1901     * Indicates that this view has reported that it can accept the current drag's content.
1902     * Cleared when the drag operation concludes.
1903     * @hide
1904     */
1905    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1906
1907    /**
1908     * Indicates that this view is currently directly under the drag location in a
1909     * drag-and-drop operation involving content that it can accept.  Cleared when
1910     * the drag exits the view, or when the drag operation concludes.
1911     * @hide
1912     */
1913    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1914
1915    /** @hide */
1916    @IntDef({
1917        LAYOUT_DIRECTION_LTR,
1918        LAYOUT_DIRECTION_RTL,
1919        LAYOUT_DIRECTION_INHERIT,
1920        LAYOUT_DIRECTION_LOCALE
1921    })
1922    @Retention(RetentionPolicy.SOURCE)
1923    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1924    public @interface LayoutDir {}
1925
1926    /** @hide */
1927    @IntDef({
1928        LAYOUT_DIRECTION_LTR,
1929        LAYOUT_DIRECTION_RTL
1930    })
1931    @Retention(RetentionPolicy.SOURCE)
1932    public @interface ResolvedLayoutDir {}
1933
1934    /**
1935     * A flag to indicate that the layout direction of this view has not been defined yet.
1936     * @hide
1937     */
1938    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1939
1940    /**
1941     * Horizontal layout direction of this view is from Left to Right.
1942     * Use with {@link #setLayoutDirection}.
1943     */
1944    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1945
1946    /**
1947     * Horizontal layout direction of this view is from Right to Left.
1948     * Use with {@link #setLayoutDirection}.
1949     */
1950    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1951
1952    /**
1953     * Horizontal layout direction of this view is inherited from its parent.
1954     * Use with {@link #setLayoutDirection}.
1955     */
1956    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1957
1958    /**
1959     * Horizontal layout direction of this view is from deduced from the default language
1960     * script for the locale. Use with {@link #setLayoutDirection}.
1961     */
1962    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1963
1964    /**
1965     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1966     * @hide
1967     */
1968    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1969
1970    /**
1971     * Mask for use with private flags indicating bits used for horizontal layout direction.
1972     * @hide
1973     */
1974    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1975
1976    /**
1977     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1978     * right-to-left direction.
1979     * @hide
1980     */
1981    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1982
1983    /**
1984     * Indicates whether the view horizontal layout direction has been resolved.
1985     * @hide
1986     */
1987    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1988
1989    /**
1990     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1991     * @hide
1992     */
1993    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1994            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1995
1996    /*
1997     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1998     * flag value.
1999     * @hide
2000     */
2001    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2002            LAYOUT_DIRECTION_LTR,
2003            LAYOUT_DIRECTION_RTL,
2004            LAYOUT_DIRECTION_INHERIT,
2005            LAYOUT_DIRECTION_LOCALE
2006    };
2007
2008    /**
2009     * Default horizontal layout direction.
2010     */
2011    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2012
2013    /**
2014     * Default horizontal layout direction.
2015     * @hide
2016     */
2017    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2018
2019    /**
2020     * Text direction is inherited through {@link ViewGroup}
2021     */
2022    public static final int TEXT_DIRECTION_INHERIT = 0;
2023
2024    /**
2025     * Text direction is using "first strong algorithm". The first strong directional character
2026     * determines the paragraph direction. If there is no strong directional character, the
2027     * paragraph direction is the view's resolved layout direction.
2028     */
2029    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2030
2031    /**
2032     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2033     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2034     * If there are neither, the paragraph direction is the view's resolved layout direction.
2035     */
2036    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2037
2038    /**
2039     * Text direction is forced to LTR.
2040     */
2041    public static final int TEXT_DIRECTION_LTR = 3;
2042
2043    /**
2044     * Text direction is forced to RTL.
2045     */
2046    public static final int TEXT_DIRECTION_RTL = 4;
2047
2048    /**
2049     * Text direction is coming from the system Locale.
2050     */
2051    public static final int TEXT_DIRECTION_LOCALE = 5;
2052
2053    /**
2054     * Text direction is using "first strong algorithm". The first strong directional character
2055     * determines the paragraph direction. If there is no strong directional character, the
2056     * paragraph direction is LTR.
2057     */
2058    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2059
2060    /**
2061     * Text direction is using "first strong algorithm". The first strong directional character
2062     * determines the paragraph direction. If there is no strong directional character, the
2063     * paragraph direction is RTL.
2064     */
2065    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2066
2067    /**
2068     * Default text direction is inherited
2069     */
2070    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2071
2072    /**
2073     * Default resolved text direction
2074     * @hide
2075     */
2076    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2077
2078    /**
2079     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2080     * @hide
2081     */
2082    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2083
2084    /**
2085     * Mask for use with private flags indicating bits used for text direction.
2086     * @hide
2087     */
2088    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2089            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2090
2091    /**
2092     * Array of text direction flags for mapping attribute "textDirection" to correct
2093     * flag value.
2094     * @hide
2095     */
2096    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2097            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2098            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2099            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2100            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2101            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2102            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2103            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2104            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2105    };
2106
2107    /**
2108     * Indicates whether the view text direction has been resolved.
2109     * @hide
2110     */
2111    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2112            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2113
2114    /**
2115     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2116     * @hide
2117     */
2118    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2119
2120    /**
2121     * Mask for use with private flags indicating bits used for resolved text direction.
2122     * @hide
2123     */
2124    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2125            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2126
2127    /**
2128     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2129     * @hide
2130     */
2131    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2132            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2133
2134    /** @hide */
2135    @IntDef({
2136        TEXT_ALIGNMENT_INHERIT,
2137        TEXT_ALIGNMENT_GRAVITY,
2138        TEXT_ALIGNMENT_CENTER,
2139        TEXT_ALIGNMENT_TEXT_START,
2140        TEXT_ALIGNMENT_TEXT_END,
2141        TEXT_ALIGNMENT_VIEW_START,
2142        TEXT_ALIGNMENT_VIEW_END
2143    })
2144    @Retention(RetentionPolicy.SOURCE)
2145    public @interface TextAlignment {}
2146
2147    /**
2148     * Default text alignment. The text alignment of this View is inherited from its parent.
2149     * Use with {@link #setTextAlignment(int)}
2150     */
2151    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2152
2153    /**
2154     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2155     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2156     *
2157     * Use with {@link #setTextAlignment(int)}
2158     */
2159    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2160
2161    /**
2162     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2163     *
2164     * Use with {@link #setTextAlignment(int)}
2165     */
2166    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2167
2168    /**
2169     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2170     *
2171     * Use with {@link #setTextAlignment(int)}
2172     */
2173    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2174
2175    /**
2176     * Center the paragraph, e.g. ALIGN_CENTER.
2177     *
2178     * Use with {@link #setTextAlignment(int)}
2179     */
2180    public static final int TEXT_ALIGNMENT_CENTER = 4;
2181
2182    /**
2183     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2184     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2185     *
2186     * Use with {@link #setTextAlignment(int)}
2187     */
2188    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2189
2190    /**
2191     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2192     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2193     *
2194     * Use with {@link #setTextAlignment(int)}
2195     */
2196    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2197
2198    /**
2199     * Default text alignment is inherited
2200     */
2201    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2202
2203    /**
2204     * Default resolved text alignment
2205     * @hide
2206     */
2207    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2208
2209    /**
2210      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2211      * @hide
2212      */
2213    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2214
2215    /**
2216      * Mask for use with private flags indicating bits used for text alignment.
2217      * @hide
2218      */
2219    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2220
2221    /**
2222     * Array of text direction flags for mapping attribute "textAlignment" to correct
2223     * flag value.
2224     * @hide
2225     */
2226    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2227            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2228            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2229            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2230            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2231            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2232            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2233            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2234    };
2235
2236    /**
2237     * Indicates whether the view text alignment has been resolved.
2238     * @hide
2239     */
2240    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2241
2242    /**
2243     * Bit shift to get the resolved text alignment.
2244     * @hide
2245     */
2246    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2247
2248    /**
2249     * Mask for use with private flags indicating bits used for text alignment.
2250     * @hide
2251     */
2252    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2253            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2254
2255    /**
2256     * Indicates whether if the view text alignment has been resolved to gravity
2257     */
2258    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2259            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2260
2261    // Accessiblity constants for mPrivateFlags2
2262
2263    /**
2264     * Shift for the bits in {@link #mPrivateFlags2} related to the
2265     * "importantForAccessibility" attribute.
2266     */
2267    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2268
2269    /**
2270     * Automatically determine whether a view is important for accessibility.
2271     */
2272    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2273
2274    /**
2275     * The view is important for accessibility.
2276     */
2277    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2278
2279    /**
2280     * The view is not important for accessibility.
2281     */
2282    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2283
2284    /**
2285     * The view is not important for accessibility, nor are any of its
2286     * descendant views.
2287     */
2288    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2289
2290    /**
2291     * The default whether the view is important for accessibility.
2292     */
2293    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2294
2295    /**
2296     * Mask for obtainig the bits which specify how to determine
2297     * whether a view is important for accessibility.
2298     */
2299    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2300        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2301        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2302        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2303
2304    /**
2305     * Shift for the bits in {@link #mPrivateFlags2} related to the
2306     * "accessibilityLiveRegion" attribute.
2307     */
2308    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2309
2310    /**
2311     * Live region mode specifying that accessibility services should not
2312     * automatically announce changes to this view. This is the default live
2313     * region mode for most views.
2314     * <p>
2315     * Use with {@link #setAccessibilityLiveRegion(int)}.
2316     */
2317    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2318
2319    /**
2320     * Live region mode specifying that accessibility services should announce
2321     * changes to this view.
2322     * <p>
2323     * Use with {@link #setAccessibilityLiveRegion(int)}.
2324     */
2325    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2326
2327    /**
2328     * Live region mode specifying that accessibility services should interrupt
2329     * ongoing speech to immediately announce changes to this view.
2330     * <p>
2331     * Use with {@link #setAccessibilityLiveRegion(int)}.
2332     */
2333    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2334
2335    /**
2336     * The default whether the view is important for accessibility.
2337     */
2338    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2339
2340    /**
2341     * Mask for obtaining the bits which specify a view's accessibility live
2342     * region mode.
2343     */
2344    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2345            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2346            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2347
2348    /**
2349     * Flag indicating whether a view has accessibility focus.
2350     */
2351    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2352
2353    /**
2354     * Flag whether the accessibility state of the subtree rooted at this view changed.
2355     */
2356    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2357
2358    /**
2359     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2360     * is used to check whether later changes to the view's transform should invalidate the
2361     * view to force the quickReject test to run again.
2362     */
2363    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2364
2365    /**
2366     * Flag indicating that start/end padding has been resolved into left/right padding
2367     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2368     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2369     * during measurement. In some special cases this is required such as when an adapter-based
2370     * view measures prospective children without attaching them to a window.
2371     */
2372    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2373
2374    /**
2375     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2376     */
2377    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2378
2379    /**
2380     * Indicates that the view is tracking some sort of transient state
2381     * that the app should not need to be aware of, but that the framework
2382     * should take special care to preserve.
2383     */
2384    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2385
2386    /**
2387     * Group of bits indicating that RTL properties resolution is done.
2388     */
2389    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2390            PFLAG2_TEXT_DIRECTION_RESOLVED |
2391            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2392            PFLAG2_PADDING_RESOLVED |
2393            PFLAG2_DRAWABLE_RESOLVED;
2394
2395    // There are a couple of flags left in mPrivateFlags2
2396
2397    /* End of masks for mPrivateFlags2 */
2398
2399    /**
2400     * Masks for mPrivateFlags3, as generated by dumpFlags():
2401     *
2402     * |-------|-------|-------|-------|
2403     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2404     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2405     *                               1   PFLAG3_IS_LAID_OUT
2406     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2407     *                             1     PFLAG3_CALLED_SUPER
2408     *                            1      PFLAG3_APPLYING_INSETS
2409     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2410     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2411     *                         1         PFLAG3_ASSIST_BLOCKED
2412     * |-------|-------|-------|-------|
2413     */
2414
2415    /**
2416     * Flag indicating that view has a transform animation set on it. This is used to track whether
2417     * an animation is cleared between successive frames, in order to tell the associated
2418     * DisplayList to clear its animation matrix.
2419     */
2420    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2421
2422    /**
2423     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2424     * animation is cleared between successive frames, in order to tell the associated
2425     * DisplayList to restore its alpha value.
2426     */
2427    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2428
2429    /**
2430     * Flag indicating that the view has been through at least one layout since it
2431     * was last attached to a window.
2432     */
2433    static final int PFLAG3_IS_LAID_OUT = 0x4;
2434
2435    /**
2436     * Flag indicating that a call to measure() was skipped and should be done
2437     * instead when layout() is invoked.
2438     */
2439    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2440
2441    /**
2442     * Flag indicating that an overridden method correctly called down to
2443     * the superclass implementation as required by the API spec.
2444     */
2445    static final int PFLAG3_CALLED_SUPER = 0x10;
2446
2447    /**
2448     * Flag indicating that we're in the process of applying window insets.
2449     */
2450    static final int PFLAG3_APPLYING_INSETS = 0x20;
2451
2452    /**
2453     * Flag indicating that we're in the process of fitting system windows using the old method.
2454     */
2455    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2456
2457    /**
2458     * Flag indicating that nested scrolling is enabled for this view.
2459     * The view will optionally cooperate with views up its parent chain to allow for
2460     * integrated nested scrolling along the same axis.
2461     */
2462    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2463
2464    /**
2465     * Flag indicating that the bottom scroll indicator should be displayed
2466     * when this view can scroll up.
2467     */
2468    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2469
2470    /**
2471     * Flag indicating that the bottom scroll indicator should be displayed
2472     * when this view can scroll down.
2473     */
2474    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2475
2476    /**
2477     * Flag indicating that the left scroll indicator should be displayed
2478     * when this view can scroll left.
2479     */
2480    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2481
2482    /**
2483     * Flag indicating that the right scroll indicator should be displayed
2484     * when this view can scroll right.
2485     */
2486    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2487
2488    /**
2489     * Flag indicating that the start scroll indicator should be displayed
2490     * when this view can scroll in the start direction.
2491     */
2492    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2493
2494    /**
2495     * Flag indicating that the end scroll indicator should be displayed
2496     * when this view can scroll in the end direction.
2497     */
2498    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2499
2500    /* End of masks for mPrivateFlags3 */
2501
2502    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2503
2504    static final int SCROLL_INDICATORS_NONE = 0x0000;
2505
2506    /**
2507     * Mask for use with setFlags indicating bits used for indicating which
2508     * scroll indicators are enabled.
2509     */
2510    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2511            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2512            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2513            | PFLAG3_SCROLL_INDICATOR_END;
2514
2515    /**
2516     * Left-shift required to translate between public scroll indicator flags
2517     * and internal PFLAGS3 flags. When used as a right-shift, translates
2518     * PFLAGS3 flags to public flags.
2519     */
2520    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2521
2522    /** @hide */
2523    @Retention(RetentionPolicy.SOURCE)
2524    @IntDef(flag = true,
2525            value = {
2526                    SCROLL_INDICATOR_TOP,
2527                    SCROLL_INDICATOR_BOTTOM,
2528                    SCROLL_INDICATOR_LEFT,
2529                    SCROLL_INDICATOR_RIGHT,
2530                    SCROLL_INDICATOR_START,
2531                    SCROLL_INDICATOR_END,
2532            })
2533    public @interface ScrollIndicators {}
2534
2535    /**
2536     * Scroll indicator direction for the top edge of the view.
2537     *
2538     * @see #setScrollIndicators(int)
2539     * @see #setScrollIndicators(int, int)
2540     * @see #getScrollIndicators()
2541     */
2542    public static final int SCROLL_INDICATOR_TOP =
2543            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2544
2545    /**
2546     * Scroll indicator direction for the bottom edge of the view.
2547     *
2548     * @see #setScrollIndicators(int)
2549     * @see #setScrollIndicators(int, int)
2550     * @see #getScrollIndicators()
2551     */
2552    public static final int SCROLL_INDICATOR_BOTTOM =
2553            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2554
2555    /**
2556     * Scroll indicator direction for the left edge of the view.
2557     *
2558     * @see #setScrollIndicators(int)
2559     * @see #setScrollIndicators(int, int)
2560     * @see #getScrollIndicators()
2561     */
2562    public static final int SCROLL_INDICATOR_LEFT =
2563            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2564
2565    /**
2566     * Scroll indicator direction for the right edge of the view.
2567     *
2568     * @see #setScrollIndicators(int)
2569     * @see #setScrollIndicators(int, int)
2570     * @see #getScrollIndicators()
2571     */
2572    public static final int SCROLL_INDICATOR_RIGHT =
2573            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2574
2575    /**
2576     * Scroll indicator direction for the starting edge of the view.
2577     * <p>
2578     * Resolved according to the view's layout direction, see
2579     * {@link #getLayoutDirection()} for more information.
2580     *
2581     * @see #setScrollIndicators(int)
2582     * @see #setScrollIndicators(int, int)
2583     * @see #getScrollIndicators()
2584     */
2585    public static final int SCROLL_INDICATOR_START =
2586            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2587
2588    /**
2589     * Scroll indicator direction for the ending edge of the view.
2590     * <p>
2591     * Resolved according to the view's layout direction, see
2592     * {@link #getLayoutDirection()} for more information.
2593     *
2594     * @see #setScrollIndicators(int)
2595     * @see #setScrollIndicators(int, int)
2596     * @see #getScrollIndicators()
2597     */
2598    public static final int SCROLL_INDICATOR_END =
2599            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2600
2601    /**
2602     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2603     * into this view.<p>
2604     */
2605    static final int PFLAG3_ASSIST_BLOCKED = 0x100;
2606
2607    /**
2608     * Always allow a user to over-scroll this view, provided it is a
2609     * view that can scroll.
2610     *
2611     * @see #getOverScrollMode()
2612     * @see #setOverScrollMode(int)
2613     */
2614    public static final int OVER_SCROLL_ALWAYS = 0;
2615
2616    /**
2617     * Allow a user to over-scroll this view only if the content is large
2618     * enough to meaningfully scroll, provided it is a view that can scroll.
2619     *
2620     * @see #getOverScrollMode()
2621     * @see #setOverScrollMode(int)
2622     */
2623    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2624
2625    /**
2626     * Never allow a user to over-scroll this view.
2627     *
2628     * @see #getOverScrollMode()
2629     * @see #setOverScrollMode(int)
2630     */
2631    public static final int OVER_SCROLL_NEVER = 2;
2632
2633    /**
2634     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2635     * requested the system UI (status bar) to be visible (the default).
2636     *
2637     * @see #setSystemUiVisibility(int)
2638     */
2639    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2640
2641    /**
2642     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2643     * system UI to enter an unobtrusive "low profile" mode.
2644     *
2645     * <p>This is for use in games, book readers, video players, or any other
2646     * "immersive" application where the usual system chrome is deemed too distracting.
2647     *
2648     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2649     *
2650     * @see #setSystemUiVisibility(int)
2651     */
2652    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2653
2654    /**
2655     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2656     * system navigation be temporarily hidden.
2657     *
2658     * <p>This is an even less obtrusive state than that called for by
2659     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2660     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2661     * those to disappear. This is useful (in conjunction with the
2662     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2663     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2664     * window flags) for displaying content using every last pixel on the display.
2665     *
2666     * <p>There is a limitation: because navigation controls are so important, the least user
2667     * interaction will cause them to reappear immediately.  When this happens, both
2668     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2669     * so that both elements reappear at the same time.
2670     *
2671     * @see #setSystemUiVisibility(int)
2672     */
2673    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2674
2675    /**
2676     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2677     * into the normal fullscreen mode so that its content can take over the screen
2678     * while still allowing the user to interact with the application.
2679     *
2680     * <p>This has the same visual effect as
2681     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2682     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2683     * meaning that non-critical screen decorations (such as the status bar) will be
2684     * hidden while the user is in the View's window, focusing the experience on
2685     * that content.  Unlike the window flag, if you are using ActionBar in
2686     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2687     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2688     * hide the action bar.
2689     *
2690     * <p>This approach to going fullscreen is best used over the window flag when
2691     * it is a transient state -- that is, the application does this at certain
2692     * points in its user interaction where it wants to allow the user to focus
2693     * on content, but not as a continuous state.  For situations where the application
2694     * would like to simply stay full screen the entire time (such as a game that
2695     * wants to take over the screen), the
2696     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2697     * is usually a better approach.  The state set here will be removed by the system
2698     * in various situations (such as the user moving to another application) like
2699     * the other system UI states.
2700     *
2701     * <p>When using this flag, the application should provide some easy facility
2702     * for the user to go out of it.  A common example would be in an e-book
2703     * reader, where tapping on the screen brings back whatever screen and UI
2704     * decorations that had been hidden while the user was immersed in reading
2705     * the book.
2706     *
2707     * @see #setSystemUiVisibility(int)
2708     */
2709    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2710
2711    /**
2712     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2713     * flags, we would like a stable view of the content insets given to
2714     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2715     * will always represent the worst case that the application can expect
2716     * as a continuous state.  In the stock Android UI this is the space for
2717     * the system bar, nav bar, and status bar, but not more transient elements
2718     * such as an input method.
2719     *
2720     * The stable layout your UI sees is based on the system UI modes you can
2721     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2722     * then you will get a stable layout for changes of the
2723     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2724     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2725     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2726     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2727     * with a stable layout.  (Note that you should avoid using
2728     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2729     *
2730     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2731     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2732     * then a hidden status bar will be considered a "stable" state for purposes
2733     * here.  This allows your UI to continually hide the status bar, while still
2734     * using the system UI flags to hide the action bar while still retaining
2735     * a stable layout.  Note that changing the window fullscreen flag will never
2736     * provide a stable layout for a clean transition.
2737     *
2738     * <p>If you are using ActionBar in
2739     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2740     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2741     * insets it adds to those given to the application.
2742     */
2743    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2744
2745    /**
2746     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2747     * to be laid out as if it has requested
2748     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2749     * allows it to avoid artifacts when switching in and out of that mode, at
2750     * the expense that some of its user interface may be covered by screen
2751     * decorations when they are shown.  You can perform layout of your inner
2752     * UI elements to account for the navigation system UI through the
2753     * {@link #fitSystemWindows(Rect)} method.
2754     */
2755    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2756
2757    /**
2758     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2759     * to be laid out as if it has requested
2760     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2761     * allows it to avoid artifacts when switching in and out of that mode, at
2762     * the expense that some of its user interface may be covered by screen
2763     * decorations when they are shown.  You can perform layout of your inner
2764     * UI elements to account for non-fullscreen system UI through the
2765     * {@link #fitSystemWindows(Rect)} method.
2766     */
2767    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2768
2769    /**
2770     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2771     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2772     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2773     * user interaction.
2774     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2775     * has an effect when used in combination with that flag.</p>
2776     */
2777    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2778
2779    /**
2780     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2781     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2782     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2783     * experience while also hiding the system bars.  If this flag is not set,
2784     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2785     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2786     * if the user swipes from the top of the screen.
2787     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2788     * system gestures, such as swiping from the top of the screen.  These transient system bars
2789     * will overlay app’s content, may have some degree of transparency, and will automatically
2790     * hide after a short timeout.
2791     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2792     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2793     * with one or both of those flags.</p>
2794     */
2795    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2796
2797    /**
2798     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2799     * is compatible with light status bar backgrounds.
2800     *
2801     * <p>For this to take effect, the window must request
2802     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2803     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2804     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2805     *         FLAG_TRANSLUCENT_STATUS}.
2806     *
2807     * @see android.R.attr#windowLightStatusBar
2808     */
2809    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2810
2811    /**
2812     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2813     */
2814    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2815
2816    /**
2817     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2818     */
2819    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2820
2821    /**
2822     * @hide
2823     *
2824     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2825     * out of the public fields to keep the undefined bits out of the developer's way.
2826     *
2827     * Flag to make the status bar not expandable.  Unless you also
2828     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2829     */
2830    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2831
2832    /**
2833     * @hide
2834     *
2835     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2836     * out of the public fields to keep the undefined bits out of the developer's way.
2837     *
2838     * Flag to hide notification icons and scrolling ticker text.
2839     */
2840    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2841
2842    /**
2843     * @hide
2844     *
2845     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2846     * out of the public fields to keep the undefined bits out of the developer's way.
2847     *
2848     * Flag to disable incoming notification alerts.  This will not block
2849     * icons, but it will block sound, vibrating and other visual or aural notifications.
2850     */
2851    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2852
2853    /**
2854     * @hide
2855     *
2856     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2857     * out of the public fields to keep the undefined bits out of the developer's way.
2858     *
2859     * Flag to hide only the scrolling ticker.  Note that
2860     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2861     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2862     */
2863    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2864
2865    /**
2866     * @hide
2867     *
2868     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2869     * out of the public fields to keep the undefined bits out of the developer's way.
2870     *
2871     * Flag to hide the center system info area.
2872     */
2873    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2874
2875    /**
2876     * @hide
2877     *
2878     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2879     * out of the public fields to keep the undefined bits out of the developer's way.
2880     *
2881     * Flag to hide only the home button.  Don't use this
2882     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2883     */
2884    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2885
2886    /**
2887     * @hide
2888     *
2889     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2890     * out of the public fields to keep the undefined bits out of the developer's way.
2891     *
2892     * Flag to hide only the back button. Don't use this
2893     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2894     */
2895    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2896
2897    /**
2898     * @hide
2899     *
2900     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2901     * out of the public fields to keep the undefined bits out of the developer's way.
2902     *
2903     * Flag to hide only the clock.  You might use this if your activity has
2904     * its own clock making the status bar's clock redundant.
2905     */
2906    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2907
2908    /**
2909     * @hide
2910     *
2911     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2912     * out of the public fields to keep the undefined bits out of the developer's way.
2913     *
2914     * Flag to hide only the recent apps button. Don't use this
2915     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2916     */
2917    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2918
2919    /**
2920     * @hide
2921     *
2922     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2923     * out of the public fields to keep the undefined bits out of the developer's way.
2924     *
2925     * Flag to disable the global search gesture. Don't use this
2926     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2927     */
2928    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2929
2930    /**
2931     * @hide
2932     *
2933     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2934     * out of the public fields to keep the undefined bits out of the developer's way.
2935     *
2936     * Flag to specify that the status bar is displayed in transient mode.
2937     */
2938    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2939
2940    /**
2941     * @hide
2942     *
2943     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2944     * out of the public fields to keep the undefined bits out of the developer's way.
2945     *
2946     * Flag to specify that the navigation bar is displayed in transient mode.
2947     */
2948    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2949
2950    /**
2951     * @hide
2952     *
2953     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2954     * out of the public fields to keep the undefined bits out of the developer's way.
2955     *
2956     * Flag to specify that the hidden status bar would like to be shown.
2957     */
2958    public static final int STATUS_BAR_UNHIDE = 0x10000000;
2959
2960    /**
2961     * @hide
2962     *
2963     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2964     * out of the public fields to keep the undefined bits out of the developer's way.
2965     *
2966     * Flag to specify that the hidden navigation bar would like to be shown.
2967     */
2968    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2969
2970    /**
2971     * @hide
2972     *
2973     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2974     * out of the public fields to keep the undefined bits out of the developer's way.
2975     *
2976     * Flag to specify that the status bar is displayed in translucent mode.
2977     */
2978    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2979
2980    /**
2981     * @hide
2982     *
2983     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2984     * out of the public fields to keep the undefined bits out of the developer's way.
2985     *
2986     * Flag to specify that the navigation bar is displayed in translucent mode.
2987     */
2988    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2989
2990    /**
2991     * @hide
2992     *
2993     * Whether Recents is visible or not.
2994     */
2995    public static final int RECENT_APPS_VISIBLE = 0x00004000;
2996
2997    /**
2998     * @hide
2999     *
3000     * Makes system ui transparent.
3001     */
3002    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
3003
3004    /**
3005     * @hide
3006     */
3007    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
3008
3009    /**
3010     * These are the system UI flags that can be cleared by events outside
3011     * of an application.  Currently this is just the ability to tap on the
3012     * screen while hiding the navigation bar to have it return.
3013     * @hide
3014     */
3015    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3016            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3017            | SYSTEM_UI_FLAG_FULLSCREEN;
3018
3019    /**
3020     * Flags that can impact the layout in relation to system UI.
3021     */
3022    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3023            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3024            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3025
3026    /** @hide */
3027    @IntDef(flag = true,
3028            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3029    @Retention(RetentionPolicy.SOURCE)
3030    public @interface FindViewFlags {}
3031
3032    /**
3033     * Find views that render the specified text.
3034     *
3035     * @see #findViewsWithText(ArrayList, CharSequence, int)
3036     */
3037    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3038
3039    /**
3040     * Find find views that contain the specified content description.
3041     *
3042     * @see #findViewsWithText(ArrayList, CharSequence, int)
3043     */
3044    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3045
3046    /**
3047     * Find views that contain {@link AccessibilityNodeProvider}. Such
3048     * a View is a root of virtual view hierarchy and may contain the searched
3049     * text. If this flag is set Views with providers are automatically
3050     * added and it is a responsibility of the client to call the APIs of
3051     * the provider to determine whether the virtual tree rooted at this View
3052     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3053     * representing the virtual views with this text.
3054     *
3055     * @see #findViewsWithText(ArrayList, CharSequence, int)
3056     *
3057     * @hide
3058     */
3059    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3060
3061    /**
3062     * The undefined cursor position.
3063     *
3064     * @hide
3065     */
3066    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3067
3068    /**
3069     * Indicates that the screen has changed state and is now off.
3070     *
3071     * @see #onScreenStateChanged(int)
3072     */
3073    public static final int SCREEN_STATE_OFF = 0x0;
3074
3075    /**
3076     * Indicates that the screen has changed state and is now on.
3077     *
3078     * @see #onScreenStateChanged(int)
3079     */
3080    public static final int SCREEN_STATE_ON = 0x1;
3081
3082    /**
3083     * Indicates no axis of view scrolling.
3084     */
3085    public static final int SCROLL_AXIS_NONE = 0;
3086
3087    /**
3088     * Indicates scrolling along the horizontal axis.
3089     */
3090    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3091
3092    /**
3093     * Indicates scrolling along the vertical axis.
3094     */
3095    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3096
3097    /**
3098     * Controls the over-scroll mode for this view.
3099     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3100     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3101     * and {@link #OVER_SCROLL_NEVER}.
3102     */
3103    private int mOverScrollMode;
3104
3105    /**
3106     * The parent this view is attached to.
3107     * {@hide}
3108     *
3109     * @see #getParent()
3110     */
3111    protected ViewParent mParent;
3112
3113    /**
3114     * {@hide}
3115     */
3116    AttachInfo mAttachInfo;
3117
3118    /**
3119     * {@hide}
3120     */
3121    @ViewDebug.ExportedProperty(flagMapping = {
3122        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3123                name = "FORCE_LAYOUT"),
3124        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3125                name = "LAYOUT_REQUIRED"),
3126        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3127            name = "DRAWING_CACHE_INVALID", outputIf = false),
3128        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3129        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3130        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3131        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3132    }, formatToHexString = true)
3133    int mPrivateFlags;
3134    int mPrivateFlags2;
3135    int mPrivateFlags3;
3136
3137    /**
3138     * This view's request for the visibility of the status bar.
3139     * @hide
3140     */
3141    @ViewDebug.ExportedProperty(flagMapping = {
3142        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3143                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3144                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3145        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3146                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3147                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3148        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3149                                equals = SYSTEM_UI_FLAG_VISIBLE,
3150                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3151    }, formatToHexString = true)
3152    int mSystemUiVisibility;
3153
3154    /**
3155     * Reference count for transient state.
3156     * @see #setHasTransientState(boolean)
3157     */
3158    int mTransientStateCount = 0;
3159
3160    /**
3161     * Count of how many windows this view has been attached to.
3162     */
3163    int mWindowAttachCount;
3164
3165    /**
3166     * The layout parameters associated with this view and used by the parent
3167     * {@link android.view.ViewGroup} to determine how this view should be
3168     * laid out.
3169     * {@hide}
3170     */
3171    protected ViewGroup.LayoutParams mLayoutParams;
3172
3173    /**
3174     * The view flags hold various views states.
3175     * {@hide}
3176     */
3177    @ViewDebug.ExportedProperty(formatToHexString = true)
3178    int mViewFlags;
3179
3180    static class TransformationInfo {
3181        /**
3182         * The transform matrix for the View. This transform is calculated internally
3183         * based on the translation, rotation, and scale properties.
3184         *
3185         * Do *not* use this variable directly; instead call getMatrix(), which will
3186         * load the value from the View's RenderNode.
3187         */
3188        private final Matrix mMatrix = new Matrix();
3189
3190        /**
3191         * The inverse transform matrix for the View. This transform is calculated
3192         * internally based on the translation, rotation, and scale properties.
3193         *
3194         * Do *not* use this variable directly; instead call getInverseMatrix(),
3195         * which will load the value from the View's RenderNode.
3196         */
3197        private Matrix mInverseMatrix;
3198
3199        /**
3200         * The opacity of the View. This is a value from 0 to 1, where 0 means
3201         * completely transparent and 1 means completely opaque.
3202         */
3203        @ViewDebug.ExportedProperty
3204        float mAlpha = 1f;
3205
3206        /**
3207         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3208         * property only used by transitions, which is composited with the other alpha
3209         * values to calculate the final visual alpha value.
3210         */
3211        float mTransitionAlpha = 1f;
3212    }
3213
3214    TransformationInfo mTransformationInfo;
3215
3216    /**
3217     * Current clip bounds. to which all drawing of this view are constrained.
3218     */
3219    Rect mClipBounds = null;
3220
3221    private boolean mLastIsOpaque;
3222
3223    /**
3224     * The distance in pixels from the left edge of this view's parent
3225     * to the left edge of this view.
3226     * {@hide}
3227     */
3228    @ViewDebug.ExportedProperty(category = "layout")
3229    protected int mLeft;
3230    /**
3231     * The distance in pixels from the left edge of this view's parent
3232     * to the right edge of this view.
3233     * {@hide}
3234     */
3235    @ViewDebug.ExportedProperty(category = "layout")
3236    protected int mRight;
3237    /**
3238     * The distance in pixels from the top edge of this view's parent
3239     * to the top edge of this view.
3240     * {@hide}
3241     */
3242    @ViewDebug.ExportedProperty(category = "layout")
3243    protected int mTop;
3244    /**
3245     * The distance in pixels from the top edge of this view's parent
3246     * to the bottom edge of this view.
3247     * {@hide}
3248     */
3249    @ViewDebug.ExportedProperty(category = "layout")
3250    protected int mBottom;
3251
3252    /**
3253     * The offset, in pixels, by which the content of this view is scrolled
3254     * horizontally.
3255     * {@hide}
3256     */
3257    @ViewDebug.ExportedProperty(category = "scrolling")
3258    protected int mScrollX;
3259    /**
3260     * The offset, in pixels, by which the content of this view is scrolled
3261     * vertically.
3262     * {@hide}
3263     */
3264    @ViewDebug.ExportedProperty(category = "scrolling")
3265    protected int mScrollY;
3266
3267    /**
3268     * The left padding in pixels, that is the distance in pixels between the
3269     * left edge of this view and the left edge of its content.
3270     * {@hide}
3271     */
3272    @ViewDebug.ExportedProperty(category = "padding")
3273    protected int mPaddingLeft = 0;
3274    /**
3275     * The right padding in pixels, that is the distance in pixels between the
3276     * right edge of this view and the right edge of its content.
3277     * {@hide}
3278     */
3279    @ViewDebug.ExportedProperty(category = "padding")
3280    protected int mPaddingRight = 0;
3281    /**
3282     * The top padding in pixels, that is the distance in pixels between the
3283     * top edge of this view and the top edge of its content.
3284     * {@hide}
3285     */
3286    @ViewDebug.ExportedProperty(category = "padding")
3287    protected int mPaddingTop;
3288    /**
3289     * The bottom padding in pixels, that is the distance in pixels between the
3290     * bottom edge of this view and the bottom edge of its content.
3291     * {@hide}
3292     */
3293    @ViewDebug.ExportedProperty(category = "padding")
3294    protected int mPaddingBottom;
3295
3296    /**
3297     * The layout insets in pixels, that is the distance in pixels between the
3298     * visible edges of this view its bounds.
3299     */
3300    private Insets mLayoutInsets;
3301
3302    /**
3303     * Briefly describes the view and is primarily used for accessibility support.
3304     */
3305    private CharSequence mContentDescription;
3306
3307    /**
3308     * Specifies the id of a view for which this view serves as a label for
3309     * accessibility purposes.
3310     */
3311    private int mLabelForId = View.NO_ID;
3312
3313    /**
3314     * Predicate for matching labeled view id with its label for
3315     * accessibility purposes.
3316     */
3317    private MatchLabelForPredicate mMatchLabelForPredicate;
3318
3319    /**
3320     * Specifies a view before which this one is visited in accessibility traversal.
3321     */
3322    private int mAccessibilityTraversalBeforeId = NO_ID;
3323
3324    /**
3325     * Specifies a view after which this one is visited in accessibility traversal.
3326     */
3327    private int mAccessibilityTraversalAfterId = NO_ID;
3328
3329    /**
3330     * Predicate for matching a view by its id.
3331     */
3332    private MatchIdPredicate mMatchIdPredicate;
3333
3334    /**
3335     * Cache the paddingRight set by the user to append to the scrollbar's size.
3336     *
3337     * @hide
3338     */
3339    @ViewDebug.ExportedProperty(category = "padding")
3340    protected int mUserPaddingRight;
3341
3342    /**
3343     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3344     *
3345     * @hide
3346     */
3347    @ViewDebug.ExportedProperty(category = "padding")
3348    protected int mUserPaddingBottom;
3349
3350    /**
3351     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3352     *
3353     * @hide
3354     */
3355    @ViewDebug.ExportedProperty(category = "padding")
3356    protected int mUserPaddingLeft;
3357
3358    /**
3359     * Cache the paddingStart set by the user to append to the scrollbar's size.
3360     *
3361     */
3362    @ViewDebug.ExportedProperty(category = "padding")
3363    int mUserPaddingStart;
3364
3365    /**
3366     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3367     *
3368     */
3369    @ViewDebug.ExportedProperty(category = "padding")
3370    int mUserPaddingEnd;
3371
3372    /**
3373     * Cache initial left padding.
3374     *
3375     * @hide
3376     */
3377    int mUserPaddingLeftInitial;
3378
3379    /**
3380     * Cache initial right padding.
3381     *
3382     * @hide
3383     */
3384    int mUserPaddingRightInitial;
3385
3386    /**
3387     * Default undefined padding
3388     */
3389    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3390
3391    /**
3392     * Cache if a left padding has been defined
3393     */
3394    private boolean mLeftPaddingDefined = false;
3395
3396    /**
3397     * Cache if a right padding has been defined
3398     */
3399    private boolean mRightPaddingDefined = false;
3400
3401    /**
3402     * @hide
3403     */
3404    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3405    /**
3406     * @hide
3407     */
3408    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3409
3410    private LongSparseLongArray mMeasureCache;
3411
3412    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3413    private Drawable mBackground;
3414    private TintInfo mBackgroundTint;
3415
3416    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3417    private ForegroundInfo mForegroundInfo;
3418
3419    private Drawable mScrollIndicatorDrawable;
3420
3421    /**
3422     * RenderNode used for backgrounds.
3423     * <p>
3424     * When non-null and valid, this is expected to contain an up-to-date copy
3425     * of the background drawable. It is cleared on temporary detach, and reset
3426     * on cleanup.
3427     */
3428    private RenderNode mBackgroundRenderNode;
3429
3430    private int mBackgroundResource;
3431    private boolean mBackgroundSizeChanged;
3432
3433    private String mTransitionName;
3434
3435    static class TintInfo {
3436        ColorStateList mTintList;
3437        PorterDuff.Mode mTintMode;
3438        boolean mHasTintMode;
3439        boolean mHasTintList;
3440    }
3441
3442    private static class ForegroundInfo {
3443        private Drawable mDrawable;
3444        private TintInfo mTintInfo;
3445        private int mGravity = Gravity.FILL;
3446        private boolean mInsidePadding = true;
3447        private boolean mBoundsChanged = true;
3448        private final Rect mSelfBounds = new Rect();
3449        private final Rect mOverlayBounds = new Rect();
3450    }
3451
3452    static class ListenerInfo {
3453        /**
3454         * Listener used to dispatch focus change events.
3455         * This field should be made private, so it is hidden from the SDK.
3456         * {@hide}
3457         */
3458        protected OnFocusChangeListener mOnFocusChangeListener;
3459
3460        /**
3461         * Listeners for layout change events.
3462         */
3463        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3464
3465        protected OnScrollChangeListener mOnScrollChangeListener;
3466
3467        /**
3468         * Listeners for attach events.
3469         */
3470        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3471
3472        /**
3473         * Listener used to dispatch click events.
3474         * This field should be made private, so it is hidden from the SDK.
3475         * {@hide}
3476         */
3477        public OnClickListener mOnClickListener;
3478
3479        /**
3480         * Listener used to dispatch long click events.
3481         * This field should be made private, so it is hidden from the SDK.
3482         * {@hide}
3483         */
3484        protected OnLongClickListener mOnLongClickListener;
3485
3486        /**
3487         * Listener used to dispatch context click events. This field should be made private, so it
3488         * is hidden from the SDK.
3489         * {@hide}
3490         */
3491        protected OnContextClickListener mOnContextClickListener;
3492
3493        /**
3494         * Listener used to build the context menu.
3495         * This field should be made private, so it is hidden from the SDK.
3496         * {@hide}
3497         */
3498        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3499
3500        private OnKeyListener mOnKeyListener;
3501
3502        private OnTouchListener mOnTouchListener;
3503
3504        private OnHoverListener mOnHoverListener;
3505
3506        private OnGenericMotionListener mOnGenericMotionListener;
3507
3508        private OnDragListener mOnDragListener;
3509
3510        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3511
3512        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3513    }
3514
3515    ListenerInfo mListenerInfo;
3516
3517    /**
3518     * The application environment this view lives in.
3519     * This field should be made private, so it is hidden from the SDK.
3520     * {@hide}
3521     */
3522    @ViewDebug.ExportedProperty(deepExport = true)
3523    protected Context mContext;
3524
3525    private final Resources mResources;
3526
3527    private ScrollabilityCache mScrollCache;
3528
3529    private int[] mDrawableState = null;
3530
3531    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3532
3533    /**
3534     * Animator that automatically runs based on state changes.
3535     */
3536    private StateListAnimator mStateListAnimator;
3537
3538    /**
3539     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3540     * the user may specify which view to go to next.
3541     */
3542    private int mNextFocusLeftId = View.NO_ID;
3543
3544    /**
3545     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3546     * the user may specify which view to go to next.
3547     */
3548    private int mNextFocusRightId = View.NO_ID;
3549
3550    /**
3551     * When this view has focus and the next focus is {@link #FOCUS_UP},
3552     * the user may specify which view to go to next.
3553     */
3554    private int mNextFocusUpId = View.NO_ID;
3555
3556    /**
3557     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3558     * the user may specify which view to go to next.
3559     */
3560    private int mNextFocusDownId = View.NO_ID;
3561
3562    /**
3563     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3564     * the user may specify which view to go to next.
3565     */
3566    int mNextFocusForwardId = View.NO_ID;
3567
3568    private CheckForLongPress mPendingCheckForLongPress;
3569    private CheckForTap mPendingCheckForTap = null;
3570    private PerformClick mPerformClick;
3571    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3572
3573    private UnsetPressedState mUnsetPressedState;
3574
3575    /**
3576     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3577     * up event while a long press is invoked as soon as the long press duration is reached, so
3578     * a long press could be performed before the tap is checked, in which case the tap's action
3579     * should not be invoked.
3580     */
3581    private boolean mHasPerformedLongPress;
3582
3583    /**
3584     * Whether a context click button is currently pressed down. This is true when the stylus is
3585     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3586     * pressed. This is false once the button is released or if the stylus has been lifted.
3587     */
3588    private boolean mInContextButtonPress;
3589
3590    /**
3591     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3592     * true after a stylus button press has occured, when the next up event should not be recognized
3593     * as a tap.
3594     */
3595    private boolean mIgnoreNextUpEvent;
3596
3597    /**
3598     * The minimum height of the view. We'll try our best to have the height
3599     * of this view to at least this amount.
3600     */
3601    @ViewDebug.ExportedProperty(category = "measurement")
3602    private int mMinHeight;
3603
3604    /**
3605     * The minimum width of the view. We'll try our best to have the width
3606     * of this view to at least this amount.
3607     */
3608    @ViewDebug.ExportedProperty(category = "measurement")
3609    private int mMinWidth;
3610
3611    /**
3612     * The delegate to handle touch events that are physically in this view
3613     * but should be handled by another view.
3614     */
3615    private TouchDelegate mTouchDelegate = null;
3616
3617    /**
3618     * Solid color to use as a background when creating the drawing cache. Enables
3619     * the cache to use 16 bit bitmaps instead of 32 bit.
3620     */
3621    private int mDrawingCacheBackgroundColor = 0;
3622
3623    /**
3624     * Special tree observer used when mAttachInfo is null.
3625     */
3626    private ViewTreeObserver mFloatingTreeObserver;
3627
3628    /**
3629     * Cache the touch slop from the context that created the view.
3630     */
3631    private int mTouchSlop;
3632
3633    /**
3634     * Object that handles automatic animation of view properties.
3635     */
3636    private ViewPropertyAnimator mAnimator = null;
3637
3638    /**
3639     * Flag indicating that a drag can cross window boundaries.  When
3640     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3641     * with this flag set, all visible applications will be able to participate
3642     * in the drag operation and receive the dragged content.
3643     *
3644     * @hide
3645     */
3646    public static final int DRAG_FLAG_GLOBAL = 1;
3647
3648    /**
3649     * Flag indicating that the drag shadow will be opaque.  When
3650     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3651     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3652     */
3653    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3654
3655    /**
3656     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3657     */
3658    private float mVerticalScrollFactor;
3659
3660    /**
3661     * Position of the vertical scroll bar.
3662     */
3663    private int mVerticalScrollbarPosition;
3664
3665    /**
3666     * Position the scroll bar at the default position as determined by the system.
3667     */
3668    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3669
3670    /**
3671     * Position the scroll bar along the left edge.
3672     */
3673    public static final int SCROLLBAR_POSITION_LEFT = 1;
3674
3675    /**
3676     * Position the scroll bar along the right edge.
3677     */
3678    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3679
3680    /**
3681     * Indicates that the view does not have a layer.
3682     *
3683     * @see #getLayerType()
3684     * @see #setLayerType(int, android.graphics.Paint)
3685     * @see #LAYER_TYPE_SOFTWARE
3686     * @see #LAYER_TYPE_HARDWARE
3687     */
3688    public static final int LAYER_TYPE_NONE = 0;
3689
3690    /**
3691     * <p>Indicates that the view has a software layer. A software layer is backed
3692     * by a bitmap and causes the view to be rendered using Android's software
3693     * rendering pipeline, even if hardware acceleration is enabled.</p>
3694     *
3695     * <p>Software layers have various usages:</p>
3696     * <p>When the application is not using hardware acceleration, a software layer
3697     * is useful to apply a specific color filter and/or blending mode and/or
3698     * translucency to a view and all its children.</p>
3699     * <p>When the application is using hardware acceleration, a software layer
3700     * is useful to render drawing primitives not supported by the hardware
3701     * accelerated pipeline. It can also be used to cache a complex view tree
3702     * into a texture and reduce the complexity of drawing operations. For instance,
3703     * when animating a complex view tree with a translation, a software layer can
3704     * be used to render the view tree only once.</p>
3705     * <p>Software layers should be avoided when the affected view tree updates
3706     * often. Every update will require to re-render the software layer, which can
3707     * potentially be slow (particularly when hardware acceleration is turned on
3708     * since the layer will have to be uploaded into a hardware texture after every
3709     * update.)</p>
3710     *
3711     * @see #getLayerType()
3712     * @see #setLayerType(int, android.graphics.Paint)
3713     * @see #LAYER_TYPE_NONE
3714     * @see #LAYER_TYPE_HARDWARE
3715     */
3716    public static final int LAYER_TYPE_SOFTWARE = 1;
3717
3718    /**
3719     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3720     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3721     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3722     * rendering pipeline, but only if hardware acceleration is turned on for the
3723     * view hierarchy. When hardware acceleration is turned off, hardware layers
3724     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3725     *
3726     * <p>A hardware layer is useful to apply a specific color filter and/or
3727     * blending mode and/or translucency to a view and all its children.</p>
3728     * <p>A hardware layer can be used to cache a complex view tree into a
3729     * texture and reduce the complexity of drawing operations. For instance,
3730     * when animating a complex view tree with a translation, a hardware layer can
3731     * be used to render the view tree only once.</p>
3732     * <p>A hardware layer can also be used to increase the rendering quality when
3733     * rotation transformations are applied on a view. It can also be used to
3734     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3735     *
3736     * @see #getLayerType()
3737     * @see #setLayerType(int, android.graphics.Paint)
3738     * @see #LAYER_TYPE_NONE
3739     * @see #LAYER_TYPE_SOFTWARE
3740     */
3741    public static final int LAYER_TYPE_HARDWARE = 2;
3742
3743    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3744            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3745            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3746            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3747    })
3748    int mLayerType = LAYER_TYPE_NONE;
3749    Paint mLayerPaint;
3750
3751    /**
3752     * Set to true when drawing cache is enabled and cannot be created.
3753     *
3754     * @hide
3755     */
3756    public boolean mCachingFailed;
3757    private Bitmap mDrawingCache;
3758    private Bitmap mUnscaledDrawingCache;
3759
3760    /**
3761     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3762     * <p>
3763     * When non-null and valid, this is expected to contain an up-to-date copy
3764     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3765     * cleanup.
3766     */
3767    final RenderNode mRenderNode;
3768
3769    /**
3770     * Set to true when the view is sending hover accessibility events because it
3771     * is the innermost hovered view.
3772     */
3773    private boolean mSendingHoverAccessibilityEvents;
3774
3775    /**
3776     * Delegate for injecting accessibility functionality.
3777     */
3778    AccessibilityDelegate mAccessibilityDelegate;
3779
3780    /**
3781     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3782     * and add/remove objects to/from the overlay directly through the Overlay methods.
3783     */
3784    ViewOverlay mOverlay;
3785
3786    /**
3787     * The currently active parent view for receiving delegated nested scrolling events.
3788     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3789     * by {@link #stopNestedScroll()} at the same point where we clear
3790     * requestDisallowInterceptTouchEvent.
3791     */
3792    private ViewParent mNestedScrollingParent;
3793
3794    /**
3795     * Consistency verifier for debugging purposes.
3796     * @hide
3797     */
3798    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3799            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3800                    new InputEventConsistencyVerifier(this, 0) : null;
3801
3802    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3803
3804    private int[] mTempNestedScrollConsumed;
3805
3806    /**
3807     * An overlay is going to draw this View instead of being drawn as part of this
3808     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3809     * when this view is invalidated.
3810     */
3811    GhostView mGhostView;
3812
3813    /**
3814     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3815     * @hide
3816     */
3817    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3818    public String[] mAttributes;
3819
3820    /**
3821     * Maps a Resource id to its name.
3822     */
3823    private static SparseArray<String> mAttributeMap;
3824
3825    /**
3826     * Queue of pending runnables. Used to postpone calls to post() until this
3827     * view is attached and has a handler.
3828     */
3829    private HandlerActionQueue mRunQueue;
3830
3831    /**
3832     * @hide
3833     */
3834    String mStartActivityRequestWho;
3835
3836    /**
3837     * Simple constructor to use when creating a view from code.
3838     *
3839     * @param context The Context the view is running in, through which it can
3840     *        access the current theme, resources, etc.
3841     */
3842    public View(Context context) {
3843        mContext = context;
3844        mResources = context != null ? context.getResources() : null;
3845        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3846        // Set some flags defaults
3847        mPrivateFlags2 =
3848                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3849                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3850                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3851                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3852                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3853                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3854        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3855        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3856        mUserPaddingStart = UNDEFINED_PADDING;
3857        mUserPaddingEnd = UNDEFINED_PADDING;
3858        mRenderNode = RenderNode.create(getClass().getName(), this);
3859
3860        if (!sCompatibilityDone && context != null) {
3861            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3862
3863            // Older apps may need this compatibility hack for measurement.
3864            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3865
3866            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3867            // of whether a layout was requested on that View.
3868            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3869
3870            Canvas.sCompatibilityRestore = targetSdkVersion < M;
3871
3872            // In M and newer, our widgets can pass a "hint" value in the size
3873            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
3874            // know what the expected parent size is going to be, so e.g. list items can size
3875            // themselves at 1/3 the size of their container. It breaks older apps though,
3876            // specifically apps that use some popular open source libraries.
3877            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
3878
3879            // Old versions of the platform would give different results from
3880            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
3881            // modes, so we always need to run an additional EXACTLY pass.
3882            sAlwaysRemeasureExactly = targetSdkVersion <= M;
3883
3884            sCompatibilityDone = true;
3885        }
3886    }
3887
3888    /**
3889     * Constructor that is called when inflating a view from XML. This is called
3890     * when a view is being constructed from an XML file, supplying attributes
3891     * that were specified in the XML file. This version uses a default style of
3892     * 0, so the only attribute values applied are those in the Context's Theme
3893     * and the given AttributeSet.
3894     *
3895     * <p>
3896     * The method onFinishInflate() will be called after all children have been
3897     * added.
3898     *
3899     * @param context The Context the view is running in, through which it can
3900     *        access the current theme, resources, etc.
3901     * @param attrs The attributes of the XML tag that is inflating the view.
3902     * @see #View(Context, AttributeSet, int)
3903     */
3904    public View(Context context, @Nullable AttributeSet attrs) {
3905        this(context, attrs, 0);
3906    }
3907
3908    /**
3909     * Perform inflation from XML and apply a class-specific base style from a
3910     * theme attribute. This constructor of View allows subclasses to use their
3911     * own base style when they are inflating. For example, a Button class's
3912     * constructor would call this version of the super class constructor and
3913     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3914     * allows the theme's button style to modify all of the base view attributes
3915     * (in particular its background) as well as the Button class's attributes.
3916     *
3917     * @param context The Context the view is running in, through which it can
3918     *        access the current theme, resources, etc.
3919     * @param attrs The attributes of the XML tag that is inflating the view.
3920     * @param defStyleAttr An attribute in the current theme that contains a
3921     *        reference to a style resource that supplies default values for
3922     *        the view. Can be 0 to not look for defaults.
3923     * @see #View(Context, AttributeSet)
3924     */
3925    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3926        this(context, attrs, defStyleAttr, 0);
3927    }
3928
3929    /**
3930     * Perform inflation from XML and apply a class-specific base style from a
3931     * theme attribute or style resource. This constructor of View allows
3932     * subclasses to use their own base style when they are inflating.
3933     * <p>
3934     * When determining the final value of a particular attribute, there are
3935     * four inputs that come into play:
3936     * <ol>
3937     * <li>Any attribute values in the given AttributeSet.
3938     * <li>The style resource specified in the AttributeSet (named "style").
3939     * <li>The default style specified by <var>defStyleAttr</var>.
3940     * <li>The default style specified by <var>defStyleRes</var>.
3941     * <li>The base values in this theme.
3942     * </ol>
3943     * <p>
3944     * Each of these inputs is considered in-order, with the first listed taking
3945     * precedence over the following ones. In other words, if in the
3946     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3947     * , then the button's text will <em>always</em> be black, regardless of
3948     * what is specified in any of the styles.
3949     *
3950     * @param context The Context the view is running in, through which it can
3951     *        access the current theme, resources, etc.
3952     * @param attrs The attributes of the XML tag that is inflating the view.
3953     * @param defStyleAttr An attribute in the current theme that contains a
3954     *        reference to a style resource that supplies default values for
3955     *        the view. Can be 0 to not look for defaults.
3956     * @param defStyleRes A resource identifier of a style resource that
3957     *        supplies default values for the view, used only if
3958     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3959     *        to not look for defaults.
3960     * @see #View(Context, AttributeSet, int)
3961     */
3962    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3963        this(context);
3964
3965        final TypedArray a = context.obtainStyledAttributes(
3966                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3967
3968        if (mDebugViewAttributes) {
3969            saveAttributeData(attrs, a);
3970        }
3971
3972        Drawable background = null;
3973
3974        int leftPadding = -1;
3975        int topPadding = -1;
3976        int rightPadding = -1;
3977        int bottomPadding = -1;
3978        int startPadding = UNDEFINED_PADDING;
3979        int endPadding = UNDEFINED_PADDING;
3980
3981        int padding = -1;
3982
3983        int viewFlagValues = 0;
3984        int viewFlagMasks = 0;
3985
3986        boolean setScrollContainer = false;
3987
3988        int x = 0;
3989        int y = 0;
3990
3991        float tx = 0;
3992        float ty = 0;
3993        float tz = 0;
3994        float elevation = 0;
3995        float rotation = 0;
3996        float rotationX = 0;
3997        float rotationY = 0;
3998        float sx = 1f;
3999        float sy = 1f;
4000        boolean transformSet = false;
4001
4002        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4003        int overScrollMode = mOverScrollMode;
4004        boolean initializeScrollbars = false;
4005        boolean initializeScrollIndicators = false;
4006
4007        boolean startPaddingDefined = false;
4008        boolean endPaddingDefined = false;
4009        boolean leftPaddingDefined = false;
4010        boolean rightPaddingDefined = false;
4011
4012        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4013
4014        final int N = a.getIndexCount();
4015        for (int i = 0; i < N; i++) {
4016            int attr = a.getIndex(i);
4017            switch (attr) {
4018                case com.android.internal.R.styleable.View_background:
4019                    background = a.getDrawable(attr);
4020                    break;
4021                case com.android.internal.R.styleable.View_padding:
4022                    padding = a.getDimensionPixelSize(attr, -1);
4023                    mUserPaddingLeftInitial = padding;
4024                    mUserPaddingRightInitial = padding;
4025                    leftPaddingDefined = true;
4026                    rightPaddingDefined = true;
4027                    break;
4028                 case com.android.internal.R.styleable.View_paddingLeft:
4029                    leftPadding = a.getDimensionPixelSize(attr, -1);
4030                    mUserPaddingLeftInitial = leftPadding;
4031                    leftPaddingDefined = true;
4032                    break;
4033                case com.android.internal.R.styleable.View_paddingTop:
4034                    topPadding = a.getDimensionPixelSize(attr, -1);
4035                    break;
4036                case com.android.internal.R.styleable.View_paddingRight:
4037                    rightPadding = a.getDimensionPixelSize(attr, -1);
4038                    mUserPaddingRightInitial = rightPadding;
4039                    rightPaddingDefined = true;
4040                    break;
4041                case com.android.internal.R.styleable.View_paddingBottom:
4042                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4043                    break;
4044                case com.android.internal.R.styleable.View_paddingStart:
4045                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4046                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4047                    break;
4048                case com.android.internal.R.styleable.View_paddingEnd:
4049                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4050                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4051                    break;
4052                case com.android.internal.R.styleable.View_scrollX:
4053                    x = a.getDimensionPixelOffset(attr, 0);
4054                    break;
4055                case com.android.internal.R.styleable.View_scrollY:
4056                    y = a.getDimensionPixelOffset(attr, 0);
4057                    break;
4058                case com.android.internal.R.styleable.View_alpha:
4059                    setAlpha(a.getFloat(attr, 1f));
4060                    break;
4061                case com.android.internal.R.styleable.View_transformPivotX:
4062                    setPivotX(a.getDimensionPixelOffset(attr, 0));
4063                    break;
4064                case com.android.internal.R.styleable.View_transformPivotY:
4065                    setPivotY(a.getDimensionPixelOffset(attr, 0));
4066                    break;
4067                case com.android.internal.R.styleable.View_translationX:
4068                    tx = a.getDimensionPixelOffset(attr, 0);
4069                    transformSet = true;
4070                    break;
4071                case com.android.internal.R.styleable.View_translationY:
4072                    ty = a.getDimensionPixelOffset(attr, 0);
4073                    transformSet = true;
4074                    break;
4075                case com.android.internal.R.styleable.View_translationZ:
4076                    tz = a.getDimensionPixelOffset(attr, 0);
4077                    transformSet = true;
4078                    break;
4079                case com.android.internal.R.styleable.View_elevation:
4080                    elevation = a.getDimensionPixelOffset(attr, 0);
4081                    transformSet = true;
4082                    break;
4083                case com.android.internal.R.styleable.View_rotation:
4084                    rotation = a.getFloat(attr, 0);
4085                    transformSet = true;
4086                    break;
4087                case com.android.internal.R.styleable.View_rotationX:
4088                    rotationX = a.getFloat(attr, 0);
4089                    transformSet = true;
4090                    break;
4091                case com.android.internal.R.styleable.View_rotationY:
4092                    rotationY = a.getFloat(attr, 0);
4093                    transformSet = true;
4094                    break;
4095                case com.android.internal.R.styleable.View_scaleX:
4096                    sx = a.getFloat(attr, 1f);
4097                    transformSet = true;
4098                    break;
4099                case com.android.internal.R.styleable.View_scaleY:
4100                    sy = a.getFloat(attr, 1f);
4101                    transformSet = true;
4102                    break;
4103                case com.android.internal.R.styleable.View_id:
4104                    mID = a.getResourceId(attr, NO_ID);
4105                    break;
4106                case com.android.internal.R.styleable.View_tag:
4107                    mTag = a.getText(attr);
4108                    break;
4109                case com.android.internal.R.styleable.View_fitsSystemWindows:
4110                    if (a.getBoolean(attr, false)) {
4111                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4112                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4113                    }
4114                    break;
4115                case com.android.internal.R.styleable.View_focusable:
4116                    if (a.getBoolean(attr, false)) {
4117                        viewFlagValues |= FOCUSABLE;
4118                        viewFlagMasks |= FOCUSABLE_MASK;
4119                    }
4120                    break;
4121                case com.android.internal.R.styleable.View_focusableInTouchMode:
4122                    if (a.getBoolean(attr, false)) {
4123                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4124                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4125                    }
4126                    break;
4127                case com.android.internal.R.styleable.View_clickable:
4128                    if (a.getBoolean(attr, false)) {
4129                        viewFlagValues |= CLICKABLE;
4130                        viewFlagMasks |= CLICKABLE;
4131                    }
4132                    break;
4133                case com.android.internal.R.styleable.View_longClickable:
4134                    if (a.getBoolean(attr, false)) {
4135                        viewFlagValues |= LONG_CLICKABLE;
4136                        viewFlagMasks |= LONG_CLICKABLE;
4137                    }
4138                    break;
4139                case com.android.internal.R.styleable.View_contextClickable:
4140                    if (a.getBoolean(attr, false)) {
4141                        viewFlagValues |= CONTEXT_CLICKABLE;
4142                        viewFlagMasks |= CONTEXT_CLICKABLE;
4143                    }
4144                    break;
4145                case com.android.internal.R.styleable.View_saveEnabled:
4146                    if (!a.getBoolean(attr, true)) {
4147                        viewFlagValues |= SAVE_DISABLED;
4148                        viewFlagMasks |= SAVE_DISABLED_MASK;
4149                    }
4150                    break;
4151                case com.android.internal.R.styleable.View_duplicateParentState:
4152                    if (a.getBoolean(attr, false)) {
4153                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4154                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4155                    }
4156                    break;
4157                case com.android.internal.R.styleable.View_visibility:
4158                    final int visibility = a.getInt(attr, 0);
4159                    if (visibility != 0) {
4160                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4161                        viewFlagMasks |= VISIBILITY_MASK;
4162                    }
4163                    break;
4164                case com.android.internal.R.styleable.View_layoutDirection:
4165                    // Clear any layout direction flags (included resolved bits) already set
4166                    mPrivateFlags2 &=
4167                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4168                    // Set the layout direction flags depending on the value of the attribute
4169                    final int layoutDirection = a.getInt(attr, -1);
4170                    final int value = (layoutDirection != -1) ?
4171                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4172                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4173                    break;
4174                case com.android.internal.R.styleable.View_drawingCacheQuality:
4175                    final int cacheQuality = a.getInt(attr, 0);
4176                    if (cacheQuality != 0) {
4177                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4178                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4179                    }
4180                    break;
4181                case com.android.internal.R.styleable.View_contentDescription:
4182                    setContentDescription(a.getString(attr));
4183                    break;
4184                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4185                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4186                    break;
4187                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4188                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4189                    break;
4190                case com.android.internal.R.styleable.View_labelFor:
4191                    setLabelFor(a.getResourceId(attr, NO_ID));
4192                    break;
4193                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4194                    if (!a.getBoolean(attr, true)) {
4195                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4196                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4197                    }
4198                    break;
4199                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4200                    if (!a.getBoolean(attr, true)) {
4201                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4202                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4203                    }
4204                    break;
4205                case R.styleable.View_scrollbars:
4206                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4207                    if (scrollbars != SCROLLBARS_NONE) {
4208                        viewFlagValues |= scrollbars;
4209                        viewFlagMasks |= SCROLLBARS_MASK;
4210                        initializeScrollbars = true;
4211                    }
4212                    break;
4213                //noinspection deprecation
4214                case R.styleable.View_fadingEdge:
4215                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4216                        // Ignore the attribute starting with ICS
4217                        break;
4218                    }
4219                    // With builds < ICS, fall through and apply fading edges
4220                case R.styleable.View_requiresFadingEdge:
4221                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4222                    if (fadingEdge != FADING_EDGE_NONE) {
4223                        viewFlagValues |= fadingEdge;
4224                        viewFlagMasks |= FADING_EDGE_MASK;
4225                        initializeFadingEdgeInternal(a);
4226                    }
4227                    break;
4228                case R.styleable.View_scrollbarStyle:
4229                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4230                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4231                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4232                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4233                    }
4234                    break;
4235                case R.styleable.View_isScrollContainer:
4236                    setScrollContainer = true;
4237                    if (a.getBoolean(attr, false)) {
4238                        setScrollContainer(true);
4239                    }
4240                    break;
4241                case com.android.internal.R.styleable.View_keepScreenOn:
4242                    if (a.getBoolean(attr, false)) {
4243                        viewFlagValues |= KEEP_SCREEN_ON;
4244                        viewFlagMasks |= KEEP_SCREEN_ON;
4245                    }
4246                    break;
4247                case R.styleable.View_filterTouchesWhenObscured:
4248                    if (a.getBoolean(attr, false)) {
4249                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4250                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4251                    }
4252                    break;
4253                case R.styleable.View_nextFocusLeft:
4254                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4255                    break;
4256                case R.styleable.View_nextFocusRight:
4257                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4258                    break;
4259                case R.styleable.View_nextFocusUp:
4260                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4261                    break;
4262                case R.styleable.View_nextFocusDown:
4263                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4264                    break;
4265                case R.styleable.View_nextFocusForward:
4266                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4267                    break;
4268                case R.styleable.View_minWidth:
4269                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4270                    break;
4271                case R.styleable.View_minHeight:
4272                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4273                    break;
4274                case R.styleable.View_onClick:
4275                    if (context.isRestricted()) {
4276                        throw new IllegalStateException("The android:onClick attribute cannot "
4277                                + "be used within a restricted context");
4278                    }
4279
4280                    final String handlerName = a.getString(attr);
4281                    if (handlerName != null) {
4282                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4283                    }
4284                    break;
4285                case R.styleable.View_overScrollMode:
4286                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4287                    break;
4288                case R.styleable.View_verticalScrollbarPosition:
4289                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4290                    break;
4291                case R.styleable.View_layerType:
4292                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4293                    break;
4294                case R.styleable.View_textDirection:
4295                    // Clear any text direction flag already set
4296                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4297                    // Set the text direction flags depending on the value of the attribute
4298                    final int textDirection = a.getInt(attr, -1);
4299                    if (textDirection != -1) {
4300                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4301                    }
4302                    break;
4303                case R.styleable.View_textAlignment:
4304                    // Clear any text alignment flag already set
4305                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4306                    // Set the text alignment flag depending on the value of the attribute
4307                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4308                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4309                    break;
4310                case R.styleable.View_importantForAccessibility:
4311                    setImportantForAccessibility(a.getInt(attr,
4312                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4313                    break;
4314                case R.styleable.View_accessibilityLiveRegion:
4315                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4316                    break;
4317                case R.styleable.View_transitionName:
4318                    setTransitionName(a.getString(attr));
4319                    break;
4320                case R.styleable.View_nestedScrollingEnabled:
4321                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4322                    break;
4323                case R.styleable.View_stateListAnimator:
4324                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4325                            a.getResourceId(attr, 0)));
4326                    break;
4327                case R.styleable.View_backgroundTint:
4328                    // This will get applied later during setBackground().
4329                    if (mBackgroundTint == null) {
4330                        mBackgroundTint = new TintInfo();
4331                    }
4332                    mBackgroundTint.mTintList = a.getColorStateList(
4333                            R.styleable.View_backgroundTint);
4334                    mBackgroundTint.mHasTintList = true;
4335                    break;
4336                case R.styleable.View_backgroundTintMode:
4337                    // This will get applied later during setBackground().
4338                    if (mBackgroundTint == null) {
4339                        mBackgroundTint = new TintInfo();
4340                    }
4341                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4342                            R.styleable.View_backgroundTintMode, -1), null);
4343                    mBackgroundTint.mHasTintMode = true;
4344                    break;
4345                case R.styleable.View_outlineProvider:
4346                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4347                            PROVIDER_BACKGROUND));
4348                    break;
4349                case R.styleable.View_foreground:
4350                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4351                        setForeground(a.getDrawable(attr));
4352                    }
4353                    break;
4354                case R.styleable.View_foregroundGravity:
4355                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4356                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4357                    }
4358                    break;
4359                case R.styleable.View_foregroundTintMode:
4360                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4361                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4362                    }
4363                    break;
4364                case R.styleable.View_foregroundTint:
4365                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4366                        setForegroundTintList(a.getColorStateList(attr));
4367                    }
4368                    break;
4369                case R.styleable.View_foregroundInsidePadding:
4370                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4371                        if (mForegroundInfo == null) {
4372                            mForegroundInfo = new ForegroundInfo();
4373                        }
4374                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4375                                mForegroundInfo.mInsidePadding);
4376                    }
4377                    break;
4378                case R.styleable.View_scrollIndicators:
4379                    final int scrollIndicators =
4380                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4381                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4382                    if (scrollIndicators != 0) {
4383                        mPrivateFlags3 |= scrollIndicators;
4384                        initializeScrollIndicators = true;
4385                    }
4386                    break;
4387            }
4388        }
4389
4390        setOverScrollMode(overScrollMode);
4391
4392        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4393        // the resolved layout direction). Those cached values will be used later during padding
4394        // resolution.
4395        mUserPaddingStart = startPadding;
4396        mUserPaddingEnd = endPadding;
4397
4398        if (background != null) {
4399            setBackground(background);
4400        }
4401
4402        // setBackground above will record that padding is currently provided by the background.
4403        // If we have padding specified via xml, record that here instead and use it.
4404        mLeftPaddingDefined = leftPaddingDefined;
4405        mRightPaddingDefined = rightPaddingDefined;
4406
4407        if (padding >= 0) {
4408            leftPadding = padding;
4409            topPadding = padding;
4410            rightPadding = padding;
4411            bottomPadding = padding;
4412            mUserPaddingLeftInitial = padding;
4413            mUserPaddingRightInitial = padding;
4414        }
4415
4416        if (isRtlCompatibilityMode()) {
4417            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4418            // left / right padding are used if defined (meaning here nothing to do). If they are not
4419            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4420            // start / end and resolve them as left / right (layout direction is not taken into account).
4421            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4422            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4423            // defined.
4424            if (!mLeftPaddingDefined && startPaddingDefined) {
4425                leftPadding = startPadding;
4426            }
4427            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4428            if (!mRightPaddingDefined && endPaddingDefined) {
4429                rightPadding = endPadding;
4430            }
4431            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4432        } else {
4433            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4434            // values defined. Otherwise, left /right values are used.
4435            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4436            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4437            // defined.
4438            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4439
4440            if (mLeftPaddingDefined && !hasRelativePadding) {
4441                mUserPaddingLeftInitial = leftPadding;
4442            }
4443            if (mRightPaddingDefined && !hasRelativePadding) {
4444                mUserPaddingRightInitial = rightPadding;
4445            }
4446        }
4447
4448        internalSetPadding(
4449                mUserPaddingLeftInitial,
4450                topPadding >= 0 ? topPadding : mPaddingTop,
4451                mUserPaddingRightInitial,
4452                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4453
4454        if (viewFlagMasks != 0) {
4455            setFlags(viewFlagValues, viewFlagMasks);
4456        }
4457
4458        if (initializeScrollbars) {
4459            initializeScrollbarsInternal(a);
4460        }
4461
4462        if (initializeScrollIndicators) {
4463            initializeScrollIndicatorsInternal();
4464        }
4465
4466        a.recycle();
4467
4468        // Needs to be called after mViewFlags is set
4469        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4470            recomputePadding();
4471        }
4472
4473        if (x != 0 || y != 0) {
4474            scrollTo(x, y);
4475        }
4476
4477        if (transformSet) {
4478            setTranslationX(tx);
4479            setTranslationY(ty);
4480            setTranslationZ(tz);
4481            setElevation(elevation);
4482            setRotation(rotation);
4483            setRotationX(rotationX);
4484            setRotationY(rotationY);
4485            setScaleX(sx);
4486            setScaleY(sy);
4487        }
4488
4489        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4490            setScrollContainer(true);
4491        }
4492
4493        computeOpaqueFlags();
4494    }
4495
4496    /**
4497     * An implementation of OnClickListener that attempts to lazily load a
4498     * named click handling method from a parent or ancestor context.
4499     */
4500    private static class DeclaredOnClickListener implements OnClickListener {
4501        private final View mHostView;
4502        private final String mMethodName;
4503
4504        private Method mResolvedMethod;
4505        private Context mResolvedContext;
4506
4507        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4508            mHostView = hostView;
4509            mMethodName = methodName;
4510        }
4511
4512        @Override
4513        public void onClick(@NonNull View v) {
4514            if (mResolvedMethod == null) {
4515                resolveMethod(mHostView.getContext(), mMethodName);
4516            }
4517
4518            try {
4519                mResolvedMethod.invoke(mResolvedContext, v);
4520            } catch (IllegalAccessException e) {
4521                throw new IllegalStateException(
4522                        "Could not execute non-public method for android:onClick", e);
4523            } catch (InvocationTargetException e) {
4524                throw new IllegalStateException(
4525                        "Could not execute method for android:onClick", e);
4526            }
4527        }
4528
4529        @NonNull
4530        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4531            while (context != null) {
4532                try {
4533                    if (!context.isRestricted()) {
4534                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4535                        if (method != null) {
4536                            mResolvedMethod = method;
4537                            mResolvedContext = context;
4538                            return;
4539                        }
4540                    }
4541                } catch (NoSuchMethodException e) {
4542                    // Failed to find method, keep searching up the hierarchy.
4543                }
4544
4545                if (context instanceof ContextWrapper) {
4546                    context = ((ContextWrapper) context).getBaseContext();
4547                } else {
4548                    // Can't search up the hierarchy, null out and fail.
4549                    context = null;
4550                }
4551            }
4552
4553            final int id = mHostView.getId();
4554            final String idText = id == NO_ID ? "" : " with id '"
4555                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4556            throw new IllegalStateException("Could not find method " + mMethodName
4557                    + "(View) in a parent or ancestor Context for android:onClick "
4558                    + "attribute defined on view " + mHostView.getClass() + idText);
4559        }
4560    }
4561
4562    /**
4563     * Non-public constructor for use in testing
4564     */
4565    View() {
4566        mResources = null;
4567        mRenderNode = RenderNode.create(getClass().getName(), this);
4568    }
4569
4570    private static SparseArray<String> getAttributeMap() {
4571        if (mAttributeMap == null) {
4572            mAttributeMap = new SparseArray<>();
4573        }
4574        return mAttributeMap;
4575    }
4576
4577    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4578        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4579        final int indexCount = t.getIndexCount();
4580        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4581
4582        int i = 0;
4583
4584        // Store raw XML attributes.
4585        for (int j = 0; j < attrsCount; ++j) {
4586            attributes[i] = attrs.getAttributeName(j);
4587            attributes[i + 1] = attrs.getAttributeValue(j);
4588            i += 2;
4589        }
4590
4591        // Store resolved styleable attributes.
4592        final Resources res = t.getResources();
4593        final SparseArray<String> attributeMap = getAttributeMap();
4594        for (int j = 0; j < indexCount; ++j) {
4595            final int index = t.getIndex(j);
4596            if (!t.hasValueOrEmpty(index)) {
4597                // Value is undefined. Skip it.
4598                continue;
4599            }
4600
4601            final int resourceId = t.getResourceId(index, 0);
4602            if (resourceId == 0) {
4603                // Value is not a reference. Skip it.
4604                continue;
4605            }
4606
4607            String resourceName = attributeMap.get(resourceId);
4608            if (resourceName == null) {
4609                try {
4610                    resourceName = res.getResourceName(resourceId);
4611                } catch (Resources.NotFoundException e) {
4612                    resourceName = "0x" + Integer.toHexString(resourceId);
4613                }
4614                attributeMap.put(resourceId, resourceName);
4615            }
4616
4617            attributes[i] = resourceName;
4618            attributes[i + 1] = t.getString(index);
4619            i += 2;
4620        }
4621
4622        // Trim to fit contents.
4623        final String[] trimmed = new String[i];
4624        System.arraycopy(attributes, 0, trimmed, 0, i);
4625        mAttributes = trimmed;
4626    }
4627
4628    public String toString() {
4629        StringBuilder out = new StringBuilder(128);
4630        out.append(getClass().getName());
4631        out.append('{');
4632        out.append(Integer.toHexString(System.identityHashCode(this)));
4633        out.append(' ');
4634        switch (mViewFlags&VISIBILITY_MASK) {
4635            case VISIBLE: out.append('V'); break;
4636            case INVISIBLE: out.append('I'); break;
4637            case GONE: out.append('G'); break;
4638            default: out.append('.'); break;
4639        }
4640        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4641        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4642        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4643        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4644        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4645        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4646        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4647        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4648        out.append(' ');
4649        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4650        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4651        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4652        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4653            out.append('p');
4654        } else {
4655            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4656        }
4657        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4658        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4659        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4660        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4661        out.append(' ');
4662        out.append(mLeft);
4663        out.append(',');
4664        out.append(mTop);
4665        out.append('-');
4666        out.append(mRight);
4667        out.append(',');
4668        out.append(mBottom);
4669        final int id = getId();
4670        if (id != NO_ID) {
4671            out.append(" #");
4672            out.append(Integer.toHexString(id));
4673            final Resources r = mResources;
4674            if (Resources.resourceHasPackage(id) && r != null) {
4675                try {
4676                    String pkgname;
4677                    switch (id&0xff000000) {
4678                        case 0x7f000000:
4679                            pkgname="app";
4680                            break;
4681                        case 0x01000000:
4682                            pkgname="android";
4683                            break;
4684                        default:
4685                            pkgname = r.getResourcePackageName(id);
4686                            break;
4687                    }
4688                    String typename = r.getResourceTypeName(id);
4689                    String entryname = r.getResourceEntryName(id);
4690                    out.append(" ");
4691                    out.append(pkgname);
4692                    out.append(":");
4693                    out.append(typename);
4694                    out.append("/");
4695                    out.append(entryname);
4696                } catch (Resources.NotFoundException e) {
4697                }
4698            }
4699        }
4700        out.append("}");
4701        return out.toString();
4702    }
4703
4704    /**
4705     * <p>
4706     * Initializes the fading edges from a given set of styled attributes. This
4707     * method should be called by subclasses that need fading edges and when an
4708     * instance of these subclasses is created programmatically rather than
4709     * being inflated from XML. This method is automatically called when the XML
4710     * is inflated.
4711     * </p>
4712     *
4713     * @param a the styled attributes set to initialize the fading edges from
4714     *
4715     * @removed
4716     */
4717    protected void initializeFadingEdge(TypedArray a) {
4718        // This method probably shouldn't have been included in the SDK to begin with.
4719        // It relies on 'a' having been initialized using an attribute filter array that is
4720        // not publicly available to the SDK. The old method has been renamed
4721        // to initializeFadingEdgeInternal and hidden for framework use only;
4722        // this one initializes using defaults to make it safe to call for apps.
4723
4724        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4725
4726        initializeFadingEdgeInternal(arr);
4727
4728        arr.recycle();
4729    }
4730
4731    /**
4732     * <p>
4733     * Initializes the fading edges from a given set of styled attributes. This
4734     * method should be called by subclasses that need fading edges and when an
4735     * instance of these subclasses is created programmatically rather than
4736     * being inflated from XML. This method is automatically called when the XML
4737     * is inflated.
4738     * </p>
4739     *
4740     * @param a the styled attributes set to initialize the fading edges from
4741     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4742     */
4743    protected void initializeFadingEdgeInternal(TypedArray a) {
4744        initScrollCache();
4745
4746        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4747                R.styleable.View_fadingEdgeLength,
4748                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4749    }
4750
4751    /**
4752     * Returns the size of the vertical faded edges used to indicate that more
4753     * content in this view is visible.
4754     *
4755     * @return The size in pixels of the vertical faded edge or 0 if vertical
4756     *         faded edges are not enabled for this view.
4757     * @attr ref android.R.styleable#View_fadingEdgeLength
4758     */
4759    public int getVerticalFadingEdgeLength() {
4760        if (isVerticalFadingEdgeEnabled()) {
4761            ScrollabilityCache cache = mScrollCache;
4762            if (cache != null) {
4763                return cache.fadingEdgeLength;
4764            }
4765        }
4766        return 0;
4767    }
4768
4769    /**
4770     * Set the size of the faded edge used to indicate that more content in this
4771     * view is available.  Will not change whether the fading edge is enabled; use
4772     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4773     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4774     * for the vertical or horizontal fading edges.
4775     *
4776     * @param length The size in pixels of the faded edge used to indicate that more
4777     *        content in this view is visible.
4778     */
4779    public void setFadingEdgeLength(int length) {
4780        initScrollCache();
4781        mScrollCache.fadingEdgeLength = length;
4782    }
4783
4784    /**
4785     * Returns the size of the horizontal faded edges used to indicate that more
4786     * content in this view is visible.
4787     *
4788     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4789     *         faded edges are not enabled for this view.
4790     * @attr ref android.R.styleable#View_fadingEdgeLength
4791     */
4792    public int getHorizontalFadingEdgeLength() {
4793        if (isHorizontalFadingEdgeEnabled()) {
4794            ScrollabilityCache cache = mScrollCache;
4795            if (cache != null) {
4796                return cache.fadingEdgeLength;
4797            }
4798        }
4799        return 0;
4800    }
4801
4802    /**
4803     * Returns the width of the vertical scrollbar.
4804     *
4805     * @return The width in pixels of the vertical scrollbar or 0 if there
4806     *         is no vertical scrollbar.
4807     */
4808    public int getVerticalScrollbarWidth() {
4809        ScrollabilityCache cache = mScrollCache;
4810        if (cache != null) {
4811            ScrollBarDrawable scrollBar = cache.scrollBar;
4812            if (scrollBar != null) {
4813                int size = scrollBar.getSize(true);
4814                if (size <= 0) {
4815                    size = cache.scrollBarSize;
4816                }
4817                return size;
4818            }
4819            return 0;
4820        }
4821        return 0;
4822    }
4823
4824    /**
4825     * Returns the height of the horizontal scrollbar.
4826     *
4827     * @return The height in pixels of the horizontal scrollbar or 0 if
4828     *         there is no horizontal scrollbar.
4829     */
4830    protected int getHorizontalScrollbarHeight() {
4831        ScrollabilityCache cache = mScrollCache;
4832        if (cache != null) {
4833            ScrollBarDrawable scrollBar = cache.scrollBar;
4834            if (scrollBar != null) {
4835                int size = scrollBar.getSize(false);
4836                if (size <= 0) {
4837                    size = cache.scrollBarSize;
4838                }
4839                return size;
4840            }
4841            return 0;
4842        }
4843        return 0;
4844    }
4845
4846    /**
4847     * <p>
4848     * Initializes the scrollbars from a given set of styled attributes. This
4849     * method should be called by subclasses that need scrollbars and when an
4850     * instance of these subclasses is created programmatically rather than
4851     * being inflated from XML. This method is automatically called when the XML
4852     * is inflated.
4853     * </p>
4854     *
4855     * @param a the styled attributes set to initialize the scrollbars from
4856     *
4857     * @removed
4858     */
4859    protected void initializeScrollbars(TypedArray a) {
4860        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4861        // using the View filter array which is not available to the SDK. As such, internal
4862        // framework usage now uses initializeScrollbarsInternal and we grab a default
4863        // TypedArray with the right filter instead here.
4864        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4865
4866        initializeScrollbarsInternal(arr);
4867
4868        // We ignored the method parameter. Recycle the one we actually did use.
4869        arr.recycle();
4870    }
4871
4872    /**
4873     * <p>
4874     * Initializes the scrollbars from a given set of styled attributes. This
4875     * method should be called by subclasses that need scrollbars and when an
4876     * instance of these subclasses is created programmatically rather than
4877     * being inflated from XML. This method is automatically called when the XML
4878     * is inflated.
4879     * </p>
4880     *
4881     * @param a the styled attributes set to initialize the scrollbars from
4882     * @hide
4883     */
4884    protected void initializeScrollbarsInternal(TypedArray a) {
4885        initScrollCache();
4886
4887        final ScrollabilityCache scrollabilityCache = mScrollCache;
4888
4889        if (scrollabilityCache.scrollBar == null) {
4890            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4891            scrollabilityCache.scrollBar.setCallback(this);
4892            scrollabilityCache.scrollBar.setState(getDrawableState());
4893        }
4894
4895        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4896
4897        if (!fadeScrollbars) {
4898            scrollabilityCache.state = ScrollabilityCache.ON;
4899        }
4900        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4901
4902
4903        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4904                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4905                        .getScrollBarFadeDuration());
4906        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4907                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4908                ViewConfiguration.getScrollDefaultDelay());
4909
4910
4911        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4912                com.android.internal.R.styleable.View_scrollbarSize,
4913                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4914
4915        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4916        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4917
4918        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4919        if (thumb != null) {
4920            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4921        }
4922
4923        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4924                false);
4925        if (alwaysDraw) {
4926            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4927        }
4928
4929        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4930        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4931
4932        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4933        if (thumb != null) {
4934            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4935        }
4936
4937        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4938                false);
4939        if (alwaysDraw) {
4940            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4941        }
4942
4943        // Apply layout direction to the new Drawables if needed
4944        final int layoutDirection = getLayoutDirection();
4945        if (track != null) {
4946            track.setLayoutDirection(layoutDirection);
4947        }
4948        if (thumb != null) {
4949            thumb.setLayoutDirection(layoutDirection);
4950        }
4951
4952        // Re-apply user/background padding so that scrollbar(s) get added
4953        resolvePadding();
4954    }
4955
4956    private void initializeScrollIndicatorsInternal() {
4957        // Some day maybe we'll break this into top/left/start/etc. and let the
4958        // client control it. Until then, you can have any scroll indicator you
4959        // want as long as it's a 1dp foreground-colored rectangle.
4960        if (mScrollIndicatorDrawable == null) {
4961            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
4962        }
4963    }
4964
4965    /**
4966     * <p>
4967     * Initalizes the scrollability cache if necessary.
4968     * </p>
4969     */
4970    private void initScrollCache() {
4971        if (mScrollCache == null) {
4972            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4973        }
4974    }
4975
4976    private ScrollabilityCache getScrollCache() {
4977        initScrollCache();
4978        return mScrollCache;
4979    }
4980
4981    /**
4982     * Set the position of the vertical scroll bar. Should be one of
4983     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4984     * {@link #SCROLLBAR_POSITION_RIGHT}.
4985     *
4986     * @param position Where the vertical scroll bar should be positioned.
4987     */
4988    public void setVerticalScrollbarPosition(int position) {
4989        if (mVerticalScrollbarPosition != position) {
4990            mVerticalScrollbarPosition = position;
4991            computeOpaqueFlags();
4992            resolvePadding();
4993        }
4994    }
4995
4996    /**
4997     * @return The position where the vertical scroll bar will show, if applicable.
4998     * @see #setVerticalScrollbarPosition(int)
4999     */
5000    public int getVerticalScrollbarPosition() {
5001        return mVerticalScrollbarPosition;
5002    }
5003
5004    /**
5005     * Sets the state of all scroll indicators.
5006     * <p>
5007     * See {@link #setScrollIndicators(int, int)} for usage information.
5008     *
5009     * @param indicators a bitmask of indicators that should be enabled, or
5010     *                   {@code 0} to disable all indicators
5011     * @see #setScrollIndicators(int, int)
5012     * @see #getScrollIndicators()
5013     * @attr ref android.R.styleable#View_scrollIndicators
5014     */
5015    public void setScrollIndicators(@ScrollIndicators int indicators) {
5016        setScrollIndicators(indicators,
5017                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5018    }
5019
5020    /**
5021     * Sets the state of the scroll indicators specified by the mask. To change
5022     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5023     * <p>
5024     * When a scroll indicator is enabled, it will be displayed if the view
5025     * can scroll in the direction of the indicator.
5026     * <p>
5027     * Multiple indicator types may be enabled or disabled by passing the
5028     * logical OR of the desired types. If multiple types are specified, they
5029     * will all be set to the same enabled state.
5030     * <p>
5031     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5032     *
5033     * @param indicators the indicator direction, or the logical OR of multiple
5034     *             indicator directions. One or more of:
5035     *             <ul>
5036     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5037     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5038     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5039     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5040     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5041     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5042     *             </ul>
5043     * @see #setScrollIndicators(int)
5044     * @see #getScrollIndicators()
5045     * @attr ref android.R.styleable#View_scrollIndicators
5046     */
5047    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5048        // Shift and sanitize mask.
5049        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5050        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5051
5052        // Shift and mask indicators.
5053        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5054        indicators &= mask;
5055
5056        // Merge with non-masked flags.
5057        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5058
5059        if (mPrivateFlags3 != updatedFlags) {
5060            mPrivateFlags3 = updatedFlags;
5061
5062            if (indicators != 0) {
5063                initializeScrollIndicatorsInternal();
5064            }
5065            invalidate();
5066        }
5067    }
5068
5069    /**
5070     * Returns a bitmask representing the enabled scroll indicators.
5071     * <p>
5072     * For example, if the top and left scroll indicators are enabled and all
5073     * other indicators are disabled, the return value will be
5074     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5075     * <p>
5076     * To check whether the bottom scroll indicator is enabled, use the value
5077     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5078     *
5079     * @return a bitmask representing the enabled scroll indicators
5080     */
5081    @ScrollIndicators
5082    public int getScrollIndicators() {
5083        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5084                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5085    }
5086
5087    ListenerInfo getListenerInfo() {
5088        if (mListenerInfo != null) {
5089            return mListenerInfo;
5090        }
5091        mListenerInfo = new ListenerInfo();
5092        return mListenerInfo;
5093    }
5094
5095    /**
5096     * Register a callback to be invoked when the scroll X or Y positions of
5097     * this view change.
5098     * <p>
5099     * <b>Note:</b> Some views handle scrolling independently from View and may
5100     * have their own separate listeners for scroll-type events. For example,
5101     * {@link android.widget.ListView ListView} allows clients to register an
5102     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5103     * to listen for changes in list scroll position.
5104     *
5105     * @param l The listener to notify when the scroll X or Y position changes.
5106     * @see android.view.View#getScrollX()
5107     * @see android.view.View#getScrollY()
5108     */
5109    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5110        getListenerInfo().mOnScrollChangeListener = l;
5111    }
5112
5113    /**
5114     * Register a callback to be invoked when focus of this view changed.
5115     *
5116     * @param l The callback that will run.
5117     */
5118    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5119        getListenerInfo().mOnFocusChangeListener = l;
5120    }
5121
5122    /**
5123     * Add a listener that will be called when the bounds of the view change due to
5124     * layout processing.
5125     *
5126     * @param listener The listener that will be called when layout bounds change.
5127     */
5128    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5129        ListenerInfo li = getListenerInfo();
5130        if (li.mOnLayoutChangeListeners == null) {
5131            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5132        }
5133        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5134            li.mOnLayoutChangeListeners.add(listener);
5135        }
5136    }
5137
5138    /**
5139     * Remove a listener for layout changes.
5140     *
5141     * @param listener The listener for layout bounds change.
5142     */
5143    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5144        ListenerInfo li = mListenerInfo;
5145        if (li == null || li.mOnLayoutChangeListeners == null) {
5146            return;
5147        }
5148        li.mOnLayoutChangeListeners.remove(listener);
5149    }
5150
5151    /**
5152     * Add a listener for attach state changes.
5153     *
5154     * This listener will be called whenever this view is attached or detached
5155     * from a window. Remove the listener using
5156     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5157     *
5158     * @param listener Listener to attach
5159     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5160     */
5161    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5162        ListenerInfo li = getListenerInfo();
5163        if (li.mOnAttachStateChangeListeners == null) {
5164            li.mOnAttachStateChangeListeners
5165                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5166        }
5167        li.mOnAttachStateChangeListeners.add(listener);
5168    }
5169
5170    /**
5171     * Remove a listener for attach state changes. The listener will receive no further
5172     * notification of window attach/detach events.
5173     *
5174     * @param listener Listener to remove
5175     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5176     */
5177    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5178        ListenerInfo li = mListenerInfo;
5179        if (li == null || li.mOnAttachStateChangeListeners == null) {
5180            return;
5181        }
5182        li.mOnAttachStateChangeListeners.remove(listener);
5183    }
5184
5185    /**
5186     * Returns the focus-change callback registered for this view.
5187     *
5188     * @return The callback, or null if one is not registered.
5189     */
5190    public OnFocusChangeListener getOnFocusChangeListener() {
5191        ListenerInfo li = mListenerInfo;
5192        return li != null ? li.mOnFocusChangeListener : null;
5193    }
5194
5195    /**
5196     * Register a callback to be invoked when this view is clicked. If this view is not
5197     * clickable, it becomes clickable.
5198     *
5199     * @param l The callback that will run
5200     *
5201     * @see #setClickable(boolean)
5202     */
5203    public void setOnClickListener(@Nullable OnClickListener l) {
5204        if (!isClickable()) {
5205            setClickable(true);
5206        }
5207        getListenerInfo().mOnClickListener = l;
5208    }
5209
5210    /**
5211     * Return whether this view has an attached OnClickListener.  Returns
5212     * true if there is a listener, false if there is none.
5213     */
5214    public boolean hasOnClickListeners() {
5215        ListenerInfo li = mListenerInfo;
5216        return (li != null && li.mOnClickListener != null);
5217    }
5218
5219    /**
5220     * Register a callback to be invoked when this view is clicked and held. If this view is not
5221     * long clickable, it becomes long clickable.
5222     *
5223     * @param l The callback that will run
5224     *
5225     * @see #setLongClickable(boolean)
5226     */
5227    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5228        if (!isLongClickable()) {
5229            setLongClickable(true);
5230        }
5231        getListenerInfo().mOnLongClickListener = l;
5232    }
5233
5234    /**
5235     * Register a callback to be invoked when this view is context clicked. If the view is not
5236     * context clickable, it becomes context clickable.
5237     *
5238     * @param l The callback that will run
5239     * @see #setContextClickable(boolean)
5240     */
5241    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5242        if (!isContextClickable()) {
5243            setContextClickable(true);
5244        }
5245        getListenerInfo().mOnContextClickListener = l;
5246    }
5247
5248    /**
5249     * Register a callback to be invoked when the context menu for this view is
5250     * being built. If this view is not long clickable, it becomes long clickable.
5251     *
5252     * @param l The callback that will run
5253     *
5254     */
5255    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5256        if (!isLongClickable()) {
5257            setLongClickable(true);
5258        }
5259        getListenerInfo().mOnCreateContextMenuListener = l;
5260    }
5261
5262    /**
5263     * Call this view's OnClickListener, if it is defined.  Performs all normal
5264     * actions associated with clicking: reporting accessibility event, playing
5265     * a sound, etc.
5266     *
5267     * @return True there was an assigned OnClickListener that was called, false
5268     *         otherwise is returned.
5269     */
5270    public boolean performClick() {
5271        final boolean result;
5272        final ListenerInfo li = mListenerInfo;
5273        if (li != null && li.mOnClickListener != null) {
5274            playSoundEffect(SoundEffectConstants.CLICK);
5275            li.mOnClickListener.onClick(this);
5276            result = true;
5277        } else {
5278            result = false;
5279        }
5280
5281        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5282        return result;
5283    }
5284
5285    /**
5286     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5287     * this only calls the listener, and does not do any associated clicking
5288     * actions like reporting an accessibility event.
5289     *
5290     * @return True there was an assigned OnClickListener that was called, false
5291     *         otherwise is returned.
5292     */
5293    public boolean callOnClick() {
5294        ListenerInfo li = mListenerInfo;
5295        if (li != null && li.mOnClickListener != null) {
5296            li.mOnClickListener.onClick(this);
5297            return true;
5298        }
5299        return false;
5300    }
5301
5302    /**
5303     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
5304     * OnLongClickListener did not consume the event.
5305     *
5306     * @return True if one of the above receivers consumed the event, false otherwise.
5307     */
5308    public boolean performLongClick() {
5309        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5310
5311        boolean handled = false;
5312        ListenerInfo li = mListenerInfo;
5313        if (li != null && li.mOnLongClickListener != null) {
5314            handled = li.mOnLongClickListener.onLongClick(View.this);
5315        }
5316        if (!handled) {
5317            handled = showContextMenu();
5318        }
5319        if (handled) {
5320            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5321        }
5322        return handled;
5323    }
5324
5325    /**
5326     * Call this view's OnContextClickListener, if it is defined.
5327     *
5328     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5329     *         otherwise.
5330     */
5331    public boolean performContextClick() {
5332        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5333
5334        boolean handled = false;
5335        ListenerInfo li = mListenerInfo;
5336        if (li != null && li.mOnContextClickListener != null) {
5337            handled = li.mOnContextClickListener.onContextClick(View.this);
5338        }
5339        if (handled) {
5340            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5341        }
5342        return handled;
5343    }
5344
5345    /**
5346     * Performs button-related actions during a touch down event.
5347     *
5348     * @param event The event.
5349     * @return True if the down was consumed.
5350     *
5351     * @hide
5352     */
5353    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5354        if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
5355            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5356            showContextMenu(event.getX(), event.getY(), event.getMetaState());
5357            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5358            return true;
5359        }
5360        return false;
5361    }
5362
5363    /**
5364     * Bring up the context menu for this view.
5365     *
5366     * @return Whether a context menu was displayed.
5367     */
5368    public boolean showContextMenu() {
5369        return getParent().showContextMenuForChild(this);
5370    }
5371
5372    /**
5373     * Bring up the context menu for this view, referring to the item under the specified point.
5374     *
5375     * @param x The referenced x coordinate.
5376     * @param y The referenced y coordinate.
5377     * @param metaState The keyboard modifiers that were pressed.
5378     * @return Whether a context menu was displayed.
5379     *
5380     * @hide
5381     */
5382    public boolean showContextMenu(float x, float y, int metaState) {
5383        return showContextMenu();
5384    }
5385
5386    /**
5387     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5388     *
5389     * @param callback Callback that will control the lifecycle of the action mode
5390     * @return The new action mode if it is started, null otherwise
5391     *
5392     * @see ActionMode
5393     * @see #startActionMode(android.view.ActionMode.Callback, int)
5394     */
5395    public ActionMode startActionMode(ActionMode.Callback callback) {
5396        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5397    }
5398
5399    /**
5400     * Start an action mode with the given type.
5401     *
5402     * @param callback Callback that will control the lifecycle of the action mode
5403     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5404     * @return The new action mode if it is started, null otherwise
5405     *
5406     * @see ActionMode
5407     */
5408    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5409        ViewParent parent = getParent();
5410        if (parent == null) return null;
5411        try {
5412            return parent.startActionModeForChild(this, callback, type);
5413        } catch (AbstractMethodError ame) {
5414            // Older implementations of custom views might not implement this.
5415            return parent.startActionModeForChild(this, callback);
5416        }
5417    }
5418
5419    /**
5420     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5421     * Context, creating a unique View identifier to retrieve the result.
5422     *
5423     * @param intent The Intent to be started.
5424     * @param requestCode The request code to use.
5425     * @hide
5426     */
5427    public void startActivityForResult(Intent intent, int requestCode) {
5428        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5429        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5430    }
5431
5432    /**
5433     * If this View corresponds to the calling who, dispatches the activity result.
5434     * @param who The identifier for the targeted View to receive the result.
5435     * @param requestCode The integer request code originally supplied to
5436     *                    startActivityForResult(), allowing you to identify who this
5437     *                    result came from.
5438     * @param resultCode The integer result code returned by the child activity
5439     *                   through its setResult().
5440     * @param data An Intent, which can return result data to the caller
5441     *               (various data can be attached to Intent "extras").
5442     * @return {@code true} if the activity result was dispatched.
5443     * @hide
5444     */
5445    public boolean dispatchActivityResult(
5446            String who, int requestCode, int resultCode, Intent data) {
5447        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5448            onActivityResult(requestCode, resultCode, data);
5449            mStartActivityRequestWho = null;
5450            return true;
5451        }
5452        return false;
5453    }
5454
5455    /**
5456     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5457     *
5458     * @param requestCode The integer request code originally supplied to
5459     *                    startActivityForResult(), allowing you to identify who this
5460     *                    result came from.
5461     * @param resultCode The integer result code returned by the child activity
5462     *                   through its setResult().
5463     * @param data An Intent, which can return result data to the caller
5464     *               (various data can be attached to Intent "extras").
5465     * @hide
5466     */
5467    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5468        // Do nothing.
5469    }
5470
5471    /**
5472     * Register a callback to be invoked when a hardware key is pressed in this view.
5473     * Key presses in software input methods will generally not trigger the methods of
5474     * this listener.
5475     * @param l the key listener to attach to this view
5476     */
5477    public void setOnKeyListener(OnKeyListener l) {
5478        getListenerInfo().mOnKeyListener = l;
5479    }
5480
5481    /**
5482     * Register a callback to be invoked when a touch event is sent to this view.
5483     * @param l the touch listener to attach to this view
5484     */
5485    public void setOnTouchListener(OnTouchListener l) {
5486        getListenerInfo().mOnTouchListener = l;
5487    }
5488
5489    /**
5490     * Register a callback to be invoked when a generic motion event is sent to this view.
5491     * @param l the generic motion listener to attach to this view
5492     */
5493    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5494        getListenerInfo().mOnGenericMotionListener = l;
5495    }
5496
5497    /**
5498     * Register a callback to be invoked when a hover event is sent to this view.
5499     * @param l the hover listener to attach to this view
5500     */
5501    public void setOnHoverListener(OnHoverListener l) {
5502        getListenerInfo().mOnHoverListener = l;
5503    }
5504
5505    /**
5506     * Register a drag event listener callback object for this View. The parameter is
5507     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5508     * View, the system calls the
5509     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5510     * @param l An implementation of {@link android.view.View.OnDragListener}.
5511     */
5512    public void setOnDragListener(OnDragListener l) {
5513        getListenerInfo().mOnDragListener = l;
5514    }
5515
5516    /**
5517     * Give this view focus. This will cause
5518     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5519     *
5520     * Note: this does not check whether this {@link View} should get focus, it just
5521     * gives it focus no matter what.  It should only be called internally by framework
5522     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5523     *
5524     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5525     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5526     *        focus moved when requestFocus() is called. It may not always
5527     *        apply, in which case use the default View.FOCUS_DOWN.
5528     * @param previouslyFocusedRect The rectangle of the view that had focus
5529     *        prior in this View's coordinate system.
5530     */
5531    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5532        if (DBG) {
5533            System.out.println(this + " requestFocus()");
5534        }
5535
5536        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5537            mPrivateFlags |= PFLAG_FOCUSED;
5538
5539            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5540
5541            if (mParent != null) {
5542                mParent.requestChildFocus(this, this);
5543            }
5544
5545            if (mAttachInfo != null) {
5546                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5547            }
5548
5549            onFocusChanged(true, direction, previouslyFocusedRect);
5550            refreshDrawableState();
5551        }
5552    }
5553
5554    /**
5555     * Populates <code>outRect</code> with the hotspot bounds. By default,
5556     * the hotspot bounds are identical to the screen bounds.
5557     *
5558     * @param outRect rect to populate with hotspot bounds
5559     * @hide Only for internal use by views and widgets.
5560     */
5561    public void getHotspotBounds(Rect outRect) {
5562        final Drawable background = getBackground();
5563        if (background != null) {
5564            background.getHotspotBounds(outRect);
5565        } else {
5566            getBoundsOnScreen(outRect);
5567        }
5568    }
5569
5570    /**
5571     * Request that a rectangle of this view be visible on the screen,
5572     * scrolling if necessary just enough.
5573     *
5574     * <p>A View should call this if it maintains some notion of which part
5575     * of its content is interesting.  For example, a text editing view
5576     * should call this when its cursor moves.
5577     *
5578     * @param rectangle The rectangle.
5579     * @return Whether any parent scrolled.
5580     */
5581    public boolean requestRectangleOnScreen(Rect rectangle) {
5582        return requestRectangleOnScreen(rectangle, false);
5583    }
5584
5585    /**
5586     * Request that a rectangle of this view be visible on the screen,
5587     * scrolling if necessary just enough.
5588     *
5589     * <p>A View should call this if it maintains some notion of which part
5590     * of its content is interesting.  For example, a text editing view
5591     * should call this when its cursor moves.
5592     *
5593     * <p>When <code>immediate</code> is set to true, scrolling will not be
5594     * animated.
5595     *
5596     * @param rectangle The rectangle.
5597     * @param immediate True to forbid animated scrolling, false otherwise
5598     * @return Whether any parent scrolled.
5599     */
5600    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5601        if (mParent == null) {
5602            return false;
5603        }
5604
5605        View child = this;
5606
5607        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5608        position.set(rectangle);
5609
5610        ViewParent parent = mParent;
5611        boolean scrolled = false;
5612        while (parent != null) {
5613            rectangle.set((int) position.left, (int) position.top,
5614                    (int) position.right, (int) position.bottom);
5615
5616            scrolled |= parent.requestChildRectangleOnScreen(child,
5617                    rectangle, immediate);
5618
5619            if (!child.hasIdentityMatrix()) {
5620                child.getMatrix().mapRect(position);
5621            }
5622
5623            position.offset(child.mLeft, child.mTop);
5624
5625            if (!(parent instanceof View)) {
5626                break;
5627            }
5628
5629            View parentView = (View) parent;
5630
5631            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5632
5633            child = parentView;
5634            parent = child.getParent();
5635        }
5636
5637        return scrolled;
5638    }
5639
5640    /**
5641     * Called when this view wants to give up focus. If focus is cleared
5642     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5643     * <p>
5644     * <strong>Note:</strong> When a View clears focus the framework is trying
5645     * to give focus to the first focusable View from the top. Hence, if this
5646     * View is the first from the top that can take focus, then all callbacks
5647     * related to clearing focus will be invoked after which the framework will
5648     * give focus to this view.
5649     * </p>
5650     */
5651    public void clearFocus() {
5652        if (DBG) {
5653            System.out.println(this + " clearFocus()");
5654        }
5655
5656        clearFocusInternal(null, true, true);
5657    }
5658
5659    /**
5660     * Clears focus from the view, optionally propagating the change up through
5661     * the parent hierarchy and requesting that the root view place new focus.
5662     *
5663     * @param propagate whether to propagate the change up through the parent
5664     *            hierarchy
5665     * @param refocus when propagate is true, specifies whether to request the
5666     *            root view place new focus
5667     */
5668    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5669        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5670            mPrivateFlags &= ~PFLAG_FOCUSED;
5671
5672            if (propagate && mParent != null) {
5673                mParent.clearChildFocus(this);
5674            }
5675
5676            onFocusChanged(false, 0, null);
5677            refreshDrawableState();
5678
5679            if (propagate && (!refocus || !rootViewRequestFocus())) {
5680                notifyGlobalFocusCleared(this);
5681            }
5682        }
5683    }
5684
5685    void notifyGlobalFocusCleared(View oldFocus) {
5686        if (oldFocus != null && mAttachInfo != null) {
5687            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5688        }
5689    }
5690
5691    boolean rootViewRequestFocus() {
5692        final View root = getRootView();
5693        return root != null && root.requestFocus();
5694    }
5695
5696    /**
5697     * Called internally by the view system when a new view is getting focus.
5698     * This is what clears the old focus.
5699     * <p>
5700     * <b>NOTE:</b> The parent view's focused child must be updated manually
5701     * after calling this method. Otherwise, the view hierarchy may be left in
5702     * an inconstent state.
5703     */
5704    void unFocus(View focused) {
5705        if (DBG) {
5706            System.out.println(this + " unFocus()");
5707        }
5708
5709        clearFocusInternal(focused, false, false);
5710    }
5711
5712    /**
5713     * Returns true if this view has focus itself, or is the ancestor of the
5714     * view that has focus.
5715     *
5716     * @return True if this view has or contains focus, false otherwise.
5717     */
5718    @ViewDebug.ExportedProperty(category = "focus")
5719    public boolean hasFocus() {
5720        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5721    }
5722
5723    /**
5724     * Returns true if this view is focusable or if it contains a reachable View
5725     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5726     * is a View whose parents do not block descendants focus.
5727     *
5728     * Only {@link #VISIBLE} views are considered focusable.
5729     *
5730     * @return True if the view is focusable or if the view contains a focusable
5731     *         View, false otherwise.
5732     *
5733     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5734     * @see ViewGroup#getTouchscreenBlocksFocus()
5735     */
5736    public boolean hasFocusable() {
5737        if (!isFocusableInTouchMode()) {
5738            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5739                final ViewGroup g = (ViewGroup) p;
5740                if (g.shouldBlockFocusForTouchscreen()) {
5741                    return false;
5742                }
5743            }
5744        }
5745        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5746    }
5747
5748    /**
5749     * Called by the view system when the focus state of this view changes.
5750     * When the focus change event is caused by directional navigation, direction
5751     * and previouslyFocusedRect provide insight into where the focus is coming from.
5752     * When overriding, be sure to call up through to the super class so that
5753     * the standard focus handling will occur.
5754     *
5755     * @param gainFocus True if the View has focus; false otherwise.
5756     * @param direction The direction focus has moved when requestFocus()
5757     *                  is called to give this view focus. Values are
5758     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5759     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5760     *                  It may not always apply, in which case use the default.
5761     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5762     *        system, of the previously focused view.  If applicable, this will be
5763     *        passed in as finer grained information about where the focus is coming
5764     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5765     */
5766    @CallSuper
5767    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5768            @Nullable Rect previouslyFocusedRect) {
5769        if (gainFocus) {
5770            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5771        } else {
5772            notifyViewAccessibilityStateChangedIfNeeded(
5773                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5774        }
5775
5776        InputMethodManager imm = InputMethodManager.peekInstance();
5777        if (!gainFocus) {
5778            if (isPressed()) {
5779                setPressed(false);
5780            }
5781            if (imm != null && mAttachInfo != null
5782                    && mAttachInfo.mHasWindowFocus) {
5783                imm.focusOut(this);
5784            }
5785            onFocusLost();
5786        } else if (imm != null && mAttachInfo != null
5787                && mAttachInfo.mHasWindowFocus) {
5788            imm.focusIn(this);
5789        }
5790
5791        invalidate(true);
5792        ListenerInfo li = mListenerInfo;
5793        if (li != null && li.mOnFocusChangeListener != null) {
5794            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5795        }
5796
5797        if (mAttachInfo != null) {
5798            mAttachInfo.mKeyDispatchState.reset(this);
5799        }
5800    }
5801
5802    /**
5803     * Sends an accessibility event of the given type. If accessibility is
5804     * not enabled this method has no effect. The default implementation calls
5805     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5806     * to populate information about the event source (this View), then calls
5807     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5808     * populate the text content of the event source including its descendants,
5809     * and last calls
5810     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5811     * on its parent to request sending of the event to interested parties.
5812     * <p>
5813     * If an {@link AccessibilityDelegate} has been specified via calling
5814     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5815     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5816     * responsible for handling this call.
5817     * </p>
5818     *
5819     * @param eventType The type of the event to send, as defined by several types from
5820     * {@link android.view.accessibility.AccessibilityEvent}, such as
5821     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5822     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5823     *
5824     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5825     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5826     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5827     * @see AccessibilityDelegate
5828     */
5829    public void sendAccessibilityEvent(int eventType) {
5830        if (mAccessibilityDelegate != null) {
5831            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5832        } else {
5833            sendAccessibilityEventInternal(eventType);
5834        }
5835    }
5836
5837    /**
5838     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5839     * {@link AccessibilityEvent} to make an announcement which is related to some
5840     * sort of a context change for which none of the events representing UI transitions
5841     * is a good fit. For example, announcing a new page in a book. If accessibility
5842     * is not enabled this method does nothing.
5843     *
5844     * @param text The announcement text.
5845     */
5846    public void announceForAccessibility(CharSequence text) {
5847        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5848            AccessibilityEvent event = AccessibilityEvent.obtain(
5849                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5850            onInitializeAccessibilityEvent(event);
5851            event.getText().add(text);
5852            event.setContentDescription(null);
5853            mParent.requestSendAccessibilityEvent(this, event);
5854        }
5855    }
5856
5857    /**
5858     * @see #sendAccessibilityEvent(int)
5859     *
5860     * Note: Called from the default {@link AccessibilityDelegate}.
5861     *
5862     * @hide
5863     */
5864    public void sendAccessibilityEventInternal(int eventType) {
5865        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5866            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5867        }
5868    }
5869
5870    /**
5871     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5872     * takes as an argument an empty {@link AccessibilityEvent} and does not
5873     * perform a check whether accessibility is enabled.
5874     * <p>
5875     * If an {@link AccessibilityDelegate} has been specified via calling
5876     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5877     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5878     * is responsible for handling this call.
5879     * </p>
5880     *
5881     * @param event The event to send.
5882     *
5883     * @see #sendAccessibilityEvent(int)
5884     */
5885    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5886        if (mAccessibilityDelegate != null) {
5887            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5888        } else {
5889            sendAccessibilityEventUncheckedInternal(event);
5890        }
5891    }
5892
5893    /**
5894     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5895     *
5896     * Note: Called from the default {@link AccessibilityDelegate}.
5897     *
5898     * @hide
5899     */
5900    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5901        if (!isShown()) {
5902            return;
5903        }
5904        onInitializeAccessibilityEvent(event);
5905        // Only a subset of accessibility events populates text content.
5906        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5907            dispatchPopulateAccessibilityEvent(event);
5908        }
5909        // In the beginning we called #isShown(), so we know that getParent() is not null.
5910        getParent().requestSendAccessibilityEvent(this, event);
5911    }
5912
5913    /**
5914     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5915     * to its children for adding their text content to the event. Note that the
5916     * event text is populated in a separate dispatch path since we add to the
5917     * event not only the text of the source but also the text of all its descendants.
5918     * A typical implementation will call
5919     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5920     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5921     * on each child. Override this method if custom population of the event text
5922     * content is required.
5923     * <p>
5924     * If an {@link AccessibilityDelegate} has been specified via calling
5925     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5926     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5927     * is responsible for handling this call.
5928     * </p>
5929     * <p>
5930     * <em>Note:</em> Accessibility events of certain types are not dispatched for
5931     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5932     * </p>
5933     *
5934     * @param event The event.
5935     *
5936     * @return True if the event population was completed.
5937     */
5938    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5939        if (mAccessibilityDelegate != null) {
5940            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5941        } else {
5942            return dispatchPopulateAccessibilityEventInternal(event);
5943        }
5944    }
5945
5946    /**
5947     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5948     *
5949     * Note: Called from the default {@link AccessibilityDelegate}.
5950     *
5951     * @hide
5952     */
5953    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5954        onPopulateAccessibilityEvent(event);
5955        return false;
5956    }
5957
5958    /**
5959     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5960     * giving a chance to this View to populate the accessibility event with its
5961     * text content. While this method is free to modify event
5962     * attributes other than text content, doing so should normally be performed in
5963     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5964     * <p>
5965     * Example: Adding formatted date string to an accessibility event in addition
5966     *          to the text added by the super implementation:
5967     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5968     *     super.onPopulateAccessibilityEvent(event);
5969     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5970     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5971     *         mCurrentDate.getTimeInMillis(), flags);
5972     *     event.getText().add(selectedDateUtterance);
5973     * }</pre>
5974     * <p>
5975     * If an {@link AccessibilityDelegate} has been specified via calling
5976     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5977     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5978     * is responsible for handling this call.
5979     * </p>
5980     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5981     * information to the event, in case the default implementation has basic information to add.
5982     * </p>
5983     *
5984     * @param event The accessibility event which to populate.
5985     *
5986     * @see #sendAccessibilityEvent(int)
5987     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5988     */
5989    @CallSuper
5990    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5991        if (mAccessibilityDelegate != null) {
5992            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5993        } else {
5994            onPopulateAccessibilityEventInternal(event);
5995        }
5996    }
5997
5998    /**
5999     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6000     *
6001     * Note: Called from the default {@link AccessibilityDelegate}.
6002     *
6003     * @hide
6004     */
6005    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6006    }
6007
6008    /**
6009     * Initializes an {@link AccessibilityEvent} with information about
6010     * this View which is the event source. In other words, the source of
6011     * an accessibility event is the view whose state change triggered firing
6012     * the event.
6013     * <p>
6014     * Example: Setting the password property of an event in addition
6015     *          to properties set by the super implementation:
6016     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6017     *     super.onInitializeAccessibilityEvent(event);
6018     *     event.setPassword(true);
6019     * }</pre>
6020     * <p>
6021     * If an {@link AccessibilityDelegate} has been specified via calling
6022     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6023     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6024     * is responsible for handling this call.
6025     * </p>
6026     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6027     * information to the event, in case the default implementation has basic information to add.
6028     * </p>
6029     * @param event The event to initialize.
6030     *
6031     * @see #sendAccessibilityEvent(int)
6032     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6033     */
6034    @CallSuper
6035    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6036        if (mAccessibilityDelegate != null) {
6037            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6038        } else {
6039            onInitializeAccessibilityEventInternal(event);
6040        }
6041    }
6042
6043    /**
6044     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6045     *
6046     * Note: Called from the default {@link AccessibilityDelegate}.
6047     *
6048     * @hide
6049     */
6050    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6051        event.setSource(this);
6052        event.setClassName(getAccessibilityClassName());
6053        event.setPackageName(getContext().getPackageName());
6054        event.setEnabled(isEnabled());
6055        event.setContentDescription(mContentDescription);
6056
6057        switch (event.getEventType()) {
6058            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6059                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6060                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6061                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6062                event.setItemCount(focusablesTempList.size());
6063                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6064                if (mAttachInfo != null) {
6065                    focusablesTempList.clear();
6066                }
6067            } break;
6068            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6069                CharSequence text = getIterableTextForAccessibility();
6070                if (text != null && text.length() > 0) {
6071                    event.setFromIndex(getAccessibilitySelectionStart());
6072                    event.setToIndex(getAccessibilitySelectionEnd());
6073                    event.setItemCount(text.length());
6074                }
6075            } break;
6076        }
6077    }
6078
6079    /**
6080     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6081     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6082     * This method is responsible for obtaining an accessibility node info from a
6083     * pool of reusable instances and calling
6084     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6085     * initialize the former.
6086     * <p>
6087     * Note: The client is responsible for recycling the obtained instance by calling
6088     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6089     * </p>
6090     *
6091     * @return A populated {@link AccessibilityNodeInfo}.
6092     *
6093     * @see AccessibilityNodeInfo
6094     */
6095    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6096        if (mAccessibilityDelegate != null) {
6097            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6098        } else {
6099            return createAccessibilityNodeInfoInternal();
6100        }
6101    }
6102
6103    /**
6104     * @see #createAccessibilityNodeInfo()
6105     *
6106     * @hide
6107     */
6108    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6109        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6110        if (provider != null) {
6111            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6112        } else {
6113            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6114            onInitializeAccessibilityNodeInfo(info);
6115            return info;
6116        }
6117    }
6118
6119    /**
6120     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6121     * The base implementation sets:
6122     * <ul>
6123     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6124     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6125     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6126     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6127     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6128     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6129     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6130     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6131     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6132     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6133     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6134     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6135     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6136     * </ul>
6137     * <p>
6138     * Subclasses should override this method, call the super implementation,
6139     * and set additional attributes.
6140     * </p>
6141     * <p>
6142     * If an {@link AccessibilityDelegate} has been specified via calling
6143     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6144     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6145     * is responsible for handling this call.
6146     * </p>
6147     *
6148     * @param info The instance to initialize.
6149     */
6150    @CallSuper
6151    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6152        if (mAccessibilityDelegate != null) {
6153            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6154        } else {
6155            onInitializeAccessibilityNodeInfoInternal(info);
6156        }
6157    }
6158
6159    /**
6160     * Gets the location of this view in screen coordinates.
6161     *
6162     * @param outRect The output location
6163     * @hide
6164     */
6165    public void getBoundsOnScreen(Rect outRect) {
6166        getBoundsOnScreen(outRect, false);
6167    }
6168
6169    /**
6170     * Gets the location of this view in screen coordinates.
6171     *
6172     * @param outRect The output location
6173     * @param clipToParent Whether to clip child bounds to the parent ones.
6174     * @hide
6175     */
6176    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6177        if (mAttachInfo == null) {
6178            return;
6179        }
6180
6181        RectF position = mAttachInfo.mTmpTransformRect;
6182        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6183
6184        if (!hasIdentityMatrix()) {
6185            getMatrix().mapRect(position);
6186        }
6187
6188        position.offset(mLeft, mTop);
6189
6190        ViewParent parent = mParent;
6191        while (parent instanceof View) {
6192            View parentView = (View) parent;
6193
6194            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6195
6196            if (clipToParent) {
6197                position.left = Math.max(position.left, 0);
6198                position.top = Math.max(position.top, 0);
6199                position.right = Math.min(position.right, parentView.getWidth());
6200                position.bottom = Math.min(position.bottom, parentView.getHeight());
6201            }
6202
6203            if (!parentView.hasIdentityMatrix()) {
6204                parentView.getMatrix().mapRect(position);
6205            }
6206
6207            position.offset(parentView.mLeft, parentView.mTop);
6208
6209            parent = parentView.mParent;
6210        }
6211
6212        if (parent instanceof ViewRootImpl) {
6213            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6214            position.offset(0, -viewRootImpl.mCurScrollY);
6215        }
6216
6217        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6218
6219        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
6220                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
6221    }
6222
6223    /**
6224     * Return the class name of this object to be used for accessibility purposes.
6225     * Subclasses should only override this if they are implementing something that
6226     * should be seen as a completely new class of view when used by accessibility,
6227     * unrelated to the class it is deriving from.  This is used to fill in
6228     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6229     */
6230    public CharSequence getAccessibilityClassName() {
6231        return View.class.getName();
6232    }
6233
6234    /**
6235     * Called when assist structure is being retrieved from a view as part of
6236     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6237     * @param structure Fill in with structured view data.  The default implementation
6238     * fills in all data that can be inferred from the view itself.
6239     */
6240    public void onProvideStructure(ViewStructure structure) {
6241        final int id = mID;
6242        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6243                && (id&0x0000ffff) != 0) {
6244            String pkg, type, entry;
6245            try {
6246                final Resources res = getResources();
6247                entry = res.getResourceEntryName(id);
6248                type = res.getResourceTypeName(id);
6249                pkg = res.getResourcePackageName(id);
6250            } catch (Resources.NotFoundException e) {
6251                entry = type = pkg = null;
6252            }
6253            structure.setId(id, pkg, type, entry);
6254        } else {
6255            structure.setId(id, null, null, null);
6256        }
6257        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6258        if (!hasIdentityMatrix()) {
6259            structure.setTransformation(getMatrix());
6260        }
6261        structure.setElevation(getZ());
6262        structure.setVisibility(getVisibility());
6263        structure.setEnabled(isEnabled());
6264        if (isClickable()) {
6265            structure.setClickable(true);
6266        }
6267        if (isFocusable()) {
6268            structure.setFocusable(true);
6269        }
6270        if (isFocused()) {
6271            structure.setFocused(true);
6272        }
6273        if (isAccessibilityFocused()) {
6274            structure.setAccessibilityFocused(true);
6275        }
6276        if (isSelected()) {
6277            structure.setSelected(true);
6278        }
6279        if (isActivated()) {
6280            structure.setActivated(true);
6281        }
6282        if (isLongClickable()) {
6283            structure.setLongClickable(true);
6284        }
6285        if (this instanceof Checkable) {
6286            structure.setCheckable(true);
6287            if (((Checkable)this).isChecked()) {
6288                structure.setChecked(true);
6289            }
6290        }
6291        if (isContextClickable()) {
6292            structure.setContextClickable(true);
6293        }
6294        structure.setClassName(getAccessibilityClassName().toString());
6295        structure.setContentDescription(getContentDescription());
6296    }
6297
6298    /**
6299     * Called when assist structure is being retrieved from a view as part of
6300     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6301     * generate additional virtual structure under this view.  The defaullt implementation
6302     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6303     * view's virtual accessibility nodes, if any.  You can override this for a more
6304     * optimal implementation providing this data.
6305     */
6306    public void onProvideVirtualStructure(ViewStructure structure) {
6307        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6308        if (provider != null) {
6309            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6310            structure.setChildCount(1);
6311            ViewStructure root = structure.newChild(0);
6312            populateVirtualStructure(root, provider, info);
6313            info.recycle();
6314        }
6315    }
6316
6317    private void populateVirtualStructure(ViewStructure structure,
6318            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6319        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6320                null, null, null);
6321        Rect rect = structure.getTempRect();
6322        info.getBoundsInParent(rect);
6323        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6324        structure.setVisibility(VISIBLE);
6325        structure.setEnabled(info.isEnabled());
6326        if (info.isClickable()) {
6327            structure.setClickable(true);
6328        }
6329        if (info.isFocusable()) {
6330            structure.setFocusable(true);
6331        }
6332        if (info.isFocused()) {
6333            structure.setFocused(true);
6334        }
6335        if (info.isAccessibilityFocused()) {
6336            structure.setAccessibilityFocused(true);
6337        }
6338        if (info.isSelected()) {
6339            structure.setSelected(true);
6340        }
6341        if (info.isLongClickable()) {
6342            structure.setLongClickable(true);
6343        }
6344        if (info.isCheckable()) {
6345            structure.setCheckable(true);
6346            if (info.isChecked()) {
6347                structure.setChecked(true);
6348            }
6349        }
6350        if (info.isContextClickable()) {
6351            structure.setContextClickable(true);
6352        }
6353        CharSequence cname = info.getClassName();
6354        structure.setClassName(cname != null ? cname.toString() : null);
6355        structure.setContentDescription(info.getContentDescription());
6356        if (info.getText() != null || info.getError() != null) {
6357            structure.setText(info.getText(), info.getTextSelectionStart(),
6358                    info.getTextSelectionEnd());
6359        }
6360        final int NCHILDREN = info.getChildCount();
6361        if (NCHILDREN > 0) {
6362            structure.setChildCount(NCHILDREN);
6363            for (int i=0; i<NCHILDREN; i++) {
6364                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6365                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6366                ViewStructure child = structure.newChild(i);
6367                populateVirtualStructure(child, provider, cinfo);
6368                cinfo.recycle();
6369            }
6370        }
6371    }
6372
6373    /**
6374     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6375     * implementation calls {@link #onProvideStructure} and
6376     * {@link #onProvideVirtualStructure}.
6377     */
6378    public void dispatchProvideStructure(ViewStructure structure) {
6379        if (!isAssistBlocked()) {
6380            onProvideStructure(structure);
6381            onProvideVirtualStructure(structure);
6382        } else {
6383            structure.setClassName(getAccessibilityClassName().toString());
6384            structure.setAssistBlocked(true);
6385        }
6386    }
6387
6388    /**
6389     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6390     *
6391     * Note: Called from the default {@link AccessibilityDelegate}.
6392     *
6393     * @hide
6394     */
6395    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6396        if (mAttachInfo == null) {
6397            return;
6398        }
6399
6400        Rect bounds = mAttachInfo.mTmpInvalRect;
6401
6402        getDrawingRect(bounds);
6403        info.setBoundsInParent(bounds);
6404
6405        getBoundsOnScreen(bounds, true);
6406        info.setBoundsInScreen(bounds);
6407
6408        ViewParent parent = getParentForAccessibility();
6409        if (parent instanceof View) {
6410            info.setParent((View) parent);
6411        }
6412
6413        if (mID != View.NO_ID) {
6414            View rootView = getRootView();
6415            if (rootView == null) {
6416                rootView = this;
6417            }
6418
6419            View label = rootView.findLabelForView(this, mID);
6420            if (label != null) {
6421                info.setLabeledBy(label);
6422            }
6423
6424            if ((mAttachInfo.mAccessibilityFetchFlags
6425                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6426                    && Resources.resourceHasPackage(mID)) {
6427                try {
6428                    String viewId = getResources().getResourceName(mID);
6429                    info.setViewIdResourceName(viewId);
6430                } catch (Resources.NotFoundException nfe) {
6431                    /* ignore */
6432                }
6433            }
6434        }
6435
6436        if (mLabelForId != View.NO_ID) {
6437            View rootView = getRootView();
6438            if (rootView == null) {
6439                rootView = this;
6440            }
6441            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6442            if (labeled != null) {
6443                info.setLabelFor(labeled);
6444            }
6445        }
6446
6447        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6448            View rootView = getRootView();
6449            if (rootView == null) {
6450                rootView = this;
6451            }
6452            View next = rootView.findViewInsideOutShouldExist(this,
6453                    mAccessibilityTraversalBeforeId);
6454            if (next != null && next.includeForAccessibility()) {
6455                info.setTraversalBefore(next);
6456            }
6457        }
6458
6459        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6460            View rootView = getRootView();
6461            if (rootView == null) {
6462                rootView = this;
6463            }
6464            View next = rootView.findViewInsideOutShouldExist(this,
6465                    mAccessibilityTraversalAfterId);
6466            if (next != null && next.includeForAccessibility()) {
6467                info.setTraversalAfter(next);
6468            }
6469        }
6470
6471        info.setVisibleToUser(isVisibleToUser());
6472
6473        info.setPackageName(mContext.getPackageName());
6474        info.setClassName(getAccessibilityClassName());
6475        info.setContentDescription(getContentDescription());
6476
6477        info.setEnabled(isEnabled());
6478        info.setClickable(isClickable());
6479        info.setFocusable(isFocusable());
6480        info.setFocused(isFocused());
6481        info.setAccessibilityFocused(isAccessibilityFocused());
6482        info.setSelected(isSelected());
6483        info.setLongClickable(isLongClickable());
6484        info.setContextClickable(isContextClickable());
6485        info.setLiveRegion(getAccessibilityLiveRegion());
6486
6487        // TODO: These make sense only if we are in an AdapterView but all
6488        // views can be selected. Maybe from accessibility perspective
6489        // we should report as selectable view in an AdapterView.
6490        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6491        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6492
6493        if (isFocusable()) {
6494            if (isFocused()) {
6495                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6496            } else {
6497                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6498            }
6499        }
6500
6501        if (!isAccessibilityFocused()) {
6502            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6503        } else {
6504            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6505        }
6506
6507        if (isClickable() && isEnabled()) {
6508            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6509        }
6510
6511        if (isLongClickable() && isEnabled()) {
6512            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6513        }
6514
6515        if (isContextClickable() && isEnabled()) {
6516            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6517        }
6518
6519        CharSequence text = getIterableTextForAccessibility();
6520        if (text != null && text.length() > 0) {
6521            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6522
6523            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6524            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6525            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6526            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6527                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6528                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6529        }
6530
6531        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6532    }
6533
6534    private View findLabelForView(View view, int labeledId) {
6535        if (mMatchLabelForPredicate == null) {
6536            mMatchLabelForPredicate = new MatchLabelForPredicate();
6537        }
6538        mMatchLabelForPredicate.mLabeledId = labeledId;
6539        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6540    }
6541
6542    /**
6543     * Computes whether this view is visible to the user. Such a view is
6544     * attached, visible, all its predecessors are visible, it is not clipped
6545     * entirely by its predecessors, and has an alpha greater than zero.
6546     *
6547     * @return Whether the view is visible on the screen.
6548     *
6549     * @hide
6550     */
6551    protected boolean isVisibleToUser() {
6552        return isVisibleToUser(null);
6553    }
6554
6555    /**
6556     * Computes whether the given portion of this view is visible to the user.
6557     * Such a view is attached, visible, all its predecessors are visible,
6558     * has an alpha greater than zero, and the specified portion is not
6559     * clipped entirely by its predecessors.
6560     *
6561     * @param boundInView the portion of the view to test; coordinates should be relative; may be
6562     *                    <code>null</code>, and the entire view will be tested in this case.
6563     *                    When <code>true</code> is returned by the function, the actual visible
6564     *                    region will be stored in this parameter; that is, if boundInView is fully
6565     *                    contained within the view, no modification will be made, otherwise regions
6566     *                    outside of the visible area of the view will be clipped.
6567     *
6568     * @return Whether the specified portion of the view is visible on the screen.
6569     *
6570     * @hide
6571     */
6572    protected boolean isVisibleToUser(Rect boundInView) {
6573        if (mAttachInfo != null) {
6574            // Attached to invisible window means this view is not visible.
6575            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6576                return false;
6577            }
6578            // An invisible predecessor or one with alpha zero means
6579            // that this view is not visible to the user.
6580            Object current = this;
6581            while (current instanceof View) {
6582                View view = (View) current;
6583                // We have attach info so this view is attached and there is no
6584                // need to check whether we reach to ViewRootImpl on the way up.
6585                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6586                        view.getVisibility() != VISIBLE) {
6587                    return false;
6588                }
6589                current = view.mParent;
6590            }
6591            // Check if the view is entirely covered by its predecessors.
6592            Rect visibleRect = mAttachInfo.mTmpInvalRect;
6593            Point offset = mAttachInfo.mPoint;
6594            if (!getGlobalVisibleRect(visibleRect, offset)) {
6595                return false;
6596            }
6597            // Check if the visible portion intersects the rectangle of interest.
6598            if (boundInView != null) {
6599                visibleRect.offset(-offset.x, -offset.y);
6600                return boundInView.intersect(visibleRect);
6601            }
6602            return true;
6603        }
6604        return false;
6605    }
6606
6607    /**
6608     * Returns the delegate for implementing accessibility support via
6609     * composition. For more details see {@link AccessibilityDelegate}.
6610     *
6611     * @return The delegate, or null if none set.
6612     *
6613     * @hide
6614     */
6615    public AccessibilityDelegate getAccessibilityDelegate() {
6616        return mAccessibilityDelegate;
6617    }
6618
6619    /**
6620     * Sets a delegate for implementing accessibility support via composition as
6621     * opposed to inheritance. The delegate's primary use is for implementing
6622     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
6623     *
6624     * @param delegate The delegate instance.
6625     *
6626     * @see AccessibilityDelegate
6627     */
6628    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6629        mAccessibilityDelegate = delegate;
6630    }
6631
6632    /**
6633     * Gets the provider for managing a virtual view hierarchy rooted at this View
6634     * and reported to {@link android.accessibilityservice.AccessibilityService}s
6635     * that explore the window content.
6636     * <p>
6637     * If this method returns an instance, this instance is responsible for managing
6638     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6639     * View including the one representing the View itself. Similarly the returned
6640     * instance is responsible for performing accessibility actions on any virtual
6641     * view or the root view itself.
6642     * </p>
6643     * <p>
6644     * If an {@link AccessibilityDelegate} has been specified via calling
6645     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6646     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6647     * is responsible for handling this call.
6648     * </p>
6649     *
6650     * @return The provider.
6651     *
6652     * @see AccessibilityNodeProvider
6653     */
6654    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6655        if (mAccessibilityDelegate != null) {
6656            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6657        } else {
6658            return null;
6659        }
6660    }
6661
6662    /**
6663     * Gets the unique identifier of this view on the screen for accessibility purposes.
6664     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6665     *
6666     * @return The view accessibility id.
6667     *
6668     * @hide
6669     */
6670    public int getAccessibilityViewId() {
6671        if (mAccessibilityViewId == NO_ID) {
6672            mAccessibilityViewId = sNextAccessibilityViewId++;
6673        }
6674        return mAccessibilityViewId;
6675    }
6676
6677    /**
6678     * Gets the unique identifier of the window in which this View reseides.
6679     *
6680     * @return The window accessibility id.
6681     *
6682     * @hide
6683     */
6684    public int getAccessibilityWindowId() {
6685        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6686                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6687    }
6688
6689    /**
6690     * Returns the {@link View}'s content description.
6691     * <p>
6692     * <strong>Note:</strong> Do not override this method, as it will have no
6693     * effect on the content description presented to accessibility services.
6694     * You must call {@link #setContentDescription(CharSequence)} to modify the
6695     * content description.
6696     *
6697     * @return the content description
6698     * @see #setContentDescription(CharSequence)
6699     * @attr ref android.R.styleable#View_contentDescription
6700     */
6701    @ViewDebug.ExportedProperty(category = "accessibility")
6702    public CharSequence getContentDescription() {
6703        return mContentDescription;
6704    }
6705
6706    /**
6707     * Sets the {@link View}'s content description.
6708     * <p>
6709     * A content description briefly describes the view and is primarily used
6710     * for accessibility support to determine how a view should be presented to
6711     * the user. In the case of a view with no textual representation, such as
6712     * {@link android.widget.ImageButton}, a useful content description
6713     * explains what the view does. For example, an image button with a phone
6714     * icon that is used to place a call may use "Call" as its content
6715     * description. An image of a floppy disk that is used to save a file may
6716     * use "Save".
6717     *
6718     * @param contentDescription The content description.
6719     * @see #getContentDescription()
6720     * @attr ref android.R.styleable#View_contentDescription
6721     */
6722    @RemotableViewMethod
6723    public void setContentDescription(CharSequence contentDescription) {
6724        if (mContentDescription == null) {
6725            if (contentDescription == null) {
6726                return;
6727            }
6728        } else if (mContentDescription.equals(contentDescription)) {
6729            return;
6730        }
6731        mContentDescription = contentDescription;
6732        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6733        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6734            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6735            notifySubtreeAccessibilityStateChangedIfNeeded();
6736        } else {
6737            notifyViewAccessibilityStateChangedIfNeeded(
6738                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6739        }
6740    }
6741
6742    /**
6743     * Sets the id of a view before which this one is visited in accessibility traversal.
6744     * A screen-reader must visit the content of this view before the content of the one
6745     * it precedes. For example, if view B is set to be before view A, then a screen-reader
6746     * will traverse the entire content of B before traversing the entire content of A,
6747     * regardles of what traversal strategy it is using.
6748     * <p>
6749     * Views that do not have specified before/after relationships are traversed in order
6750     * determined by the screen-reader.
6751     * </p>
6752     * <p>
6753     * Setting that this view is before a view that is not important for accessibility
6754     * or if this view is not important for accessibility will have no effect as the
6755     * screen-reader is not aware of unimportant views.
6756     * </p>
6757     *
6758     * @param beforeId The id of a view this one precedes in accessibility traversal.
6759     *
6760     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6761     *
6762     * @see #setImportantForAccessibility(int)
6763     */
6764    @RemotableViewMethod
6765    public void setAccessibilityTraversalBefore(int beforeId) {
6766        if (mAccessibilityTraversalBeforeId == beforeId) {
6767            return;
6768        }
6769        mAccessibilityTraversalBeforeId = beforeId;
6770        notifyViewAccessibilityStateChangedIfNeeded(
6771                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6772    }
6773
6774    /**
6775     * Gets the id of a view before which this one is visited in accessibility traversal.
6776     *
6777     * @return The id of a view this one precedes in accessibility traversal if
6778     *         specified, otherwise {@link #NO_ID}.
6779     *
6780     * @see #setAccessibilityTraversalBefore(int)
6781     */
6782    public int getAccessibilityTraversalBefore() {
6783        return mAccessibilityTraversalBeforeId;
6784    }
6785
6786    /**
6787     * Sets the id of a view after which this one is visited in accessibility traversal.
6788     * A screen-reader must visit the content of the other view before the content of this
6789     * one. For example, if view B is set to be after view A, then a screen-reader
6790     * will traverse the entire content of A before traversing the entire content of B,
6791     * regardles of what traversal strategy it is using.
6792     * <p>
6793     * Views that do not have specified before/after relationships are traversed in order
6794     * determined by the screen-reader.
6795     * </p>
6796     * <p>
6797     * Setting that this view is after a view that is not important for accessibility
6798     * or if this view is not important for accessibility will have no effect as the
6799     * screen-reader is not aware of unimportant views.
6800     * </p>
6801     *
6802     * @param afterId The id of a view this one succedees in accessibility traversal.
6803     *
6804     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6805     *
6806     * @see #setImportantForAccessibility(int)
6807     */
6808    @RemotableViewMethod
6809    public void setAccessibilityTraversalAfter(int afterId) {
6810        if (mAccessibilityTraversalAfterId == afterId) {
6811            return;
6812        }
6813        mAccessibilityTraversalAfterId = afterId;
6814        notifyViewAccessibilityStateChangedIfNeeded(
6815                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6816    }
6817
6818    /**
6819     * Gets the id of a view after which this one is visited in accessibility traversal.
6820     *
6821     * @return The id of a view this one succeedes in accessibility traversal if
6822     *         specified, otherwise {@link #NO_ID}.
6823     *
6824     * @see #setAccessibilityTraversalAfter(int)
6825     */
6826    public int getAccessibilityTraversalAfter() {
6827        return mAccessibilityTraversalAfterId;
6828    }
6829
6830    /**
6831     * Gets the id of a view for which this view serves as a label for
6832     * accessibility purposes.
6833     *
6834     * @return The labeled view id.
6835     */
6836    @ViewDebug.ExportedProperty(category = "accessibility")
6837    public int getLabelFor() {
6838        return mLabelForId;
6839    }
6840
6841    /**
6842     * Sets the id of a view for which this view serves as a label for
6843     * accessibility purposes.
6844     *
6845     * @param id The labeled view id.
6846     */
6847    @RemotableViewMethod
6848    public void setLabelFor(@IdRes int id) {
6849        if (mLabelForId == id) {
6850            return;
6851        }
6852        mLabelForId = id;
6853        if (mLabelForId != View.NO_ID
6854                && mID == View.NO_ID) {
6855            mID = generateViewId();
6856        }
6857        notifyViewAccessibilityStateChangedIfNeeded(
6858                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6859    }
6860
6861    /**
6862     * Invoked whenever this view loses focus, either by losing window focus or by losing
6863     * focus within its window. This method can be used to clear any state tied to the
6864     * focus. For instance, if a button is held pressed with the trackball and the window
6865     * loses focus, this method can be used to cancel the press.
6866     *
6867     * Subclasses of View overriding this method should always call super.onFocusLost().
6868     *
6869     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6870     * @see #onWindowFocusChanged(boolean)
6871     *
6872     * @hide pending API council approval
6873     */
6874    @CallSuper
6875    protected void onFocusLost() {
6876        resetPressedState();
6877    }
6878
6879    private void resetPressedState() {
6880        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6881            return;
6882        }
6883
6884        if (isPressed()) {
6885            setPressed(false);
6886
6887            if (!mHasPerformedLongPress) {
6888                removeLongPressCallback();
6889            }
6890        }
6891    }
6892
6893    /**
6894     * Returns true if this view has focus
6895     *
6896     * @return True if this view has focus, false otherwise.
6897     */
6898    @ViewDebug.ExportedProperty(category = "focus")
6899    public boolean isFocused() {
6900        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6901    }
6902
6903    /**
6904     * Find the view in the hierarchy rooted at this view that currently has
6905     * focus.
6906     *
6907     * @return The view that currently has focus, or null if no focused view can
6908     *         be found.
6909     */
6910    public View findFocus() {
6911        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6912    }
6913
6914    /**
6915     * Indicates whether this view is one of the set of scrollable containers in
6916     * its window.
6917     *
6918     * @return whether this view is one of the set of scrollable containers in
6919     * its window
6920     *
6921     * @attr ref android.R.styleable#View_isScrollContainer
6922     */
6923    public boolean isScrollContainer() {
6924        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6925    }
6926
6927    /**
6928     * Change whether this view is one of the set of scrollable containers in
6929     * its window.  This will be used to determine whether the window can
6930     * resize or must pan when a soft input area is open -- scrollable
6931     * containers allow the window to use resize mode since the container
6932     * will appropriately shrink.
6933     *
6934     * @attr ref android.R.styleable#View_isScrollContainer
6935     */
6936    public void setScrollContainer(boolean isScrollContainer) {
6937        if (isScrollContainer) {
6938            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6939                mAttachInfo.mScrollContainers.add(this);
6940                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6941            }
6942            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6943        } else {
6944            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6945                mAttachInfo.mScrollContainers.remove(this);
6946            }
6947            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6948        }
6949    }
6950
6951    /**
6952     * Returns the quality of the drawing cache.
6953     *
6954     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6955     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6956     *
6957     * @see #setDrawingCacheQuality(int)
6958     * @see #setDrawingCacheEnabled(boolean)
6959     * @see #isDrawingCacheEnabled()
6960     *
6961     * @attr ref android.R.styleable#View_drawingCacheQuality
6962     */
6963    @DrawingCacheQuality
6964    public int getDrawingCacheQuality() {
6965        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6966    }
6967
6968    /**
6969     * Set the drawing cache quality of this view. This value is used only when the
6970     * drawing cache is enabled
6971     *
6972     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6973     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6974     *
6975     * @see #getDrawingCacheQuality()
6976     * @see #setDrawingCacheEnabled(boolean)
6977     * @see #isDrawingCacheEnabled()
6978     *
6979     * @attr ref android.R.styleable#View_drawingCacheQuality
6980     */
6981    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6982        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6983    }
6984
6985    /**
6986     * Returns whether the screen should remain on, corresponding to the current
6987     * value of {@link #KEEP_SCREEN_ON}.
6988     *
6989     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6990     *
6991     * @see #setKeepScreenOn(boolean)
6992     *
6993     * @attr ref android.R.styleable#View_keepScreenOn
6994     */
6995    public boolean getKeepScreenOn() {
6996        return (mViewFlags & KEEP_SCREEN_ON) != 0;
6997    }
6998
6999    /**
7000     * Controls whether the screen should remain on, modifying the
7001     * value of {@link #KEEP_SCREEN_ON}.
7002     *
7003     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7004     *
7005     * @see #getKeepScreenOn()
7006     *
7007     * @attr ref android.R.styleable#View_keepScreenOn
7008     */
7009    public void setKeepScreenOn(boolean keepScreenOn) {
7010        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7011    }
7012
7013    /**
7014     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7015     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7016     *
7017     * @attr ref android.R.styleable#View_nextFocusLeft
7018     */
7019    public int getNextFocusLeftId() {
7020        return mNextFocusLeftId;
7021    }
7022
7023    /**
7024     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7025     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7026     * decide automatically.
7027     *
7028     * @attr ref android.R.styleable#View_nextFocusLeft
7029     */
7030    public void setNextFocusLeftId(int nextFocusLeftId) {
7031        mNextFocusLeftId = nextFocusLeftId;
7032    }
7033
7034    /**
7035     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7036     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7037     *
7038     * @attr ref android.R.styleable#View_nextFocusRight
7039     */
7040    public int getNextFocusRightId() {
7041        return mNextFocusRightId;
7042    }
7043
7044    /**
7045     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7046     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7047     * decide automatically.
7048     *
7049     * @attr ref android.R.styleable#View_nextFocusRight
7050     */
7051    public void setNextFocusRightId(int nextFocusRightId) {
7052        mNextFocusRightId = nextFocusRightId;
7053    }
7054
7055    /**
7056     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7057     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7058     *
7059     * @attr ref android.R.styleable#View_nextFocusUp
7060     */
7061    public int getNextFocusUpId() {
7062        return mNextFocusUpId;
7063    }
7064
7065    /**
7066     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7067     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7068     * decide automatically.
7069     *
7070     * @attr ref android.R.styleable#View_nextFocusUp
7071     */
7072    public void setNextFocusUpId(int nextFocusUpId) {
7073        mNextFocusUpId = nextFocusUpId;
7074    }
7075
7076    /**
7077     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7078     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7079     *
7080     * @attr ref android.R.styleable#View_nextFocusDown
7081     */
7082    public int getNextFocusDownId() {
7083        return mNextFocusDownId;
7084    }
7085
7086    /**
7087     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7088     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7089     * decide automatically.
7090     *
7091     * @attr ref android.R.styleable#View_nextFocusDown
7092     */
7093    public void setNextFocusDownId(int nextFocusDownId) {
7094        mNextFocusDownId = nextFocusDownId;
7095    }
7096
7097    /**
7098     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7099     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7100     *
7101     * @attr ref android.R.styleable#View_nextFocusForward
7102     */
7103    public int getNextFocusForwardId() {
7104        return mNextFocusForwardId;
7105    }
7106
7107    /**
7108     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7109     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7110     * decide automatically.
7111     *
7112     * @attr ref android.R.styleable#View_nextFocusForward
7113     */
7114    public void setNextFocusForwardId(int nextFocusForwardId) {
7115        mNextFocusForwardId = nextFocusForwardId;
7116    }
7117
7118    /**
7119     * Returns the visibility of this view and all of its ancestors
7120     *
7121     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7122     */
7123    public boolean isShown() {
7124        View current = this;
7125        //noinspection ConstantConditions
7126        do {
7127            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7128                return false;
7129            }
7130            ViewParent parent = current.mParent;
7131            if (parent == null) {
7132                return false; // We are not attached to the view root
7133            }
7134            if (!(parent instanceof View)) {
7135                return true;
7136            }
7137            current = (View) parent;
7138        } while (current != null);
7139
7140        return false;
7141    }
7142
7143    /**
7144     * Called by the view hierarchy when the content insets for a window have
7145     * changed, to allow it to adjust its content to fit within those windows.
7146     * The content insets tell you the space that the status bar, input method,
7147     * and other system windows infringe on the application's window.
7148     *
7149     * <p>You do not normally need to deal with this function, since the default
7150     * window decoration given to applications takes care of applying it to the
7151     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7152     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7153     * and your content can be placed under those system elements.  You can then
7154     * use this method within your view hierarchy if you have parts of your UI
7155     * which you would like to ensure are not being covered.
7156     *
7157     * <p>The default implementation of this method simply applies the content
7158     * insets to the view's padding, consuming that content (modifying the
7159     * insets to be 0), and returning true.  This behavior is off by default, but can
7160     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7161     *
7162     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7163     * insets object is propagated down the hierarchy, so any changes made to it will
7164     * be seen by all following views (including potentially ones above in
7165     * the hierarchy since this is a depth-first traversal).  The first view
7166     * that returns true will abort the entire traversal.
7167     *
7168     * <p>The default implementation works well for a situation where it is
7169     * used with a container that covers the entire window, allowing it to
7170     * apply the appropriate insets to its content on all edges.  If you need
7171     * a more complicated layout (such as two different views fitting system
7172     * windows, one on the top of the window, and one on the bottom),
7173     * you can override the method and handle the insets however you would like.
7174     * Note that the insets provided by the framework are always relative to the
7175     * far edges of the window, not accounting for the location of the called view
7176     * within that window.  (In fact when this method is called you do not yet know
7177     * where the layout will place the view, as it is done before layout happens.)
7178     *
7179     * <p>Note: unlike many View methods, there is no dispatch phase to this
7180     * call.  If you are overriding it in a ViewGroup and want to allow the
7181     * call to continue to your children, you must be sure to call the super
7182     * implementation.
7183     *
7184     * <p>Here is a sample layout that makes use of fitting system windows
7185     * to have controls for a video view placed inside of the window decorations
7186     * that it hides and shows.  This can be used with code like the second
7187     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7188     *
7189     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7190     *
7191     * @param insets Current content insets of the window.  Prior to
7192     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7193     * the insets or else you and Android will be unhappy.
7194     *
7195     * @return {@code true} if this view applied the insets and it should not
7196     * continue propagating further down the hierarchy, {@code false} otherwise.
7197     * @see #getFitsSystemWindows()
7198     * @see #setFitsSystemWindows(boolean)
7199     * @see #setSystemUiVisibility(int)
7200     *
7201     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7202     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7203     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7204     * to implement handling their own insets.
7205     */
7206    protected boolean fitSystemWindows(Rect insets) {
7207        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7208            if (insets == null) {
7209                // Null insets by definition have already been consumed.
7210                // This call cannot apply insets since there are none to apply,
7211                // so return false.
7212                return false;
7213            }
7214            // If we're not in the process of dispatching the newer apply insets call,
7215            // that means we're not in the compatibility path. Dispatch into the newer
7216            // apply insets path and take things from there.
7217            try {
7218                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7219                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7220            } finally {
7221                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7222            }
7223        } else {
7224            // We're being called from the newer apply insets path.
7225            // Perform the standard fallback behavior.
7226            return fitSystemWindowsInt(insets);
7227        }
7228    }
7229
7230    private boolean fitSystemWindowsInt(Rect insets) {
7231        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7232            mUserPaddingStart = UNDEFINED_PADDING;
7233            mUserPaddingEnd = UNDEFINED_PADDING;
7234            Rect localInsets = sThreadLocal.get();
7235            if (localInsets == null) {
7236                localInsets = new Rect();
7237                sThreadLocal.set(localInsets);
7238            }
7239            boolean res = computeFitSystemWindows(insets, localInsets);
7240            mUserPaddingLeftInitial = localInsets.left;
7241            mUserPaddingRightInitial = localInsets.right;
7242            internalSetPadding(localInsets.left, localInsets.top,
7243                    localInsets.right, localInsets.bottom);
7244            return res;
7245        }
7246        return false;
7247    }
7248
7249    /**
7250     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7251     *
7252     * <p>This method should be overridden by views that wish to apply a policy different from or
7253     * in addition to the default behavior. Clients that wish to force a view subtree
7254     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7255     *
7256     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7257     * it will be called during dispatch instead of this method. The listener may optionally
7258     * call this method from its own implementation if it wishes to apply the view's default
7259     * insets policy in addition to its own.</p>
7260     *
7261     * <p>Implementations of this method should either return the insets parameter unchanged
7262     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7263     * that this view applied itself. This allows new inset types added in future platform
7264     * versions to pass through existing implementations unchanged without being erroneously
7265     * consumed.</p>
7266     *
7267     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7268     * property is set then the view will consume the system window insets and apply them
7269     * as padding for the view.</p>
7270     *
7271     * @param insets Insets to apply
7272     * @return The supplied insets with any applied insets consumed
7273     */
7274    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7275        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7276            // We weren't called from within a direct call to fitSystemWindows,
7277            // call into it as a fallback in case we're in a class that overrides it
7278            // and has logic to perform.
7279            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7280                return insets.consumeSystemWindowInsets();
7281            }
7282        } else {
7283            // We were called from within a direct call to fitSystemWindows.
7284            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7285                return insets.consumeSystemWindowInsets();
7286            }
7287        }
7288        return insets;
7289    }
7290
7291    /**
7292     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7293     * window insets to this view. The listener's
7294     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7295     * method will be called instead of the view's
7296     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7297     *
7298     * @param listener Listener to set
7299     *
7300     * @see #onApplyWindowInsets(WindowInsets)
7301     */
7302    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7303        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7304    }
7305
7306    /**
7307     * Request to apply the given window insets to this view or another view in its subtree.
7308     *
7309     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7310     * obscured by window decorations or overlays. This can include the status and navigation bars,
7311     * action bars, input methods and more. New inset categories may be added in the future.
7312     * The method returns the insets provided minus any that were applied by this view or its
7313     * children.</p>
7314     *
7315     * <p>Clients wishing to provide custom behavior should override the
7316     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7317     * {@link OnApplyWindowInsetsListener} via the
7318     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7319     * method.</p>
7320     *
7321     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7322     * </p>
7323     *
7324     * @param insets Insets to apply
7325     * @return The provided insets minus the insets that were consumed
7326     */
7327    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7328        try {
7329            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7330            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7331                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7332            } else {
7333                return onApplyWindowInsets(insets);
7334            }
7335        } finally {
7336            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7337        }
7338    }
7339
7340    /**
7341     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7342     * only available if the view is attached.
7343     *
7344     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7345     */
7346    public WindowInsets getRootWindowInsets() {
7347        if (mAttachInfo != null) {
7348            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7349        }
7350        return null;
7351    }
7352
7353    /**
7354     * @hide Compute the insets that should be consumed by this view and the ones
7355     * that should propagate to those under it.
7356     */
7357    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7358        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7359                || mAttachInfo == null
7360                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7361                        && !mAttachInfo.mOverscanRequested)) {
7362            outLocalInsets.set(inoutInsets);
7363            inoutInsets.set(0, 0, 0, 0);
7364            return true;
7365        } else {
7366            // The application wants to take care of fitting system window for
7367            // the content...  however we still need to take care of any overscan here.
7368            final Rect overscan = mAttachInfo.mOverscanInsets;
7369            outLocalInsets.set(overscan);
7370            inoutInsets.left -= overscan.left;
7371            inoutInsets.top -= overscan.top;
7372            inoutInsets.right -= overscan.right;
7373            inoutInsets.bottom -= overscan.bottom;
7374            return false;
7375        }
7376    }
7377
7378    /**
7379     * Compute insets that should be consumed by this view and the ones that should propagate
7380     * to those under it.
7381     *
7382     * @param in Insets currently being processed by this View, likely received as a parameter
7383     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7384     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7385     *                       by this view
7386     * @return Insets that should be passed along to views under this one
7387     */
7388    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7389        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7390                || mAttachInfo == null
7391                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7392            outLocalInsets.set(in.getSystemWindowInsets());
7393            return in.consumeSystemWindowInsets();
7394        } else {
7395            outLocalInsets.set(0, 0, 0, 0);
7396            return in;
7397        }
7398    }
7399
7400    /**
7401     * Sets whether or not this view should account for system screen decorations
7402     * such as the status bar and inset its content; that is, controlling whether
7403     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7404     * executed.  See that method for more details.
7405     *
7406     * <p>Note that if you are providing your own implementation of
7407     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7408     * flag to true -- your implementation will be overriding the default
7409     * implementation that checks this flag.
7410     *
7411     * @param fitSystemWindows If true, then the default implementation of
7412     * {@link #fitSystemWindows(Rect)} will be executed.
7413     *
7414     * @attr ref android.R.styleable#View_fitsSystemWindows
7415     * @see #getFitsSystemWindows()
7416     * @see #fitSystemWindows(Rect)
7417     * @see #setSystemUiVisibility(int)
7418     */
7419    public void setFitsSystemWindows(boolean fitSystemWindows) {
7420        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7421    }
7422
7423    /**
7424     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7425     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7426     * will be executed.
7427     *
7428     * @return {@code true} if the default implementation of
7429     * {@link #fitSystemWindows(Rect)} will be executed.
7430     *
7431     * @attr ref android.R.styleable#View_fitsSystemWindows
7432     * @see #setFitsSystemWindows(boolean)
7433     * @see #fitSystemWindows(Rect)
7434     * @see #setSystemUiVisibility(int)
7435     */
7436    @ViewDebug.ExportedProperty
7437    public boolean getFitsSystemWindows() {
7438        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7439    }
7440
7441    /** @hide */
7442    public boolean fitsSystemWindows() {
7443        return getFitsSystemWindows();
7444    }
7445
7446    /**
7447     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7448     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7449     */
7450    public void requestFitSystemWindows() {
7451        if (mParent != null) {
7452            mParent.requestFitSystemWindows();
7453        }
7454    }
7455
7456    /**
7457     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7458     */
7459    public void requestApplyInsets() {
7460        requestFitSystemWindows();
7461    }
7462
7463    /**
7464     * For use by PhoneWindow to make its own system window fitting optional.
7465     * @hide
7466     */
7467    public void makeOptionalFitsSystemWindows() {
7468        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7469    }
7470
7471    /**
7472     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
7473     * treat them as such.
7474     * @hide
7475     */
7476    public void getOutsets(Rect outOutsetRect) {
7477        if (mAttachInfo != null) {
7478            outOutsetRect.set(mAttachInfo.mOutsets);
7479        } else {
7480            outOutsetRect.setEmpty();
7481        }
7482    }
7483
7484    /**
7485     * Returns the visibility status for this view.
7486     *
7487     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7488     * @attr ref android.R.styleable#View_visibility
7489     */
7490    @ViewDebug.ExportedProperty(mapping = {
7491        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
7492        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7493        @ViewDebug.IntToString(from = GONE,      to = "GONE")
7494    })
7495    @Visibility
7496    public int getVisibility() {
7497        return mViewFlags & VISIBILITY_MASK;
7498    }
7499
7500    /**
7501     * Set the enabled state of this view.
7502     *
7503     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7504     * @attr ref android.R.styleable#View_visibility
7505     */
7506    @RemotableViewMethod
7507    public void setVisibility(@Visibility int visibility) {
7508        setFlags(visibility, VISIBILITY_MASK);
7509    }
7510
7511    /**
7512     * Returns the enabled status for this view. The interpretation of the
7513     * enabled state varies by subclass.
7514     *
7515     * @return True if this view is enabled, false otherwise.
7516     */
7517    @ViewDebug.ExportedProperty
7518    public boolean isEnabled() {
7519        return (mViewFlags & ENABLED_MASK) == ENABLED;
7520    }
7521
7522    /**
7523     * Set the enabled state of this view. The interpretation of the enabled
7524     * state varies by subclass.
7525     *
7526     * @param enabled True if this view is enabled, false otherwise.
7527     */
7528    @RemotableViewMethod
7529    public void setEnabled(boolean enabled) {
7530        if (enabled == isEnabled()) return;
7531
7532        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7533
7534        /*
7535         * The View most likely has to change its appearance, so refresh
7536         * the drawable state.
7537         */
7538        refreshDrawableState();
7539
7540        // Invalidate too, since the default behavior for views is to be
7541        // be drawn at 50% alpha rather than to change the drawable.
7542        invalidate(true);
7543
7544        if (!enabled) {
7545            cancelPendingInputEvents();
7546        }
7547    }
7548
7549    /**
7550     * Set whether this view can receive the focus.
7551     *
7552     * Setting this to false will also ensure that this view is not focusable
7553     * in touch mode.
7554     *
7555     * @param focusable If true, this view can receive the focus.
7556     *
7557     * @see #setFocusableInTouchMode(boolean)
7558     * @attr ref android.R.styleable#View_focusable
7559     */
7560    public void setFocusable(boolean focusable) {
7561        if (!focusable) {
7562            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7563        }
7564        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7565    }
7566
7567    /**
7568     * Set whether this view can receive focus while in touch mode.
7569     *
7570     * Setting this to true will also ensure that this view is focusable.
7571     *
7572     * @param focusableInTouchMode If true, this view can receive the focus while
7573     *   in touch mode.
7574     *
7575     * @see #setFocusable(boolean)
7576     * @attr ref android.R.styleable#View_focusableInTouchMode
7577     */
7578    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7579        // Focusable in touch mode should always be set before the focusable flag
7580        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7581        // which, in touch mode, will not successfully request focus on this view
7582        // because the focusable in touch mode flag is not set
7583        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7584        if (focusableInTouchMode) {
7585            setFlags(FOCUSABLE, FOCUSABLE_MASK);
7586        }
7587    }
7588
7589    /**
7590     * Set whether this view should have sound effects enabled for events such as
7591     * clicking and touching.
7592     *
7593     * <p>You may wish to disable sound effects for a view if you already play sounds,
7594     * for instance, a dial key that plays dtmf tones.
7595     *
7596     * @param soundEffectsEnabled whether sound effects are enabled for this view.
7597     * @see #isSoundEffectsEnabled()
7598     * @see #playSoundEffect(int)
7599     * @attr ref android.R.styleable#View_soundEffectsEnabled
7600     */
7601    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7602        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7603    }
7604
7605    /**
7606     * @return whether this view should have sound effects enabled for events such as
7607     *     clicking and touching.
7608     *
7609     * @see #setSoundEffectsEnabled(boolean)
7610     * @see #playSoundEffect(int)
7611     * @attr ref android.R.styleable#View_soundEffectsEnabled
7612     */
7613    @ViewDebug.ExportedProperty
7614    public boolean isSoundEffectsEnabled() {
7615        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7616    }
7617
7618    /**
7619     * Set whether this view should have haptic feedback for events such as
7620     * long presses.
7621     *
7622     * <p>You may wish to disable haptic feedback if your view already controls
7623     * its own haptic feedback.
7624     *
7625     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7626     * @see #isHapticFeedbackEnabled()
7627     * @see #performHapticFeedback(int)
7628     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7629     */
7630    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7631        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7632    }
7633
7634    /**
7635     * @return whether this view should have haptic feedback enabled for events
7636     * long presses.
7637     *
7638     * @see #setHapticFeedbackEnabled(boolean)
7639     * @see #performHapticFeedback(int)
7640     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7641     */
7642    @ViewDebug.ExportedProperty
7643    public boolean isHapticFeedbackEnabled() {
7644        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7645    }
7646
7647    /**
7648     * Returns the layout direction for this view.
7649     *
7650     * @return One of {@link #LAYOUT_DIRECTION_LTR},
7651     *   {@link #LAYOUT_DIRECTION_RTL},
7652     *   {@link #LAYOUT_DIRECTION_INHERIT} or
7653     *   {@link #LAYOUT_DIRECTION_LOCALE}.
7654     *
7655     * @attr ref android.R.styleable#View_layoutDirection
7656     *
7657     * @hide
7658     */
7659    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7660        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7661        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7662        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7663        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7664    })
7665    @LayoutDir
7666    public int getRawLayoutDirection() {
7667        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7668    }
7669
7670    /**
7671     * Set the layout direction for this view. This will propagate a reset of layout direction
7672     * resolution to the view's children and resolve layout direction for this view.
7673     *
7674     * @param layoutDirection the layout direction to set. Should be one of:
7675     *
7676     * {@link #LAYOUT_DIRECTION_LTR},
7677     * {@link #LAYOUT_DIRECTION_RTL},
7678     * {@link #LAYOUT_DIRECTION_INHERIT},
7679     * {@link #LAYOUT_DIRECTION_LOCALE}.
7680     *
7681     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7682     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7683     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7684     *
7685     * @attr ref android.R.styleable#View_layoutDirection
7686     */
7687    @RemotableViewMethod
7688    public void setLayoutDirection(@LayoutDir int layoutDirection) {
7689        if (getRawLayoutDirection() != layoutDirection) {
7690            // Reset the current layout direction and the resolved one
7691            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7692            resetRtlProperties();
7693            // Set the new layout direction (filtered)
7694            mPrivateFlags2 |=
7695                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7696            // We need to resolve all RTL properties as they all depend on layout direction
7697            resolveRtlPropertiesIfNeeded();
7698            requestLayout();
7699            invalidate(true);
7700        }
7701    }
7702
7703    /**
7704     * Returns the resolved layout direction for this view.
7705     *
7706     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7707     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7708     *
7709     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7710     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7711     *
7712     * @attr ref android.R.styleable#View_layoutDirection
7713     */
7714    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7715        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7716        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7717    })
7718    @ResolvedLayoutDir
7719    public int getLayoutDirection() {
7720        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7721        if (targetSdkVersion < JELLY_BEAN_MR1) {
7722            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7723            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7724        }
7725        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7726                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7727    }
7728
7729    /**
7730     * Indicates whether or not this view's layout is right-to-left. This is resolved from
7731     * layout attribute and/or the inherited value from the parent
7732     *
7733     * @return true if the layout is right-to-left.
7734     *
7735     * @hide
7736     */
7737    @ViewDebug.ExportedProperty(category = "layout")
7738    public boolean isLayoutRtl() {
7739        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7740    }
7741
7742    /**
7743     * Indicates whether the view is currently tracking transient state that the
7744     * app should not need to concern itself with saving and restoring, but that
7745     * the framework should take special note to preserve when possible.
7746     *
7747     * <p>A view with transient state cannot be trivially rebound from an external
7748     * data source, such as an adapter binding item views in a list. This may be
7749     * because the view is performing an animation, tracking user selection
7750     * of content, or similar.</p>
7751     *
7752     * @return true if the view has transient state
7753     */
7754    @ViewDebug.ExportedProperty(category = "layout")
7755    public boolean hasTransientState() {
7756        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7757    }
7758
7759    /**
7760     * Set whether this view is currently tracking transient state that the
7761     * framework should attempt to preserve when possible. This flag is reference counted,
7762     * so every call to setHasTransientState(true) should be paired with a later call
7763     * to setHasTransientState(false).
7764     *
7765     * <p>A view with transient state cannot be trivially rebound from an external
7766     * data source, such as an adapter binding item views in a list. This may be
7767     * because the view is performing an animation, tracking user selection
7768     * of content, or similar.</p>
7769     *
7770     * @param hasTransientState true if this view has transient state
7771     */
7772    public void setHasTransientState(boolean hasTransientState) {
7773        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7774                mTransientStateCount - 1;
7775        if (mTransientStateCount < 0) {
7776            mTransientStateCount = 0;
7777            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7778                    "unmatched pair of setHasTransientState calls");
7779        } else if ((hasTransientState && mTransientStateCount == 1) ||
7780                (!hasTransientState && mTransientStateCount == 0)) {
7781            // update flag if we've just incremented up from 0 or decremented down to 0
7782            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7783                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7784            if (mParent != null) {
7785                try {
7786                    mParent.childHasTransientStateChanged(this, hasTransientState);
7787                } catch (AbstractMethodError e) {
7788                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7789                            " does not fully implement ViewParent", e);
7790                }
7791            }
7792        }
7793    }
7794
7795    /**
7796     * Returns true if this view is currently attached to a window.
7797     */
7798    public boolean isAttachedToWindow() {
7799        return mAttachInfo != null;
7800    }
7801
7802    /**
7803     * Returns true if this view has been through at least one layout since it
7804     * was last attached to or detached from a window.
7805     */
7806    public boolean isLaidOut() {
7807        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7808    }
7809
7810    /**
7811     * If this view doesn't do any drawing on its own, set this flag to
7812     * allow further optimizations. By default, this flag is not set on
7813     * View, but could be set on some View subclasses such as ViewGroup.
7814     *
7815     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7816     * you should clear this flag.
7817     *
7818     * @param willNotDraw whether or not this View draw on its own
7819     */
7820    public void setWillNotDraw(boolean willNotDraw) {
7821        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7822    }
7823
7824    /**
7825     * Returns whether or not this View draws on its own.
7826     *
7827     * @return true if this view has nothing to draw, false otherwise
7828     */
7829    @ViewDebug.ExportedProperty(category = "drawing")
7830    public boolean willNotDraw() {
7831        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7832    }
7833
7834    /**
7835     * When a View's drawing cache is enabled, drawing is redirected to an
7836     * offscreen bitmap. Some views, like an ImageView, must be able to
7837     * bypass this mechanism if they already draw a single bitmap, to avoid
7838     * unnecessary usage of the memory.
7839     *
7840     * @param willNotCacheDrawing true if this view does not cache its
7841     *        drawing, false otherwise
7842     */
7843    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7844        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7845    }
7846
7847    /**
7848     * Returns whether or not this View can cache its drawing or not.
7849     *
7850     * @return true if this view does not cache its drawing, false otherwise
7851     */
7852    @ViewDebug.ExportedProperty(category = "drawing")
7853    public boolean willNotCacheDrawing() {
7854        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7855    }
7856
7857    /**
7858     * Indicates whether this view reacts to click events or not.
7859     *
7860     * @return true if the view is clickable, false otherwise
7861     *
7862     * @see #setClickable(boolean)
7863     * @attr ref android.R.styleable#View_clickable
7864     */
7865    @ViewDebug.ExportedProperty
7866    public boolean isClickable() {
7867        return (mViewFlags & CLICKABLE) == CLICKABLE;
7868    }
7869
7870    /**
7871     * Enables or disables click events for this view. When a view
7872     * is clickable it will change its state to "pressed" on every click.
7873     * Subclasses should set the view clickable to visually react to
7874     * user's clicks.
7875     *
7876     * @param clickable true to make the view clickable, false otherwise
7877     *
7878     * @see #isClickable()
7879     * @attr ref android.R.styleable#View_clickable
7880     */
7881    public void setClickable(boolean clickable) {
7882        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7883    }
7884
7885    /**
7886     * Indicates whether this view reacts to long click events or not.
7887     *
7888     * @return true if the view is long clickable, false otherwise
7889     *
7890     * @see #setLongClickable(boolean)
7891     * @attr ref android.R.styleable#View_longClickable
7892     */
7893    public boolean isLongClickable() {
7894        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7895    }
7896
7897    /**
7898     * Enables or disables long click events for this view. When a view is long
7899     * clickable it reacts to the user holding down the button for a longer
7900     * duration than a tap. This event can either launch the listener or a
7901     * context menu.
7902     *
7903     * @param longClickable true to make the view long clickable, false otherwise
7904     * @see #isLongClickable()
7905     * @attr ref android.R.styleable#View_longClickable
7906     */
7907    public void setLongClickable(boolean longClickable) {
7908        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7909    }
7910
7911    /**
7912     * Indicates whether this view reacts to context clicks or not.
7913     *
7914     * @return true if the view is context clickable, false otherwise
7915     * @see #setContextClickable(boolean)
7916     * @attr ref android.R.styleable#View_contextClickable
7917     */
7918    public boolean isContextClickable() {
7919        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
7920    }
7921
7922    /**
7923     * Enables or disables context clicking for this view. This event can launch the listener.
7924     *
7925     * @param contextClickable true to make the view react to a context click, false otherwise
7926     * @see #isContextClickable()
7927     * @attr ref android.R.styleable#View_contextClickable
7928     */
7929    public void setContextClickable(boolean contextClickable) {
7930        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
7931    }
7932
7933    /**
7934     * Sets the pressed state for this view and provides a touch coordinate for
7935     * animation hinting.
7936     *
7937     * @param pressed Pass true to set the View's internal state to "pressed",
7938     *            or false to reverts the View's internal state from a
7939     *            previously set "pressed" state.
7940     * @param x The x coordinate of the touch that caused the press
7941     * @param y The y coordinate of the touch that caused the press
7942     */
7943    private void setPressed(boolean pressed, float x, float y) {
7944        if (pressed) {
7945            drawableHotspotChanged(x, y);
7946        }
7947
7948        setPressed(pressed);
7949    }
7950
7951    /**
7952     * Sets the pressed state for this view.
7953     *
7954     * @see #isClickable()
7955     * @see #setClickable(boolean)
7956     *
7957     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7958     *        the View's internal state from a previously set "pressed" state.
7959     */
7960    public void setPressed(boolean pressed) {
7961        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7962
7963        if (pressed) {
7964            mPrivateFlags |= PFLAG_PRESSED;
7965        } else {
7966            mPrivateFlags &= ~PFLAG_PRESSED;
7967        }
7968
7969        if (needsRefresh) {
7970            refreshDrawableState();
7971        }
7972        dispatchSetPressed(pressed);
7973    }
7974
7975    /**
7976     * Dispatch setPressed to all of this View's children.
7977     *
7978     * @see #setPressed(boolean)
7979     *
7980     * @param pressed The new pressed state
7981     */
7982    protected void dispatchSetPressed(boolean pressed) {
7983    }
7984
7985    /**
7986     * Indicates whether the view is currently in pressed state. Unless
7987     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7988     * the pressed state.
7989     *
7990     * @see #setPressed(boolean)
7991     * @see #isClickable()
7992     * @see #setClickable(boolean)
7993     *
7994     * @return true if the view is currently pressed, false otherwise
7995     */
7996    @ViewDebug.ExportedProperty
7997    public boolean isPressed() {
7998        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7999    }
8000
8001    /**
8002     * @hide
8003     * Indicates whether this view will participate in data collection through
8004     * {@link ViewStructure}.  If true, it will not provide any data
8005     * for itself or its children.  If false, the normal data collection will be allowed.
8006     *
8007     * @return Returns false if assist data collection is not blocked, else true.
8008     *
8009     * @see #setAssistBlocked(boolean)
8010     * @attr ref android.R.styleable#View_assistBlocked
8011     */
8012    public boolean isAssistBlocked() {
8013        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8014    }
8015
8016    /**
8017     * @hide
8018     * Controls whether assist data collection from this view and its children is enabled
8019     * (that is, whether {@link #onProvideStructure} and
8020     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8021     * allowing normal assist collection.  Setting this to false will disable assist collection.
8022     *
8023     * @param enabled Set to true to <em>disable</em> assist data collection, or false
8024     * (the default) to allow it.
8025     *
8026     * @see #isAssistBlocked()
8027     * @see #onProvideStructure
8028     * @see #onProvideVirtualStructure
8029     * @attr ref android.R.styleable#View_assistBlocked
8030     */
8031    public void setAssistBlocked(boolean enabled) {
8032        if (enabled) {
8033            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8034        } else {
8035            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8036        }
8037    }
8038
8039    /**
8040     * Indicates whether this view will save its state (that is,
8041     * whether its {@link #onSaveInstanceState} method will be called).
8042     *
8043     * @return Returns true if the view state saving is enabled, else false.
8044     *
8045     * @see #setSaveEnabled(boolean)
8046     * @attr ref android.R.styleable#View_saveEnabled
8047     */
8048    public boolean isSaveEnabled() {
8049        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8050    }
8051
8052    /**
8053     * Controls whether the saving of this view's state is
8054     * enabled (that is, whether its {@link #onSaveInstanceState} method
8055     * will be called).  Note that even if freezing is enabled, the
8056     * view still must have an id assigned to it (via {@link #setId(int)})
8057     * for its state to be saved.  This flag can only disable the
8058     * saving of this view; any child views may still have their state saved.
8059     *
8060     * @param enabled Set to false to <em>disable</em> state saving, or true
8061     * (the default) to allow it.
8062     *
8063     * @see #isSaveEnabled()
8064     * @see #setId(int)
8065     * @see #onSaveInstanceState()
8066     * @attr ref android.R.styleable#View_saveEnabled
8067     */
8068    public void setSaveEnabled(boolean enabled) {
8069        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8070    }
8071
8072    /**
8073     * Gets whether the framework should discard touches when the view's
8074     * window is obscured by another visible window.
8075     * Refer to the {@link View} security documentation for more details.
8076     *
8077     * @return True if touch filtering is enabled.
8078     *
8079     * @see #setFilterTouchesWhenObscured(boolean)
8080     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8081     */
8082    @ViewDebug.ExportedProperty
8083    public boolean getFilterTouchesWhenObscured() {
8084        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8085    }
8086
8087    /**
8088     * Sets whether the framework should discard touches when the view's
8089     * window is obscured by another visible window.
8090     * Refer to the {@link View} security documentation for more details.
8091     *
8092     * @param enabled True if touch filtering should be enabled.
8093     *
8094     * @see #getFilterTouchesWhenObscured
8095     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8096     */
8097    public void setFilterTouchesWhenObscured(boolean enabled) {
8098        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8099                FILTER_TOUCHES_WHEN_OBSCURED);
8100    }
8101
8102    /**
8103     * Indicates whether the entire hierarchy under this view will save its
8104     * state when a state saving traversal occurs from its parent.  The default
8105     * is true; if false, these views will not be saved unless
8106     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8107     *
8108     * @return Returns true if the view state saving from parent is enabled, else false.
8109     *
8110     * @see #setSaveFromParentEnabled(boolean)
8111     */
8112    public boolean isSaveFromParentEnabled() {
8113        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8114    }
8115
8116    /**
8117     * Controls whether the entire hierarchy under this view will save its
8118     * state when a state saving traversal occurs from its parent.  The default
8119     * is true; if false, these views will not be saved unless
8120     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8121     *
8122     * @param enabled Set to false to <em>disable</em> state saving, or true
8123     * (the default) to allow it.
8124     *
8125     * @see #isSaveFromParentEnabled()
8126     * @see #setId(int)
8127     * @see #onSaveInstanceState()
8128     */
8129    public void setSaveFromParentEnabled(boolean enabled) {
8130        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8131    }
8132
8133
8134    /**
8135     * Returns whether this View is able to take focus.
8136     *
8137     * @return True if this view can take focus, or false otherwise.
8138     * @attr ref android.R.styleable#View_focusable
8139     */
8140    @ViewDebug.ExportedProperty(category = "focus")
8141    public final boolean isFocusable() {
8142        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8143    }
8144
8145    /**
8146     * When a view is focusable, it may not want to take focus when in touch mode.
8147     * For example, a button would like focus when the user is navigating via a D-pad
8148     * so that the user can click on it, but once the user starts touching the screen,
8149     * the button shouldn't take focus
8150     * @return Whether the view is focusable in touch mode.
8151     * @attr ref android.R.styleable#View_focusableInTouchMode
8152     */
8153    @ViewDebug.ExportedProperty
8154    public final boolean isFocusableInTouchMode() {
8155        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8156    }
8157
8158    /**
8159     * Find the nearest view in the specified direction that can take focus.
8160     * This does not actually give focus to that view.
8161     *
8162     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8163     *
8164     * @return The nearest focusable in the specified direction, or null if none
8165     *         can be found.
8166     */
8167    public View focusSearch(@FocusRealDirection int direction) {
8168        if (mParent != null) {
8169            return mParent.focusSearch(this, direction);
8170        } else {
8171            return null;
8172        }
8173    }
8174
8175    /**
8176     * This method is the last chance for the focused view and its ancestors to
8177     * respond to an arrow key. This is called when the focused view did not
8178     * consume the key internally, nor could the view system find a new view in
8179     * the requested direction to give focus to.
8180     *
8181     * @param focused The currently focused view.
8182     * @param direction The direction focus wants to move. One of FOCUS_UP,
8183     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8184     * @return True if the this view consumed this unhandled move.
8185     */
8186    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8187        return false;
8188    }
8189
8190    /**
8191     * If a user manually specified the next view id for a particular direction,
8192     * use the root to look up the view.
8193     * @param root The root view of the hierarchy containing this view.
8194     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8195     * or FOCUS_BACKWARD.
8196     * @return The user specified next view, or null if there is none.
8197     */
8198    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8199        switch (direction) {
8200            case FOCUS_LEFT:
8201                if (mNextFocusLeftId == View.NO_ID) return null;
8202                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8203            case FOCUS_RIGHT:
8204                if (mNextFocusRightId == View.NO_ID) return null;
8205                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8206            case FOCUS_UP:
8207                if (mNextFocusUpId == View.NO_ID) return null;
8208                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8209            case FOCUS_DOWN:
8210                if (mNextFocusDownId == View.NO_ID) return null;
8211                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8212            case FOCUS_FORWARD:
8213                if (mNextFocusForwardId == View.NO_ID) return null;
8214                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8215            case FOCUS_BACKWARD: {
8216                if (mID == View.NO_ID) return null;
8217                final int id = mID;
8218                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8219                    @Override
8220                    public boolean apply(View t) {
8221                        return t.mNextFocusForwardId == id;
8222                    }
8223                });
8224            }
8225        }
8226        return null;
8227    }
8228
8229    private View findViewInsideOutShouldExist(View root, int id) {
8230        if (mMatchIdPredicate == null) {
8231            mMatchIdPredicate = new MatchIdPredicate();
8232        }
8233        mMatchIdPredicate.mId = id;
8234        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8235        if (result == null) {
8236            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8237        }
8238        return result;
8239    }
8240
8241    /**
8242     * Find and return all focusable views that are descendants of this view,
8243     * possibly including this view if it is focusable itself.
8244     *
8245     * @param direction The direction of the focus
8246     * @return A list of focusable views
8247     */
8248    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8249        ArrayList<View> result = new ArrayList<View>(24);
8250        addFocusables(result, direction);
8251        return result;
8252    }
8253
8254    /**
8255     * Add any focusable views that are descendants of this view (possibly
8256     * including this view if it is focusable itself) to views.  If we are in touch mode,
8257     * only add views that are also focusable in touch mode.
8258     *
8259     * @param views Focusable views found so far
8260     * @param direction The direction of the focus
8261     */
8262    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8263        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
8264    }
8265
8266    /**
8267     * Adds any focusable views that are descendants of this view (possibly
8268     * including this view if it is focusable itself) to views. This method
8269     * adds all focusable views regardless if we are in touch mode or
8270     * only views focusable in touch mode if we are in touch mode or
8271     * only views that can take accessibility focus if accessibility is enabled
8272     * depending on the focusable mode parameter.
8273     *
8274     * @param views Focusable views found so far or null if all we are interested is
8275     *        the number of focusables.
8276     * @param direction The direction of the focus.
8277     * @param focusableMode The type of focusables to be added.
8278     *
8279     * @see #FOCUSABLES_ALL
8280     * @see #FOCUSABLES_TOUCH_MODE
8281     */
8282    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8283            @FocusableMode int focusableMode) {
8284        if (views == null) {
8285            return;
8286        }
8287        if (!isFocusable()) {
8288            return;
8289        }
8290        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8291                && isInTouchMode() && !isFocusableInTouchMode()) {
8292            return;
8293        }
8294        views.add(this);
8295    }
8296
8297    /**
8298     * Finds the Views that contain given text. The containment is case insensitive.
8299     * The search is performed by either the text that the View renders or the content
8300     * description that describes the view for accessibility purposes and the view does
8301     * not render or both. Clients can specify how the search is to be performed via
8302     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8303     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8304     *
8305     * @param outViews The output list of matching Views.
8306     * @param searched The text to match against.
8307     *
8308     * @see #FIND_VIEWS_WITH_TEXT
8309     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8310     * @see #setContentDescription(CharSequence)
8311     */
8312    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8313            @FindViewFlags int flags) {
8314        if (getAccessibilityNodeProvider() != null) {
8315            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8316                outViews.add(this);
8317            }
8318        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8319                && (searched != null && searched.length() > 0)
8320                && (mContentDescription != null && mContentDescription.length() > 0)) {
8321            String searchedLowerCase = searched.toString().toLowerCase();
8322            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8323            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8324                outViews.add(this);
8325            }
8326        }
8327    }
8328
8329    /**
8330     * Find and return all touchable views that are descendants of this view,
8331     * possibly including this view if it is touchable itself.
8332     *
8333     * @return A list of touchable views
8334     */
8335    public ArrayList<View> getTouchables() {
8336        ArrayList<View> result = new ArrayList<View>();
8337        addTouchables(result);
8338        return result;
8339    }
8340
8341    /**
8342     * Add any touchable views that are descendants of this view (possibly
8343     * including this view if it is touchable itself) to views.
8344     *
8345     * @param views Touchable views found so far
8346     */
8347    public void addTouchables(ArrayList<View> views) {
8348        final int viewFlags = mViewFlags;
8349
8350        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8351                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8352                && (viewFlags & ENABLED_MASK) == ENABLED) {
8353            views.add(this);
8354        }
8355    }
8356
8357    /**
8358     * Returns whether this View is accessibility focused.
8359     *
8360     * @return True if this View is accessibility focused.
8361     */
8362    public boolean isAccessibilityFocused() {
8363        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8364    }
8365
8366    /**
8367     * Call this to try to give accessibility focus to this view.
8368     *
8369     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8370     * returns false or the view is no visible or the view already has accessibility
8371     * focus.
8372     *
8373     * See also {@link #focusSearch(int)}, which is what you call to say that you
8374     * have focus, and you want your parent to look for the next one.
8375     *
8376     * @return Whether this view actually took accessibility focus.
8377     *
8378     * @hide
8379     */
8380    public boolean requestAccessibilityFocus() {
8381        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8382        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8383            return false;
8384        }
8385        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8386            return false;
8387        }
8388        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8389            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8390            ViewRootImpl viewRootImpl = getViewRootImpl();
8391            if (viewRootImpl != null) {
8392                viewRootImpl.setAccessibilityFocus(this, null);
8393            }
8394            invalidate();
8395            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8396            return true;
8397        }
8398        return false;
8399    }
8400
8401    /**
8402     * Call this to try to clear accessibility focus of this view.
8403     *
8404     * See also {@link #focusSearch(int)}, which is what you call to say that you
8405     * have focus, and you want your parent to look for the next one.
8406     *
8407     * @hide
8408     */
8409    public void clearAccessibilityFocus() {
8410        clearAccessibilityFocusNoCallbacks();
8411
8412        // Clear the global reference of accessibility focus if this view or
8413        // any of its descendants had accessibility focus. This will NOT send
8414        // an event or update internal state if focus is cleared from a
8415        // descendant view, which may leave views in inconsistent states.
8416        final ViewRootImpl viewRootImpl = getViewRootImpl();
8417        if (viewRootImpl != null) {
8418            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8419            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8420                viewRootImpl.setAccessibilityFocus(null, null);
8421            }
8422        }
8423    }
8424
8425    private void sendAccessibilityHoverEvent(int eventType) {
8426        // Since we are not delivering to a client accessibility events from not
8427        // important views (unless the clinet request that) we need to fire the
8428        // event from the deepest view exposed to the client. As a consequence if
8429        // the user crosses a not exposed view the client will see enter and exit
8430        // of the exposed predecessor followed by and enter and exit of that same
8431        // predecessor when entering and exiting the not exposed descendant. This
8432        // is fine since the client has a clear idea which view is hovered at the
8433        // price of a couple more events being sent. This is a simple and
8434        // working solution.
8435        View source = this;
8436        while (true) {
8437            if (source.includeForAccessibility()) {
8438                source.sendAccessibilityEvent(eventType);
8439                return;
8440            }
8441            ViewParent parent = source.getParent();
8442            if (parent instanceof View) {
8443                source = (View) parent;
8444            } else {
8445                return;
8446            }
8447        }
8448    }
8449
8450    /**
8451     * Clears accessibility focus without calling any callback methods
8452     * normally invoked in {@link #clearAccessibilityFocus()}. This method
8453     * is used for clearing accessibility focus when giving this focus to
8454     * another view.
8455     */
8456    void clearAccessibilityFocusNoCallbacks() {
8457        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
8458            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
8459            invalidate();
8460            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
8461        }
8462    }
8463
8464    /**
8465     * Call this to try to give focus to a specific view or to one of its
8466     * descendants.
8467     *
8468     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8469     * false), or if it is focusable and it is not focusable in touch mode
8470     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8471     *
8472     * See also {@link #focusSearch(int)}, which is what you call to say that you
8473     * have focus, and you want your parent to look for the next one.
8474     *
8475     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
8476     * {@link #FOCUS_DOWN} and <code>null</code>.
8477     *
8478     * @return Whether this view or one of its descendants actually took focus.
8479     */
8480    public final boolean requestFocus() {
8481        return requestFocus(View.FOCUS_DOWN);
8482    }
8483
8484    /**
8485     * Call this to try to give focus to a specific view or to one of its
8486     * descendants and give it a hint about what direction focus is heading.
8487     *
8488     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8489     * false), or if it is focusable and it is not focusable in touch mode
8490     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8491     *
8492     * See also {@link #focusSearch(int)}, which is what you call to say that you
8493     * have focus, and you want your parent to look for the next one.
8494     *
8495     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
8496     * <code>null</code> set for the previously focused rectangle.
8497     *
8498     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8499     * @return Whether this view or one of its descendants actually took focus.
8500     */
8501    public final boolean requestFocus(int direction) {
8502        return requestFocus(direction, null);
8503    }
8504
8505    /**
8506     * Call this to try to give focus to a specific view or to one of its descendants
8507     * and give it hints about the direction and a specific rectangle that the focus
8508     * is coming from.  The rectangle can help give larger views a finer grained hint
8509     * about where focus is coming from, and therefore, where to show selection, or
8510     * forward focus change internally.
8511     *
8512     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8513     * false), or if it is focusable and it is not focusable in touch mode
8514     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8515     *
8516     * A View will not take focus if it is not visible.
8517     *
8518     * A View will not take focus if one of its parents has
8519     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
8520     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
8521     *
8522     * See also {@link #focusSearch(int)}, which is what you call to say that you
8523     * have focus, and you want your parent to look for the next one.
8524     *
8525     * You may wish to override this method if your custom {@link View} has an internal
8526     * {@link View} that it wishes to forward the request to.
8527     *
8528     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8529     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8530     *        to give a finer grained hint about where focus is coming from.  May be null
8531     *        if there is no hint.
8532     * @return Whether this view or one of its descendants actually took focus.
8533     */
8534    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8535        return requestFocusNoSearch(direction, previouslyFocusedRect);
8536    }
8537
8538    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8539        // need to be focusable
8540        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8541                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8542            return false;
8543        }
8544
8545        // need to be focusable in touch mode if in touch mode
8546        if (isInTouchMode() &&
8547            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8548               return false;
8549        }
8550
8551        // need to not have any parents blocking us
8552        if (hasAncestorThatBlocksDescendantFocus()) {
8553            return false;
8554        }
8555
8556        handleFocusGainInternal(direction, previouslyFocusedRect);
8557        return true;
8558    }
8559
8560    /**
8561     * Call this to try to give focus to a specific view or to one of its descendants. This is a
8562     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8563     * touch mode to request focus when they are touched.
8564     *
8565     * @return Whether this view or one of its descendants actually took focus.
8566     *
8567     * @see #isInTouchMode()
8568     *
8569     */
8570    public final boolean requestFocusFromTouch() {
8571        // Leave touch mode if we need to
8572        if (isInTouchMode()) {
8573            ViewRootImpl viewRoot = getViewRootImpl();
8574            if (viewRoot != null) {
8575                viewRoot.ensureTouchMode(false);
8576            }
8577        }
8578        return requestFocus(View.FOCUS_DOWN);
8579    }
8580
8581    /**
8582     * @return Whether any ancestor of this view blocks descendant focus.
8583     */
8584    private boolean hasAncestorThatBlocksDescendantFocus() {
8585        final boolean focusableInTouchMode = isFocusableInTouchMode();
8586        ViewParent ancestor = mParent;
8587        while (ancestor instanceof ViewGroup) {
8588            final ViewGroup vgAncestor = (ViewGroup) ancestor;
8589            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8590                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8591                return true;
8592            } else {
8593                ancestor = vgAncestor.getParent();
8594            }
8595        }
8596        return false;
8597    }
8598
8599    /**
8600     * Gets the mode for determining whether this View is important for accessibility
8601     * which is if it fires accessibility events and if it is reported to
8602     * accessibility services that query the screen.
8603     *
8604     * @return The mode for determining whether a View is important for accessibility.
8605     *
8606     * @attr ref android.R.styleable#View_importantForAccessibility
8607     *
8608     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8609     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8610     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8611     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8612     */
8613    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8614            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8615            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8616            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8617            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8618                    to = "noHideDescendants")
8619        })
8620    public int getImportantForAccessibility() {
8621        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8622                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8623    }
8624
8625    /**
8626     * Sets the live region mode for this view. This indicates to accessibility
8627     * services whether they should automatically notify the user about changes
8628     * to the view's content description or text, or to the content descriptions
8629     * or text of the view's children (where applicable).
8630     * <p>
8631     * For example, in a login screen with a TextView that displays an "incorrect
8632     * password" notification, that view should be marked as a live region with
8633     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8634     * <p>
8635     * To disable change notifications for this view, use
8636     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8637     * mode for most views.
8638     * <p>
8639     * To indicate that the user should be notified of changes, use
8640     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8641     * <p>
8642     * If the view's changes should interrupt ongoing speech and notify the user
8643     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8644     *
8645     * @param mode The live region mode for this view, one of:
8646     *        <ul>
8647     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8648     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8649     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8650     *        </ul>
8651     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8652     */
8653    public void setAccessibilityLiveRegion(int mode) {
8654        if (mode != getAccessibilityLiveRegion()) {
8655            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8656            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8657                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8658            notifyViewAccessibilityStateChangedIfNeeded(
8659                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8660        }
8661    }
8662
8663    /**
8664     * Gets the live region mode for this View.
8665     *
8666     * @return The live region mode for the view.
8667     *
8668     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8669     *
8670     * @see #setAccessibilityLiveRegion(int)
8671     */
8672    public int getAccessibilityLiveRegion() {
8673        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8674                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8675    }
8676
8677    /**
8678     * Sets how to determine whether this view is important for accessibility
8679     * which is if it fires accessibility events and if it is reported to
8680     * accessibility services that query the screen.
8681     *
8682     * @param mode How to determine whether this view is important for accessibility.
8683     *
8684     * @attr ref android.R.styleable#View_importantForAccessibility
8685     *
8686     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8687     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8688     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8689     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8690     */
8691    public void setImportantForAccessibility(int mode) {
8692        final int oldMode = getImportantForAccessibility();
8693        if (mode != oldMode) {
8694            final boolean hideDescendants =
8695                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
8696
8697            // If this node or its descendants are no longer important, try to
8698            // clear accessibility focus.
8699            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
8700                final View focusHost = findAccessibilityFocusHost(hideDescendants);
8701                if (focusHost != null) {
8702                    focusHost.clearAccessibilityFocus();
8703                }
8704            }
8705
8706            // If we're moving between AUTO and another state, we might not need
8707            // to send a subtree changed notification. We'll store the computed
8708            // importance, since we'll need to check it later to make sure.
8709            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8710                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8711            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8712            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8713            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8714                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8715            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8716                notifySubtreeAccessibilityStateChangedIfNeeded();
8717            } else {
8718                notifyViewAccessibilityStateChangedIfNeeded(
8719                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8720            }
8721        }
8722    }
8723
8724    /**
8725     * Returns the view within this view's hierarchy that is hosting
8726     * accessibility focus.
8727     *
8728     * @param searchDescendants whether to search for focus in descendant views
8729     * @return the view hosting accessibility focus, or {@code null}
8730     */
8731    private View findAccessibilityFocusHost(boolean searchDescendants) {
8732        if (isAccessibilityFocusedViewOrHost()) {
8733            return this;
8734        }
8735
8736        if (searchDescendants) {
8737            final ViewRootImpl viewRoot = getViewRootImpl();
8738            if (viewRoot != null) {
8739                final View focusHost = viewRoot.getAccessibilityFocusedHost();
8740                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8741                    return focusHost;
8742                }
8743            }
8744        }
8745
8746        return null;
8747    }
8748
8749    /**
8750     * Computes whether this view should be exposed for accessibility. In
8751     * general, views that are interactive or provide information are exposed
8752     * while views that serve only as containers are hidden.
8753     * <p>
8754     * If an ancestor of this view has importance
8755     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8756     * returns <code>false</code>.
8757     * <p>
8758     * Otherwise, the value is computed according to the view's
8759     * {@link #getImportantForAccessibility()} value:
8760     * <ol>
8761     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8762     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8763     * </code>
8764     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8765     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8766     * view satisfies any of the following:
8767     * <ul>
8768     * <li>Is actionable, e.g. {@link #isClickable()},
8769     * {@link #isLongClickable()}, or {@link #isFocusable()}
8770     * <li>Has an {@link AccessibilityDelegate}
8771     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8772     * {@link OnKeyListener}, etc.
8773     * <li>Is an accessibility live region, e.g.
8774     * {@link #getAccessibilityLiveRegion()} is not
8775     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8776     * </ul>
8777     * </ol>
8778     *
8779     * @return Whether the view is exposed for accessibility.
8780     * @see #setImportantForAccessibility(int)
8781     * @see #getImportantForAccessibility()
8782     */
8783    public boolean isImportantForAccessibility() {
8784        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8785                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8786        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8787                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8788            return false;
8789        }
8790
8791        // Check parent mode to ensure we're not hidden.
8792        ViewParent parent = mParent;
8793        while (parent instanceof View) {
8794            if (((View) parent).getImportantForAccessibility()
8795                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8796                return false;
8797            }
8798            parent = parent.getParent();
8799        }
8800
8801        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8802                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8803                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8804    }
8805
8806    /**
8807     * Gets the parent for accessibility purposes. Note that the parent for
8808     * accessibility is not necessary the immediate parent. It is the first
8809     * predecessor that is important for accessibility.
8810     *
8811     * @return The parent for accessibility purposes.
8812     */
8813    public ViewParent getParentForAccessibility() {
8814        if (mParent instanceof View) {
8815            View parentView = (View) mParent;
8816            if (parentView.includeForAccessibility()) {
8817                return mParent;
8818            } else {
8819                return mParent.getParentForAccessibility();
8820            }
8821        }
8822        return null;
8823    }
8824
8825    /**
8826     * Adds the children of this View relevant for accessibility to the given list
8827     * as output. Since some Views are not important for accessibility the added
8828     * child views are not necessarily direct children of this view, rather they are
8829     * the first level of descendants important for accessibility.
8830     *
8831     * @param outChildren The output list that will receive children for accessibility.
8832     */
8833    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
8834
8835    }
8836
8837    /**
8838     * Whether to regard this view for accessibility. A view is regarded for
8839     * accessibility if it is important for accessibility or the querying
8840     * accessibility service has explicitly requested that view not
8841     * important for accessibility are regarded.
8842     *
8843     * @return Whether to regard the view for accessibility.
8844     *
8845     * @hide
8846     */
8847    public boolean includeForAccessibility() {
8848        if (mAttachInfo != null) {
8849            return (mAttachInfo.mAccessibilityFetchFlags
8850                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8851                    || isImportantForAccessibility();
8852        }
8853        return false;
8854    }
8855
8856    /**
8857     * Returns whether the View is considered actionable from
8858     * accessibility perspective. Such view are important for
8859     * accessibility.
8860     *
8861     * @return True if the view is actionable for accessibility.
8862     *
8863     * @hide
8864     */
8865    public boolean isActionableForAccessibility() {
8866        return (isClickable() || isLongClickable() || isFocusable());
8867    }
8868
8869    /**
8870     * Returns whether the View has registered callbacks which makes it
8871     * important for accessibility.
8872     *
8873     * @return True if the view is actionable for accessibility.
8874     */
8875    private boolean hasListenersForAccessibility() {
8876        ListenerInfo info = getListenerInfo();
8877        return mTouchDelegate != null || info.mOnKeyListener != null
8878                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
8879                || info.mOnHoverListener != null || info.mOnDragListener != null;
8880    }
8881
8882    /**
8883     * Notifies that the accessibility state of this view changed. The change
8884     * is local to this view and does not represent structural changes such
8885     * as children and parent. For example, the view became focusable. The
8886     * notification is at at most once every
8887     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8888     * to avoid unnecessary load to the system. Also once a view has a pending
8889     * notification this method is a NOP until the notification has been sent.
8890     *
8891     * @hide
8892     */
8893    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
8894        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8895            return;
8896        }
8897        if (mSendViewStateChangedAccessibilityEvent == null) {
8898            mSendViewStateChangedAccessibilityEvent =
8899                    new SendViewStateChangedAccessibilityEvent();
8900        }
8901        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
8902    }
8903
8904    /**
8905     * Notifies that the accessibility state of this view changed. The change
8906     * is *not* local to this view and does represent structural changes such
8907     * as children and parent. For example, the view size changed. The
8908     * notification is at at most once every
8909     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8910     * to avoid unnecessary load to the system. Also once a view has a pending
8911     * notification this method is a NOP until the notification has been sent.
8912     *
8913     * @hide
8914     */
8915    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8916        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8917            return;
8918        }
8919        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8920            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8921            if (mParent != null) {
8922                try {
8923                    mParent.notifySubtreeAccessibilityStateChanged(
8924                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8925                } catch (AbstractMethodError e) {
8926                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8927                            " does not fully implement ViewParent", e);
8928                }
8929            }
8930        }
8931    }
8932
8933    /**
8934     * Change the visibility of the View without triggering any other changes. This is
8935     * important for transitions, where visibility changes should not adjust focus or
8936     * trigger a new layout. This is only used when the visibility has already been changed
8937     * and we need a transient value during an animation. When the animation completes,
8938     * the original visibility value is always restored.
8939     *
8940     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8941     * @hide
8942     */
8943    public void setTransitionVisibility(@Visibility int visibility) {
8944        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
8945    }
8946
8947    /**
8948     * Reset the flag indicating the accessibility state of the subtree rooted
8949     * at this view changed.
8950     */
8951    void resetSubtreeAccessibilityStateChanged() {
8952        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8953    }
8954
8955    /**
8956     * Report an accessibility action to this view's parents for delegated processing.
8957     *
8958     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8959     * call this method to delegate an accessibility action to a supporting parent. If the parent
8960     * returns true from its
8961     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8962     * method this method will return true to signify that the action was consumed.</p>
8963     *
8964     * <p>This method is useful for implementing nested scrolling child views. If
8965     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8966     * a custom view implementation may invoke this method to allow a parent to consume the
8967     * scroll first. If this method returns true the custom view should skip its own scrolling
8968     * behavior.</p>
8969     *
8970     * @param action Accessibility action to delegate
8971     * @param arguments Optional action arguments
8972     * @return true if the action was consumed by a parent
8973     */
8974    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8975        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8976            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8977                return true;
8978            }
8979        }
8980        return false;
8981    }
8982
8983    /**
8984     * Performs the specified accessibility action on the view. For
8985     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8986     * <p>
8987     * If an {@link AccessibilityDelegate} has been specified via calling
8988     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8989     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8990     * is responsible for handling this call.
8991     * </p>
8992     *
8993     * <p>The default implementation will delegate
8994     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8995     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8996     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8997     *
8998     * @param action The action to perform.
8999     * @param arguments Optional action arguments.
9000     * @return Whether the action was performed.
9001     */
9002    public boolean performAccessibilityAction(int action, Bundle arguments) {
9003      if (mAccessibilityDelegate != null) {
9004          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9005      } else {
9006          return performAccessibilityActionInternal(action, arguments);
9007      }
9008    }
9009
9010   /**
9011    * @see #performAccessibilityAction(int, Bundle)
9012    *
9013    * Note: Called from the default {@link AccessibilityDelegate}.
9014    *
9015    * @hide
9016    */
9017    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9018        if (isNestedScrollingEnabled()
9019                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9020                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9021                || action == R.id.accessibilityActionScrollUp
9022                || action == R.id.accessibilityActionScrollLeft
9023                || action == R.id.accessibilityActionScrollDown
9024                || action == R.id.accessibilityActionScrollRight)) {
9025            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9026                return true;
9027            }
9028        }
9029
9030        switch (action) {
9031            case AccessibilityNodeInfo.ACTION_CLICK: {
9032                if (isClickable()) {
9033                    performClick();
9034                    return true;
9035                }
9036            } break;
9037            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9038                if (isLongClickable()) {
9039                    performLongClick();
9040                    return true;
9041                }
9042            } break;
9043            case AccessibilityNodeInfo.ACTION_FOCUS: {
9044                if (!hasFocus()) {
9045                    // Get out of touch mode since accessibility
9046                    // wants to move focus around.
9047                    getViewRootImpl().ensureTouchMode(false);
9048                    return requestFocus();
9049                }
9050            } break;
9051            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9052                if (hasFocus()) {
9053                    clearFocus();
9054                    return !isFocused();
9055                }
9056            } break;
9057            case AccessibilityNodeInfo.ACTION_SELECT: {
9058                if (!isSelected()) {
9059                    setSelected(true);
9060                    return isSelected();
9061                }
9062            } break;
9063            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9064                if (isSelected()) {
9065                    setSelected(false);
9066                    return !isSelected();
9067                }
9068            } break;
9069            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9070                if (!isAccessibilityFocused()) {
9071                    return requestAccessibilityFocus();
9072                }
9073            } break;
9074            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9075                if (isAccessibilityFocused()) {
9076                    clearAccessibilityFocus();
9077                    return true;
9078                }
9079            } break;
9080            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9081                if (arguments != null) {
9082                    final int granularity = arguments.getInt(
9083                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9084                    final boolean extendSelection = arguments.getBoolean(
9085                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9086                    return traverseAtGranularity(granularity, true, extendSelection);
9087                }
9088            } break;
9089            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9090                if (arguments != null) {
9091                    final int granularity = arguments.getInt(
9092                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9093                    final boolean extendSelection = arguments.getBoolean(
9094                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9095                    return traverseAtGranularity(granularity, false, extendSelection);
9096                }
9097            } break;
9098            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9099                CharSequence text = getIterableTextForAccessibility();
9100                if (text == null) {
9101                    return false;
9102                }
9103                final int start = (arguments != null) ? arguments.getInt(
9104                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9105                final int end = (arguments != null) ? arguments.getInt(
9106                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9107                // Only cursor position can be specified (selection length == 0)
9108                if ((getAccessibilitySelectionStart() != start
9109                        || getAccessibilitySelectionEnd() != end)
9110                        && (start == end)) {
9111                    setAccessibilitySelection(start, end);
9112                    notifyViewAccessibilityStateChangedIfNeeded(
9113                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9114                    return true;
9115                }
9116            } break;
9117            case R.id.accessibilityActionShowOnScreen: {
9118                if (mAttachInfo != null) {
9119                    final Rect r = mAttachInfo.mTmpInvalRect;
9120                    getDrawingRect(r);
9121                    return requestRectangleOnScreen(r, true);
9122                }
9123            } break;
9124            case R.id.accessibilityActionContextClick: {
9125                if (isContextClickable()) {
9126                    performContextClick();
9127                    return true;
9128                }
9129            } break;
9130        }
9131        return false;
9132    }
9133
9134    private boolean traverseAtGranularity(int granularity, boolean forward,
9135            boolean extendSelection) {
9136        CharSequence text = getIterableTextForAccessibility();
9137        if (text == null || text.length() == 0) {
9138            return false;
9139        }
9140        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9141        if (iterator == null) {
9142            return false;
9143        }
9144        int current = getAccessibilitySelectionEnd();
9145        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9146            current = forward ? 0 : text.length();
9147        }
9148        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9149        if (range == null) {
9150            return false;
9151        }
9152        final int segmentStart = range[0];
9153        final int segmentEnd = range[1];
9154        int selectionStart;
9155        int selectionEnd;
9156        if (extendSelection && isAccessibilitySelectionExtendable()) {
9157            selectionStart = getAccessibilitySelectionStart();
9158            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9159                selectionStart = forward ? segmentStart : segmentEnd;
9160            }
9161            selectionEnd = forward ? segmentEnd : segmentStart;
9162        } else {
9163            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9164        }
9165        setAccessibilitySelection(selectionStart, selectionEnd);
9166        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9167                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9168        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9169        return true;
9170    }
9171
9172    /**
9173     * Gets the text reported for accessibility purposes.
9174     *
9175     * @return The accessibility text.
9176     *
9177     * @hide
9178     */
9179    public CharSequence getIterableTextForAccessibility() {
9180        return getContentDescription();
9181    }
9182
9183    /**
9184     * Gets whether accessibility selection can be extended.
9185     *
9186     * @return If selection is extensible.
9187     *
9188     * @hide
9189     */
9190    public boolean isAccessibilitySelectionExtendable() {
9191        return false;
9192    }
9193
9194    /**
9195     * @hide
9196     */
9197    public int getAccessibilitySelectionStart() {
9198        return mAccessibilityCursorPosition;
9199    }
9200
9201    /**
9202     * @hide
9203     */
9204    public int getAccessibilitySelectionEnd() {
9205        return getAccessibilitySelectionStart();
9206    }
9207
9208    /**
9209     * @hide
9210     */
9211    public void setAccessibilitySelection(int start, int end) {
9212        if (start ==  end && end == mAccessibilityCursorPosition) {
9213            return;
9214        }
9215        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9216            mAccessibilityCursorPosition = start;
9217        } else {
9218            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9219        }
9220        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9221    }
9222
9223    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9224            int fromIndex, int toIndex) {
9225        if (mParent == null) {
9226            return;
9227        }
9228        AccessibilityEvent event = AccessibilityEvent.obtain(
9229                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9230        onInitializeAccessibilityEvent(event);
9231        onPopulateAccessibilityEvent(event);
9232        event.setFromIndex(fromIndex);
9233        event.setToIndex(toIndex);
9234        event.setAction(action);
9235        event.setMovementGranularity(granularity);
9236        mParent.requestSendAccessibilityEvent(this, event);
9237    }
9238
9239    /**
9240     * @hide
9241     */
9242    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9243        switch (granularity) {
9244            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9245                CharSequence text = getIterableTextForAccessibility();
9246                if (text != null && text.length() > 0) {
9247                    CharacterTextSegmentIterator iterator =
9248                        CharacterTextSegmentIterator.getInstance(
9249                                mContext.getResources().getConfiguration().locale);
9250                    iterator.initialize(text.toString());
9251                    return iterator;
9252                }
9253            } break;
9254            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9255                CharSequence text = getIterableTextForAccessibility();
9256                if (text != null && text.length() > 0) {
9257                    WordTextSegmentIterator iterator =
9258                        WordTextSegmentIterator.getInstance(
9259                                mContext.getResources().getConfiguration().locale);
9260                    iterator.initialize(text.toString());
9261                    return iterator;
9262                }
9263            } break;
9264            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9265                CharSequence text = getIterableTextForAccessibility();
9266                if (text != null && text.length() > 0) {
9267                    ParagraphTextSegmentIterator iterator =
9268                        ParagraphTextSegmentIterator.getInstance();
9269                    iterator.initialize(text.toString());
9270                    return iterator;
9271                }
9272            } break;
9273        }
9274        return null;
9275    }
9276
9277    /**
9278     * @hide
9279     */
9280    public void dispatchStartTemporaryDetach() {
9281        onStartTemporaryDetach();
9282    }
9283
9284    /**
9285     * This is called when a container is going to temporarily detach a child, with
9286     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9287     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9288     * {@link #onDetachedFromWindow()} when the container is done.
9289     */
9290    public void onStartTemporaryDetach() {
9291        removeUnsetPressCallback();
9292        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9293    }
9294
9295    /**
9296     * @hide
9297     */
9298    public void dispatchFinishTemporaryDetach() {
9299        onFinishTemporaryDetach();
9300    }
9301
9302    /**
9303     * Called after {@link #onStartTemporaryDetach} when the container is done
9304     * changing the view.
9305     */
9306    public void onFinishTemporaryDetach() {
9307    }
9308
9309    /**
9310     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9311     * for this view's window.  Returns null if the view is not currently attached
9312     * to the window.  Normally you will not need to use this directly, but
9313     * just use the standard high-level event callbacks like
9314     * {@link #onKeyDown(int, KeyEvent)}.
9315     */
9316    public KeyEvent.DispatcherState getKeyDispatcherState() {
9317        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9318    }
9319
9320    /**
9321     * Dispatch a key event before it is processed by any input method
9322     * associated with the view hierarchy.  This can be used to intercept
9323     * key events in special situations before the IME consumes them; a
9324     * typical example would be handling the BACK key to update the application's
9325     * UI instead of allowing the IME to see it and close itself.
9326     *
9327     * @param event The key event to be dispatched.
9328     * @return True if the event was handled, false otherwise.
9329     */
9330    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9331        return onKeyPreIme(event.getKeyCode(), event);
9332    }
9333
9334    /**
9335     * Dispatch a key event to the next view on the focus path. This path runs
9336     * from the top of the view tree down to the currently focused view. If this
9337     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9338     * the next node down the focus path. This method also fires any key
9339     * listeners.
9340     *
9341     * @param event The key event to be dispatched.
9342     * @return True if the event was handled, false otherwise.
9343     */
9344    public boolean dispatchKeyEvent(KeyEvent event) {
9345        if (mInputEventConsistencyVerifier != null) {
9346            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9347        }
9348
9349        // Give any attached key listener a first crack at the event.
9350        //noinspection SimplifiableIfStatement
9351        ListenerInfo li = mListenerInfo;
9352        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9353                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9354            return true;
9355        }
9356
9357        if (event.dispatch(this, mAttachInfo != null
9358                ? mAttachInfo.mKeyDispatchState : null, this)) {
9359            return true;
9360        }
9361
9362        if (mInputEventConsistencyVerifier != null) {
9363            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9364        }
9365        return false;
9366    }
9367
9368    /**
9369     * Dispatches a key shortcut event.
9370     *
9371     * @param event The key event to be dispatched.
9372     * @return True if the event was handled by the view, false otherwise.
9373     */
9374    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9375        return onKeyShortcut(event.getKeyCode(), event);
9376    }
9377
9378    /**
9379     * Pass the touch screen motion event down to the target view, or this
9380     * view if it is the target.
9381     *
9382     * @param event The motion event to be dispatched.
9383     * @return True if the event was handled by the view, false otherwise.
9384     */
9385    public boolean dispatchTouchEvent(MotionEvent event) {
9386        // If the event should be handled by accessibility focus first.
9387        if (event.isTargetAccessibilityFocus()) {
9388            // We don't have focus or no virtual descendant has it, do not handle the event.
9389            if (!isAccessibilityFocusedViewOrHost()) {
9390                return false;
9391            }
9392            // We have focus and got the event, then use normal event dispatch.
9393            event.setTargetAccessibilityFocus(false);
9394        }
9395
9396        boolean result = false;
9397
9398        if (mInputEventConsistencyVerifier != null) {
9399            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9400        }
9401
9402        final int actionMasked = event.getActionMasked();
9403        if (actionMasked == MotionEvent.ACTION_DOWN) {
9404            // Defensive cleanup for new gesture
9405            stopNestedScroll();
9406        }
9407
9408        if (onFilterTouchEventForSecurity(event)) {
9409            //noinspection SimplifiableIfStatement
9410            ListenerInfo li = mListenerInfo;
9411            if (li != null && li.mOnTouchListener != null
9412                    && (mViewFlags & ENABLED_MASK) == ENABLED
9413                    && li.mOnTouchListener.onTouch(this, event)) {
9414                result = true;
9415            }
9416
9417            if (!result && onTouchEvent(event)) {
9418                result = true;
9419            }
9420        }
9421
9422        if (!result && mInputEventConsistencyVerifier != null) {
9423            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9424        }
9425
9426        // Clean up after nested scrolls if this is the end of a gesture;
9427        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
9428        // of the gesture.
9429        if (actionMasked == MotionEvent.ACTION_UP ||
9430                actionMasked == MotionEvent.ACTION_CANCEL ||
9431                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
9432            stopNestedScroll();
9433        }
9434
9435        return result;
9436    }
9437
9438    boolean isAccessibilityFocusedViewOrHost() {
9439        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
9440                .getAccessibilityFocusedHost() == this);
9441    }
9442
9443    /**
9444     * Filter the touch event to apply security policies.
9445     *
9446     * @param event The motion event to be filtered.
9447     * @return True if the event should be dispatched, false if the event should be dropped.
9448     *
9449     * @see #getFilterTouchesWhenObscured
9450     */
9451    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
9452        //noinspection RedundantIfStatement
9453        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
9454                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
9455            // Window is obscured, drop this touch.
9456            return false;
9457        }
9458        return true;
9459    }
9460
9461    /**
9462     * Pass a trackball motion event down to the focused view.
9463     *
9464     * @param event The motion event to be dispatched.
9465     * @return True if the event was handled by the view, false otherwise.
9466     */
9467    public boolean dispatchTrackballEvent(MotionEvent event) {
9468        if (mInputEventConsistencyVerifier != null) {
9469            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
9470        }
9471
9472        return onTrackballEvent(event);
9473    }
9474
9475    /**
9476     * Dispatch a generic motion event.
9477     * <p>
9478     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9479     * are delivered to the view under the pointer.  All other generic motion events are
9480     * delivered to the focused view.  Hover events are handled specially and are delivered
9481     * to {@link #onHoverEvent(MotionEvent)}.
9482     * </p>
9483     *
9484     * @param event The motion event to be dispatched.
9485     * @return True if the event was handled by the view, false otherwise.
9486     */
9487    public boolean dispatchGenericMotionEvent(MotionEvent event) {
9488        if (mInputEventConsistencyVerifier != null) {
9489            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
9490        }
9491
9492        final int source = event.getSource();
9493        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
9494            final int action = event.getAction();
9495            if (action == MotionEvent.ACTION_HOVER_ENTER
9496                    || action == MotionEvent.ACTION_HOVER_MOVE
9497                    || action == MotionEvent.ACTION_HOVER_EXIT) {
9498                if (dispatchHoverEvent(event)) {
9499                    return true;
9500                }
9501            } else if (dispatchGenericPointerEvent(event)) {
9502                return true;
9503            }
9504        } else if (dispatchGenericFocusedEvent(event)) {
9505            return true;
9506        }
9507
9508        if (dispatchGenericMotionEventInternal(event)) {
9509            return true;
9510        }
9511
9512        if (mInputEventConsistencyVerifier != null) {
9513            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9514        }
9515        return false;
9516    }
9517
9518    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
9519        //noinspection SimplifiableIfStatement
9520        ListenerInfo li = mListenerInfo;
9521        if (li != null && li.mOnGenericMotionListener != null
9522                && (mViewFlags & ENABLED_MASK) == ENABLED
9523                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
9524            return true;
9525        }
9526
9527        if (onGenericMotionEvent(event)) {
9528            return true;
9529        }
9530
9531        final int actionButton = event.getActionButton();
9532        switch (event.getActionMasked()) {
9533            case MotionEvent.ACTION_BUTTON_PRESS:
9534                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
9535                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9536                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9537                    if (performContextClick()) {
9538                        mInContextButtonPress = true;
9539                        setPressed(true, event.getX(), event.getY());
9540                        removeTapCallback();
9541                        removeLongPressCallback();
9542                        return true;
9543                    }
9544                }
9545                break;
9546
9547            case MotionEvent.ACTION_BUTTON_RELEASE:
9548                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9549                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9550                    mInContextButtonPress = false;
9551                    mIgnoreNextUpEvent = true;
9552                }
9553                break;
9554        }
9555
9556        if (mInputEventConsistencyVerifier != null) {
9557            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9558        }
9559        return false;
9560    }
9561
9562    /**
9563     * Dispatch a hover event.
9564     * <p>
9565     * Do not call this method directly.
9566     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9567     * </p>
9568     *
9569     * @param event The motion event to be dispatched.
9570     * @return True if the event was handled by the view, false otherwise.
9571     */
9572    protected boolean dispatchHoverEvent(MotionEvent event) {
9573        ListenerInfo li = mListenerInfo;
9574        //noinspection SimplifiableIfStatement
9575        if (li != null && li.mOnHoverListener != null
9576                && (mViewFlags & ENABLED_MASK) == ENABLED
9577                && li.mOnHoverListener.onHover(this, event)) {
9578            return true;
9579        }
9580
9581        return onHoverEvent(event);
9582    }
9583
9584    /**
9585     * Returns true if the view has a child to which it has recently sent
9586     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
9587     * it does not have a hovered child, then it must be the innermost hovered view.
9588     * @hide
9589     */
9590    protected boolean hasHoveredChild() {
9591        return false;
9592    }
9593
9594    /**
9595     * Dispatch a generic motion event to the view under the first pointer.
9596     * <p>
9597     * Do not call this method directly.
9598     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9599     * </p>
9600     *
9601     * @param event The motion event to be dispatched.
9602     * @return True if the event was handled by the view, false otherwise.
9603     */
9604    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
9605        return false;
9606    }
9607
9608    /**
9609     * Dispatch a generic motion event to the currently focused view.
9610     * <p>
9611     * Do not call this method directly.
9612     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9613     * </p>
9614     *
9615     * @param event The motion event to be dispatched.
9616     * @return True if the event was handled by the view, false otherwise.
9617     */
9618    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9619        return false;
9620    }
9621
9622    /**
9623     * Dispatch a pointer event.
9624     * <p>
9625     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9626     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
9627     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9628     * and should not be expected to handle other pointing device features.
9629     * </p>
9630     *
9631     * @param event The motion event to be dispatched.
9632     * @return True if the event was handled by the view, false otherwise.
9633     * @hide
9634     */
9635    public final boolean dispatchPointerEvent(MotionEvent event) {
9636        if (event.isTouchEvent()) {
9637            return dispatchTouchEvent(event);
9638        } else {
9639            return dispatchGenericMotionEvent(event);
9640        }
9641    }
9642
9643    /**
9644     * Called when the window containing this view gains or loses window focus.
9645     * ViewGroups should override to route to their children.
9646     *
9647     * @param hasFocus True if the window containing this view now has focus,
9648     *        false otherwise.
9649     */
9650    public void dispatchWindowFocusChanged(boolean hasFocus) {
9651        onWindowFocusChanged(hasFocus);
9652    }
9653
9654    /**
9655     * Called when the window containing this view gains or loses focus.  Note
9656     * that this is separate from view focus: to receive key events, both
9657     * your view and its window must have focus.  If a window is displayed
9658     * on top of yours that takes input focus, then your own window will lose
9659     * focus but the view focus will remain unchanged.
9660     *
9661     * @param hasWindowFocus True if the window containing this view now has
9662     *        focus, false otherwise.
9663     */
9664    public void onWindowFocusChanged(boolean hasWindowFocus) {
9665        InputMethodManager imm = InputMethodManager.peekInstance();
9666        if (!hasWindowFocus) {
9667            if (isPressed()) {
9668                setPressed(false);
9669            }
9670            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9671                imm.focusOut(this);
9672            }
9673            removeLongPressCallback();
9674            removeTapCallback();
9675            onFocusLost();
9676        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9677            imm.focusIn(this);
9678        }
9679        refreshDrawableState();
9680    }
9681
9682    /**
9683     * Returns true if this view is in a window that currently has window focus.
9684     * Note that this is not the same as the view itself having focus.
9685     *
9686     * @return True if this view is in a window that currently has window focus.
9687     */
9688    public boolean hasWindowFocus() {
9689        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9690    }
9691
9692    /**
9693     * Dispatch a view visibility change down the view hierarchy.
9694     * ViewGroups should override to route to their children.
9695     * @param changedView The view whose visibility changed. Could be 'this' or
9696     * an ancestor view.
9697     * @param visibility The new visibility of changedView: {@link #VISIBLE},
9698     * {@link #INVISIBLE} or {@link #GONE}.
9699     */
9700    protected void dispatchVisibilityChanged(@NonNull View changedView,
9701            @Visibility int visibility) {
9702        onVisibilityChanged(changedView, visibility);
9703    }
9704
9705    /**
9706     * Called when the visibility of the view or an ancestor of the view has
9707     * changed.
9708     *
9709     * @param changedView The view whose visibility changed. May be
9710     *                    {@code this} or an ancestor view.
9711     * @param visibility The new visibility, one of {@link #VISIBLE},
9712     *                   {@link #INVISIBLE} or {@link #GONE}.
9713     */
9714    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9715        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9716        if (visible && mAttachInfo != null) {
9717            initialAwakenScrollBars();
9718        }
9719
9720        final Drawable dr = mBackground;
9721        if (dr != null && visible != dr.isVisible()) {
9722            dr.setVisible(visible, false);
9723        }
9724        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9725        if (fg != null && visible != fg.isVisible()) {
9726            fg.setVisible(visible, false);
9727        }
9728    }
9729
9730    /**
9731     * Dispatch a hint about whether this view is displayed. For instance, when
9732     * a View moves out of the screen, it might receives a display hint indicating
9733     * the view is not displayed. Applications should not <em>rely</em> on this hint
9734     * as there is no guarantee that they will receive one.
9735     *
9736     * @param hint A hint about whether or not this view is displayed:
9737     * {@link #VISIBLE} or {@link #INVISIBLE}.
9738     */
9739    public void dispatchDisplayHint(@Visibility int hint) {
9740        onDisplayHint(hint);
9741    }
9742
9743    /**
9744     * Gives this view a hint about whether is displayed or not. For instance, when
9745     * a View moves out of the screen, it might receives a display hint indicating
9746     * the view is not displayed. Applications should not <em>rely</em> on this hint
9747     * as there is no guarantee that they will receive one.
9748     *
9749     * @param hint A hint about whether or not this view is displayed:
9750     * {@link #VISIBLE} or {@link #INVISIBLE}.
9751     */
9752    protected void onDisplayHint(@Visibility int hint) {
9753    }
9754
9755    /**
9756     * Dispatch a window visibility change down the view hierarchy.
9757     * ViewGroups should override to route to their children.
9758     *
9759     * @param visibility The new visibility of the window.
9760     *
9761     * @see #onWindowVisibilityChanged(int)
9762     */
9763    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9764        onWindowVisibilityChanged(visibility);
9765    }
9766
9767    /**
9768     * Called when the window containing has change its visibility
9769     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9770     * that this tells you whether or not your window is being made visible
9771     * to the window manager; this does <em>not</em> tell you whether or not
9772     * your window is obscured by other windows on the screen, even if it
9773     * is itself visible.
9774     *
9775     * @param visibility The new visibility of the window.
9776     */
9777    protected void onWindowVisibilityChanged(@Visibility int visibility) {
9778        if (visibility == VISIBLE) {
9779            initialAwakenScrollBars();
9780        }
9781    }
9782
9783    /**
9784     * Returns the current visibility of the window this view is attached to
9785     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9786     *
9787     * @return Returns the current visibility of the view's window.
9788     */
9789    @Visibility
9790    public int getWindowVisibility() {
9791        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9792    }
9793
9794    /**
9795     * Retrieve the overall visible display size in which the window this view is
9796     * attached to has been positioned in.  This takes into account screen
9797     * decorations above the window, for both cases where the window itself
9798     * is being position inside of them or the window is being placed under
9799     * then and covered insets are used for the window to position its content
9800     * inside.  In effect, this tells you the available area where content can
9801     * be placed and remain visible to users.
9802     *
9803     * <p>This function requires an IPC back to the window manager to retrieve
9804     * the requested information, so should not be used in performance critical
9805     * code like drawing.
9806     *
9807     * @param outRect Filled in with the visible display frame.  If the view
9808     * is not attached to a window, this is simply the raw display size.
9809     */
9810    public void getWindowVisibleDisplayFrame(Rect outRect) {
9811        if (mAttachInfo != null) {
9812            try {
9813                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9814            } catch (RemoteException e) {
9815                return;
9816            }
9817            // XXX This is really broken, and probably all needs to be done
9818            // in the window manager, and we need to know more about whether
9819            // we want the area behind or in front of the IME.
9820            final Rect insets = mAttachInfo.mVisibleInsets;
9821            outRect.left += insets.left;
9822            outRect.top += insets.top;
9823            outRect.right -= insets.right;
9824            outRect.bottom -= insets.bottom;
9825            return;
9826        }
9827        // The view is not attached to a display so we don't have a context.
9828        // Make a best guess about the display size.
9829        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9830        d.getRectSize(outRect);
9831    }
9832
9833    /**
9834     * Dispatch a notification about a resource configuration change down
9835     * the view hierarchy.
9836     * ViewGroups should override to route to their children.
9837     *
9838     * @param newConfig The new resource configuration.
9839     *
9840     * @see #onConfigurationChanged(android.content.res.Configuration)
9841     */
9842    public void dispatchConfigurationChanged(Configuration newConfig) {
9843        onConfigurationChanged(newConfig);
9844    }
9845
9846    /**
9847     * Called when the current configuration of the resources being used
9848     * by the application have changed.  You can use this to decide when
9849     * to reload resources that can changed based on orientation and other
9850     * configuration characteristics.  You only need to use this if you are
9851     * not relying on the normal {@link android.app.Activity} mechanism of
9852     * recreating the activity instance upon a configuration change.
9853     *
9854     * @param newConfig The new resource configuration.
9855     */
9856    protected void onConfigurationChanged(Configuration newConfig) {
9857    }
9858
9859    /**
9860     * Private function to aggregate all per-view attributes in to the view
9861     * root.
9862     */
9863    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9864        performCollectViewAttributes(attachInfo, visibility);
9865    }
9866
9867    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9868        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
9869            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
9870                attachInfo.mKeepScreenOn = true;
9871            }
9872            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
9873            ListenerInfo li = mListenerInfo;
9874            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
9875                attachInfo.mHasSystemUiListeners = true;
9876            }
9877        }
9878    }
9879
9880    void needGlobalAttributesUpdate(boolean force) {
9881        final AttachInfo ai = mAttachInfo;
9882        if (ai != null && !ai.mRecomputeGlobalAttributes) {
9883            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
9884                    || ai.mHasSystemUiListeners) {
9885                ai.mRecomputeGlobalAttributes = true;
9886            }
9887        }
9888    }
9889
9890    /**
9891     * Returns whether the device is currently in touch mode.  Touch mode is entered
9892     * once the user begins interacting with the device by touch, and affects various
9893     * things like whether focus is always visible to the user.
9894     *
9895     * @return Whether the device is in touch mode.
9896     */
9897    @ViewDebug.ExportedProperty
9898    public boolean isInTouchMode() {
9899        if (mAttachInfo != null) {
9900            return mAttachInfo.mInTouchMode;
9901        } else {
9902            return ViewRootImpl.isInTouchMode();
9903        }
9904    }
9905
9906    /**
9907     * Returns the context the view is running in, through which it can
9908     * access the current theme, resources, etc.
9909     *
9910     * @return The view's Context.
9911     */
9912    @ViewDebug.CapturedViewProperty
9913    public final Context getContext() {
9914        return mContext;
9915    }
9916
9917    /**
9918     * Handle a key event before it is processed by any input method
9919     * associated with the view hierarchy.  This can be used to intercept
9920     * key events in special situations before the IME consumes them; a
9921     * typical example would be handling the BACK key to update the application's
9922     * UI instead of allowing the IME to see it and close itself.
9923     *
9924     * @param keyCode The value in event.getKeyCode().
9925     * @param event Description of the key event.
9926     * @return If you handled the event, return true. If you want to allow the
9927     *         event to be handled by the next receiver, return false.
9928     */
9929    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
9930        return false;
9931    }
9932
9933    /**
9934     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
9935     * KeyEvent.Callback.onKeyDown()}: perform press of the view
9936     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
9937     * is released, if the view is enabled and clickable.
9938     *
9939     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9940     * although some may elect to do so in some situations. Do not rely on this to
9941     * catch software key presses.
9942     *
9943     * @param keyCode A key code that represents the button pressed, from
9944     *                {@link android.view.KeyEvent}.
9945     * @param event   The KeyEvent object that defines the button action.
9946     */
9947    public boolean onKeyDown(int keyCode, KeyEvent event) {
9948        boolean result = false;
9949
9950        if (KeyEvent.isConfirmKey(keyCode)) {
9951            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9952                return true;
9953            }
9954            // Long clickable items don't necessarily have to be clickable
9955            if (((mViewFlags & CLICKABLE) == CLICKABLE ||
9956                    (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
9957                    (event.getRepeatCount() == 0)) {
9958                setPressed(true);
9959                checkForLongClick(0);
9960                return true;
9961            }
9962        }
9963        return result;
9964    }
9965
9966    /**
9967     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
9968     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
9969     * the event).
9970     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9971     * although some may elect to do so in some situations. Do not rely on this to
9972     * catch software key presses.
9973     */
9974    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
9975        return false;
9976    }
9977
9978    /**
9979     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9980     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9981     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9982     * {@link KeyEvent#KEYCODE_ENTER} is released.
9983     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9984     * although some may elect to do so in some situations. Do not rely on this to
9985     * catch software key presses.
9986     *
9987     * @param keyCode A key code that represents the button pressed, from
9988     *                {@link android.view.KeyEvent}.
9989     * @param event   The KeyEvent object that defines the button action.
9990     */
9991    public boolean onKeyUp(int keyCode, KeyEvent event) {
9992        if (KeyEvent.isConfirmKey(keyCode)) {
9993            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9994                return true;
9995            }
9996            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9997                setPressed(false);
9998
9999                if (!mHasPerformedLongPress) {
10000                    // This is a tap, so remove the longpress check
10001                    removeLongPressCallback();
10002                    return performClick();
10003                }
10004            }
10005        }
10006        return false;
10007    }
10008
10009    /**
10010     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10011     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
10012     * the event).
10013     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10014     * although some may elect to do so in some situations. Do not rely on this to
10015     * catch software key presses.
10016     *
10017     * @param keyCode     A key code that represents the button pressed, from
10018     *                    {@link android.view.KeyEvent}.
10019     * @param repeatCount The number of times the action was made.
10020     * @param event       The KeyEvent object that defines the button action.
10021     */
10022    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10023        return false;
10024    }
10025
10026    /**
10027     * Called on the focused view when a key shortcut event is not handled.
10028     * Override this method to implement local key shortcuts for the View.
10029     * Key shortcuts can also be implemented by setting the
10030     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10031     *
10032     * @param keyCode The value in event.getKeyCode().
10033     * @param event Description of the key event.
10034     * @return If you handled the event, return true. If you want to allow the
10035     *         event to be handled by the next receiver, return false.
10036     */
10037    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10038        return false;
10039    }
10040
10041    /**
10042     * Check whether the called view is a text editor, in which case it
10043     * would make sense to automatically display a soft input window for
10044     * it.  Subclasses should override this if they implement
10045     * {@link #onCreateInputConnection(EditorInfo)} to return true if
10046     * a call on that method would return a non-null InputConnection, and
10047     * they are really a first-class editor that the user would normally
10048     * start typing on when the go into a window containing your view.
10049     *
10050     * <p>The default implementation always returns false.  This does
10051     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10052     * will not be called or the user can not otherwise perform edits on your
10053     * view; it is just a hint to the system that this is not the primary
10054     * purpose of this view.
10055     *
10056     * @return Returns true if this view is a text editor, else false.
10057     */
10058    public boolean onCheckIsTextEditor() {
10059        return false;
10060    }
10061
10062    /**
10063     * Create a new InputConnection for an InputMethod to interact
10064     * with the view.  The default implementation returns null, since it doesn't
10065     * support input methods.  You can override this to implement such support.
10066     * This is only needed for views that take focus and text input.
10067     *
10068     * <p>When implementing this, you probably also want to implement
10069     * {@link #onCheckIsTextEditor()} to indicate you will return a
10070     * non-null InputConnection.</p>
10071     *
10072     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10073     * object correctly and in its entirety, so that the connected IME can rely
10074     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10075     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10076     * must be filled in with the correct cursor position for IMEs to work correctly
10077     * with your application.</p>
10078     *
10079     * @param outAttrs Fill in with attribute information about the connection.
10080     */
10081    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10082        return null;
10083    }
10084
10085    /**
10086     * Called by the {@link android.view.inputmethod.InputMethodManager}
10087     * when a view who is not the current
10088     * input connection target is trying to make a call on the manager.  The
10089     * default implementation returns false; you can override this to return
10090     * true for certain views if you are performing InputConnection proxying
10091     * to them.
10092     * @param view The View that is making the InputMethodManager call.
10093     * @return Return true to allow the call, false to reject.
10094     */
10095    public boolean checkInputConnectionProxy(View view) {
10096        return false;
10097    }
10098
10099    /**
10100     * Show the context menu for this view. It is not safe to hold on to the
10101     * menu after returning from this method.
10102     *
10103     * You should normally not overload this method. Overload
10104     * {@link #onCreateContextMenu(ContextMenu)} or define an
10105     * {@link OnCreateContextMenuListener} to add items to the context menu.
10106     *
10107     * @param menu The context menu to populate
10108     */
10109    public void createContextMenu(ContextMenu menu) {
10110        ContextMenuInfo menuInfo = getContextMenuInfo();
10111
10112        // Sets the current menu info so all items added to menu will have
10113        // my extra info set.
10114        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10115
10116        onCreateContextMenu(menu);
10117        ListenerInfo li = mListenerInfo;
10118        if (li != null && li.mOnCreateContextMenuListener != null) {
10119            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10120        }
10121
10122        // Clear the extra information so subsequent items that aren't mine don't
10123        // have my extra info.
10124        ((MenuBuilder)menu).setCurrentMenuInfo(null);
10125
10126        if (mParent != null) {
10127            mParent.createContextMenu(menu);
10128        }
10129    }
10130
10131    /**
10132     * Views should implement this if they have extra information to associate
10133     * with the context menu. The return result is supplied as a parameter to
10134     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10135     * callback.
10136     *
10137     * @return Extra information about the item for which the context menu
10138     *         should be shown. This information will vary across different
10139     *         subclasses of View.
10140     */
10141    protected ContextMenuInfo getContextMenuInfo() {
10142        return null;
10143    }
10144
10145    /**
10146     * Views should implement this if the view itself is going to add items to
10147     * the context menu.
10148     *
10149     * @param menu the context menu to populate
10150     */
10151    protected void onCreateContextMenu(ContextMenu menu) {
10152    }
10153
10154    /**
10155     * Implement this method to handle trackball motion events.  The
10156     * <em>relative</em> movement of the trackball since the last event
10157     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10158     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10159     * that a movement of 1 corresponds to the user pressing one DPAD key (so
10160     * they will often be fractional values, representing the more fine-grained
10161     * movement information available from a trackball).
10162     *
10163     * @param event The motion event.
10164     * @return True if the event was handled, false otherwise.
10165     */
10166    public boolean onTrackballEvent(MotionEvent event) {
10167        return false;
10168    }
10169
10170    /**
10171     * Implement this method to handle generic motion events.
10172     * <p>
10173     * Generic motion events describe joystick movements, mouse hovers, track pad
10174     * touches, scroll wheel movements and other input events.  The
10175     * {@link MotionEvent#getSource() source} of the motion event specifies
10176     * the class of input that was received.  Implementations of this method
10177     * must examine the bits in the source before processing the event.
10178     * The following code example shows how this is done.
10179     * </p><p>
10180     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10181     * are delivered to the view under the pointer.  All other generic motion events are
10182     * delivered to the focused view.
10183     * </p>
10184     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10185     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10186     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10187     *             // process the joystick movement...
10188     *             return true;
10189     *         }
10190     *     }
10191     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10192     *         switch (event.getAction()) {
10193     *             case MotionEvent.ACTION_HOVER_MOVE:
10194     *                 // process the mouse hover movement...
10195     *                 return true;
10196     *             case MotionEvent.ACTION_SCROLL:
10197     *                 // process the scroll wheel movement...
10198     *                 return true;
10199     *         }
10200     *     }
10201     *     return super.onGenericMotionEvent(event);
10202     * }</pre>
10203     *
10204     * @param event The generic motion event being processed.
10205     * @return True if the event was handled, false otherwise.
10206     */
10207    public boolean onGenericMotionEvent(MotionEvent event) {
10208        return false;
10209    }
10210
10211    /**
10212     * Implement this method to handle hover events.
10213     * <p>
10214     * This method is called whenever a pointer is hovering into, over, or out of the
10215     * bounds of a view and the view is not currently being touched.
10216     * Hover events are represented as pointer events with action
10217     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10218     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10219     * </p>
10220     * <ul>
10221     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10222     * when the pointer enters the bounds of the view.</li>
10223     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10224     * when the pointer has already entered the bounds of the view and has moved.</li>
10225     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10226     * when the pointer has exited the bounds of the view or when the pointer is
10227     * about to go down due to a button click, tap, or similar user action that
10228     * causes the view to be touched.</li>
10229     * </ul>
10230     * <p>
10231     * The view should implement this method to return true to indicate that it is
10232     * handling the hover event, such as by changing its drawable state.
10233     * </p><p>
10234     * The default implementation calls {@link #setHovered} to update the hovered state
10235     * of the view when a hover enter or hover exit event is received, if the view
10236     * is enabled and is clickable.  The default implementation also sends hover
10237     * accessibility events.
10238     * </p>
10239     *
10240     * @param event The motion event that describes the hover.
10241     * @return True if the view handled the hover event.
10242     *
10243     * @see #isHovered
10244     * @see #setHovered
10245     * @see #onHoverChanged
10246     */
10247    public boolean onHoverEvent(MotionEvent event) {
10248        // The root view may receive hover (or touch) events that are outside the bounds of
10249        // the window.  This code ensures that we only send accessibility events for
10250        // hovers that are actually within the bounds of the root view.
10251        final int action = event.getActionMasked();
10252        if (!mSendingHoverAccessibilityEvents) {
10253            if ((action == MotionEvent.ACTION_HOVER_ENTER
10254                    || action == MotionEvent.ACTION_HOVER_MOVE)
10255                    && !hasHoveredChild()
10256                    && pointInView(event.getX(), event.getY())) {
10257                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10258                mSendingHoverAccessibilityEvents = true;
10259            }
10260        } else {
10261            if (action == MotionEvent.ACTION_HOVER_EXIT
10262                    || (action == MotionEvent.ACTION_MOVE
10263                            && !pointInView(event.getX(), event.getY()))) {
10264                mSendingHoverAccessibilityEvents = false;
10265                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10266            }
10267        }
10268
10269        if (isHoverable()) {
10270            switch (action) {
10271                case MotionEvent.ACTION_HOVER_ENTER:
10272                    setHovered(true);
10273                    break;
10274                case MotionEvent.ACTION_HOVER_EXIT:
10275                    setHovered(false);
10276                    break;
10277            }
10278
10279            // Dispatch the event to onGenericMotionEvent before returning true.
10280            // This is to provide compatibility with existing applications that
10281            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10282            // break because of the new default handling for hoverable views
10283            // in onHoverEvent.
10284            // Note that onGenericMotionEvent will be called by default when
10285            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10286            dispatchGenericMotionEventInternal(event);
10287            // The event was already handled by calling setHovered(), so always
10288            // return true.
10289            return true;
10290        }
10291
10292        return false;
10293    }
10294
10295    /**
10296     * Returns true if the view should handle {@link #onHoverEvent}
10297     * by calling {@link #setHovered} to change its hovered state.
10298     *
10299     * @return True if the view is hoverable.
10300     */
10301    private boolean isHoverable() {
10302        final int viewFlags = mViewFlags;
10303        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10304            return false;
10305        }
10306
10307        return (viewFlags & CLICKABLE) == CLICKABLE
10308                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10309                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10310    }
10311
10312    /**
10313     * Returns true if the view is currently hovered.
10314     *
10315     * @return True if the view is currently hovered.
10316     *
10317     * @see #setHovered
10318     * @see #onHoverChanged
10319     */
10320    @ViewDebug.ExportedProperty
10321    public boolean isHovered() {
10322        return (mPrivateFlags & PFLAG_HOVERED) != 0;
10323    }
10324
10325    /**
10326     * Sets whether the view is currently hovered.
10327     * <p>
10328     * Calling this method also changes the drawable state of the view.  This
10329     * enables the view to react to hover by using different drawable resources
10330     * to change its appearance.
10331     * </p><p>
10332     * The {@link #onHoverChanged} method is called when the hovered state changes.
10333     * </p>
10334     *
10335     * @param hovered True if the view is hovered.
10336     *
10337     * @see #isHovered
10338     * @see #onHoverChanged
10339     */
10340    public void setHovered(boolean hovered) {
10341        if (hovered) {
10342            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10343                mPrivateFlags |= PFLAG_HOVERED;
10344                refreshDrawableState();
10345                onHoverChanged(true);
10346            }
10347        } else {
10348            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10349                mPrivateFlags &= ~PFLAG_HOVERED;
10350                refreshDrawableState();
10351                onHoverChanged(false);
10352            }
10353        }
10354    }
10355
10356    /**
10357     * Implement this method to handle hover state changes.
10358     * <p>
10359     * This method is called whenever the hover state changes as a result of a
10360     * call to {@link #setHovered}.
10361     * </p>
10362     *
10363     * @param hovered The current hover state, as returned by {@link #isHovered}.
10364     *
10365     * @see #isHovered
10366     * @see #setHovered
10367     */
10368    public void onHoverChanged(boolean hovered) {
10369    }
10370
10371    /**
10372     * Implement this method to handle touch screen motion events.
10373     * <p>
10374     * If this method is used to detect click actions, it is recommended that
10375     * the actions be performed by implementing and calling
10376     * {@link #performClick()}. This will ensure consistent system behavior,
10377     * including:
10378     * <ul>
10379     * <li>obeying click sound preferences
10380     * <li>dispatching OnClickListener calls
10381     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
10382     * accessibility features are enabled
10383     * </ul>
10384     *
10385     * @param event The motion event.
10386     * @return True if the event was handled, false otherwise.
10387     */
10388    public boolean onTouchEvent(MotionEvent event) {
10389        final float x = event.getX();
10390        final float y = event.getY();
10391        final int viewFlags = mViewFlags;
10392        final int action = event.getAction();
10393
10394        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10395            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
10396                setPressed(false);
10397            }
10398            // A disabled view that is clickable still consumes the touch
10399            // events, it just doesn't respond to them.
10400            return (((viewFlags & CLICKABLE) == CLICKABLE
10401                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10402                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
10403        }
10404
10405        if (mTouchDelegate != null) {
10406            if (mTouchDelegate.onTouchEvent(event)) {
10407                return true;
10408            }
10409        }
10410
10411        if (((viewFlags & CLICKABLE) == CLICKABLE ||
10412                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
10413                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
10414            switch (action) {
10415                case MotionEvent.ACTION_UP:
10416                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
10417                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
10418                        // take focus if we don't have it already and we should in
10419                        // touch mode.
10420                        boolean focusTaken = false;
10421                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
10422                            focusTaken = requestFocus();
10423                        }
10424
10425                        if (prepressed) {
10426                            // The button is being released before we actually
10427                            // showed it as pressed.  Make it show the pressed
10428                            // state now (before scheduling the click) to ensure
10429                            // the user sees it.
10430                            setPressed(true, x, y);
10431                       }
10432
10433                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
10434                            // This is a tap, so remove the longpress check
10435                            removeLongPressCallback();
10436
10437                            // Only perform take click actions if we were in the pressed state
10438                            if (!focusTaken) {
10439                                // Use a Runnable and post this rather than calling
10440                                // performClick directly. This lets other visual state
10441                                // of the view update before click actions start.
10442                                if (mPerformClick == null) {
10443                                    mPerformClick = new PerformClick();
10444                                }
10445                                if (!post(mPerformClick)) {
10446                                    performClick();
10447                                }
10448                            }
10449                        }
10450
10451                        if (mUnsetPressedState == null) {
10452                            mUnsetPressedState = new UnsetPressedState();
10453                        }
10454
10455                        if (prepressed) {
10456                            postDelayed(mUnsetPressedState,
10457                                    ViewConfiguration.getPressedStateDuration());
10458                        } else if (!post(mUnsetPressedState)) {
10459                            // If the post failed, unpress right now
10460                            mUnsetPressedState.run();
10461                        }
10462
10463                        removeTapCallback();
10464                    }
10465                    mIgnoreNextUpEvent = false;
10466                    break;
10467
10468                case MotionEvent.ACTION_DOWN:
10469                    mHasPerformedLongPress = false;
10470
10471                    if (performButtonActionOnTouchDown(event)) {
10472                        break;
10473                    }
10474
10475                    // Walk up the hierarchy to determine if we're inside a scrolling container.
10476                    boolean isInScrollingContainer = isInScrollingContainer();
10477
10478                    // For views inside a scrolling container, delay the pressed feedback for
10479                    // a short period in case this is a scroll.
10480                    if (isInScrollingContainer) {
10481                        mPrivateFlags |= PFLAG_PREPRESSED;
10482                        if (mPendingCheckForTap == null) {
10483                            mPendingCheckForTap = new CheckForTap();
10484                        }
10485                        mPendingCheckForTap.x = event.getX();
10486                        mPendingCheckForTap.y = event.getY();
10487                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
10488                    } else {
10489                        // Not inside a scrolling container, so show the feedback right away
10490                        setPressed(true, x, y);
10491                        checkForLongClick(0);
10492                    }
10493                    break;
10494
10495                case MotionEvent.ACTION_CANCEL:
10496                    setPressed(false);
10497                    removeTapCallback();
10498                    removeLongPressCallback();
10499                    mInContextButtonPress = false;
10500                    mHasPerformedLongPress = false;
10501                    mIgnoreNextUpEvent = false;
10502                    break;
10503
10504                case MotionEvent.ACTION_MOVE:
10505                    drawableHotspotChanged(x, y);
10506
10507                    // Be lenient about moving outside of buttons
10508                    if (!pointInView(x, y, mTouchSlop)) {
10509                        // Outside button
10510                        removeTapCallback();
10511                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
10512                            // Remove any future long press/tap checks
10513                            removeLongPressCallback();
10514
10515                            setPressed(false);
10516                        }
10517                    }
10518                    break;
10519            }
10520
10521            return true;
10522        }
10523
10524        return false;
10525    }
10526
10527    /**
10528     * @hide
10529     */
10530    public boolean isInScrollingContainer() {
10531        ViewParent p = getParent();
10532        while (p != null && p instanceof ViewGroup) {
10533            if (((ViewGroup) p).shouldDelayChildPressedState()) {
10534                return true;
10535            }
10536            p = p.getParent();
10537        }
10538        return false;
10539    }
10540
10541    /**
10542     * Remove the longpress detection timer.
10543     */
10544    private void removeLongPressCallback() {
10545        if (mPendingCheckForLongPress != null) {
10546          removeCallbacks(mPendingCheckForLongPress);
10547        }
10548    }
10549
10550    /**
10551     * Remove the pending click action
10552     */
10553    private void removePerformClickCallback() {
10554        if (mPerformClick != null) {
10555            removeCallbacks(mPerformClick);
10556        }
10557    }
10558
10559    /**
10560     * Remove the prepress detection timer.
10561     */
10562    private void removeUnsetPressCallback() {
10563        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
10564            setPressed(false);
10565            removeCallbacks(mUnsetPressedState);
10566        }
10567    }
10568
10569    /**
10570     * Remove the tap detection timer.
10571     */
10572    private void removeTapCallback() {
10573        if (mPendingCheckForTap != null) {
10574            mPrivateFlags &= ~PFLAG_PREPRESSED;
10575            removeCallbacks(mPendingCheckForTap);
10576        }
10577    }
10578
10579    /**
10580     * Cancels a pending long press.  Your subclass can use this if you
10581     * want the context menu to come up if the user presses and holds
10582     * at the same place, but you don't want it to come up if they press
10583     * and then move around enough to cause scrolling.
10584     */
10585    public void cancelLongPress() {
10586        removeLongPressCallback();
10587
10588        /*
10589         * The prepressed state handled by the tap callback is a display
10590         * construct, but the tap callback will post a long press callback
10591         * less its own timeout. Remove it here.
10592         */
10593        removeTapCallback();
10594    }
10595
10596    /**
10597     * Remove the pending callback for sending a
10598     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
10599     */
10600    private void removeSendViewScrolledAccessibilityEventCallback() {
10601        if (mSendViewScrolledAccessibilityEvent != null) {
10602            removeCallbacks(mSendViewScrolledAccessibilityEvent);
10603            mSendViewScrolledAccessibilityEvent.mIsPending = false;
10604        }
10605    }
10606
10607    /**
10608     * Sets the TouchDelegate for this View.
10609     */
10610    public void setTouchDelegate(TouchDelegate delegate) {
10611        mTouchDelegate = delegate;
10612    }
10613
10614    /**
10615     * Gets the TouchDelegate for this View.
10616     */
10617    public TouchDelegate getTouchDelegate() {
10618        return mTouchDelegate;
10619    }
10620
10621    /**
10622     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10623     *
10624     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10625     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10626     * available. This method should only be called for touch events.
10627     *
10628     * <p class="note">This api is not intended for most applications. Buffered dispatch
10629     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10630     * streams will not improve your input latency. Side effects include: increased latency,
10631     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10632     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10633     * you.</p>
10634     */
10635    public final void requestUnbufferedDispatch(MotionEvent event) {
10636        final int action = event.getAction();
10637        if (mAttachInfo == null
10638                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10639                || !event.isTouchEvent()) {
10640            return;
10641        }
10642        mAttachInfo.mUnbufferedDispatchRequested = true;
10643    }
10644
10645    /**
10646     * Set flags controlling behavior of this view.
10647     *
10648     * @param flags Constant indicating the value which should be set
10649     * @param mask Constant indicating the bit range that should be changed
10650     */
10651    void setFlags(int flags, int mask) {
10652        final boolean accessibilityEnabled =
10653                AccessibilityManager.getInstance(mContext).isEnabled();
10654        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10655
10656        int old = mViewFlags;
10657        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10658
10659        int changed = mViewFlags ^ old;
10660        if (changed == 0) {
10661            return;
10662        }
10663        int privateFlags = mPrivateFlags;
10664
10665        /* Check if the FOCUSABLE bit has changed */
10666        if (((changed & FOCUSABLE_MASK) != 0) &&
10667                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10668            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10669                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10670                /* Give up focus if we are no longer focusable */
10671                clearFocus();
10672            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10673                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10674                /*
10675                 * Tell the view system that we are now available to take focus
10676                 * if no one else already has it.
10677                 */
10678                if (mParent != null) mParent.focusableViewAvailable(this);
10679            }
10680        }
10681
10682        final int newVisibility = flags & VISIBILITY_MASK;
10683        if (newVisibility == VISIBLE) {
10684            if ((changed & VISIBILITY_MASK) != 0) {
10685                /*
10686                 * If this view is becoming visible, invalidate it in case it changed while
10687                 * it was not visible. Marking it drawn ensures that the invalidation will
10688                 * go through.
10689                 */
10690                mPrivateFlags |= PFLAG_DRAWN;
10691                invalidate(true);
10692
10693                needGlobalAttributesUpdate(true);
10694
10695                // a view becoming visible is worth notifying the parent
10696                // about in case nothing has focus.  even if this specific view
10697                // isn't focusable, it may contain something that is, so let
10698                // the root view try to give this focus if nothing else does.
10699                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10700                    mParent.focusableViewAvailable(this);
10701                }
10702            }
10703        }
10704
10705        /* Check if the GONE bit has changed */
10706        if ((changed & GONE) != 0) {
10707            needGlobalAttributesUpdate(false);
10708            requestLayout();
10709
10710            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10711                if (hasFocus()) clearFocus();
10712                clearAccessibilityFocus();
10713                destroyDrawingCache();
10714                if (mParent instanceof View) {
10715                    // GONE views noop invalidation, so invalidate the parent
10716                    ((View) mParent).invalidate(true);
10717                }
10718                // Mark the view drawn to ensure that it gets invalidated properly the next
10719                // time it is visible and gets invalidated
10720                mPrivateFlags |= PFLAG_DRAWN;
10721            }
10722            if (mAttachInfo != null) {
10723                mAttachInfo.mViewVisibilityChanged = true;
10724            }
10725        }
10726
10727        /* Check if the VISIBLE bit has changed */
10728        if ((changed & INVISIBLE) != 0) {
10729            needGlobalAttributesUpdate(false);
10730            /*
10731             * If this view is becoming invisible, set the DRAWN flag so that
10732             * the next invalidate() will not be skipped.
10733             */
10734            mPrivateFlags |= PFLAG_DRAWN;
10735
10736            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10737                // root view becoming invisible shouldn't clear focus and accessibility focus
10738                if (getRootView() != this) {
10739                    if (hasFocus()) clearFocus();
10740                    clearAccessibilityFocus();
10741                }
10742            }
10743            if (mAttachInfo != null) {
10744                mAttachInfo.mViewVisibilityChanged = true;
10745            }
10746        }
10747
10748        if ((changed & VISIBILITY_MASK) != 0) {
10749            // If the view is invisible, cleanup its display list to free up resources
10750            if (newVisibility != VISIBLE && mAttachInfo != null) {
10751                cleanupDraw();
10752            }
10753
10754            if (mParent instanceof ViewGroup) {
10755                ((ViewGroup) mParent).onChildVisibilityChanged(this,
10756                        (changed & VISIBILITY_MASK), newVisibility);
10757                ((View) mParent).invalidate(true);
10758            } else if (mParent != null) {
10759                mParent.invalidateChild(this, null);
10760            }
10761
10762            if (mAttachInfo != null) {
10763                dispatchVisibilityChanged(this, newVisibility);
10764                notifySubtreeAccessibilityStateChangedIfNeeded();
10765            }
10766        }
10767
10768        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10769            destroyDrawingCache();
10770        }
10771
10772        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10773            destroyDrawingCache();
10774            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10775            invalidateParentCaches();
10776        }
10777
10778        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10779            destroyDrawingCache();
10780            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10781        }
10782
10783        if ((changed & DRAW_MASK) != 0) {
10784            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10785                if (mBackground != null
10786                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
10787                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10788                } else {
10789                    mPrivateFlags |= PFLAG_SKIP_DRAW;
10790                }
10791            } else {
10792                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10793            }
10794            requestLayout();
10795            invalidate(true);
10796        }
10797
10798        if ((changed & KEEP_SCREEN_ON) != 0) {
10799            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10800                mParent.recomputeViewAttributes(this);
10801            }
10802        }
10803
10804        if (accessibilityEnabled) {
10805            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10806                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
10807                    || (changed & CONTEXT_CLICKABLE) != 0) {
10808                if (oldIncludeForAccessibility != includeForAccessibility()) {
10809                    notifySubtreeAccessibilityStateChangedIfNeeded();
10810                } else {
10811                    notifyViewAccessibilityStateChangedIfNeeded(
10812                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10813                }
10814            } else if ((changed & ENABLED_MASK) != 0) {
10815                notifyViewAccessibilityStateChangedIfNeeded(
10816                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10817            }
10818        }
10819    }
10820
10821    /**
10822     * Change the view's z order in the tree, so it's on top of other sibling
10823     * views. This ordering change may affect layout, if the parent container
10824     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10825     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10826     * method should be followed by calls to {@link #requestLayout()} and
10827     * {@link View#invalidate()} on the view's parent to force the parent to redraw
10828     * with the new child ordering.
10829     *
10830     * @see ViewGroup#bringChildToFront(View)
10831     */
10832    public void bringToFront() {
10833        if (mParent != null) {
10834            mParent.bringChildToFront(this);
10835        }
10836    }
10837
10838    /**
10839     * This is called in response to an internal scroll in this view (i.e., the
10840     * view scrolled its own contents). This is typically as a result of
10841     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10842     * called.
10843     *
10844     * @param l Current horizontal scroll origin.
10845     * @param t Current vertical scroll origin.
10846     * @param oldl Previous horizontal scroll origin.
10847     * @param oldt Previous vertical scroll origin.
10848     */
10849    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10850        notifySubtreeAccessibilityStateChangedIfNeeded();
10851
10852        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10853            postSendViewScrolledAccessibilityEventCallback();
10854        }
10855
10856        mBackgroundSizeChanged = true;
10857        if (mForegroundInfo != null) {
10858            mForegroundInfo.mBoundsChanged = true;
10859        }
10860
10861        final AttachInfo ai = mAttachInfo;
10862        if (ai != null) {
10863            ai.mViewScrollChanged = true;
10864        }
10865
10866        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
10867            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
10868        }
10869    }
10870
10871    /**
10872     * Interface definition for a callback to be invoked when the scroll
10873     * X or Y positions of a view change.
10874     * <p>
10875     * <b>Note:</b> Some views handle scrolling independently from View and may
10876     * have their own separate listeners for scroll-type events. For example,
10877     * {@link android.widget.ListView ListView} allows clients to register an
10878     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
10879     * to listen for changes in list scroll position.
10880     *
10881     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
10882     */
10883    public interface OnScrollChangeListener {
10884        /**
10885         * Called when the scroll position of a view changes.
10886         *
10887         * @param v The view whose scroll position has changed.
10888         * @param scrollX Current horizontal scroll origin.
10889         * @param scrollY Current vertical scroll origin.
10890         * @param oldScrollX Previous horizontal scroll origin.
10891         * @param oldScrollY Previous vertical scroll origin.
10892         */
10893        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
10894    }
10895
10896    /**
10897     * Interface definition for a callback to be invoked when the layout bounds of a view
10898     * changes due to layout processing.
10899     */
10900    public interface OnLayoutChangeListener {
10901        /**
10902         * Called when the layout bounds of a view changes due to layout processing.
10903         *
10904         * @param v The view whose bounds have changed.
10905         * @param left The new value of the view's left property.
10906         * @param top The new value of the view's top property.
10907         * @param right The new value of the view's right property.
10908         * @param bottom The new value of the view's bottom property.
10909         * @param oldLeft The previous value of the view's left property.
10910         * @param oldTop The previous value of the view's top property.
10911         * @param oldRight The previous value of the view's right property.
10912         * @param oldBottom The previous value of the view's bottom property.
10913         */
10914        void onLayoutChange(View v, int left, int top, int right, int bottom,
10915            int oldLeft, int oldTop, int oldRight, int oldBottom);
10916    }
10917
10918    /**
10919     * This is called during layout when the size of this view has changed. If
10920     * you were just added to the view hierarchy, you're called with the old
10921     * values of 0.
10922     *
10923     * @param w Current width of this view.
10924     * @param h Current height of this view.
10925     * @param oldw Old width of this view.
10926     * @param oldh Old height of this view.
10927     */
10928    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
10929    }
10930
10931    /**
10932     * Called by draw to draw the child views. This may be overridden
10933     * by derived classes to gain control just before its children are drawn
10934     * (but after its own view has been drawn).
10935     * @param canvas the canvas on which to draw the view
10936     */
10937    protected void dispatchDraw(Canvas canvas) {
10938
10939    }
10940
10941    /**
10942     * Gets the parent of this view. Note that the parent is a
10943     * ViewParent and not necessarily a View.
10944     *
10945     * @return Parent of this view.
10946     */
10947    public final ViewParent getParent() {
10948        return mParent;
10949    }
10950
10951    /**
10952     * Set the horizontal scrolled position of your view. This will cause a call to
10953     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10954     * invalidated.
10955     * @param value the x position to scroll to
10956     */
10957    public void setScrollX(int value) {
10958        scrollTo(value, mScrollY);
10959    }
10960
10961    /**
10962     * Set the vertical scrolled position of your view. This will cause a call to
10963     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10964     * invalidated.
10965     * @param value the y position to scroll to
10966     */
10967    public void setScrollY(int value) {
10968        scrollTo(mScrollX, value);
10969    }
10970
10971    /**
10972     * Return the scrolled left position of this view. This is the left edge of
10973     * the displayed part of your view. You do not need to draw any pixels
10974     * farther left, since those are outside of the frame of your view on
10975     * screen.
10976     *
10977     * @return The left edge of the displayed part of your view, in pixels.
10978     */
10979    public final int getScrollX() {
10980        return mScrollX;
10981    }
10982
10983    /**
10984     * Return the scrolled top position of this view. This is the top edge of
10985     * the displayed part of your view. You do not need to draw any pixels above
10986     * it, since those are outside of the frame of your view on screen.
10987     *
10988     * @return The top edge of the displayed part of your view, in pixels.
10989     */
10990    public final int getScrollY() {
10991        return mScrollY;
10992    }
10993
10994    /**
10995     * Return the width of the your view.
10996     *
10997     * @return The width of your view, in pixels.
10998     */
10999    @ViewDebug.ExportedProperty(category = "layout")
11000    public final int getWidth() {
11001        return mRight - mLeft;
11002    }
11003
11004    /**
11005     * Return the height of your view.
11006     *
11007     * @return The height of your view, in pixels.
11008     */
11009    @ViewDebug.ExportedProperty(category = "layout")
11010    public final int getHeight() {
11011        return mBottom - mTop;
11012    }
11013
11014    /**
11015     * Return the visible drawing bounds of your view. Fills in the output
11016     * rectangle with the values from getScrollX(), getScrollY(),
11017     * getWidth(), and getHeight(). These bounds do not account for any
11018     * transformation properties currently set on the view, such as
11019     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11020     *
11021     * @param outRect The (scrolled) drawing bounds of the view.
11022     */
11023    public void getDrawingRect(Rect outRect) {
11024        outRect.left = mScrollX;
11025        outRect.top = mScrollY;
11026        outRect.right = mScrollX + (mRight - mLeft);
11027        outRect.bottom = mScrollY + (mBottom - mTop);
11028    }
11029
11030    /**
11031     * Like {@link #getMeasuredWidthAndState()}, but only returns the
11032     * raw width component (that is the result is masked by
11033     * {@link #MEASURED_SIZE_MASK}).
11034     *
11035     * @return The raw measured width of this view.
11036     */
11037    public final int getMeasuredWidth() {
11038        return mMeasuredWidth & MEASURED_SIZE_MASK;
11039    }
11040
11041    /**
11042     * Return the full width measurement information for this view as computed
11043     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11044     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11045     * This should be used during measurement and layout calculations only. Use
11046     * {@link #getWidth()} to see how wide a view is after layout.
11047     *
11048     * @return The measured width of this view as a bit mask.
11049     */
11050    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11051            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11052                    name = "MEASURED_STATE_TOO_SMALL"),
11053    })
11054    public final int getMeasuredWidthAndState() {
11055        return mMeasuredWidth;
11056    }
11057
11058    /**
11059     * Like {@link #getMeasuredHeightAndState()}, but only returns the
11060     * raw width component (that is the result is masked by
11061     * {@link #MEASURED_SIZE_MASK}).
11062     *
11063     * @return The raw measured height of this view.
11064     */
11065    public final int getMeasuredHeight() {
11066        return mMeasuredHeight & MEASURED_SIZE_MASK;
11067    }
11068
11069    /**
11070     * Return the full height measurement information for this view as computed
11071     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11072     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11073     * This should be used during measurement and layout calculations only. Use
11074     * {@link #getHeight()} to see how wide a view is after layout.
11075     *
11076     * @return The measured width of this view as a bit mask.
11077     */
11078    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11079            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11080                    name = "MEASURED_STATE_TOO_SMALL"),
11081    })
11082    public final int getMeasuredHeightAndState() {
11083        return mMeasuredHeight;
11084    }
11085
11086    /**
11087     * Return only the state bits of {@link #getMeasuredWidthAndState()}
11088     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11089     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11090     * and the height component is at the shifted bits
11091     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11092     */
11093    public final int getMeasuredState() {
11094        return (mMeasuredWidth&MEASURED_STATE_MASK)
11095                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11096                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11097    }
11098
11099    /**
11100     * The transform matrix of this view, which is calculated based on the current
11101     * rotation, scale, and pivot properties.
11102     *
11103     * @see #getRotation()
11104     * @see #getScaleX()
11105     * @see #getScaleY()
11106     * @see #getPivotX()
11107     * @see #getPivotY()
11108     * @return The current transform matrix for the view
11109     */
11110    public Matrix getMatrix() {
11111        ensureTransformationInfo();
11112        final Matrix matrix = mTransformationInfo.mMatrix;
11113        mRenderNode.getMatrix(matrix);
11114        return matrix;
11115    }
11116
11117    /**
11118     * Returns true if the transform matrix is the identity matrix.
11119     * Recomputes the matrix if necessary.
11120     *
11121     * @return True if the transform matrix is the identity matrix, false otherwise.
11122     */
11123    final boolean hasIdentityMatrix() {
11124        return mRenderNode.hasIdentityMatrix();
11125    }
11126
11127    void ensureTransformationInfo() {
11128        if (mTransformationInfo == null) {
11129            mTransformationInfo = new TransformationInfo();
11130        }
11131    }
11132
11133   /**
11134     * Utility method to retrieve the inverse of the current mMatrix property.
11135     * We cache the matrix to avoid recalculating it when transform properties
11136     * have not changed.
11137     *
11138     * @return The inverse of the current matrix of this view.
11139     * @hide
11140     */
11141    public final Matrix getInverseMatrix() {
11142        ensureTransformationInfo();
11143        if (mTransformationInfo.mInverseMatrix == null) {
11144            mTransformationInfo.mInverseMatrix = new Matrix();
11145        }
11146        final Matrix matrix = mTransformationInfo.mInverseMatrix;
11147        mRenderNode.getInverseMatrix(matrix);
11148        return matrix;
11149    }
11150
11151    /**
11152     * Gets the distance along the Z axis from the camera to this view.
11153     *
11154     * @see #setCameraDistance(float)
11155     *
11156     * @return The distance along the Z axis.
11157     */
11158    public float getCameraDistance() {
11159        final float dpi = mResources.getDisplayMetrics().densityDpi;
11160        return -(mRenderNode.getCameraDistance() * dpi);
11161    }
11162
11163    /**
11164     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11165     * views are drawn) from the camera to this view. The camera's distance
11166     * affects 3D transformations, for instance rotations around the X and Y
11167     * axis. If the rotationX or rotationY properties are changed and this view is
11168     * large (more than half the size of the screen), it is recommended to always
11169     * use a camera distance that's greater than the height (X axis rotation) or
11170     * the width (Y axis rotation) of this view.</p>
11171     *
11172     * <p>The distance of the camera from the view plane can have an affect on the
11173     * perspective distortion of the view when it is rotated around the x or y axis.
11174     * For example, a large distance will result in a large viewing angle, and there
11175     * will not be much perspective distortion of the view as it rotates. A short
11176     * distance may cause much more perspective distortion upon rotation, and can
11177     * also result in some drawing artifacts if the rotated view ends up partially
11178     * behind the camera (which is why the recommendation is to use a distance at
11179     * least as far as the size of the view, if the view is to be rotated.)</p>
11180     *
11181     * <p>The distance is expressed in "depth pixels." The default distance depends
11182     * on the screen density. For instance, on a medium density display, the
11183     * default distance is 1280. On a high density display, the default distance
11184     * is 1920.</p>
11185     *
11186     * <p>If you want to specify a distance that leads to visually consistent
11187     * results across various densities, use the following formula:</p>
11188     * <pre>
11189     * float scale = context.getResources().getDisplayMetrics().density;
11190     * view.setCameraDistance(distance * scale);
11191     * </pre>
11192     *
11193     * <p>The density scale factor of a high density display is 1.5,
11194     * and 1920 = 1280 * 1.5.</p>
11195     *
11196     * @param distance The distance in "depth pixels", if negative the opposite
11197     *        value is used
11198     *
11199     * @see #setRotationX(float)
11200     * @see #setRotationY(float)
11201     */
11202    public void setCameraDistance(float distance) {
11203        final float dpi = mResources.getDisplayMetrics().densityDpi;
11204
11205        invalidateViewProperty(true, false);
11206        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11207        invalidateViewProperty(false, false);
11208
11209        invalidateParentIfNeededAndWasQuickRejected();
11210    }
11211
11212    /**
11213     * The degrees that the view is rotated around the pivot point.
11214     *
11215     * @see #setRotation(float)
11216     * @see #getPivotX()
11217     * @see #getPivotY()
11218     *
11219     * @return The degrees of rotation.
11220     */
11221    @ViewDebug.ExportedProperty(category = "drawing")
11222    public float getRotation() {
11223        return mRenderNode.getRotation();
11224    }
11225
11226    /**
11227     * Sets the degrees that the view is rotated around the pivot point. Increasing values
11228     * result in clockwise rotation.
11229     *
11230     * @param rotation The degrees of rotation.
11231     *
11232     * @see #getRotation()
11233     * @see #getPivotX()
11234     * @see #getPivotY()
11235     * @see #setRotationX(float)
11236     * @see #setRotationY(float)
11237     *
11238     * @attr ref android.R.styleable#View_rotation
11239     */
11240    public void setRotation(float rotation) {
11241        if (rotation != getRotation()) {
11242            // Double-invalidation is necessary to capture view's old and new areas
11243            invalidateViewProperty(true, false);
11244            mRenderNode.setRotation(rotation);
11245            invalidateViewProperty(false, true);
11246
11247            invalidateParentIfNeededAndWasQuickRejected();
11248            notifySubtreeAccessibilityStateChangedIfNeeded();
11249        }
11250    }
11251
11252    /**
11253     * The degrees that the view is rotated around the vertical axis through the pivot point.
11254     *
11255     * @see #getPivotX()
11256     * @see #getPivotY()
11257     * @see #setRotationY(float)
11258     *
11259     * @return The degrees of Y rotation.
11260     */
11261    @ViewDebug.ExportedProperty(category = "drawing")
11262    public float getRotationY() {
11263        return mRenderNode.getRotationY();
11264    }
11265
11266    /**
11267     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
11268     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
11269     * down the y axis.
11270     *
11271     * When rotating large views, it is recommended to adjust the camera distance
11272     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11273     *
11274     * @param rotationY The degrees of Y rotation.
11275     *
11276     * @see #getRotationY()
11277     * @see #getPivotX()
11278     * @see #getPivotY()
11279     * @see #setRotation(float)
11280     * @see #setRotationX(float)
11281     * @see #setCameraDistance(float)
11282     *
11283     * @attr ref android.R.styleable#View_rotationY
11284     */
11285    public void setRotationY(float rotationY) {
11286        if (rotationY != getRotationY()) {
11287            invalidateViewProperty(true, false);
11288            mRenderNode.setRotationY(rotationY);
11289            invalidateViewProperty(false, true);
11290
11291            invalidateParentIfNeededAndWasQuickRejected();
11292            notifySubtreeAccessibilityStateChangedIfNeeded();
11293        }
11294    }
11295
11296    /**
11297     * The degrees that the view is rotated around the horizontal axis through the pivot point.
11298     *
11299     * @see #getPivotX()
11300     * @see #getPivotY()
11301     * @see #setRotationX(float)
11302     *
11303     * @return The degrees of X rotation.
11304     */
11305    @ViewDebug.ExportedProperty(category = "drawing")
11306    public float getRotationX() {
11307        return mRenderNode.getRotationX();
11308    }
11309
11310    /**
11311     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
11312     * Increasing values result in clockwise rotation from the viewpoint of looking down the
11313     * x axis.
11314     *
11315     * When rotating large views, it is recommended to adjust the camera distance
11316     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11317     *
11318     * @param rotationX The degrees of X rotation.
11319     *
11320     * @see #getRotationX()
11321     * @see #getPivotX()
11322     * @see #getPivotY()
11323     * @see #setRotation(float)
11324     * @see #setRotationY(float)
11325     * @see #setCameraDistance(float)
11326     *
11327     * @attr ref android.R.styleable#View_rotationX
11328     */
11329    public void setRotationX(float rotationX) {
11330        if (rotationX != getRotationX()) {
11331            invalidateViewProperty(true, false);
11332            mRenderNode.setRotationX(rotationX);
11333            invalidateViewProperty(false, true);
11334
11335            invalidateParentIfNeededAndWasQuickRejected();
11336            notifySubtreeAccessibilityStateChangedIfNeeded();
11337        }
11338    }
11339
11340    /**
11341     * The amount that the view is scaled in x around the pivot point, as a proportion of
11342     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
11343     *
11344     * <p>By default, this is 1.0f.
11345     *
11346     * @see #getPivotX()
11347     * @see #getPivotY()
11348     * @return The scaling factor.
11349     */
11350    @ViewDebug.ExportedProperty(category = "drawing")
11351    public float getScaleX() {
11352        return mRenderNode.getScaleX();
11353    }
11354
11355    /**
11356     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
11357     * the view's unscaled width. A value of 1 means that no scaling is applied.
11358     *
11359     * @param scaleX The scaling factor.
11360     * @see #getPivotX()
11361     * @see #getPivotY()
11362     *
11363     * @attr ref android.R.styleable#View_scaleX
11364     */
11365    public void setScaleX(float scaleX) {
11366        if (scaleX != getScaleX()) {
11367            invalidateViewProperty(true, false);
11368            mRenderNode.setScaleX(scaleX);
11369            invalidateViewProperty(false, true);
11370
11371            invalidateParentIfNeededAndWasQuickRejected();
11372            notifySubtreeAccessibilityStateChangedIfNeeded();
11373        }
11374    }
11375
11376    /**
11377     * The amount that the view is scaled in y around the pivot point, as a proportion of
11378     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
11379     *
11380     * <p>By default, this is 1.0f.
11381     *
11382     * @see #getPivotX()
11383     * @see #getPivotY()
11384     * @return The scaling factor.
11385     */
11386    @ViewDebug.ExportedProperty(category = "drawing")
11387    public float getScaleY() {
11388        return mRenderNode.getScaleY();
11389    }
11390
11391    /**
11392     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
11393     * the view's unscaled width. A value of 1 means that no scaling is applied.
11394     *
11395     * @param scaleY The scaling factor.
11396     * @see #getPivotX()
11397     * @see #getPivotY()
11398     *
11399     * @attr ref android.R.styleable#View_scaleY
11400     */
11401    public void setScaleY(float scaleY) {
11402        if (scaleY != getScaleY()) {
11403            invalidateViewProperty(true, false);
11404            mRenderNode.setScaleY(scaleY);
11405            invalidateViewProperty(false, true);
11406
11407            invalidateParentIfNeededAndWasQuickRejected();
11408            notifySubtreeAccessibilityStateChangedIfNeeded();
11409        }
11410    }
11411
11412    /**
11413     * The x location of the point around which the view is {@link #setRotation(float) rotated}
11414     * and {@link #setScaleX(float) scaled}.
11415     *
11416     * @see #getRotation()
11417     * @see #getScaleX()
11418     * @see #getScaleY()
11419     * @see #getPivotY()
11420     * @return The x location of the pivot point.
11421     *
11422     * @attr ref android.R.styleable#View_transformPivotX
11423     */
11424    @ViewDebug.ExportedProperty(category = "drawing")
11425    public float getPivotX() {
11426        return mRenderNode.getPivotX();
11427    }
11428
11429    /**
11430     * Sets the x location of the point around which the view is
11431     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
11432     * By default, the pivot point is centered on the object.
11433     * Setting this property disables this behavior and causes the view to use only the
11434     * explicitly set pivotX and pivotY values.
11435     *
11436     * @param pivotX The x location of the pivot point.
11437     * @see #getRotation()
11438     * @see #getScaleX()
11439     * @see #getScaleY()
11440     * @see #getPivotY()
11441     *
11442     * @attr ref android.R.styleable#View_transformPivotX
11443     */
11444    public void setPivotX(float pivotX) {
11445        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
11446            invalidateViewProperty(true, false);
11447            mRenderNode.setPivotX(pivotX);
11448            invalidateViewProperty(false, true);
11449
11450            invalidateParentIfNeededAndWasQuickRejected();
11451        }
11452    }
11453
11454    /**
11455     * The y location of the point around which the view is {@link #setRotation(float) rotated}
11456     * and {@link #setScaleY(float) scaled}.
11457     *
11458     * @see #getRotation()
11459     * @see #getScaleX()
11460     * @see #getScaleY()
11461     * @see #getPivotY()
11462     * @return The y location of the pivot point.
11463     *
11464     * @attr ref android.R.styleable#View_transformPivotY
11465     */
11466    @ViewDebug.ExportedProperty(category = "drawing")
11467    public float getPivotY() {
11468        return mRenderNode.getPivotY();
11469    }
11470
11471    /**
11472     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
11473     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
11474     * Setting this property disables this behavior and causes the view to use only the
11475     * explicitly set pivotX and pivotY values.
11476     *
11477     * @param pivotY The y location of the pivot point.
11478     * @see #getRotation()
11479     * @see #getScaleX()
11480     * @see #getScaleY()
11481     * @see #getPivotY()
11482     *
11483     * @attr ref android.R.styleable#View_transformPivotY
11484     */
11485    public void setPivotY(float pivotY) {
11486        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
11487            invalidateViewProperty(true, false);
11488            mRenderNode.setPivotY(pivotY);
11489            invalidateViewProperty(false, true);
11490
11491            invalidateParentIfNeededAndWasQuickRejected();
11492        }
11493    }
11494
11495    /**
11496     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
11497     * completely transparent and 1 means the view is completely opaque.
11498     *
11499     * <p>By default this is 1.0f.
11500     * @return The opacity of the view.
11501     */
11502    @ViewDebug.ExportedProperty(category = "drawing")
11503    public float getAlpha() {
11504        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
11505    }
11506
11507    /**
11508     * Returns whether this View has content which overlaps.
11509     *
11510     * <p>This function, intended to be overridden by specific View types, is an optimization when
11511     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
11512     * an offscreen buffer and then composited into place, which can be expensive. If the view has
11513     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
11514     * directly. An example of overlapping rendering is a TextView with a background image, such as
11515     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
11516     * ImageView with only the foreground image. The default implementation returns true; subclasses
11517     * should override if they have cases which can be optimized.</p>
11518     *
11519     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
11520     * necessitates that a View return true if it uses the methods internally without passing the
11521     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
11522     *
11523     * @return true if the content in this view might overlap, false otherwise.
11524     */
11525    @ViewDebug.ExportedProperty(category = "drawing")
11526    public boolean hasOverlappingRendering() {
11527        return true;
11528    }
11529
11530    /**
11531     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
11532     * completely transparent and 1 means the view is completely opaque.
11533     *
11534     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
11535     * can have significant performance implications, especially for large views. It is best to use
11536     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
11537     *
11538     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
11539     * strongly recommended for performance reasons to either override
11540     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
11541     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
11542     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
11543     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
11544     * of rendering cost, even for simple or small views. Starting with
11545     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
11546     * applied to the view at the rendering level.</p>
11547     *
11548     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
11549     * responsible for applying the opacity itself.</p>
11550     *
11551     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
11552     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
11553     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
11554     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
11555     *
11556     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
11557     * value will clip a View to its bounds, unless the View returns <code>false</code> from
11558     * {@link #hasOverlappingRendering}.</p>
11559     *
11560     * @param alpha The opacity of the view.
11561     *
11562     * @see #hasOverlappingRendering()
11563     * @see #setLayerType(int, android.graphics.Paint)
11564     *
11565     * @attr ref android.R.styleable#View_alpha
11566     */
11567    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
11568        ensureTransformationInfo();
11569        if (mTransformationInfo.mAlpha != alpha) {
11570            mTransformationInfo.mAlpha = alpha;
11571            if (onSetAlpha((int) (alpha * 255))) {
11572                mPrivateFlags |= PFLAG_ALPHA_SET;
11573                // subclass is handling alpha - don't optimize rendering cache invalidation
11574                invalidateParentCaches();
11575                invalidate(true);
11576            } else {
11577                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11578                invalidateViewProperty(true, false);
11579                mRenderNode.setAlpha(getFinalAlpha());
11580                notifyViewAccessibilityStateChangedIfNeeded(
11581                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11582            }
11583        }
11584    }
11585
11586    /**
11587     * Faster version of setAlpha() which performs the same steps except there are
11588     * no calls to invalidate(). The caller of this function should perform proper invalidation
11589     * on the parent and this object. The return value indicates whether the subclass handles
11590     * alpha (the return value for onSetAlpha()).
11591     *
11592     * @param alpha The new value for the alpha property
11593     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
11594     *         the new value for the alpha property is different from the old value
11595     */
11596    boolean setAlphaNoInvalidation(float alpha) {
11597        ensureTransformationInfo();
11598        if (mTransformationInfo.mAlpha != alpha) {
11599            mTransformationInfo.mAlpha = alpha;
11600            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
11601            if (subclassHandlesAlpha) {
11602                mPrivateFlags |= PFLAG_ALPHA_SET;
11603                return true;
11604            } else {
11605                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11606                mRenderNode.setAlpha(getFinalAlpha());
11607            }
11608        }
11609        return false;
11610    }
11611
11612    /**
11613     * This property is hidden and intended only for use by the Fade transition, which
11614     * animates it to produce a visual translucency that does not side-effect (or get
11615     * affected by) the real alpha property. This value is composited with the other
11616     * alpha value (and the AlphaAnimation value, when that is present) to produce
11617     * a final visual translucency result, which is what is passed into the DisplayList.
11618     *
11619     * @hide
11620     */
11621    public void setTransitionAlpha(float alpha) {
11622        ensureTransformationInfo();
11623        if (mTransformationInfo.mTransitionAlpha != alpha) {
11624            mTransformationInfo.mTransitionAlpha = alpha;
11625            mPrivateFlags &= ~PFLAG_ALPHA_SET;
11626            invalidateViewProperty(true, false);
11627            mRenderNode.setAlpha(getFinalAlpha());
11628        }
11629    }
11630
11631    /**
11632     * Calculates the visual alpha of this view, which is a combination of the actual
11633     * alpha value and the transitionAlpha value (if set).
11634     */
11635    private float getFinalAlpha() {
11636        if (mTransformationInfo != null) {
11637            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11638        }
11639        return 1;
11640    }
11641
11642    /**
11643     * This property is hidden and intended only for use by the Fade transition, which
11644     * animates it to produce a visual translucency that does not side-effect (or get
11645     * affected by) the real alpha property. This value is composited with the other
11646     * alpha value (and the AlphaAnimation value, when that is present) to produce
11647     * a final visual translucency result, which is what is passed into the DisplayList.
11648     *
11649     * @hide
11650     */
11651    @ViewDebug.ExportedProperty(category = "drawing")
11652    public float getTransitionAlpha() {
11653        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11654    }
11655
11656    /**
11657     * Top position of this view relative to its parent.
11658     *
11659     * @return The top of this view, in pixels.
11660     */
11661    @ViewDebug.CapturedViewProperty
11662    public final int getTop() {
11663        return mTop;
11664    }
11665
11666    /**
11667     * Sets the top position of this view relative to its parent. This method is meant to be called
11668     * by the layout system and should not generally be called otherwise, because the property
11669     * may be changed at any time by the layout.
11670     *
11671     * @param top The top of this view, in pixels.
11672     */
11673    public final void setTop(int top) {
11674        if (top != mTop) {
11675            final boolean matrixIsIdentity = hasIdentityMatrix();
11676            if (matrixIsIdentity) {
11677                if (mAttachInfo != null) {
11678                    int minTop;
11679                    int yLoc;
11680                    if (top < mTop) {
11681                        minTop = top;
11682                        yLoc = top - mTop;
11683                    } else {
11684                        minTop = mTop;
11685                        yLoc = 0;
11686                    }
11687                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11688                }
11689            } else {
11690                // Double-invalidation is necessary to capture view's old and new areas
11691                invalidate(true);
11692            }
11693
11694            int width = mRight - mLeft;
11695            int oldHeight = mBottom - mTop;
11696
11697            mTop = top;
11698            mRenderNode.setTop(mTop);
11699
11700            sizeChange(width, mBottom - mTop, width, oldHeight);
11701
11702            if (!matrixIsIdentity) {
11703                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11704                invalidate(true);
11705            }
11706            mBackgroundSizeChanged = true;
11707            if (mForegroundInfo != null) {
11708                mForegroundInfo.mBoundsChanged = true;
11709            }
11710            invalidateParentIfNeeded();
11711            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11712                // View was rejected last time it was drawn by its parent; this may have changed
11713                invalidateParentIfNeeded();
11714            }
11715        }
11716    }
11717
11718    /**
11719     * Bottom position of this view relative to its parent.
11720     *
11721     * @return The bottom of this view, in pixels.
11722     */
11723    @ViewDebug.CapturedViewProperty
11724    public final int getBottom() {
11725        return mBottom;
11726    }
11727
11728    /**
11729     * True if this view has changed since the last time being drawn.
11730     *
11731     * @return The dirty state of this view.
11732     */
11733    public boolean isDirty() {
11734        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11735    }
11736
11737    /**
11738     * Sets the bottom position of this view relative to its parent. This method is meant to be
11739     * called by the layout system and should not generally be called otherwise, because the
11740     * property may be changed at any time by the layout.
11741     *
11742     * @param bottom The bottom of this view, in pixels.
11743     */
11744    public final void setBottom(int bottom) {
11745        if (bottom != mBottom) {
11746            final boolean matrixIsIdentity = hasIdentityMatrix();
11747            if (matrixIsIdentity) {
11748                if (mAttachInfo != null) {
11749                    int maxBottom;
11750                    if (bottom < mBottom) {
11751                        maxBottom = mBottom;
11752                    } else {
11753                        maxBottom = bottom;
11754                    }
11755                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11756                }
11757            } else {
11758                // Double-invalidation is necessary to capture view's old and new areas
11759                invalidate(true);
11760            }
11761
11762            int width = mRight - mLeft;
11763            int oldHeight = mBottom - mTop;
11764
11765            mBottom = bottom;
11766            mRenderNode.setBottom(mBottom);
11767
11768            sizeChange(width, mBottom - mTop, width, oldHeight);
11769
11770            if (!matrixIsIdentity) {
11771                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11772                invalidate(true);
11773            }
11774            mBackgroundSizeChanged = true;
11775            if (mForegroundInfo != null) {
11776                mForegroundInfo.mBoundsChanged = true;
11777            }
11778            invalidateParentIfNeeded();
11779            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11780                // View was rejected last time it was drawn by its parent; this may have changed
11781                invalidateParentIfNeeded();
11782            }
11783        }
11784    }
11785
11786    /**
11787     * Left position of this view relative to its parent.
11788     *
11789     * @return The left edge of this view, in pixels.
11790     */
11791    @ViewDebug.CapturedViewProperty
11792    public final int getLeft() {
11793        return mLeft;
11794    }
11795
11796    /**
11797     * Sets the left position of this view relative to its parent. This method is meant to be called
11798     * by the layout system and should not generally be called otherwise, because the property
11799     * may be changed at any time by the layout.
11800     *
11801     * @param left The left of this view, in pixels.
11802     */
11803    public final void setLeft(int left) {
11804        if (left != mLeft) {
11805            final boolean matrixIsIdentity = hasIdentityMatrix();
11806            if (matrixIsIdentity) {
11807                if (mAttachInfo != null) {
11808                    int minLeft;
11809                    int xLoc;
11810                    if (left < mLeft) {
11811                        minLeft = left;
11812                        xLoc = left - mLeft;
11813                    } else {
11814                        minLeft = mLeft;
11815                        xLoc = 0;
11816                    }
11817                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11818                }
11819            } else {
11820                // Double-invalidation is necessary to capture view's old and new areas
11821                invalidate(true);
11822            }
11823
11824            int oldWidth = mRight - mLeft;
11825            int height = mBottom - mTop;
11826
11827            mLeft = left;
11828            mRenderNode.setLeft(left);
11829
11830            sizeChange(mRight - mLeft, height, oldWidth, height);
11831
11832            if (!matrixIsIdentity) {
11833                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11834                invalidate(true);
11835            }
11836            mBackgroundSizeChanged = true;
11837            if (mForegroundInfo != null) {
11838                mForegroundInfo.mBoundsChanged = true;
11839            }
11840            invalidateParentIfNeeded();
11841            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11842                // View was rejected last time it was drawn by its parent; this may have changed
11843                invalidateParentIfNeeded();
11844            }
11845        }
11846    }
11847
11848    /**
11849     * Right position of this view relative to its parent.
11850     *
11851     * @return The right edge of this view, in pixels.
11852     */
11853    @ViewDebug.CapturedViewProperty
11854    public final int getRight() {
11855        return mRight;
11856    }
11857
11858    /**
11859     * Sets the right position of this view relative to its parent. This method is meant to be called
11860     * by the layout system and should not generally be called otherwise, because the property
11861     * may be changed at any time by the layout.
11862     *
11863     * @param right The right of this view, in pixels.
11864     */
11865    public final void setRight(int right) {
11866        if (right != mRight) {
11867            final boolean matrixIsIdentity = hasIdentityMatrix();
11868            if (matrixIsIdentity) {
11869                if (mAttachInfo != null) {
11870                    int maxRight;
11871                    if (right < mRight) {
11872                        maxRight = mRight;
11873                    } else {
11874                        maxRight = right;
11875                    }
11876                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
11877                }
11878            } else {
11879                // Double-invalidation is necessary to capture view's old and new areas
11880                invalidate(true);
11881            }
11882
11883            int oldWidth = mRight - mLeft;
11884            int height = mBottom - mTop;
11885
11886            mRight = right;
11887            mRenderNode.setRight(mRight);
11888
11889            sizeChange(mRight - mLeft, height, oldWidth, height);
11890
11891            if (!matrixIsIdentity) {
11892                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11893                invalidate(true);
11894            }
11895            mBackgroundSizeChanged = true;
11896            if (mForegroundInfo != null) {
11897                mForegroundInfo.mBoundsChanged = true;
11898            }
11899            invalidateParentIfNeeded();
11900            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11901                // View was rejected last time it was drawn by its parent; this may have changed
11902                invalidateParentIfNeeded();
11903            }
11904        }
11905    }
11906
11907    /**
11908     * The visual x position of this view, in pixels. This is equivalent to the
11909     * {@link #setTranslationX(float) translationX} property plus the current
11910     * {@link #getLeft() left} property.
11911     *
11912     * @return The visual x position of this view, in pixels.
11913     */
11914    @ViewDebug.ExportedProperty(category = "drawing")
11915    public float getX() {
11916        return mLeft + getTranslationX();
11917    }
11918
11919    /**
11920     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
11921     * {@link #setTranslationX(float) translationX} property to be the difference between
11922     * the x value passed in and the current {@link #getLeft() left} property.
11923     *
11924     * @param x The visual x position of this view, in pixels.
11925     */
11926    public void setX(float x) {
11927        setTranslationX(x - mLeft);
11928    }
11929
11930    /**
11931     * The visual y position of this view, in pixels. This is equivalent to the
11932     * {@link #setTranslationY(float) translationY} property plus the current
11933     * {@link #getTop() top} property.
11934     *
11935     * @return The visual y position of this view, in pixels.
11936     */
11937    @ViewDebug.ExportedProperty(category = "drawing")
11938    public float getY() {
11939        return mTop + getTranslationY();
11940    }
11941
11942    /**
11943     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
11944     * {@link #setTranslationY(float) translationY} property to be the difference between
11945     * the y value passed in and the current {@link #getTop() top} property.
11946     *
11947     * @param y The visual y position of this view, in pixels.
11948     */
11949    public void setY(float y) {
11950        setTranslationY(y - mTop);
11951    }
11952
11953    /**
11954     * The visual z position of this view, in pixels. This is equivalent to the
11955     * {@link #setTranslationZ(float) translationZ} property plus the current
11956     * {@link #getElevation() elevation} property.
11957     *
11958     * @return The visual z position of this view, in pixels.
11959     */
11960    @ViewDebug.ExportedProperty(category = "drawing")
11961    public float getZ() {
11962        return getElevation() + getTranslationZ();
11963    }
11964
11965    /**
11966     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
11967     * {@link #setTranslationZ(float) translationZ} property to be the difference between
11968     * the x value passed in and the current {@link #getElevation() elevation} property.
11969     *
11970     * @param z The visual z position of this view, in pixels.
11971     */
11972    public void setZ(float z) {
11973        setTranslationZ(z - getElevation());
11974    }
11975
11976    /**
11977     * The base elevation of this view relative to its parent, in pixels.
11978     *
11979     * @return The base depth position of the view, in pixels.
11980     */
11981    @ViewDebug.ExportedProperty(category = "drawing")
11982    public float getElevation() {
11983        return mRenderNode.getElevation();
11984    }
11985
11986    /**
11987     * Sets the base elevation of this view, in pixels.
11988     *
11989     * @attr ref android.R.styleable#View_elevation
11990     */
11991    public void setElevation(float elevation) {
11992        if (elevation != getElevation()) {
11993            invalidateViewProperty(true, false);
11994            mRenderNode.setElevation(elevation);
11995            invalidateViewProperty(false, true);
11996
11997            invalidateParentIfNeededAndWasQuickRejected();
11998        }
11999    }
12000
12001    /**
12002     * The horizontal location of this view relative to its {@link #getLeft() left} position.
12003     * This position is post-layout, in addition to wherever the object's
12004     * layout placed it.
12005     *
12006     * @return The horizontal position of this view relative to its left position, in pixels.
12007     */
12008    @ViewDebug.ExportedProperty(category = "drawing")
12009    public float getTranslationX() {
12010        return mRenderNode.getTranslationX();
12011    }
12012
12013    /**
12014     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12015     * This effectively positions the object post-layout, in addition to wherever the object's
12016     * layout placed it.
12017     *
12018     * @param translationX The horizontal position of this view relative to its left position,
12019     * in pixels.
12020     *
12021     * @attr ref android.R.styleable#View_translationX
12022     */
12023    public void setTranslationX(float translationX) {
12024        if (translationX != getTranslationX()) {
12025            invalidateViewProperty(true, false);
12026            mRenderNode.setTranslationX(translationX);
12027            invalidateViewProperty(false, true);
12028
12029            invalidateParentIfNeededAndWasQuickRejected();
12030            notifySubtreeAccessibilityStateChangedIfNeeded();
12031        }
12032    }
12033
12034    /**
12035     * The vertical location of this view relative to its {@link #getTop() top} position.
12036     * This position is post-layout, in addition to wherever the object's
12037     * layout placed it.
12038     *
12039     * @return The vertical position of this view relative to its top position,
12040     * in pixels.
12041     */
12042    @ViewDebug.ExportedProperty(category = "drawing")
12043    public float getTranslationY() {
12044        return mRenderNode.getTranslationY();
12045    }
12046
12047    /**
12048     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12049     * This effectively positions the object post-layout, in addition to wherever the object's
12050     * layout placed it.
12051     *
12052     * @param translationY The vertical position of this view relative to its top position,
12053     * in pixels.
12054     *
12055     * @attr ref android.R.styleable#View_translationY
12056     */
12057    public void setTranslationY(float translationY) {
12058        if (translationY != getTranslationY()) {
12059            invalidateViewProperty(true, false);
12060            mRenderNode.setTranslationY(translationY);
12061            invalidateViewProperty(false, true);
12062
12063            invalidateParentIfNeededAndWasQuickRejected();
12064            notifySubtreeAccessibilityStateChangedIfNeeded();
12065        }
12066    }
12067
12068    /**
12069     * The depth location of this view relative to its {@link #getElevation() elevation}.
12070     *
12071     * @return The depth of this view relative to its elevation.
12072     */
12073    @ViewDebug.ExportedProperty(category = "drawing")
12074    public float getTranslationZ() {
12075        return mRenderNode.getTranslationZ();
12076    }
12077
12078    /**
12079     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12080     *
12081     * @attr ref android.R.styleable#View_translationZ
12082     */
12083    public void setTranslationZ(float translationZ) {
12084        if (translationZ != getTranslationZ()) {
12085            invalidateViewProperty(true, false);
12086            mRenderNode.setTranslationZ(translationZ);
12087            invalidateViewProperty(false, true);
12088
12089            invalidateParentIfNeededAndWasQuickRejected();
12090        }
12091    }
12092
12093    /** @hide */
12094    public void setAnimationMatrix(Matrix matrix) {
12095        invalidateViewProperty(true, false);
12096        mRenderNode.setAnimationMatrix(matrix);
12097        invalidateViewProperty(false, true);
12098
12099        invalidateParentIfNeededAndWasQuickRejected();
12100    }
12101
12102    /**
12103     * Returns the current StateListAnimator if exists.
12104     *
12105     * @return StateListAnimator or null if it does not exists
12106     * @see    #setStateListAnimator(android.animation.StateListAnimator)
12107     */
12108    public StateListAnimator getStateListAnimator() {
12109        return mStateListAnimator;
12110    }
12111
12112    /**
12113     * Attaches the provided StateListAnimator to this View.
12114     * <p>
12115     * Any previously attached StateListAnimator will be detached.
12116     *
12117     * @param stateListAnimator The StateListAnimator to update the view
12118     * @see {@link android.animation.StateListAnimator}
12119     */
12120    public void setStateListAnimator(StateListAnimator stateListAnimator) {
12121        if (mStateListAnimator == stateListAnimator) {
12122            return;
12123        }
12124        if (mStateListAnimator != null) {
12125            mStateListAnimator.setTarget(null);
12126        }
12127        mStateListAnimator = stateListAnimator;
12128        if (stateListAnimator != null) {
12129            stateListAnimator.setTarget(this);
12130            if (isAttachedToWindow()) {
12131                stateListAnimator.setState(getDrawableState());
12132            }
12133        }
12134    }
12135
12136    /**
12137     * Returns whether the Outline should be used to clip the contents of the View.
12138     * <p>
12139     * Note that this flag will only be respected if the View's Outline returns true from
12140     * {@link Outline#canClip()}.
12141     *
12142     * @see #setOutlineProvider(ViewOutlineProvider)
12143     * @see #setClipToOutline(boolean)
12144     */
12145    public final boolean getClipToOutline() {
12146        return mRenderNode.getClipToOutline();
12147    }
12148
12149    /**
12150     * Sets whether the View's Outline should be used to clip the contents of the View.
12151     * <p>
12152     * Only a single non-rectangular clip can be applied on a View at any time.
12153     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12154     * circular reveal} animation take priority over Outline clipping, and
12155     * child Outline clipping takes priority over Outline clipping done by a
12156     * parent.
12157     * <p>
12158     * Note that this flag will only be respected if the View's Outline returns true from
12159     * {@link Outline#canClip()}.
12160     *
12161     * @see #setOutlineProvider(ViewOutlineProvider)
12162     * @see #getClipToOutline()
12163     */
12164    public void setClipToOutline(boolean clipToOutline) {
12165        damageInParent();
12166        if (getClipToOutline() != clipToOutline) {
12167            mRenderNode.setClipToOutline(clipToOutline);
12168        }
12169    }
12170
12171    // correspond to the enum values of View_outlineProvider
12172    private static final int PROVIDER_BACKGROUND = 0;
12173    private static final int PROVIDER_NONE = 1;
12174    private static final int PROVIDER_BOUNDS = 2;
12175    private static final int PROVIDER_PADDED_BOUNDS = 3;
12176    private void setOutlineProviderFromAttribute(int providerInt) {
12177        switch (providerInt) {
12178            case PROVIDER_BACKGROUND:
12179                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12180                break;
12181            case PROVIDER_NONE:
12182                setOutlineProvider(null);
12183                break;
12184            case PROVIDER_BOUNDS:
12185                setOutlineProvider(ViewOutlineProvider.BOUNDS);
12186                break;
12187            case PROVIDER_PADDED_BOUNDS:
12188                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12189                break;
12190        }
12191    }
12192
12193    /**
12194     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12195     * the shape of the shadow it casts, and enables outline clipping.
12196     * <p>
12197     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12198     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12199     * outline provider with this method allows this behavior to be overridden.
12200     * <p>
12201     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12202     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12203     * <p>
12204     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12205     *
12206     * @see #setClipToOutline(boolean)
12207     * @see #getClipToOutline()
12208     * @see #getOutlineProvider()
12209     */
12210    public void setOutlineProvider(ViewOutlineProvider provider) {
12211        mOutlineProvider = provider;
12212        invalidateOutline();
12213    }
12214
12215    /**
12216     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
12217     * that defines the shape of the shadow it casts, and enables outline clipping.
12218     *
12219     * @see #setOutlineProvider(ViewOutlineProvider)
12220     */
12221    public ViewOutlineProvider getOutlineProvider() {
12222        return mOutlineProvider;
12223    }
12224
12225    /**
12226     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
12227     *
12228     * @see #setOutlineProvider(ViewOutlineProvider)
12229     */
12230    public void invalidateOutline() {
12231        rebuildOutline();
12232
12233        notifySubtreeAccessibilityStateChangedIfNeeded();
12234        invalidateViewProperty(false, false);
12235    }
12236
12237    /**
12238     * Internal version of {@link #invalidateOutline()} which invalidates the
12239     * outline without invalidating the view itself. This is intended to be called from
12240     * within methods in the View class itself which are the result of the view being
12241     * invalidated already. For example, when we are drawing the background of a View,
12242     * we invalidate the outline in case it changed in the meantime, but we do not
12243     * need to invalidate the view because we're already drawing the background as part
12244     * of drawing the view in response to an earlier invalidation of the view.
12245     */
12246    private void rebuildOutline() {
12247        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
12248        if (mAttachInfo == null) return;
12249
12250        if (mOutlineProvider == null) {
12251            // no provider, remove outline
12252            mRenderNode.setOutline(null);
12253        } else {
12254            final Outline outline = mAttachInfo.mTmpOutline;
12255            outline.setEmpty();
12256            outline.setAlpha(1.0f);
12257
12258            mOutlineProvider.getOutline(this, outline);
12259            mRenderNode.setOutline(outline);
12260        }
12261    }
12262
12263    /**
12264     * HierarchyViewer only
12265     *
12266     * @hide
12267     */
12268    @ViewDebug.ExportedProperty(category = "drawing")
12269    public boolean hasShadow() {
12270        return mRenderNode.hasShadow();
12271    }
12272
12273
12274    /** @hide */
12275    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
12276        mRenderNode.setRevealClip(shouldClip, x, y, radius);
12277        invalidateViewProperty(false, false);
12278    }
12279
12280    /**
12281     * Hit rectangle in parent's coordinates
12282     *
12283     * @param outRect The hit rectangle of the view.
12284     */
12285    public void getHitRect(Rect outRect) {
12286        if (hasIdentityMatrix() || mAttachInfo == null) {
12287            outRect.set(mLeft, mTop, mRight, mBottom);
12288        } else {
12289            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
12290            tmpRect.set(0, 0, getWidth(), getHeight());
12291            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
12292            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
12293                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
12294        }
12295    }
12296
12297    /**
12298     * Determines whether the given point, in local coordinates is inside the view.
12299     */
12300    /*package*/ final boolean pointInView(float localX, float localY) {
12301        return localX >= 0 && localX < (mRight - mLeft)
12302                && localY >= 0 && localY < (mBottom - mTop);
12303    }
12304
12305    /**
12306     * Utility method to determine whether the given point, in local coordinates,
12307     * is inside the view, where the area of the view is expanded by the slop factor.
12308     * This method is called while processing touch-move events to determine if the event
12309     * is still within the view.
12310     *
12311     * @hide
12312     */
12313    public boolean pointInView(float localX, float localY, float slop) {
12314        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
12315                localY < ((mBottom - mTop) + slop);
12316    }
12317
12318    /**
12319     * When a view has focus and the user navigates away from it, the next view is searched for
12320     * starting from the rectangle filled in by this method.
12321     *
12322     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
12323     * of the view.  However, if your view maintains some idea of internal selection,
12324     * such as a cursor, or a selected row or column, you should override this method and
12325     * fill in a more specific rectangle.
12326     *
12327     * @param r The rectangle to fill in, in this view's coordinates.
12328     */
12329    public void getFocusedRect(Rect r) {
12330        getDrawingRect(r);
12331    }
12332
12333    /**
12334     * If some part of this view is not clipped by any of its parents, then
12335     * return that area in r in global (root) coordinates. To convert r to local
12336     * coordinates (without taking possible View rotations into account), offset
12337     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
12338     * If the view is completely clipped or translated out, return false.
12339     *
12340     * @param r If true is returned, r holds the global coordinates of the
12341     *        visible portion of this view.
12342     * @param globalOffset If true is returned, globalOffset holds the dx,dy
12343     *        between this view and its root. globalOffet may be null.
12344     * @return true if r is non-empty (i.e. part of the view is visible at the
12345     *         root level.
12346     */
12347    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
12348        int width = mRight - mLeft;
12349        int height = mBottom - mTop;
12350        if (width > 0 && height > 0) {
12351            r.set(0, 0, width, height);
12352            if (globalOffset != null) {
12353                globalOffset.set(-mScrollX, -mScrollY);
12354            }
12355            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
12356        }
12357        return false;
12358    }
12359
12360    public final boolean getGlobalVisibleRect(Rect r) {
12361        return getGlobalVisibleRect(r, null);
12362    }
12363
12364    public final boolean getLocalVisibleRect(Rect r) {
12365        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
12366        if (getGlobalVisibleRect(r, offset)) {
12367            r.offset(-offset.x, -offset.y); // make r local
12368            return true;
12369        }
12370        return false;
12371    }
12372
12373    /**
12374     * Offset this view's vertical location by the specified number of pixels.
12375     *
12376     * @param offset the number of pixels to offset the view by
12377     */
12378    public void offsetTopAndBottom(int offset) {
12379        if (offset != 0) {
12380            final boolean matrixIsIdentity = hasIdentityMatrix();
12381            if (matrixIsIdentity) {
12382                if (isHardwareAccelerated()) {
12383                    invalidateViewProperty(false, false);
12384                } else {
12385                    final ViewParent p = mParent;
12386                    if (p != null && mAttachInfo != null) {
12387                        final Rect r = mAttachInfo.mTmpInvalRect;
12388                        int minTop;
12389                        int maxBottom;
12390                        int yLoc;
12391                        if (offset < 0) {
12392                            minTop = mTop + offset;
12393                            maxBottom = mBottom;
12394                            yLoc = offset;
12395                        } else {
12396                            minTop = mTop;
12397                            maxBottom = mBottom + offset;
12398                            yLoc = 0;
12399                        }
12400                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
12401                        p.invalidateChild(this, r);
12402                    }
12403                }
12404            } else {
12405                invalidateViewProperty(false, false);
12406            }
12407
12408            mTop += offset;
12409            mBottom += offset;
12410            mRenderNode.offsetTopAndBottom(offset);
12411            if (isHardwareAccelerated()) {
12412                invalidateViewProperty(false, false);
12413                invalidateParentIfNeededAndWasQuickRejected();
12414            } else {
12415                if (!matrixIsIdentity) {
12416                    invalidateViewProperty(false, true);
12417                }
12418                invalidateParentIfNeeded();
12419            }
12420            notifySubtreeAccessibilityStateChangedIfNeeded();
12421        }
12422    }
12423
12424    /**
12425     * Offset this view's horizontal location by the specified amount of pixels.
12426     *
12427     * @param offset the number of pixels to offset the view by
12428     */
12429    public void offsetLeftAndRight(int offset) {
12430        if (offset != 0) {
12431            final boolean matrixIsIdentity = hasIdentityMatrix();
12432            if (matrixIsIdentity) {
12433                if (isHardwareAccelerated()) {
12434                    invalidateViewProperty(false, false);
12435                } else {
12436                    final ViewParent p = mParent;
12437                    if (p != null && mAttachInfo != null) {
12438                        final Rect r = mAttachInfo.mTmpInvalRect;
12439                        int minLeft;
12440                        int maxRight;
12441                        if (offset < 0) {
12442                            minLeft = mLeft + offset;
12443                            maxRight = mRight;
12444                        } else {
12445                            minLeft = mLeft;
12446                            maxRight = mRight + offset;
12447                        }
12448                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
12449                        p.invalidateChild(this, r);
12450                    }
12451                }
12452            } else {
12453                invalidateViewProperty(false, false);
12454            }
12455
12456            mLeft += offset;
12457            mRight += offset;
12458            mRenderNode.offsetLeftAndRight(offset);
12459            if (isHardwareAccelerated()) {
12460                invalidateViewProperty(false, false);
12461                invalidateParentIfNeededAndWasQuickRejected();
12462            } else {
12463                if (!matrixIsIdentity) {
12464                    invalidateViewProperty(false, true);
12465                }
12466                invalidateParentIfNeeded();
12467            }
12468            notifySubtreeAccessibilityStateChangedIfNeeded();
12469        }
12470    }
12471
12472    /**
12473     * Get the LayoutParams associated with this view. All views should have
12474     * layout parameters. These supply parameters to the <i>parent</i> of this
12475     * view specifying how it should be arranged. There are many subclasses of
12476     * ViewGroup.LayoutParams, and these correspond to the different subclasses
12477     * of ViewGroup that are responsible for arranging their children.
12478     *
12479     * This method may return null if this View is not attached to a parent
12480     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
12481     * was not invoked successfully. When a View is attached to a parent
12482     * ViewGroup, this method must not return null.
12483     *
12484     * @return The LayoutParams associated with this view, or null if no
12485     *         parameters have been set yet
12486     */
12487    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
12488    public ViewGroup.LayoutParams getLayoutParams() {
12489        return mLayoutParams;
12490    }
12491
12492    /**
12493     * Set the layout parameters associated with this view. These supply
12494     * parameters to the <i>parent</i> of this view specifying how it should be
12495     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
12496     * correspond to the different subclasses of ViewGroup that are responsible
12497     * for arranging their children.
12498     *
12499     * @param params The layout parameters for this view, cannot be null
12500     */
12501    public void setLayoutParams(ViewGroup.LayoutParams params) {
12502        if (params == null) {
12503            throw new NullPointerException("Layout parameters cannot be null");
12504        }
12505        mLayoutParams = params;
12506        resolveLayoutParams();
12507        if (mParent instanceof ViewGroup) {
12508            ((ViewGroup) mParent).onSetLayoutParams(this, params);
12509        }
12510        requestLayout();
12511    }
12512
12513    /**
12514     * Resolve the layout parameters depending on the resolved layout direction
12515     *
12516     * @hide
12517     */
12518    public void resolveLayoutParams() {
12519        if (mLayoutParams != null) {
12520            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
12521        }
12522    }
12523
12524    /**
12525     * Set the scrolled position of your view. This will cause a call to
12526     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12527     * invalidated.
12528     * @param x the x position to scroll to
12529     * @param y the y position to scroll to
12530     */
12531    public void scrollTo(int x, int y) {
12532        if (mScrollX != x || mScrollY != y) {
12533            int oldX = mScrollX;
12534            int oldY = mScrollY;
12535            mScrollX = x;
12536            mScrollY = y;
12537            invalidateParentCaches();
12538            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
12539            if (!awakenScrollBars()) {
12540                postInvalidateOnAnimation();
12541            }
12542        }
12543    }
12544
12545    /**
12546     * Move the scrolled position of your view. This will cause a call to
12547     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12548     * invalidated.
12549     * @param x the amount of pixels to scroll by horizontally
12550     * @param y the amount of pixels to scroll by vertically
12551     */
12552    public void scrollBy(int x, int y) {
12553        scrollTo(mScrollX + x, mScrollY + y);
12554    }
12555
12556    /**
12557     * <p>Trigger the scrollbars to draw. When invoked this method starts an
12558     * animation to fade the scrollbars out after a default delay. If a subclass
12559     * provides animated scrolling, the start delay should equal the duration
12560     * of the scrolling animation.</p>
12561     *
12562     * <p>The animation starts only if at least one of the scrollbars is
12563     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
12564     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12565     * this method returns true, and false otherwise. If the animation is
12566     * started, this method calls {@link #invalidate()}; in that case the
12567     * caller should not call {@link #invalidate()}.</p>
12568     *
12569     * <p>This method should be invoked every time a subclass directly updates
12570     * the scroll parameters.</p>
12571     *
12572     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
12573     * and {@link #scrollTo(int, int)}.</p>
12574     *
12575     * @return true if the animation is played, false otherwise
12576     *
12577     * @see #awakenScrollBars(int)
12578     * @see #scrollBy(int, int)
12579     * @see #scrollTo(int, int)
12580     * @see #isHorizontalScrollBarEnabled()
12581     * @see #isVerticalScrollBarEnabled()
12582     * @see #setHorizontalScrollBarEnabled(boolean)
12583     * @see #setVerticalScrollBarEnabled(boolean)
12584     */
12585    protected boolean awakenScrollBars() {
12586        return mScrollCache != null &&
12587                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
12588    }
12589
12590    /**
12591     * Trigger the scrollbars to draw.
12592     * This method differs from awakenScrollBars() only in its default duration.
12593     * initialAwakenScrollBars() will show the scroll bars for longer than
12594     * usual to give the user more of a chance to notice them.
12595     *
12596     * @return true if the animation is played, false otherwise.
12597     */
12598    private boolean initialAwakenScrollBars() {
12599        return mScrollCache != null &&
12600                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
12601    }
12602
12603    /**
12604     * <p>
12605     * Trigger the scrollbars to draw. When invoked this method starts an
12606     * animation to fade the scrollbars out after a fixed delay. If a subclass
12607     * provides animated scrolling, the start delay should equal the duration of
12608     * the scrolling animation.
12609     * </p>
12610     *
12611     * <p>
12612     * The animation starts only if at least one of the scrollbars is enabled,
12613     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12614     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12615     * this method returns true, and false otherwise. If the animation is
12616     * started, this method calls {@link #invalidate()}; in that case the caller
12617     * should not call {@link #invalidate()}.
12618     * </p>
12619     *
12620     * <p>
12621     * This method should be invoked every time a subclass directly updates the
12622     * scroll parameters.
12623     * </p>
12624     *
12625     * @param startDelay the delay, in milliseconds, after which the animation
12626     *        should start; when the delay is 0, the animation starts
12627     *        immediately
12628     * @return true if the animation is played, false otherwise
12629     *
12630     * @see #scrollBy(int, int)
12631     * @see #scrollTo(int, int)
12632     * @see #isHorizontalScrollBarEnabled()
12633     * @see #isVerticalScrollBarEnabled()
12634     * @see #setHorizontalScrollBarEnabled(boolean)
12635     * @see #setVerticalScrollBarEnabled(boolean)
12636     */
12637    protected boolean awakenScrollBars(int startDelay) {
12638        return awakenScrollBars(startDelay, true);
12639    }
12640
12641    /**
12642     * <p>
12643     * Trigger the scrollbars to draw. When invoked this method starts an
12644     * animation to fade the scrollbars out after a fixed delay. If a subclass
12645     * provides animated scrolling, the start delay should equal the duration of
12646     * the scrolling animation.
12647     * </p>
12648     *
12649     * <p>
12650     * The animation starts only if at least one of the scrollbars is enabled,
12651     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12652     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12653     * this method returns true, and false otherwise. If the animation is
12654     * started, this method calls {@link #invalidate()} if the invalidate parameter
12655     * is set to true; in that case the caller
12656     * should not call {@link #invalidate()}.
12657     * </p>
12658     *
12659     * <p>
12660     * This method should be invoked every time a subclass directly updates the
12661     * scroll parameters.
12662     * </p>
12663     *
12664     * @param startDelay the delay, in milliseconds, after which the animation
12665     *        should start; when the delay is 0, the animation starts
12666     *        immediately
12667     *
12668     * @param invalidate Whether this method should call invalidate
12669     *
12670     * @return true if the animation is played, false otherwise
12671     *
12672     * @see #scrollBy(int, int)
12673     * @see #scrollTo(int, int)
12674     * @see #isHorizontalScrollBarEnabled()
12675     * @see #isVerticalScrollBarEnabled()
12676     * @see #setHorizontalScrollBarEnabled(boolean)
12677     * @see #setVerticalScrollBarEnabled(boolean)
12678     */
12679    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12680        final ScrollabilityCache scrollCache = mScrollCache;
12681
12682        if (scrollCache == null || !scrollCache.fadeScrollBars) {
12683            return false;
12684        }
12685
12686        if (scrollCache.scrollBar == null) {
12687            scrollCache.scrollBar = new ScrollBarDrawable();
12688            scrollCache.scrollBar.setCallback(this);
12689            scrollCache.scrollBar.setState(getDrawableState());
12690        }
12691
12692        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12693
12694            if (invalidate) {
12695                // Invalidate to show the scrollbars
12696                postInvalidateOnAnimation();
12697            }
12698
12699            if (scrollCache.state == ScrollabilityCache.OFF) {
12700                // FIXME: this is copied from WindowManagerService.
12701                // We should get this value from the system when it
12702                // is possible to do so.
12703                final int KEY_REPEAT_FIRST_DELAY = 750;
12704                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12705            }
12706
12707            // Tell mScrollCache when we should start fading. This may
12708            // extend the fade start time if one was already scheduled
12709            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12710            scrollCache.fadeStartTime = fadeStartTime;
12711            scrollCache.state = ScrollabilityCache.ON;
12712
12713            // Schedule our fader to run, unscheduling any old ones first
12714            if (mAttachInfo != null) {
12715                mAttachInfo.mHandler.removeCallbacks(scrollCache);
12716                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12717            }
12718
12719            return true;
12720        }
12721
12722        return false;
12723    }
12724
12725    /**
12726     * Do not invalidate views which are not visible and which are not running an animation. They
12727     * will not get drawn and they should not set dirty flags as if they will be drawn
12728     */
12729    private boolean skipInvalidate() {
12730        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12731                (!(mParent instanceof ViewGroup) ||
12732                        !((ViewGroup) mParent).isViewTransitioning(this));
12733    }
12734
12735    /**
12736     * Mark the area defined by dirty as needing to be drawn. If the view is
12737     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12738     * point in the future.
12739     * <p>
12740     * This must be called from a UI thread. To call from a non-UI thread, call
12741     * {@link #postInvalidate()}.
12742     * <p>
12743     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12744     * {@code dirty}.
12745     *
12746     * @param dirty the rectangle representing the bounds of the dirty region
12747     */
12748    public void invalidate(Rect dirty) {
12749        final int scrollX = mScrollX;
12750        final int scrollY = mScrollY;
12751        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12752                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12753    }
12754
12755    /**
12756     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12757     * coordinates of the dirty rect are relative to the view. If the view is
12758     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12759     * point in the future.
12760     * <p>
12761     * This must be called from a UI thread. To call from a non-UI thread, call
12762     * {@link #postInvalidate()}.
12763     *
12764     * @param l the left position of the dirty region
12765     * @param t the top position of the dirty region
12766     * @param r the right position of the dirty region
12767     * @param b the bottom position of the dirty region
12768     */
12769    public void invalidate(int l, int t, int r, int b) {
12770        final int scrollX = mScrollX;
12771        final int scrollY = mScrollY;
12772        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12773    }
12774
12775    /**
12776     * Invalidate the whole view. If the view is visible,
12777     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12778     * the future.
12779     * <p>
12780     * This must be called from a UI thread. To call from a non-UI thread, call
12781     * {@link #postInvalidate()}.
12782     */
12783    public void invalidate() {
12784        invalidate(true);
12785    }
12786
12787    /**
12788     * This is where the invalidate() work actually happens. A full invalidate()
12789     * causes the drawing cache to be invalidated, but this function can be
12790     * called with invalidateCache set to false to skip that invalidation step
12791     * for cases that do not need it (for example, a component that remains at
12792     * the same dimensions with the same content).
12793     *
12794     * @param invalidateCache Whether the drawing cache for this view should be
12795     *            invalidated as well. This is usually true for a full
12796     *            invalidate, but may be set to false if the View's contents or
12797     *            dimensions have not changed.
12798     */
12799    void invalidate(boolean invalidateCache) {
12800        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12801    }
12802
12803    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12804            boolean fullInvalidate) {
12805        if (mGhostView != null) {
12806            mGhostView.invalidate(true);
12807            return;
12808        }
12809
12810        if (skipInvalidate()) {
12811            return;
12812        }
12813
12814        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12815                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12816                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12817                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12818            if (fullInvalidate) {
12819                mLastIsOpaque = isOpaque();
12820                mPrivateFlags &= ~PFLAG_DRAWN;
12821            }
12822
12823            mPrivateFlags |= PFLAG_DIRTY;
12824
12825            if (invalidateCache) {
12826                mPrivateFlags |= PFLAG_INVALIDATED;
12827                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12828            }
12829
12830            // Propagate the damage rectangle to the parent view.
12831            final AttachInfo ai = mAttachInfo;
12832            final ViewParent p = mParent;
12833            if (p != null && ai != null && l < r && t < b) {
12834                final Rect damage = ai.mTmpInvalRect;
12835                damage.set(l, t, r, b);
12836                p.invalidateChild(this, damage);
12837            }
12838
12839            // Damage the entire projection receiver, if necessary.
12840            if (mBackground != null && mBackground.isProjected()) {
12841                final View receiver = getProjectionReceiver();
12842                if (receiver != null) {
12843                    receiver.damageInParent();
12844                }
12845            }
12846
12847            // Damage the entire IsolatedZVolume receiving this view's shadow.
12848            if (isHardwareAccelerated() && getZ() != 0) {
12849                damageShadowReceiver();
12850            }
12851        }
12852    }
12853
12854    /**
12855     * @return this view's projection receiver, or {@code null} if none exists
12856     */
12857    private View getProjectionReceiver() {
12858        ViewParent p = getParent();
12859        while (p != null && p instanceof View) {
12860            final View v = (View) p;
12861            if (v.isProjectionReceiver()) {
12862                return v;
12863            }
12864            p = p.getParent();
12865        }
12866
12867        return null;
12868    }
12869
12870    /**
12871     * @return whether the view is a projection receiver
12872     */
12873    private boolean isProjectionReceiver() {
12874        return mBackground != null;
12875    }
12876
12877    /**
12878     * Damage area of the screen that can be covered by this View's shadow.
12879     *
12880     * This method will guarantee that any changes to shadows cast by a View
12881     * are damaged on the screen for future redraw.
12882     */
12883    private void damageShadowReceiver() {
12884        final AttachInfo ai = mAttachInfo;
12885        if (ai != null) {
12886            ViewParent p = getParent();
12887            if (p != null && p instanceof ViewGroup) {
12888                final ViewGroup vg = (ViewGroup) p;
12889                vg.damageInParent();
12890            }
12891        }
12892    }
12893
12894    /**
12895     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
12896     * set any flags or handle all of the cases handled by the default invalidation methods.
12897     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
12898     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
12899     * walk up the hierarchy, transforming the dirty rect as necessary.
12900     *
12901     * The method also handles normal invalidation logic if display list properties are not
12902     * being used in this view. The invalidateParent and forceRedraw flags are used by that
12903     * backup approach, to handle these cases used in the various property-setting methods.
12904     *
12905     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
12906     * are not being used in this view
12907     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
12908     * list properties are not being used in this view
12909     */
12910    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
12911        if (!isHardwareAccelerated()
12912                || !mRenderNode.isValid()
12913                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
12914            if (invalidateParent) {
12915                invalidateParentCaches();
12916            }
12917            if (forceRedraw) {
12918                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12919            }
12920            invalidate(false);
12921        } else {
12922            damageInParent();
12923        }
12924        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
12925            damageShadowReceiver();
12926        }
12927    }
12928
12929    /**
12930     * Tells the parent view to damage this view's bounds.
12931     *
12932     * @hide
12933     */
12934    protected void damageInParent() {
12935        final AttachInfo ai = mAttachInfo;
12936        final ViewParent p = mParent;
12937        if (p != null && ai != null) {
12938            final Rect r = ai.mTmpInvalRect;
12939            r.set(0, 0, mRight - mLeft, mBottom - mTop);
12940            if (mParent instanceof ViewGroup) {
12941                ((ViewGroup) mParent).damageChild(this, r);
12942            } else {
12943                mParent.invalidateChild(this, r);
12944            }
12945        }
12946    }
12947
12948    /**
12949     * Utility method to transform a given Rect by the current matrix of this view.
12950     */
12951    void transformRect(final Rect rect) {
12952        if (!getMatrix().isIdentity()) {
12953            RectF boundingRect = mAttachInfo.mTmpTransformRect;
12954            boundingRect.set(rect);
12955            getMatrix().mapRect(boundingRect);
12956            rect.set((int) Math.floor(boundingRect.left),
12957                    (int) Math.floor(boundingRect.top),
12958                    (int) Math.ceil(boundingRect.right),
12959                    (int) Math.ceil(boundingRect.bottom));
12960        }
12961    }
12962
12963    /**
12964     * Used to indicate that the parent of this view should clear its caches. This functionality
12965     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12966     * which is necessary when various parent-managed properties of the view change, such as
12967     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
12968     * clears the parent caches and does not causes an invalidate event.
12969     *
12970     * @hide
12971     */
12972    protected void invalidateParentCaches() {
12973        if (mParent instanceof View) {
12974            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
12975        }
12976    }
12977
12978    /**
12979     * Used to indicate that the parent of this view should be invalidated. This functionality
12980     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12981     * which is necessary when various parent-managed properties of the view change, such as
12982     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
12983     * an invalidation event to the parent.
12984     *
12985     * @hide
12986     */
12987    protected void invalidateParentIfNeeded() {
12988        if (isHardwareAccelerated() && mParent instanceof View) {
12989            ((View) mParent).invalidate(true);
12990        }
12991    }
12992
12993    /**
12994     * @hide
12995     */
12996    protected void invalidateParentIfNeededAndWasQuickRejected() {
12997        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
12998            // View was rejected last time it was drawn by its parent; this may have changed
12999            invalidateParentIfNeeded();
13000        }
13001    }
13002
13003    /**
13004     * Indicates whether this View is opaque. An opaque View guarantees that it will
13005     * draw all the pixels overlapping its bounds using a fully opaque color.
13006     *
13007     * Subclasses of View should override this method whenever possible to indicate
13008     * whether an instance is opaque. Opaque Views are treated in a special way by
13009     * the View hierarchy, possibly allowing it to perform optimizations during
13010     * invalidate/draw passes.
13011     *
13012     * @return True if this View is guaranteed to be fully opaque, false otherwise.
13013     */
13014    @ViewDebug.ExportedProperty(category = "drawing")
13015    public boolean isOpaque() {
13016        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13017                getFinalAlpha() >= 1.0f;
13018    }
13019
13020    /**
13021     * @hide
13022     */
13023    protected void computeOpaqueFlags() {
13024        // Opaque if:
13025        //   - Has a background
13026        //   - Background is opaque
13027        //   - Doesn't have scrollbars or scrollbars overlay
13028
13029        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13030            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13031        } else {
13032            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13033        }
13034
13035        final int flags = mViewFlags;
13036        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13037                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13038                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13039            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13040        } else {
13041            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13042        }
13043    }
13044
13045    /**
13046     * @hide
13047     */
13048    protected boolean hasOpaqueScrollbars() {
13049        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13050    }
13051
13052    /**
13053     * @return A handler associated with the thread running the View. This
13054     * handler can be used to pump events in the UI events queue.
13055     */
13056    public Handler getHandler() {
13057        final AttachInfo attachInfo = mAttachInfo;
13058        if (attachInfo != null) {
13059            return attachInfo.mHandler;
13060        }
13061        return null;
13062    }
13063
13064    /**
13065     * Returns the queue of runnable for this view.
13066     *
13067     * @return the queue of runnables for this view
13068     */
13069    private HandlerActionQueue getRunQueue() {
13070        if (mRunQueue == null) {
13071            mRunQueue = new HandlerActionQueue();
13072        }
13073        return mRunQueue;
13074    }
13075
13076    /**
13077     * Gets the view root associated with the View.
13078     * @return The view root, or null if none.
13079     * @hide
13080     */
13081    public ViewRootImpl getViewRootImpl() {
13082        if (mAttachInfo != null) {
13083            return mAttachInfo.mViewRootImpl;
13084        }
13085        return null;
13086    }
13087
13088    /**
13089     * @hide
13090     */
13091    public HardwareRenderer getHardwareRenderer() {
13092        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
13093    }
13094
13095    /**
13096     * <p>Causes the Runnable to be added to the message queue.
13097     * The runnable will be run on the user interface thread.</p>
13098     *
13099     * @param action The Runnable that will be executed.
13100     *
13101     * @return Returns true if the Runnable was successfully placed in to the
13102     *         message queue.  Returns false on failure, usually because the
13103     *         looper processing the message queue is exiting.
13104     *
13105     * @see #postDelayed
13106     * @see #removeCallbacks
13107     */
13108    public boolean post(Runnable action) {
13109        final AttachInfo attachInfo = mAttachInfo;
13110        if (attachInfo != null) {
13111            return attachInfo.mHandler.post(action);
13112        }
13113
13114        // Postpone the runnable until we know on which thread it needs to run.
13115        // Assume that the runnable will be successfully placed after attach.
13116        getRunQueue().post(action);
13117        return true;
13118    }
13119
13120    /**
13121     * <p>Causes the Runnable to be added to the message queue, to be run
13122     * after the specified amount of time elapses.
13123     * The runnable will be run on the user interface thread.</p>
13124     *
13125     * @param action The Runnable that will be executed.
13126     * @param delayMillis The delay (in milliseconds) until the Runnable
13127     *        will be executed.
13128     *
13129     * @return true if the Runnable was successfully placed in to the
13130     *         message queue.  Returns false on failure, usually because the
13131     *         looper processing the message queue is exiting.  Note that a
13132     *         result of true does not mean the Runnable will be processed --
13133     *         if the looper is quit before the delivery time of the message
13134     *         occurs then the message will be dropped.
13135     *
13136     * @see #post
13137     * @see #removeCallbacks
13138     */
13139    public boolean postDelayed(Runnable action, long delayMillis) {
13140        final AttachInfo attachInfo = mAttachInfo;
13141        if (attachInfo != null) {
13142            return attachInfo.mHandler.postDelayed(action, delayMillis);
13143        }
13144
13145        // Postpone the runnable until we know on which thread it needs to run.
13146        // Assume that the runnable will be successfully placed after attach.
13147        getRunQueue().postDelayed(action, delayMillis);
13148        return true;
13149    }
13150
13151    /**
13152     * <p>Causes the Runnable to execute on the next animation time step.
13153     * The runnable will be run on the user interface thread.</p>
13154     *
13155     * @param action The Runnable that will be executed.
13156     *
13157     * @see #postOnAnimationDelayed
13158     * @see #removeCallbacks
13159     */
13160    public void postOnAnimation(Runnable action) {
13161        final AttachInfo attachInfo = mAttachInfo;
13162        if (attachInfo != null) {
13163            attachInfo.mViewRootImpl.mChoreographer.postCallback(
13164                    Choreographer.CALLBACK_ANIMATION, action, null);
13165        } else {
13166            // Postpone the runnable until we know
13167            // on which thread it needs to run.
13168            getRunQueue().post(action);
13169        }
13170    }
13171
13172    /**
13173     * <p>Causes the Runnable to execute on the next animation time step,
13174     * after the specified amount of time elapses.
13175     * The runnable will be run on the user interface thread.</p>
13176     *
13177     * @param action The Runnable that will be executed.
13178     * @param delayMillis The delay (in milliseconds) until the Runnable
13179     *        will be executed.
13180     *
13181     * @see #postOnAnimation
13182     * @see #removeCallbacks
13183     */
13184    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13185        final AttachInfo attachInfo = mAttachInfo;
13186        if (attachInfo != null) {
13187            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13188                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13189        } else {
13190            // Postpone the runnable until we know
13191            // on which thread it needs to run.
13192            getRunQueue().postDelayed(action, delayMillis);
13193        }
13194    }
13195
13196    /**
13197     * <p>Removes the specified Runnable from the message queue.</p>
13198     *
13199     * @param action The Runnable to remove from the message handling queue
13200     *
13201     * @return true if this view could ask the Handler to remove the Runnable,
13202     *         false otherwise. When the returned value is true, the Runnable
13203     *         may or may not have been actually removed from the message queue
13204     *         (for instance, if the Runnable was not in the queue already.)
13205     *
13206     * @see #post
13207     * @see #postDelayed
13208     * @see #postOnAnimation
13209     * @see #postOnAnimationDelayed
13210     */
13211    public boolean removeCallbacks(Runnable action) {
13212        if (action != null) {
13213            final AttachInfo attachInfo = mAttachInfo;
13214            if (attachInfo != null) {
13215                attachInfo.mHandler.removeCallbacks(action);
13216                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13217                        Choreographer.CALLBACK_ANIMATION, action, null);
13218            }
13219            getRunQueue().removeCallbacks(action);
13220        }
13221        return true;
13222    }
13223
13224    /**
13225     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
13226     * Use this to invalidate the View from a non-UI thread.</p>
13227     *
13228     * <p>This method can be invoked from outside of the UI thread
13229     * only when this View is attached to a window.</p>
13230     *
13231     * @see #invalidate()
13232     * @see #postInvalidateDelayed(long)
13233     */
13234    public void postInvalidate() {
13235        postInvalidateDelayed(0);
13236    }
13237
13238    /**
13239     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13240     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
13241     *
13242     * <p>This method can be invoked from outside of the UI thread
13243     * only when this View is attached to a window.</p>
13244     *
13245     * @param left The left coordinate of the rectangle to invalidate.
13246     * @param top The top coordinate of the rectangle to invalidate.
13247     * @param right The right coordinate of the rectangle to invalidate.
13248     * @param bottom The bottom coordinate of the rectangle to invalidate.
13249     *
13250     * @see #invalidate(int, int, int, int)
13251     * @see #invalidate(Rect)
13252     * @see #postInvalidateDelayed(long, int, int, int, int)
13253     */
13254    public void postInvalidate(int left, int top, int right, int bottom) {
13255        postInvalidateDelayed(0, left, top, right, bottom);
13256    }
13257
13258    /**
13259     * <p>Cause an invalidate to happen on a subsequent cycle through the event
13260     * loop. Waits for the specified amount of time.</p>
13261     *
13262     * <p>This method can be invoked from outside of the UI thread
13263     * only when this View is attached to a window.</p>
13264     *
13265     * @param delayMilliseconds the duration in milliseconds to delay the
13266     *         invalidation by
13267     *
13268     * @see #invalidate()
13269     * @see #postInvalidate()
13270     */
13271    public void postInvalidateDelayed(long delayMilliseconds) {
13272        // We try only with the AttachInfo because there's no point in invalidating
13273        // if we are not attached to our window
13274        final AttachInfo attachInfo = mAttachInfo;
13275        if (attachInfo != null) {
13276            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
13277        }
13278    }
13279
13280    /**
13281     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13282     * through the event loop. Waits for the specified amount of time.</p>
13283     *
13284     * <p>This method can be invoked from outside of the UI thread
13285     * only when this View is attached to a window.</p>
13286     *
13287     * @param delayMilliseconds the duration in milliseconds to delay the
13288     *         invalidation by
13289     * @param left The left coordinate of the rectangle to invalidate.
13290     * @param top The top coordinate of the rectangle to invalidate.
13291     * @param right The right coordinate of the rectangle to invalidate.
13292     * @param bottom The bottom coordinate of the rectangle to invalidate.
13293     *
13294     * @see #invalidate(int, int, int, int)
13295     * @see #invalidate(Rect)
13296     * @see #postInvalidate(int, int, int, int)
13297     */
13298    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
13299            int right, int bottom) {
13300
13301        // We try only with the AttachInfo because there's no point in invalidating
13302        // if we are not attached to our window
13303        final AttachInfo attachInfo = mAttachInfo;
13304        if (attachInfo != null) {
13305            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13306            info.target = this;
13307            info.left = left;
13308            info.top = top;
13309            info.right = right;
13310            info.bottom = bottom;
13311
13312            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
13313        }
13314    }
13315
13316    /**
13317     * <p>Cause an invalidate to happen on the next animation time step, typically the
13318     * next display frame.</p>
13319     *
13320     * <p>This method can be invoked from outside of the UI thread
13321     * only when this View is attached to a window.</p>
13322     *
13323     * @see #invalidate()
13324     */
13325    public void postInvalidateOnAnimation() {
13326        // We try only with the AttachInfo because there's no point in invalidating
13327        // if we are not attached to our window
13328        final AttachInfo attachInfo = mAttachInfo;
13329        if (attachInfo != null) {
13330            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
13331        }
13332    }
13333
13334    /**
13335     * <p>Cause an invalidate of the specified area to happen on the next animation
13336     * time step, typically the next display frame.</p>
13337     *
13338     * <p>This method can be invoked from outside of the UI thread
13339     * only when this View is attached to a window.</p>
13340     *
13341     * @param left The left coordinate of the rectangle to invalidate.
13342     * @param top The top coordinate of the rectangle to invalidate.
13343     * @param right The right coordinate of the rectangle to invalidate.
13344     * @param bottom The bottom coordinate of the rectangle to invalidate.
13345     *
13346     * @see #invalidate(int, int, int, int)
13347     * @see #invalidate(Rect)
13348     */
13349    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
13350        // We try only with the AttachInfo because there's no point in invalidating
13351        // if we are not attached to our window
13352        final AttachInfo attachInfo = mAttachInfo;
13353        if (attachInfo != null) {
13354            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13355            info.target = this;
13356            info.left = left;
13357            info.top = top;
13358            info.right = right;
13359            info.bottom = bottom;
13360
13361            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
13362        }
13363    }
13364
13365    /**
13366     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
13367     * This event is sent at most once every
13368     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
13369     */
13370    private void postSendViewScrolledAccessibilityEventCallback() {
13371        if (mSendViewScrolledAccessibilityEvent == null) {
13372            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
13373        }
13374        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
13375            mSendViewScrolledAccessibilityEvent.mIsPending = true;
13376            postDelayed(mSendViewScrolledAccessibilityEvent,
13377                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
13378        }
13379    }
13380
13381    /**
13382     * Called by a parent to request that a child update its values for mScrollX
13383     * and mScrollY if necessary. This will typically be done if the child is
13384     * animating a scroll using a {@link android.widget.Scroller Scroller}
13385     * object.
13386     */
13387    public void computeScroll() {
13388    }
13389
13390    /**
13391     * <p>Indicate whether the horizontal edges are faded when the view is
13392     * scrolled horizontally.</p>
13393     *
13394     * @return true if the horizontal edges should are faded on scroll, false
13395     *         otherwise
13396     *
13397     * @see #setHorizontalFadingEdgeEnabled(boolean)
13398     *
13399     * @attr ref android.R.styleable#View_requiresFadingEdge
13400     */
13401    public boolean isHorizontalFadingEdgeEnabled() {
13402        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
13403    }
13404
13405    /**
13406     * <p>Define whether the horizontal edges should be faded when this view
13407     * is scrolled horizontally.</p>
13408     *
13409     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
13410     *                                    be faded when the view is scrolled
13411     *                                    horizontally
13412     *
13413     * @see #isHorizontalFadingEdgeEnabled()
13414     *
13415     * @attr ref android.R.styleable#View_requiresFadingEdge
13416     */
13417    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
13418        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
13419            if (horizontalFadingEdgeEnabled) {
13420                initScrollCache();
13421            }
13422
13423            mViewFlags ^= FADING_EDGE_HORIZONTAL;
13424        }
13425    }
13426
13427    /**
13428     * <p>Indicate whether the vertical edges are faded when the view is
13429     * scrolled horizontally.</p>
13430     *
13431     * @return true if the vertical edges should are faded on scroll, false
13432     *         otherwise
13433     *
13434     * @see #setVerticalFadingEdgeEnabled(boolean)
13435     *
13436     * @attr ref android.R.styleable#View_requiresFadingEdge
13437     */
13438    public boolean isVerticalFadingEdgeEnabled() {
13439        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
13440    }
13441
13442    /**
13443     * <p>Define whether the vertical edges should be faded when this view
13444     * is scrolled vertically.</p>
13445     *
13446     * @param verticalFadingEdgeEnabled true if the vertical edges should
13447     *                                  be faded when the view is scrolled
13448     *                                  vertically
13449     *
13450     * @see #isVerticalFadingEdgeEnabled()
13451     *
13452     * @attr ref android.R.styleable#View_requiresFadingEdge
13453     */
13454    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
13455        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
13456            if (verticalFadingEdgeEnabled) {
13457                initScrollCache();
13458            }
13459
13460            mViewFlags ^= FADING_EDGE_VERTICAL;
13461        }
13462    }
13463
13464    /**
13465     * Returns the strength, or intensity, of the top faded edge. The strength is
13466     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13467     * returns 0.0 or 1.0 but no value in between.
13468     *
13469     * Subclasses should override this method to provide a smoother fade transition
13470     * when scrolling occurs.
13471     *
13472     * @return the intensity of the top fade as a float between 0.0f and 1.0f
13473     */
13474    protected float getTopFadingEdgeStrength() {
13475        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
13476    }
13477
13478    /**
13479     * Returns the strength, or intensity, of the bottom faded edge. The strength is
13480     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13481     * returns 0.0 or 1.0 but no value in between.
13482     *
13483     * Subclasses should override this method to provide a smoother fade transition
13484     * when scrolling occurs.
13485     *
13486     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
13487     */
13488    protected float getBottomFadingEdgeStrength() {
13489        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
13490                computeVerticalScrollRange() ? 1.0f : 0.0f;
13491    }
13492
13493    /**
13494     * Returns the strength, or intensity, of the left faded edge. The strength is
13495     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13496     * returns 0.0 or 1.0 but no value in between.
13497     *
13498     * Subclasses should override this method to provide a smoother fade transition
13499     * when scrolling occurs.
13500     *
13501     * @return the intensity of the left fade as a float between 0.0f and 1.0f
13502     */
13503    protected float getLeftFadingEdgeStrength() {
13504        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
13505    }
13506
13507    /**
13508     * Returns the strength, or intensity, of the right faded edge. The strength is
13509     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13510     * returns 0.0 or 1.0 but no value in between.
13511     *
13512     * Subclasses should override this method to provide a smoother fade transition
13513     * when scrolling occurs.
13514     *
13515     * @return the intensity of the right fade as a float between 0.0f and 1.0f
13516     */
13517    protected float getRightFadingEdgeStrength() {
13518        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
13519                computeHorizontalScrollRange() ? 1.0f : 0.0f;
13520    }
13521
13522    /**
13523     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
13524     * scrollbar is not drawn by default.</p>
13525     *
13526     * @return true if the horizontal scrollbar should be painted, false
13527     *         otherwise
13528     *
13529     * @see #setHorizontalScrollBarEnabled(boolean)
13530     */
13531    public boolean isHorizontalScrollBarEnabled() {
13532        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13533    }
13534
13535    /**
13536     * <p>Define whether the horizontal scrollbar should be drawn or not. The
13537     * scrollbar is not drawn by default.</p>
13538     *
13539     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
13540     *                                   be painted
13541     *
13542     * @see #isHorizontalScrollBarEnabled()
13543     */
13544    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
13545        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
13546            mViewFlags ^= SCROLLBARS_HORIZONTAL;
13547            computeOpaqueFlags();
13548            resolvePadding();
13549        }
13550    }
13551
13552    /**
13553     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
13554     * scrollbar is not drawn by default.</p>
13555     *
13556     * @return true if the vertical scrollbar should be painted, false
13557     *         otherwise
13558     *
13559     * @see #setVerticalScrollBarEnabled(boolean)
13560     */
13561    public boolean isVerticalScrollBarEnabled() {
13562        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
13563    }
13564
13565    /**
13566     * <p>Define whether the vertical scrollbar should be drawn or not. The
13567     * scrollbar is not drawn by default.</p>
13568     *
13569     * @param verticalScrollBarEnabled true if the vertical scrollbar should
13570     *                                 be painted
13571     *
13572     * @see #isVerticalScrollBarEnabled()
13573     */
13574    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
13575        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
13576            mViewFlags ^= SCROLLBARS_VERTICAL;
13577            computeOpaqueFlags();
13578            resolvePadding();
13579        }
13580    }
13581
13582    /**
13583     * @hide
13584     */
13585    protected void recomputePadding() {
13586        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13587    }
13588
13589    /**
13590     * Define whether scrollbars will fade when the view is not scrolling.
13591     *
13592     * @param fadeScrollbars whether to enable fading
13593     *
13594     * @attr ref android.R.styleable#View_fadeScrollbars
13595     */
13596    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
13597        initScrollCache();
13598        final ScrollabilityCache scrollabilityCache = mScrollCache;
13599        scrollabilityCache.fadeScrollBars = fadeScrollbars;
13600        if (fadeScrollbars) {
13601            scrollabilityCache.state = ScrollabilityCache.OFF;
13602        } else {
13603            scrollabilityCache.state = ScrollabilityCache.ON;
13604        }
13605    }
13606
13607    /**
13608     *
13609     * Returns true if scrollbars will fade when this view is not scrolling
13610     *
13611     * @return true if scrollbar fading is enabled
13612     *
13613     * @attr ref android.R.styleable#View_fadeScrollbars
13614     */
13615    public boolean isScrollbarFadingEnabled() {
13616        return mScrollCache != null && mScrollCache.fadeScrollBars;
13617    }
13618
13619    /**
13620     *
13621     * Returns the delay before scrollbars fade.
13622     *
13623     * @return the delay before scrollbars fade
13624     *
13625     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13626     */
13627    public int getScrollBarDefaultDelayBeforeFade() {
13628        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
13629                mScrollCache.scrollBarDefaultDelayBeforeFade;
13630    }
13631
13632    /**
13633     * Define the delay before scrollbars fade.
13634     *
13635     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
13636     *
13637     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13638     */
13639    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
13640        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
13641    }
13642
13643    /**
13644     *
13645     * Returns the scrollbar fade duration.
13646     *
13647     * @return the scrollbar fade duration
13648     *
13649     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13650     */
13651    public int getScrollBarFadeDuration() {
13652        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13653                mScrollCache.scrollBarFadeDuration;
13654    }
13655
13656    /**
13657     * Define the scrollbar fade duration.
13658     *
13659     * @param scrollBarFadeDuration - the scrollbar fade duration
13660     *
13661     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13662     */
13663    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13664        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13665    }
13666
13667    /**
13668     *
13669     * Returns the scrollbar size.
13670     *
13671     * @return the scrollbar size
13672     *
13673     * @attr ref android.R.styleable#View_scrollbarSize
13674     */
13675    public int getScrollBarSize() {
13676        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13677                mScrollCache.scrollBarSize;
13678    }
13679
13680    /**
13681     * Define the scrollbar size.
13682     *
13683     * @param scrollBarSize - the scrollbar size
13684     *
13685     * @attr ref android.R.styleable#View_scrollbarSize
13686     */
13687    public void setScrollBarSize(int scrollBarSize) {
13688        getScrollCache().scrollBarSize = scrollBarSize;
13689    }
13690
13691    /**
13692     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13693     * inset. When inset, they add to the padding of the view. And the scrollbars
13694     * can be drawn inside the padding area or on the edge of the view. For example,
13695     * if a view has a background drawable and you want to draw the scrollbars
13696     * inside the padding specified by the drawable, you can use
13697     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13698     * appear at the edge of the view, ignoring the padding, then you can use
13699     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13700     * @param style the style of the scrollbars. Should be one of
13701     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13702     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13703     * @see #SCROLLBARS_INSIDE_OVERLAY
13704     * @see #SCROLLBARS_INSIDE_INSET
13705     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13706     * @see #SCROLLBARS_OUTSIDE_INSET
13707     *
13708     * @attr ref android.R.styleable#View_scrollbarStyle
13709     */
13710    public void setScrollBarStyle(@ScrollBarStyle int style) {
13711        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13712            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13713            computeOpaqueFlags();
13714            resolvePadding();
13715        }
13716    }
13717
13718    /**
13719     * <p>Returns the current scrollbar style.</p>
13720     * @return the current scrollbar style
13721     * @see #SCROLLBARS_INSIDE_OVERLAY
13722     * @see #SCROLLBARS_INSIDE_INSET
13723     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13724     * @see #SCROLLBARS_OUTSIDE_INSET
13725     *
13726     * @attr ref android.R.styleable#View_scrollbarStyle
13727     */
13728    @ViewDebug.ExportedProperty(mapping = {
13729            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13730            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13731            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13732            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13733    })
13734    @ScrollBarStyle
13735    public int getScrollBarStyle() {
13736        return mViewFlags & SCROLLBARS_STYLE_MASK;
13737    }
13738
13739    /**
13740     * <p>Compute the horizontal range that the horizontal scrollbar
13741     * represents.</p>
13742     *
13743     * <p>The range is expressed in arbitrary units that must be the same as the
13744     * units used by {@link #computeHorizontalScrollExtent()} and
13745     * {@link #computeHorizontalScrollOffset()}.</p>
13746     *
13747     * <p>The default range is the drawing width of this view.</p>
13748     *
13749     * @return the total horizontal range represented by the horizontal
13750     *         scrollbar
13751     *
13752     * @see #computeHorizontalScrollExtent()
13753     * @see #computeHorizontalScrollOffset()
13754     * @see android.widget.ScrollBarDrawable
13755     */
13756    protected int computeHorizontalScrollRange() {
13757        return getWidth();
13758    }
13759
13760    /**
13761     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13762     * within the horizontal range. This value is used to compute the position
13763     * of the thumb within the scrollbar's track.</p>
13764     *
13765     * <p>The range is expressed in arbitrary units that must be the same as the
13766     * units used by {@link #computeHorizontalScrollRange()} and
13767     * {@link #computeHorizontalScrollExtent()}.</p>
13768     *
13769     * <p>The default offset is the scroll offset of this view.</p>
13770     *
13771     * @return the horizontal offset of the scrollbar's thumb
13772     *
13773     * @see #computeHorizontalScrollRange()
13774     * @see #computeHorizontalScrollExtent()
13775     * @see android.widget.ScrollBarDrawable
13776     */
13777    protected int computeHorizontalScrollOffset() {
13778        return mScrollX;
13779    }
13780
13781    /**
13782     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13783     * within the horizontal range. This value is used to compute the length
13784     * of the thumb within the scrollbar's track.</p>
13785     *
13786     * <p>The range is expressed in arbitrary units that must be the same as the
13787     * units used by {@link #computeHorizontalScrollRange()} and
13788     * {@link #computeHorizontalScrollOffset()}.</p>
13789     *
13790     * <p>The default extent is the drawing width of this view.</p>
13791     *
13792     * @return the horizontal extent of the scrollbar's thumb
13793     *
13794     * @see #computeHorizontalScrollRange()
13795     * @see #computeHorizontalScrollOffset()
13796     * @see android.widget.ScrollBarDrawable
13797     */
13798    protected int computeHorizontalScrollExtent() {
13799        return getWidth();
13800    }
13801
13802    /**
13803     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13804     *
13805     * <p>The range is expressed in arbitrary units that must be the same as the
13806     * units used by {@link #computeVerticalScrollExtent()} and
13807     * {@link #computeVerticalScrollOffset()}.</p>
13808     *
13809     * @return the total vertical range represented by the vertical scrollbar
13810     *
13811     * <p>The default range is the drawing height of this view.</p>
13812     *
13813     * @see #computeVerticalScrollExtent()
13814     * @see #computeVerticalScrollOffset()
13815     * @see android.widget.ScrollBarDrawable
13816     */
13817    protected int computeVerticalScrollRange() {
13818        return getHeight();
13819    }
13820
13821    /**
13822     * <p>Compute the vertical offset of the vertical scrollbar's thumb
13823     * within the horizontal range. This value is used to compute the position
13824     * of the thumb within the scrollbar's track.</p>
13825     *
13826     * <p>The range is expressed in arbitrary units that must be the same as the
13827     * units used by {@link #computeVerticalScrollRange()} and
13828     * {@link #computeVerticalScrollExtent()}.</p>
13829     *
13830     * <p>The default offset is the scroll offset of this view.</p>
13831     *
13832     * @return the vertical offset of the scrollbar's thumb
13833     *
13834     * @see #computeVerticalScrollRange()
13835     * @see #computeVerticalScrollExtent()
13836     * @see android.widget.ScrollBarDrawable
13837     */
13838    protected int computeVerticalScrollOffset() {
13839        return mScrollY;
13840    }
13841
13842    /**
13843     * <p>Compute the vertical extent of the vertical scrollbar's thumb
13844     * within the vertical range. This value is used to compute the length
13845     * of the thumb within the scrollbar's track.</p>
13846     *
13847     * <p>The range is expressed in arbitrary units that must be the same as the
13848     * units used by {@link #computeVerticalScrollRange()} and
13849     * {@link #computeVerticalScrollOffset()}.</p>
13850     *
13851     * <p>The default extent is the drawing height of this view.</p>
13852     *
13853     * @return the vertical extent of the scrollbar's thumb
13854     *
13855     * @see #computeVerticalScrollRange()
13856     * @see #computeVerticalScrollOffset()
13857     * @see android.widget.ScrollBarDrawable
13858     */
13859    protected int computeVerticalScrollExtent() {
13860        return getHeight();
13861    }
13862
13863    /**
13864     * Check if this view can be scrolled horizontally in a certain direction.
13865     *
13866     * @param direction Negative to check scrolling left, positive to check scrolling right.
13867     * @return true if this view can be scrolled in the specified direction, false otherwise.
13868     */
13869    public boolean canScrollHorizontally(int direction) {
13870        final int offset = computeHorizontalScrollOffset();
13871        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
13872        if (range == 0) return false;
13873        if (direction < 0) {
13874            return offset > 0;
13875        } else {
13876            return offset < range - 1;
13877        }
13878    }
13879
13880    /**
13881     * Check if this view can be scrolled vertically in a certain direction.
13882     *
13883     * @param direction Negative to check scrolling up, positive to check scrolling down.
13884     * @return true if this view can be scrolled in the specified direction, false otherwise.
13885     */
13886    public boolean canScrollVertically(int direction) {
13887        final int offset = computeVerticalScrollOffset();
13888        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
13889        if (range == 0) return false;
13890        if (direction < 0) {
13891            return offset > 0;
13892        } else {
13893            return offset < range - 1;
13894        }
13895    }
13896
13897    void getScrollIndicatorBounds(@NonNull Rect out) {
13898        out.left = mScrollX;
13899        out.right = mScrollX + mRight - mLeft;
13900        out.top = mScrollY;
13901        out.bottom = mScrollY + mBottom - mTop;
13902    }
13903
13904    private void onDrawScrollIndicators(Canvas c) {
13905        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
13906            // No scroll indicators enabled.
13907            return;
13908        }
13909
13910        final Drawable dr = mScrollIndicatorDrawable;
13911        if (dr == null) {
13912            // Scroll indicators aren't supported here.
13913            return;
13914        }
13915
13916        final int h = dr.getIntrinsicHeight();
13917        final int w = dr.getIntrinsicWidth();
13918        final Rect rect = mAttachInfo.mTmpInvalRect;
13919        getScrollIndicatorBounds(rect);
13920
13921        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
13922            final boolean canScrollUp = canScrollVertically(-1);
13923            if (canScrollUp) {
13924                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
13925                dr.draw(c);
13926            }
13927        }
13928
13929        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
13930            final boolean canScrollDown = canScrollVertically(1);
13931            if (canScrollDown) {
13932                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
13933                dr.draw(c);
13934            }
13935        }
13936
13937        final int leftRtl;
13938        final int rightRtl;
13939        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13940            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
13941            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
13942        } else {
13943            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
13944            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
13945        }
13946
13947        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
13948        if ((mPrivateFlags3 & leftMask) != 0) {
13949            final boolean canScrollLeft = canScrollHorizontally(-1);
13950            if (canScrollLeft) {
13951                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
13952                dr.draw(c);
13953            }
13954        }
13955
13956        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
13957        if ((mPrivateFlags3 & rightMask) != 0) {
13958            final boolean canScrollRight = canScrollHorizontally(1);
13959            if (canScrollRight) {
13960                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
13961                dr.draw(c);
13962            }
13963        }
13964    }
13965
13966    /**
13967     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
13968     * scrollbars are painted only if they have been awakened first.</p>
13969     *
13970     * @param canvas the canvas on which to draw the scrollbars
13971     *
13972     * @see #awakenScrollBars(int)
13973     */
13974    protected final void onDrawScrollBars(Canvas canvas) {
13975        // scrollbars are drawn only when the animation is running
13976        final ScrollabilityCache cache = mScrollCache;
13977        if (cache != null) {
13978
13979            int state = cache.state;
13980
13981            if (state == ScrollabilityCache.OFF) {
13982                return;
13983            }
13984
13985            boolean invalidate = false;
13986
13987            if (state == ScrollabilityCache.FADING) {
13988                // We're fading -- get our fade interpolation
13989                if (cache.interpolatorValues == null) {
13990                    cache.interpolatorValues = new float[1];
13991                }
13992
13993                float[] values = cache.interpolatorValues;
13994
13995                // Stops the animation if we're done
13996                if (cache.scrollBarInterpolator.timeToValues(values) ==
13997                        Interpolator.Result.FREEZE_END) {
13998                    cache.state = ScrollabilityCache.OFF;
13999                } else {
14000                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14001                }
14002
14003                // This will make the scroll bars inval themselves after
14004                // drawing. We only want this when we're fading so that
14005                // we prevent excessive redraws
14006                invalidate = true;
14007            } else {
14008                // We're just on -- but we may have been fading before so
14009                // reset alpha
14010                cache.scrollBar.mutate().setAlpha(255);
14011            }
14012
14013
14014            final int viewFlags = mViewFlags;
14015
14016            final boolean drawHorizontalScrollBar =
14017                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14018            final boolean drawVerticalScrollBar =
14019                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
14020                && !isVerticalScrollBarHidden();
14021
14022            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14023                final int width = mRight - mLeft;
14024                final int height = mBottom - mTop;
14025
14026                final ScrollBarDrawable scrollBar = cache.scrollBar;
14027
14028                final int scrollX = mScrollX;
14029                final int scrollY = mScrollY;
14030                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14031
14032                int left;
14033                int top;
14034                int right;
14035                int bottom;
14036
14037                if (drawHorizontalScrollBar) {
14038                    int size = scrollBar.getSize(false);
14039                    if (size <= 0) {
14040                        size = cache.scrollBarSize;
14041                    }
14042
14043                    scrollBar.setParameters(computeHorizontalScrollRange(),
14044                                            computeHorizontalScrollOffset(),
14045                                            computeHorizontalScrollExtent(), false);
14046                    final int verticalScrollBarGap = drawVerticalScrollBar ?
14047                            getVerticalScrollbarWidth() : 0;
14048                    top = scrollY + height - size - (mUserPaddingBottom & inside);
14049                    left = scrollX + (mPaddingLeft & inside);
14050                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14051                    bottom = top + size;
14052                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
14053                    if (invalidate) {
14054                        invalidate(left, top, right, bottom);
14055                    }
14056                }
14057
14058                if (drawVerticalScrollBar) {
14059                    int size = scrollBar.getSize(true);
14060                    if (size <= 0) {
14061                        size = cache.scrollBarSize;
14062                    }
14063
14064                    scrollBar.setParameters(computeVerticalScrollRange(),
14065                                            computeVerticalScrollOffset(),
14066                                            computeVerticalScrollExtent(), true);
14067                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
14068                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14069                        verticalScrollbarPosition = isLayoutRtl() ?
14070                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14071                    }
14072                    switch (verticalScrollbarPosition) {
14073                        default:
14074                        case SCROLLBAR_POSITION_RIGHT:
14075                            left = scrollX + width - size - (mUserPaddingRight & inside);
14076                            break;
14077                        case SCROLLBAR_POSITION_LEFT:
14078                            left = scrollX + (mUserPaddingLeft & inside);
14079                            break;
14080                    }
14081                    top = scrollY + (mPaddingTop & inside);
14082                    right = left + size;
14083                    bottom = scrollY + height - (mUserPaddingBottom & inside);
14084                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
14085                    if (invalidate) {
14086                        invalidate(left, top, right, bottom);
14087                    }
14088                }
14089            }
14090        }
14091    }
14092
14093    /**
14094     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14095     * FastScroller is visible.
14096     * @return whether to temporarily hide the vertical scrollbar
14097     * @hide
14098     */
14099    protected boolean isVerticalScrollBarHidden() {
14100        return false;
14101    }
14102
14103    /**
14104     * <p>Draw the horizontal scrollbar if
14105     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14106     *
14107     * @param canvas the canvas on which to draw the scrollbar
14108     * @param scrollBar the scrollbar's drawable
14109     *
14110     * @see #isHorizontalScrollBarEnabled()
14111     * @see #computeHorizontalScrollRange()
14112     * @see #computeHorizontalScrollExtent()
14113     * @see #computeHorizontalScrollOffset()
14114     * @see android.widget.ScrollBarDrawable
14115     * @hide
14116     */
14117    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14118            int l, int t, int r, int b) {
14119        scrollBar.setBounds(l, t, r, b);
14120        scrollBar.draw(canvas);
14121    }
14122
14123    /**
14124     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14125     * returns true.</p>
14126     *
14127     * @param canvas the canvas on which to draw the scrollbar
14128     * @param scrollBar the scrollbar's drawable
14129     *
14130     * @see #isVerticalScrollBarEnabled()
14131     * @see #computeVerticalScrollRange()
14132     * @see #computeVerticalScrollExtent()
14133     * @see #computeVerticalScrollOffset()
14134     * @see android.widget.ScrollBarDrawable
14135     * @hide
14136     */
14137    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14138            int l, int t, int r, int b) {
14139        scrollBar.setBounds(l, t, r, b);
14140        scrollBar.draw(canvas);
14141    }
14142
14143    /**
14144     * Implement this to do your drawing.
14145     *
14146     * @param canvas the canvas on which the background will be drawn
14147     */
14148    protected void onDraw(Canvas canvas) {
14149    }
14150
14151    /*
14152     * Caller is responsible for calling requestLayout if necessary.
14153     * (This allows addViewInLayout to not request a new layout.)
14154     */
14155    void assignParent(ViewParent parent) {
14156        if (mParent == null) {
14157            mParent = parent;
14158        } else if (parent == null) {
14159            mParent = null;
14160        } else {
14161            throw new RuntimeException("view " + this + " being added, but"
14162                    + " it already has a parent");
14163        }
14164    }
14165
14166    /**
14167     * This is called when the view is attached to a window.  At this point it
14168     * has a Surface and will start drawing.  Note that this function is
14169     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14170     * however it may be called any time before the first onDraw -- including
14171     * before or after {@link #onMeasure(int, int)}.
14172     *
14173     * @see #onDetachedFromWindow()
14174     */
14175    @CallSuper
14176    protected void onAttachedToWindow() {
14177        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
14178            mParent.requestTransparentRegion(this);
14179        }
14180
14181        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14182
14183        jumpDrawablesToCurrentState();
14184
14185        resetSubtreeAccessibilityStateChanged();
14186
14187        // rebuild, since Outline not maintained while View is detached
14188        rebuildOutline();
14189
14190        if (isFocused()) {
14191            InputMethodManager imm = InputMethodManager.peekInstance();
14192            if (imm != null) {
14193                imm.focusIn(this);
14194            }
14195        }
14196    }
14197
14198    /**
14199     * Resolve all RTL related properties.
14200     *
14201     * @return true if resolution of RTL properties has been done
14202     *
14203     * @hide
14204     */
14205    public boolean resolveRtlPropertiesIfNeeded() {
14206        if (!needRtlPropertiesResolution()) return false;
14207
14208        // Order is important here: LayoutDirection MUST be resolved first
14209        if (!isLayoutDirectionResolved()) {
14210            resolveLayoutDirection();
14211            resolveLayoutParams();
14212        }
14213        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
14214        if (!isTextDirectionResolved()) {
14215            resolveTextDirection();
14216        }
14217        if (!isTextAlignmentResolved()) {
14218            resolveTextAlignment();
14219        }
14220        // Should resolve Drawables before Padding because we need the layout direction of the
14221        // Drawable to correctly resolve Padding.
14222        if (!areDrawablesResolved()) {
14223            resolveDrawables();
14224        }
14225        if (!isPaddingResolved()) {
14226            resolvePadding();
14227        }
14228        onRtlPropertiesChanged(getLayoutDirection());
14229        return true;
14230    }
14231
14232    /**
14233     * Reset resolution of all RTL related properties.
14234     *
14235     * @hide
14236     */
14237    public void resetRtlProperties() {
14238        resetResolvedLayoutDirection();
14239        resetResolvedTextDirection();
14240        resetResolvedTextAlignment();
14241        resetResolvedPadding();
14242        resetResolvedDrawables();
14243    }
14244
14245    /**
14246     * @see #onScreenStateChanged(int)
14247     */
14248    void dispatchScreenStateChanged(int screenState) {
14249        onScreenStateChanged(screenState);
14250    }
14251
14252    /**
14253     * This method is called whenever the state of the screen this view is
14254     * attached to changes. A state change will usually occurs when the screen
14255     * turns on or off (whether it happens automatically or the user does it
14256     * manually.)
14257     *
14258     * @param screenState The new state of the screen. Can be either
14259     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
14260     */
14261    public void onScreenStateChanged(int screenState) {
14262    }
14263
14264    /**
14265     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
14266     */
14267    private boolean hasRtlSupport() {
14268        return mContext.getApplicationInfo().hasRtlSupport();
14269    }
14270
14271    /**
14272     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
14273     * RTL not supported)
14274     */
14275    private boolean isRtlCompatibilityMode() {
14276        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
14277        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
14278    }
14279
14280    /**
14281     * @return true if RTL properties need resolution.
14282     *
14283     */
14284    private boolean needRtlPropertiesResolution() {
14285        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
14286    }
14287
14288    /**
14289     * Called when any RTL property (layout direction or text direction or text alignment) has
14290     * been changed.
14291     *
14292     * Subclasses need to override this method to take care of cached information that depends on the
14293     * resolved layout direction, or to inform child views that inherit their layout direction.
14294     *
14295     * The default implementation does nothing.
14296     *
14297     * @param layoutDirection the direction of the layout
14298     *
14299     * @see #LAYOUT_DIRECTION_LTR
14300     * @see #LAYOUT_DIRECTION_RTL
14301     */
14302    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
14303    }
14304
14305    /**
14306     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
14307     * that the parent directionality can and will be resolved before its children.
14308     *
14309     * @return true if resolution has been done, false otherwise.
14310     *
14311     * @hide
14312     */
14313    public boolean resolveLayoutDirection() {
14314        // Clear any previous layout direction resolution
14315        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14316
14317        if (hasRtlSupport()) {
14318            // Set resolved depending on layout direction
14319            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
14320                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
14321                case LAYOUT_DIRECTION_INHERIT:
14322                    // We cannot resolve yet. LTR is by default and let the resolution happen again
14323                    // later to get the correct resolved value
14324                    if (!canResolveLayoutDirection()) return false;
14325
14326                    // Parent has not yet resolved, LTR is still the default
14327                    try {
14328                        if (!mParent.isLayoutDirectionResolved()) return false;
14329
14330                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14331                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14332                        }
14333                    } catch (AbstractMethodError e) {
14334                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14335                                " does not fully implement ViewParent", e);
14336                    }
14337                    break;
14338                case LAYOUT_DIRECTION_RTL:
14339                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14340                    break;
14341                case LAYOUT_DIRECTION_LOCALE:
14342                    if((LAYOUT_DIRECTION_RTL ==
14343                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
14344                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14345                    }
14346                    break;
14347                default:
14348                    // Nothing to do, LTR by default
14349            }
14350        }
14351
14352        // Set to resolved
14353        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14354        return true;
14355    }
14356
14357    /**
14358     * Check if layout direction resolution can be done.
14359     *
14360     * @return true if layout direction resolution can be done otherwise return false.
14361     */
14362    public boolean canResolveLayoutDirection() {
14363        switch (getRawLayoutDirection()) {
14364            case LAYOUT_DIRECTION_INHERIT:
14365                if (mParent != null) {
14366                    try {
14367                        return mParent.canResolveLayoutDirection();
14368                    } catch (AbstractMethodError e) {
14369                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14370                                " does not fully implement ViewParent", e);
14371                    }
14372                }
14373                return false;
14374
14375            default:
14376                return true;
14377        }
14378    }
14379
14380    /**
14381     * Reset the resolved layout direction. Layout direction will be resolved during a call to
14382     * {@link #onMeasure(int, int)}.
14383     *
14384     * @hide
14385     */
14386    public void resetResolvedLayoutDirection() {
14387        // Reset the current resolved bits
14388        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14389    }
14390
14391    /**
14392     * @return true if the layout direction is inherited.
14393     *
14394     * @hide
14395     */
14396    public boolean isLayoutDirectionInherited() {
14397        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
14398    }
14399
14400    /**
14401     * @return true if layout direction has been resolved.
14402     */
14403    public boolean isLayoutDirectionResolved() {
14404        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14405    }
14406
14407    /**
14408     * Return if padding has been resolved
14409     *
14410     * @hide
14411     */
14412    boolean isPaddingResolved() {
14413        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
14414    }
14415
14416    /**
14417     * Resolves padding depending on layout direction, if applicable, and
14418     * recomputes internal padding values to adjust for scroll bars.
14419     *
14420     * @hide
14421     */
14422    public void resolvePadding() {
14423        final int resolvedLayoutDirection = getLayoutDirection();
14424
14425        if (!isRtlCompatibilityMode()) {
14426            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
14427            // If start / end padding are defined, they will be resolved (hence overriding) to
14428            // left / right or right / left depending on the resolved layout direction.
14429            // If start / end padding are not defined, use the left / right ones.
14430            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
14431                Rect padding = sThreadLocal.get();
14432                if (padding == null) {
14433                    padding = new Rect();
14434                    sThreadLocal.set(padding);
14435                }
14436                mBackground.getPadding(padding);
14437                if (!mLeftPaddingDefined) {
14438                    mUserPaddingLeftInitial = padding.left;
14439                }
14440                if (!mRightPaddingDefined) {
14441                    mUserPaddingRightInitial = padding.right;
14442                }
14443            }
14444            switch (resolvedLayoutDirection) {
14445                case LAYOUT_DIRECTION_RTL:
14446                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14447                        mUserPaddingRight = mUserPaddingStart;
14448                    } else {
14449                        mUserPaddingRight = mUserPaddingRightInitial;
14450                    }
14451                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14452                        mUserPaddingLeft = mUserPaddingEnd;
14453                    } else {
14454                        mUserPaddingLeft = mUserPaddingLeftInitial;
14455                    }
14456                    break;
14457                case LAYOUT_DIRECTION_LTR:
14458                default:
14459                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14460                        mUserPaddingLeft = mUserPaddingStart;
14461                    } else {
14462                        mUserPaddingLeft = mUserPaddingLeftInitial;
14463                    }
14464                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14465                        mUserPaddingRight = mUserPaddingEnd;
14466                    } else {
14467                        mUserPaddingRight = mUserPaddingRightInitial;
14468                    }
14469            }
14470
14471            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
14472        }
14473
14474        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14475        onRtlPropertiesChanged(resolvedLayoutDirection);
14476
14477        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
14478    }
14479
14480    /**
14481     * Reset the resolved layout direction.
14482     *
14483     * @hide
14484     */
14485    public void resetResolvedPadding() {
14486        resetResolvedPaddingInternal();
14487    }
14488
14489    /**
14490     * Used when we only want to reset *this* view's padding and not trigger overrides
14491     * in ViewGroup that reset children too.
14492     */
14493    void resetResolvedPaddingInternal() {
14494        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14495    }
14496
14497    /**
14498     * This is called when the view is detached from a window.  At this point it
14499     * no longer has a surface for drawing.
14500     *
14501     * @see #onAttachedToWindow()
14502     */
14503    @CallSuper
14504    protected void onDetachedFromWindow() {
14505    }
14506
14507    /**
14508     * This is a framework-internal mirror of onDetachedFromWindow() that's called
14509     * after onDetachedFromWindow().
14510     *
14511     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
14512     * The super method should be called at the end of the overridden method to ensure
14513     * subclasses are destroyed first
14514     *
14515     * @hide
14516     */
14517    @CallSuper
14518    protected void onDetachedFromWindowInternal() {
14519        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
14520        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14521
14522        removeUnsetPressCallback();
14523        removeLongPressCallback();
14524        removePerformClickCallback();
14525        removeSendViewScrolledAccessibilityEventCallback();
14526        stopNestedScroll();
14527
14528        // Anything that started animating right before detach should already
14529        // be in its final state when re-attached.
14530        jumpDrawablesToCurrentState();
14531
14532        destroyDrawingCache();
14533
14534        cleanupDraw();
14535        mCurrentAnimation = null;
14536    }
14537
14538    private void cleanupDraw() {
14539        resetDisplayList();
14540        if (mAttachInfo != null) {
14541            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
14542        }
14543    }
14544
14545    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
14546    }
14547
14548    /**
14549     * @return The number of times this view has been attached to a window
14550     */
14551    protected int getWindowAttachCount() {
14552        return mWindowAttachCount;
14553    }
14554
14555    /**
14556     * Retrieve a unique token identifying the window this view is attached to.
14557     * @return Return the window's token for use in
14558     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
14559     */
14560    public IBinder getWindowToken() {
14561        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
14562    }
14563
14564    /**
14565     * Retrieve the {@link WindowId} for the window this view is
14566     * currently attached to.
14567     */
14568    public WindowId getWindowId() {
14569        if (mAttachInfo == null) {
14570            return null;
14571        }
14572        if (mAttachInfo.mWindowId == null) {
14573            try {
14574                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
14575                        mAttachInfo.mWindowToken);
14576                mAttachInfo.mWindowId = new WindowId(
14577                        mAttachInfo.mIWindowId);
14578            } catch (RemoteException e) {
14579            }
14580        }
14581        return mAttachInfo.mWindowId;
14582    }
14583
14584    /**
14585     * Retrieve a unique token identifying the top-level "real" window of
14586     * the window that this view is attached to.  That is, this is like
14587     * {@link #getWindowToken}, except if the window this view in is a panel
14588     * window (attached to another containing window), then the token of
14589     * the containing window is returned instead.
14590     *
14591     * @return Returns the associated window token, either
14592     * {@link #getWindowToken()} or the containing window's token.
14593     */
14594    public IBinder getApplicationWindowToken() {
14595        AttachInfo ai = mAttachInfo;
14596        if (ai != null) {
14597            IBinder appWindowToken = ai.mPanelParentWindowToken;
14598            if (appWindowToken == null) {
14599                appWindowToken = ai.mWindowToken;
14600            }
14601            return appWindowToken;
14602        }
14603        return null;
14604    }
14605
14606    /**
14607     * Gets the logical display to which the view's window has been attached.
14608     *
14609     * @return The logical display, or null if the view is not currently attached to a window.
14610     */
14611    public Display getDisplay() {
14612        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
14613    }
14614
14615    /**
14616     * Retrieve private session object this view hierarchy is using to
14617     * communicate with the window manager.
14618     * @return the session object to communicate with the window manager
14619     */
14620    /*package*/ IWindowSession getWindowSession() {
14621        return mAttachInfo != null ? mAttachInfo.mSession : null;
14622    }
14623
14624    /**
14625     * Return the visibility value of the least visible component passed.
14626     */
14627    int combineVisibility(int vis1, int vis2) {
14628        // This works because VISIBLE < INVISIBLE < GONE.
14629        return Math.max(vis1, vis2);
14630    }
14631
14632    /**
14633     * @param info the {@link android.view.View.AttachInfo} to associated with
14634     *        this view
14635     */
14636    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
14637        mAttachInfo = info;
14638        if (mOverlay != null) {
14639            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
14640        }
14641        mWindowAttachCount++;
14642        // We will need to evaluate the drawable state at least once.
14643        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14644        if (mFloatingTreeObserver != null) {
14645            info.mTreeObserver.merge(mFloatingTreeObserver);
14646            mFloatingTreeObserver = null;
14647        }
14648        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
14649            mAttachInfo.mScrollContainers.add(this);
14650            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
14651        }
14652        // Transfer all pending runnables.
14653        if (mRunQueue != null) {
14654            mRunQueue.executeActions(info.mHandler);
14655            mRunQueue = null;
14656        }
14657        performCollectViewAttributes(mAttachInfo, visibility);
14658        onAttachedToWindow();
14659
14660        ListenerInfo li = mListenerInfo;
14661        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14662                li != null ? li.mOnAttachStateChangeListeners : null;
14663        if (listeners != null && listeners.size() > 0) {
14664            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14665            // perform the dispatching. The iterator is a safe guard against listeners that
14666            // could mutate the list by calling the various add/remove methods. This prevents
14667            // the array from being modified while we iterate it.
14668            for (OnAttachStateChangeListener listener : listeners) {
14669                listener.onViewAttachedToWindow(this);
14670            }
14671        }
14672
14673        int vis = info.mWindowVisibility;
14674        if (vis != GONE) {
14675            onWindowVisibilityChanged(vis);
14676        }
14677
14678        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
14679        // As all views in the subtree will already receive dispatchAttachedToWindow
14680        // traversing the subtree again here is not desired.
14681        onVisibilityChanged(this, visibility);
14682
14683        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
14684            // If nobody has evaluated the drawable state yet, then do it now.
14685            refreshDrawableState();
14686        }
14687        needGlobalAttributesUpdate(false);
14688    }
14689
14690    void dispatchDetachedFromWindow() {
14691        AttachInfo info = mAttachInfo;
14692        if (info != null) {
14693            int vis = info.mWindowVisibility;
14694            if (vis != GONE) {
14695                onWindowVisibilityChanged(GONE);
14696            }
14697        }
14698
14699        onDetachedFromWindow();
14700        onDetachedFromWindowInternal();
14701
14702        InputMethodManager imm = InputMethodManager.peekInstance();
14703        if (imm != null) {
14704            imm.onViewDetachedFromWindow(this);
14705        }
14706
14707        ListenerInfo li = mListenerInfo;
14708        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14709                li != null ? li.mOnAttachStateChangeListeners : null;
14710        if (listeners != null && listeners.size() > 0) {
14711            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14712            // perform the dispatching. The iterator is a safe guard against listeners that
14713            // could mutate the list by calling the various add/remove methods. This prevents
14714            // the array from being modified while we iterate it.
14715            for (OnAttachStateChangeListener listener : listeners) {
14716                listener.onViewDetachedFromWindow(this);
14717            }
14718        }
14719
14720        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
14721            mAttachInfo.mScrollContainers.remove(this);
14722            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
14723        }
14724
14725        mAttachInfo = null;
14726        if (mOverlay != null) {
14727            mOverlay.getOverlayView().dispatchDetachedFromWindow();
14728        }
14729    }
14730
14731    /**
14732     * Cancel any deferred high-level input events that were previously posted to the event queue.
14733     *
14734     * <p>Many views post high-level events such as click handlers to the event queue
14735     * to run deferred in order to preserve a desired user experience - clearing visible
14736     * pressed states before executing, etc. This method will abort any events of this nature
14737     * that are currently in flight.</p>
14738     *
14739     * <p>Custom views that generate their own high-level deferred input events should override
14740     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14741     *
14742     * <p>This will also cancel pending input events for any child views.</p>
14743     *
14744     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14745     * This will not impact newer events posted after this call that may occur as a result of
14746     * lower-level input events still waiting in the queue. If you are trying to prevent
14747     * double-submitted  events for the duration of some sort of asynchronous transaction
14748     * you should also take other steps to protect against unexpected double inputs e.g. calling
14749     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14750     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14751     */
14752    public final void cancelPendingInputEvents() {
14753        dispatchCancelPendingInputEvents();
14754    }
14755
14756    /**
14757     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14758     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14759     */
14760    void dispatchCancelPendingInputEvents() {
14761        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14762        onCancelPendingInputEvents();
14763        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14764            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14765                    " did not call through to super.onCancelPendingInputEvents()");
14766        }
14767    }
14768
14769    /**
14770     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14771     * a parent view.
14772     *
14773     * <p>This method is responsible for removing any pending high-level input events that were
14774     * posted to the event queue to run later. Custom view classes that post their own deferred
14775     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14776     * {@link android.os.Handler} should override this method, call
14777     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14778     * </p>
14779     */
14780    public void onCancelPendingInputEvents() {
14781        removePerformClickCallback();
14782        cancelLongPress();
14783        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14784    }
14785
14786    /**
14787     * Store this view hierarchy's frozen state into the given container.
14788     *
14789     * @param container The SparseArray in which to save the view's state.
14790     *
14791     * @see #restoreHierarchyState(android.util.SparseArray)
14792     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14793     * @see #onSaveInstanceState()
14794     */
14795    public void saveHierarchyState(SparseArray<Parcelable> container) {
14796        dispatchSaveInstanceState(container);
14797    }
14798
14799    /**
14800     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
14801     * this view and its children. May be overridden to modify how freezing happens to a
14802     * view's children; for example, some views may want to not store state for their children.
14803     *
14804     * @param container The SparseArray in which to save the view's state.
14805     *
14806     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14807     * @see #saveHierarchyState(android.util.SparseArray)
14808     * @see #onSaveInstanceState()
14809     */
14810    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
14811        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
14812            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14813            Parcelable state = onSaveInstanceState();
14814            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14815                throw new IllegalStateException(
14816                        "Derived class did not call super.onSaveInstanceState()");
14817            }
14818            if (state != null) {
14819                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
14820                // + ": " + state);
14821                container.put(mID, state);
14822            }
14823        }
14824    }
14825
14826    /**
14827     * Hook allowing a view to generate a representation of its internal state
14828     * that can later be used to create a new instance with that same state.
14829     * This state should only contain information that is not persistent or can
14830     * not be reconstructed later. For example, you will never store your
14831     * current position on screen because that will be computed again when a
14832     * new instance of the view is placed in its view hierarchy.
14833     * <p>
14834     * Some examples of things you may store here: the current cursor position
14835     * in a text view (but usually not the text itself since that is stored in a
14836     * content provider or other persistent storage), the currently selected
14837     * item in a list view.
14838     *
14839     * @return Returns a Parcelable object containing the view's current dynamic
14840     *         state, or null if there is nothing interesting to save. The
14841     *         default implementation returns null.
14842     * @see #onRestoreInstanceState(android.os.Parcelable)
14843     * @see #saveHierarchyState(android.util.SparseArray)
14844     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14845     * @see #setSaveEnabled(boolean)
14846     */
14847    @CallSuper
14848    protected Parcelable onSaveInstanceState() {
14849        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14850        if (mStartActivityRequestWho != null) {
14851            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
14852            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
14853            return state;
14854        }
14855        return BaseSavedState.EMPTY_STATE;
14856    }
14857
14858    /**
14859     * Restore this view hierarchy's frozen state from the given container.
14860     *
14861     * @param container The SparseArray which holds previously frozen states.
14862     *
14863     * @see #saveHierarchyState(android.util.SparseArray)
14864     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14865     * @see #onRestoreInstanceState(android.os.Parcelable)
14866     */
14867    public void restoreHierarchyState(SparseArray<Parcelable> container) {
14868        dispatchRestoreInstanceState(container);
14869    }
14870
14871    /**
14872     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
14873     * state for this view and its children. May be overridden to modify how restoring
14874     * happens to a view's children; for example, some views may want to not store state
14875     * for their children.
14876     *
14877     * @param container The SparseArray which holds previously saved state.
14878     *
14879     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14880     * @see #restoreHierarchyState(android.util.SparseArray)
14881     * @see #onRestoreInstanceState(android.os.Parcelable)
14882     */
14883    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
14884        if (mID != NO_ID) {
14885            Parcelable state = container.get(mID);
14886            if (state != null) {
14887                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
14888                // + ": " + state);
14889                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14890                onRestoreInstanceState(state);
14891                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14892                    throw new IllegalStateException(
14893                            "Derived class did not call super.onRestoreInstanceState()");
14894                }
14895            }
14896        }
14897    }
14898
14899    /**
14900     * Hook allowing a view to re-apply a representation of its internal state that had previously
14901     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
14902     * null state.
14903     *
14904     * @param state The frozen state that had previously been returned by
14905     *        {@link #onSaveInstanceState}.
14906     *
14907     * @see #onSaveInstanceState()
14908     * @see #restoreHierarchyState(android.util.SparseArray)
14909     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14910     */
14911    @CallSuper
14912    protected void onRestoreInstanceState(Parcelable state) {
14913        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14914        if (state != null && !(state instanceof AbsSavedState)) {
14915            throw new IllegalArgumentException("Wrong state class, expecting View State but "
14916                    + "received " + state.getClass().toString() + " instead. This usually happens "
14917                    + "when two views of different type have the same id in the same hierarchy. "
14918                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
14919                    + "other views do not use the same id.");
14920        }
14921        if (state != null && state instanceof BaseSavedState) {
14922            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
14923        }
14924    }
14925
14926    /**
14927     * <p>Return the time at which the drawing of the view hierarchy started.</p>
14928     *
14929     * @return the drawing start time in milliseconds
14930     */
14931    public long getDrawingTime() {
14932        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
14933    }
14934
14935    /**
14936     * <p>Enables or disables the duplication of the parent's state into this view. When
14937     * duplication is enabled, this view gets its drawable state from its parent rather
14938     * than from its own internal properties.</p>
14939     *
14940     * <p>Note: in the current implementation, setting this property to true after the
14941     * view was added to a ViewGroup might have no effect at all. This property should
14942     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
14943     *
14944     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
14945     * property is enabled, an exception will be thrown.</p>
14946     *
14947     * <p>Note: if the child view uses and updates additional states which are unknown to the
14948     * parent, these states should not be affected by this method.</p>
14949     *
14950     * @param enabled True to enable duplication of the parent's drawable state, false
14951     *                to disable it.
14952     *
14953     * @see #getDrawableState()
14954     * @see #isDuplicateParentStateEnabled()
14955     */
14956    public void setDuplicateParentStateEnabled(boolean enabled) {
14957        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
14958    }
14959
14960    /**
14961     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
14962     *
14963     * @return True if this view's drawable state is duplicated from the parent,
14964     *         false otherwise
14965     *
14966     * @see #getDrawableState()
14967     * @see #setDuplicateParentStateEnabled(boolean)
14968     */
14969    public boolean isDuplicateParentStateEnabled() {
14970        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
14971    }
14972
14973    /**
14974     * <p>Specifies the type of layer backing this view. The layer can be
14975     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14976     * {@link #LAYER_TYPE_HARDWARE}.</p>
14977     *
14978     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14979     * instance that controls how the layer is composed on screen. The following
14980     * properties of the paint are taken into account when composing the layer:</p>
14981     * <ul>
14982     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14983     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14984     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14985     * </ul>
14986     *
14987     * <p>If this view has an alpha value set to < 1.0 by calling
14988     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
14989     * by this view's alpha value.</p>
14990     *
14991     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
14992     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
14993     * for more information on when and how to use layers.</p>
14994     *
14995     * @param layerType The type of layer to use with this view, must be one of
14996     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14997     *        {@link #LAYER_TYPE_HARDWARE}
14998     * @param paint The paint used to compose the layer. This argument is optional
14999     *        and can be null. It is ignored when the layer type is
15000     *        {@link #LAYER_TYPE_NONE}
15001     *
15002     * @see #getLayerType()
15003     * @see #LAYER_TYPE_NONE
15004     * @see #LAYER_TYPE_SOFTWARE
15005     * @see #LAYER_TYPE_HARDWARE
15006     * @see #setAlpha(float)
15007     *
15008     * @attr ref android.R.styleable#View_layerType
15009     */
15010    public void setLayerType(int layerType, Paint paint) {
15011        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15012            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15013                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15014        }
15015
15016        boolean typeChanged = mRenderNode.setLayerType(layerType);
15017
15018        if (!typeChanged) {
15019            setLayerPaint(paint);
15020            return;
15021        }
15022
15023        // Destroy any previous software drawing cache if needed
15024        if (mLayerType == LAYER_TYPE_SOFTWARE) {
15025            destroyDrawingCache();
15026        }
15027
15028        mLayerType = layerType;
15029        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
15030        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
15031        mRenderNode.setLayerPaint(mLayerPaint);
15032
15033        // draw() behaves differently if we are on a layer, so we need to
15034        // invalidate() here
15035        invalidateParentCaches();
15036        invalidate(true);
15037    }
15038
15039    /**
15040     * Updates the {@link Paint} object used with the current layer (used only if the current
15041     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15042     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15043     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15044     * ensure that the view gets redrawn immediately.
15045     *
15046     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15047     * instance that controls how the layer is composed on screen. The following
15048     * properties of the paint are taken into account when composing the layer:</p>
15049     * <ul>
15050     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15051     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15052     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15053     * </ul>
15054     *
15055     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15056     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15057     *
15058     * @param paint The paint used to compose the layer. This argument is optional
15059     *        and can be null. It is ignored when the layer type is
15060     *        {@link #LAYER_TYPE_NONE}
15061     *
15062     * @see #setLayerType(int, android.graphics.Paint)
15063     */
15064    public void setLayerPaint(Paint paint) {
15065        int layerType = getLayerType();
15066        if (layerType != LAYER_TYPE_NONE) {
15067            mLayerPaint = paint == null ? new Paint() : paint;
15068            if (layerType == LAYER_TYPE_HARDWARE) {
15069                if (mRenderNode.setLayerPaint(mLayerPaint)) {
15070                    invalidateViewProperty(false, false);
15071                }
15072            } else {
15073                invalidate();
15074            }
15075        }
15076    }
15077
15078    /**
15079     * Indicates what type of layer is currently associated with this view. By default
15080     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15081     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15082     * for more information on the different types of layers.
15083     *
15084     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15085     *         {@link #LAYER_TYPE_HARDWARE}
15086     *
15087     * @see #setLayerType(int, android.graphics.Paint)
15088     * @see #buildLayer()
15089     * @see #LAYER_TYPE_NONE
15090     * @see #LAYER_TYPE_SOFTWARE
15091     * @see #LAYER_TYPE_HARDWARE
15092     */
15093    public int getLayerType() {
15094        return mLayerType;
15095    }
15096
15097    /**
15098     * Forces this view's layer to be created and this view to be rendered
15099     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15100     * invoking this method will have no effect.
15101     *
15102     * This method can for instance be used to render a view into its layer before
15103     * starting an animation. If this view is complex, rendering into the layer
15104     * before starting the animation will avoid skipping frames.
15105     *
15106     * @throws IllegalStateException If this view is not attached to a window
15107     *
15108     * @see #setLayerType(int, android.graphics.Paint)
15109     */
15110    public void buildLayer() {
15111        if (mLayerType == LAYER_TYPE_NONE) return;
15112
15113        final AttachInfo attachInfo = mAttachInfo;
15114        if (attachInfo == null) {
15115            throw new IllegalStateException("This view must be attached to a window first");
15116        }
15117
15118        if (getWidth() == 0 || getHeight() == 0) {
15119            return;
15120        }
15121
15122        switch (mLayerType) {
15123            case LAYER_TYPE_HARDWARE:
15124                updateDisplayListIfDirty();
15125                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
15126                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
15127                }
15128                break;
15129            case LAYER_TYPE_SOFTWARE:
15130                buildDrawingCache(true);
15131                break;
15132        }
15133    }
15134
15135    /**
15136     * Destroys all hardware rendering resources. This method is invoked
15137     * when the system needs to reclaim resources. Upon execution of this
15138     * method, you should free any OpenGL resources created by the view.
15139     *
15140     * Note: you <strong>must</strong> call
15141     * <code>super.destroyHardwareResources()</code> when overriding
15142     * this method.
15143     *
15144     * @hide
15145     */
15146    @CallSuper
15147    protected void destroyHardwareResources() {
15148        // Although the Layer will be destroyed by RenderNode, we want to release
15149        // the staging display list, which is also a signal to RenderNode that it's
15150        // safe to free its copy of the display list as it knows that we will
15151        // push an updated DisplayList if we try to draw again
15152        resetDisplayList();
15153    }
15154
15155    /**
15156     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
15157     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
15158     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
15159     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
15160     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
15161     * null.</p>
15162     *
15163     * <p>Enabling the drawing cache is similar to
15164     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
15165     * acceleration is turned off. When hardware acceleration is turned on, enabling the
15166     * drawing cache has no effect on rendering because the system uses a different mechanism
15167     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
15168     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
15169     * for information on how to enable software and hardware layers.</p>
15170     *
15171     * <p>This API can be used to manually generate
15172     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
15173     * {@link #getDrawingCache()}.</p>
15174     *
15175     * @param enabled true to enable the drawing cache, false otherwise
15176     *
15177     * @see #isDrawingCacheEnabled()
15178     * @see #getDrawingCache()
15179     * @see #buildDrawingCache()
15180     * @see #setLayerType(int, android.graphics.Paint)
15181     */
15182    public void setDrawingCacheEnabled(boolean enabled) {
15183        mCachingFailed = false;
15184        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
15185    }
15186
15187    /**
15188     * <p>Indicates whether the drawing cache is enabled for this view.</p>
15189     *
15190     * @return true if the drawing cache is enabled
15191     *
15192     * @see #setDrawingCacheEnabled(boolean)
15193     * @see #getDrawingCache()
15194     */
15195    @ViewDebug.ExportedProperty(category = "drawing")
15196    public boolean isDrawingCacheEnabled() {
15197        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
15198    }
15199
15200    /**
15201     * Debugging utility which recursively outputs the dirty state of a view and its
15202     * descendants.
15203     *
15204     * @hide
15205     */
15206    @SuppressWarnings({"UnusedDeclaration"})
15207    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
15208        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
15209                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
15210                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
15211                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
15212        if (clear) {
15213            mPrivateFlags &= clearMask;
15214        }
15215        if (this instanceof ViewGroup) {
15216            ViewGroup parent = (ViewGroup) this;
15217            final int count = parent.getChildCount();
15218            for (int i = 0; i < count; i++) {
15219                final View child = parent.getChildAt(i);
15220                child.outputDirtyFlags(indent + "  ", clear, clearMask);
15221            }
15222        }
15223    }
15224
15225    /**
15226     * This method is used by ViewGroup to cause its children to restore or recreate their
15227     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
15228     * to recreate its own display list, which would happen if it went through the normal
15229     * draw/dispatchDraw mechanisms.
15230     *
15231     * @hide
15232     */
15233    protected void dispatchGetDisplayList() {}
15234
15235    /**
15236     * A view that is not attached or hardware accelerated cannot create a display list.
15237     * This method checks these conditions and returns the appropriate result.
15238     *
15239     * @return true if view has the ability to create a display list, false otherwise.
15240     *
15241     * @hide
15242     */
15243    public boolean canHaveDisplayList() {
15244        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
15245    }
15246
15247    /**
15248     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
15249     * @hide
15250     */
15251    @NonNull
15252    public RenderNode updateDisplayListIfDirty() {
15253        final RenderNode renderNode = mRenderNode;
15254        if (!canHaveDisplayList()) {
15255            // can't populate RenderNode, don't try
15256            return renderNode;
15257        }
15258
15259        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
15260                || !renderNode.isValid()
15261                || (mRecreateDisplayList)) {
15262            // Don't need to recreate the display list, just need to tell our
15263            // children to restore/recreate theirs
15264            if (renderNode.isValid()
15265                    && !mRecreateDisplayList) {
15266                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15267                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15268                dispatchGetDisplayList();
15269
15270                return renderNode; // no work needed
15271            }
15272
15273            // If we got here, we're recreating it. Mark it as such to ensure that
15274            // we copy in child display lists into ours in drawChild()
15275            mRecreateDisplayList = true;
15276
15277            int width = mRight - mLeft;
15278            int height = mBottom - mTop;
15279            int layerType = getLayerType();
15280
15281            final DisplayListCanvas canvas = renderNode.start(width, height);
15282            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
15283
15284            try {
15285                if (layerType == LAYER_TYPE_SOFTWARE) {
15286                    buildDrawingCache(true);
15287                    Bitmap cache = getDrawingCache(true);
15288                    if (cache != null) {
15289                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
15290                    }
15291                } else {
15292                    computeScroll();
15293
15294                    canvas.translate(-mScrollX, -mScrollY);
15295                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15296                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15297
15298                    // Fast path for layouts with no backgrounds
15299                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15300                        dispatchDraw(canvas);
15301                        if (mOverlay != null && !mOverlay.isEmpty()) {
15302                            mOverlay.getOverlayView().draw(canvas);
15303                        }
15304                    } else {
15305                        draw(canvas);
15306                    }
15307                }
15308            } finally {
15309                renderNode.end(canvas);
15310                setDisplayListProperties(renderNode);
15311            }
15312        } else {
15313            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15314            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15315        }
15316        return renderNode;
15317    }
15318
15319    private void resetDisplayList() {
15320        if (mRenderNode.isValid()) {
15321            mRenderNode.destroyDisplayListData();
15322        }
15323
15324        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
15325            mBackgroundRenderNode.destroyDisplayListData();
15326        }
15327    }
15328
15329    /**
15330     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
15331     *
15332     * @return A non-scaled bitmap representing this view or null if cache is disabled.
15333     *
15334     * @see #getDrawingCache(boolean)
15335     */
15336    public Bitmap getDrawingCache() {
15337        return getDrawingCache(false);
15338    }
15339
15340    /**
15341     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
15342     * is null when caching is disabled. If caching is enabled and the cache is not ready,
15343     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
15344     * draw from the cache when the cache is enabled. To benefit from the cache, you must
15345     * request the drawing cache by calling this method and draw it on screen if the
15346     * returned bitmap is not null.</p>
15347     *
15348     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15349     * this method will create a bitmap of the same size as this view. Because this bitmap
15350     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15351     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15352     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15353     * size than the view. This implies that your application must be able to handle this
15354     * size.</p>
15355     *
15356     * @param autoScale Indicates whether the generated bitmap should be scaled based on
15357     *        the current density of the screen when the application is in compatibility
15358     *        mode.
15359     *
15360     * @return A bitmap representing this view or null if cache is disabled.
15361     *
15362     * @see #setDrawingCacheEnabled(boolean)
15363     * @see #isDrawingCacheEnabled()
15364     * @see #buildDrawingCache(boolean)
15365     * @see #destroyDrawingCache()
15366     */
15367    public Bitmap getDrawingCache(boolean autoScale) {
15368        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
15369            return null;
15370        }
15371        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
15372            buildDrawingCache(autoScale);
15373        }
15374        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
15375    }
15376
15377    /**
15378     * <p>Frees the resources used by the drawing cache. If you call
15379     * {@link #buildDrawingCache()} manually without calling
15380     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15381     * should cleanup the cache with this method afterwards.</p>
15382     *
15383     * @see #setDrawingCacheEnabled(boolean)
15384     * @see #buildDrawingCache()
15385     * @see #getDrawingCache()
15386     */
15387    public void destroyDrawingCache() {
15388        if (mDrawingCache != null) {
15389            mDrawingCache.recycle();
15390            mDrawingCache = null;
15391        }
15392        if (mUnscaledDrawingCache != null) {
15393            mUnscaledDrawingCache.recycle();
15394            mUnscaledDrawingCache = null;
15395        }
15396    }
15397
15398    /**
15399     * Setting a solid background color for the drawing cache's bitmaps will improve
15400     * performance and memory usage. Note, though that this should only be used if this
15401     * view will always be drawn on top of a solid color.
15402     *
15403     * @param color The background color to use for the drawing cache's bitmap
15404     *
15405     * @see #setDrawingCacheEnabled(boolean)
15406     * @see #buildDrawingCache()
15407     * @see #getDrawingCache()
15408     */
15409    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
15410        if (color != mDrawingCacheBackgroundColor) {
15411            mDrawingCacheBackgroundColor = color;
15412            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15413        }
15414    }
15415
15416    /**
15417     * @see #setDrawingCacheBackgroundColor(int)
15418     *
15419     * @return The background color to used for the drawing cache's bitmap
15420     */
15421    @ColorInt
15422    public int getDrawingCacheBackgroundColor() {
15423        return mDrawingCacheBackgroundColor;
15424    }
15425
15426    /**
15427     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
15428     *
15429     * @see #buildDrawingCache(boolean)
15430     */
15431    public void buildDrawingCache() {
15432        buildDrawingCache(false);
15433    }
15434
15435    /**
15436     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
15437     *
15438     * <p>If you call {@link #buildDrawingCache()} manually without calling
15439     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15440     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
15441     *
15442     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15443     * this method will create a bitmap of the same size as this view. Because this bitmap
15444     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15445     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15446     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15447     * size than the view. This implies that your application must be able to handle this
15448     * size.</p>
15449     *
15450     * <p>You should avoid calling this method when hardware acceleration is enabled. If
15451     * you do not need the drawing cache bitmap, calling this method will increase memory
15452     * usage and cause the view to be rendered in software once, thus negatively impacting
15453     * performance.</p>
15454     *
15455     * @see #getDrawingCache()
15456     * @see #destroyDrawingCache()
15457     */
15458    public void buildDrawingCache(boolean autoScale) {
15459        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
15460                mDrawingCache == null : mUnscaledDrawingCache == null)) {
15461            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
15462                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
15463                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
15464            }
15465            try {
15466                buildDrawingCacheImpl(autoScale);
15467            } finally {
15468                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
15469            }
15470        }
15471    }
15472
15473    /**
15474     * private, internal implementation of buildDrawingCache, used to enable tracing
15475     */
15476    private void buildDrawingCacheImpl(boolean autoScale) {
15477        mCachingFailed = false;
15478
15479        int width = mRight - mLeft;
15480        int height = mBottom - mTop;
15481
15482        final AttachInfo attachInfo = mAttachInfo;
15483        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
15484
15485        if (autoScale && scalingRequired) {
15486            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
15487            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
15488        }
15489
15490        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
15491        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
15492        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
15493
15494        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
15495        final long drawingCacheSize =
15496                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
15497        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
15498            if (width > 0 && height > 0) {
15499                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
15500                        + " too large to fit into a software layer (or drawing cache), needs "
15501                        + projectedBitmapSize + " bytes, only "
15502                        + drawingCacheSize + " available");
15503            }
15504            destroyDrawingCache();
15505            mCachingFailed = true;
15506            return;
15507        }
15508
15509        boolean clear = true;
15510        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
15511
15512        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
15513            Bitmap.Config quality;
15514            if (!opaque) {
15515                // Never pick ARGB_4444 because it looks awful
15516                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
15517                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
15518                    case DRAWING_CACHE_QUALITY_AUTO:
15519                    case DRAWING_CACHE_QUALITY_LOW:
15520                    case DRAWING_CACHE_QUALITY_HIGH:
15521                    default:
15522                        quality = Bitmap.Config.ARGB_8888;
15523                        break;
15524                }
15525            } else {
15526                // Optimization for translucent windows
15527                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
15528                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
15529            }
15530
15531            // Try to cleanup memory
15532            if (bitmap != null) bitmap.recycle();
15533
15534            try {
15535                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15536                        width, height, quality);
15537                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
15538                if (autoScale) {
15539                    mDrawingCache = bitmap;
15540                } else {
15541                    mUnscaledDrawingCache = bitmap;
15542                }
15543                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
15544            } catch (OutOfMemoryError e) {
15545                // If there is not enough memory to create the bitmap cache, just
15546                // ignore the issue as bitmap caches are not required to draw the
15547                // view hierarchy
15548                if (autoScale) {
15549                    mDrawingCache = null;
15550                } else {
15551                    mUnscaledDrawingCache = null;
15552                }
15553                mCachingFailed = true;
15554                return;
15555            }
15556
15557            clear = drawingCacheBackgroundColor != 0;
15558        }
15559
15560        Canvas canvas;
15561        if (attachInfo != null) {
15562            canvas = attachInfo.mCanvas;
15563            if (canvas == null) {
15564                canvas = new Canvas();
15565            }
15566            canvas.setBitmap(bitmap);
15567            // Temporarily clobber the cached Canvas in case one of our children
15568            // is also using a drawing cache. Without this, the children would
15569            // steal the canvas by attaching their own bitmap to it and bad, bad
15570            // thing would happen (invisible views, corrupted drawings, etc.)
15571            attachInfo.mCanvas = null;
15572        } else {
15573            // This case should hopefully never or seldom happen
15574            canvas = new Canvas(bitmap);
15575        }
15576
15577        if (clear) {
15578            bitmap.eraseColor(drawingCacheBackgroundColor);
15579        }
15580
15581        computeScroll();
15582        final int restoreCount = canvas.save();
15583
15584        if (autoScale && scalingRequired) {
15585            final float scale = attachInfo.mApplicationScale;
15586            canvas.scale(scale, scale);
15587        }
15588
15589        canvas.translate(-mScrollX, -mScrollY);
15590
15591        mPrivateFlags |= PFLAG_DRAWN;
15592        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
15593                mLayerType != LAYER_TYPE_NONE) {
15594            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
15595        }
15596
15597        // Fast path for layouts with no backgrounds
15598        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15599            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15600            dispatchDraw(canvas);
15601            if (mOverlay != null && !mOverlay.isEmpty()) {
15602                mOverlay.getOverlayView().draw(canvas);
15603            }
15604        } else {
15605            draw(canvas);
15606        }
15607
15608        canvas.restoreToCount(restoreCount);
15609        canvas.setBitmap(null);
15610
15611        if (attachInfo != null) {
15612            // Restore the cached Canvas for our siblings
15613            attachInfo.mCanvas = canvas;
15614        }
15615    }
15616
15617    /**
15618     * Create a snapshot of the view into a bitmap.  We should probably make
15619     * some form of this public, but should think about the API.
15620     */
15621    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
15622        int width = mRight - mLeft;
15623        int height = mBottom - mTop;
15624
15625        final AttachInfo attachInfo = mAttachInfo;
15626        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
15627        width = (int) ((width * scale) + 0.5f);
15628        height = (int) ((height * scale) + 0.5f);
15629
15630        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15631                width > 0 ? width : 1, height > 0 ? height : 1, quality);
15632        if (bitmap == null) {
15633            throw new OutOfMemoryError();
15634        }
15635
15636        Resources resources = getResources();
15637        if (resources != null) {
15638            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
15639        }
15640
15641        Canvas canvas;
15642        if (attachInfo != null) {
15643            canvas = attachInfo.mCanvas;
15644            if (canvas == null) {
15645                canvas = new Canvas();
15646            }
15647            canvas.setBitmap(bitmap);
15648            // Temporarily clobber the cached Canvas in case one of our children
15649            // is also using a drawing cache. Without this, the children would
15650            // steal the canvas by attaching their own bitmap to it and bad, bad
15651            // things would happen (invisible views, corrupted drawings, etc.)
15652            attachInfo.mCanvas = null;
15653        } else {
15654            // This case should hopefully never or seldom happen
15655            canvas = new Canvas(bitmap);
15656        }
15657
15658        if ((backgroundColor & 0xff000000) != 0) {
15659            bitmap.eraseColor(backgroundColor);
15660        }
15661
15662        computeScroll();
15663        final int restoreCount = canvas.save();
15664        canvas.scale(scale, scale);
15665        canvas.translate(-mScrollX, -mScrollY);
15666
15667        // Temporarily remove the dirty mask
15668        int flags = mPrivateFlags;
15669        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15670
15671        // Fast path for layouts with no backgrounds
15672        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15673            dispatchDraw(canvas);
15674            if (mOverlay != null && !mOverlay.isEmpty()) {
15675                mOverlay.getOverlayView().draw(canvas);
15676            }
15677        } else {
15678            draw(canvas);
15679        }
15680
15681        mPrivateFlags = flags;
15682
15683        canvas.restoreToCount(restoreCount);
15684        canvas.setBitmap(null);
15685
15686        if (attachInfo != null) {
15687            // Restore the cached Canvas for our siblings
15688            attachInfo.mCanvas = canvas;
15689        }
15690
15691        return bitmap;
15692    }
15693
15694    /**
15695     * Indicates whether this View is currently in edit mode. A View is usually
15696     * in edit mode when displayed within a developer tool. For instance, if
15697     * this View is being drawn by a visual user interface builder, this method
15698     * should return true.
15699     *
15700     * Subclasses should check the return value of this method to provide
15701     * different behaviors if their normal behavior might interfere with the
15702     * host environment. For instance: the class spawns a thread in its
15703     * constructor, the drawing code relies on device-specific features, etc.
15704     *
15705     * This method is usually checked in the drawing code of custom widgets.
15706     *
15707     * @return True if this View is in edit mode, false otherwise.
15708     */
15709    public boolean isInEditMode() {
15710        return false;
15711    }
15712
15713    /**
15714     * If the View draws content inside its padding and enables fading edges,
15715     * it needs to support padding offsets. Padding offsets are added to the
15716     * fading edges to extend the length of the fade so that it covers pixels
15717     * drawn inside the padding.
15718     *
15719     * Subclasses of this class should override this method if they need
15720     * to draw content inside the padding.
15721     *
15722     * @return True if padding offset must be applied, false otherwise.
15723     *
15724     * @see #getLeftPaddingOffset()
15725     * @see #getRightPaddingOffset()
15726     * @see #getTopPaddingOffset()
15727     * @see #getBottomPaddingOffset()
15728     *
15729     * @since CURRENT
15730     */
15731    protected boolean isPaddingOffsetRequired() {
15732        return false;
15733    }
15734
15735    /**
15736     * Amount by which to extend the left fading region. Called only when
15737     * {@link #isPaddingOffsetRequired()} returns true.
15738     *
15739     * @return The left padding offset in pixels.
15740     *
15741     * @see #isPaddingOffsetRequired()
15742     *
15743     * @since CURRENT
15744     */
15745    protected int getLeftPaddingOffset() {
15746        return 0;
15747    }
15748
15749    /**
15750     * Amount by which to extend the right fading region. Called only when
15751     * {@link #isPaddingOffsetRequired()} returns true.
15752     *
15753     * @return The right padding offset in pixels.
15754     *
15755     * @see #isPaddingOffsetRequired()
15756     *
15757     * @since CURRENT
15758     */
15759    protected int getRightPaddingOffset() {
15760        return 0;
15761    }
15762
15763    /**
15764     * Amount by which to extend the top fading region. Called only when
15765     * {@link #isPaddingOffsetRequired()} returns true.
15766     *
15767     * @return The top padding offset in pixels.
15768     *
15769     * @see #isPaddingOffsetRequired()
15770     *
15771     * @since CURRENT
15772     */
15773    protected int getTopPaddingOffset() {
15774        return 0;
15775    }
15776
15777    /**
15778     * Amount by which to extend the bottom fading region. Called only when
15779     * {@link #isPaddingOffsetRequired()} returns true.
15780     *
15781     * @return The bottom padding offset in pixels.
15782     *
15783     * @see #isPaddingOffsetRequired()
15784     *
15785     * @since CURRENT
15786     */
15787    protected int getBottomPaddingOffset() {
15788        return 0;
15789    }
15790
15791    /**
15792     * @hide
15793     * @param offsetRequired
15794     */
15795    protected int getFadeTop(boolean offsetRequired) {
15796        int top = mPaddingTop;
15797        if (offsetRequired) top += getTopPaddingOffset();
15798        return top;
15799    }
15800
15801    /**
15802     * @hide
15803     * @param offsetRequired
15804     */
15805    protected int getFadeHeight(boolean offsetRequired) {
15806        int padding = mPaddingTop;
15807        if (offsetRequired) padding += getTopPaddingOffset();
15808        return mBottom - mTop - mPaddingBottom - padding;
15809    }
15810
15811    /**
15812     * <p>Indicates whether this view is attached to a hardware accelerated
15813     * window or not.</p>
15814     *
15815     * <p>Even if this method returns true, it does not mean that every call
15816     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
15817     * accelerated {@link android.graphics.Canvas}. For instance, if this view
15818     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
15819     * window is hardware accelerated,
15820     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
15821     * return false, and this method will return true.</p>
15822     *
15823     * @return True if the view is attached to a window and the window is
15824     *         hardware accelerated; false in any other case.
15825     */
15826    @ViewDebug.ExportedProperty(category = "drawing")
15827    public boolean isHardwareAccelerated() {
15828        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15829    }
15830
15831    /**
15832     * Sets a rectangular area on this view to which the view will be clipped
15833     * when it is drawn. Setting the value to null will remove the clip bounds
15834     * and the view will draw normally, using its full bounds.
15835     *
15836     * @param clipBounds The rectangular area, in the local coordinates of
15837     * this view, to which future drawing operations will be clipped.
15838     */
15839    public void setClipBounds(Rect clipBounds) {
15840        if (clipBounds == mClipBounds
15841                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
15842            return;
15843        }
15844        if (clipBounds != null) {
15845            if (mClipBounds == null) {
15846                mClipBounds = new Rect(clipBounds);
15847            } else {
15848                mClipBounds.set(clipBounds);
15849            }
15850        } else {
15851            mClipBounds = null;
15852        }
15853        mRenderNode.setClipBounds(mClipBounds);
15854        invalidateViewProperty(false, false);
15855    }
15856
15857    /**
15858     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
15859     *
15860     * @return A copy of the current clip bounds if clip bounds are set,
15861     * otherwise null.
15862     */
15863    public Rect getClipBounds() {
15864        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
15865    }
15866
15867
15868    /**
15869     * Populates an output rectangle with the clip bounds of the view,
15870     * returning {@code true} if successful or {@code false} if the view's
15871     * clip bounds are {@code null}.
15872     *
15873     * @param outRect rectangle in which to place the clip bounds of the view
15874     * @return {@code true} if successful or {@code false} if the view's
15875     *         clip bounds are {@code null}
15876     */
15877    public boolean getClipBounds(Rect outRect) {
15878        if (mClipBounds != null) {
15879            outRect.set(mClipBounds);
15880            return true;
15881        }
15882        return false;
15883    }
15884
15885    /**
15886     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
15887     * case of an active Animation being run on the view.
15888     */
15889    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
15890            Animation a, boolean scalingRequired) {
15891        Transformation invalidationTransform;
15892        final int flags = parent.mGroupFlags;
15893        final boolean initialized = a.isInitialized();
15894        if (!initialized) {
15895            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
15896            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
15897            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
15898            onAnimationStart();
15899        }
15900
15901        final Transformation t = parent.getChildTransformation();
15902        boolean more = a.getTransformation(drawingTime, t, 1f);
15903        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
15904            if (parent.mInvalidationTransformation == null) {
15905                parent.mInvalidationTransformation = new Transformation();
15906            }
15907            invalidationTransform = parent.mInvalidationTransformation;
15908            a.getTransformation(drawingTime, invalidationTransform, 1f);
15909        } else {
15910            invalidationTransform = t;
15911        }
15912
15913        if (more) {
15914            if (!a.willChangeBounds()) {
15915                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
15916                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
15917                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
15918                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
15919                    // The child need to draw an animation, potentially offscreen, so
15920                    // make sure we do not cancel invalidate requests
15921                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15922                    parent.invalidate(mLeft, mTop, mRight, mBottom);
15923                }
15924            } else {
15925                if (parent.mInvalidateRegion == null) {
15926                    parent.mInvalidateRegion = new RectF();
15927                }
15928                final RectF region = parent.mInvalidateRegion;
15929                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
15930                        invalidationTransform);
15931
15932                // The child need to draw an animation, potentially offscreen, so
15933                // make sure we do not cancel invalidate requests
15934                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15935
15936                final int left = mLeft + (int) region.left;
15937                final int top = mTop + (int) region.top;
15938                parent.invalidate(left, top, left + (int) (region.width() + .5f),
15939                        top + (int) (region.height() + .5f));
15940            }
15941        }
15942        return more;
15943    }
15944
15945    /**
15946     * This method is called by getDisplayList() when a display list is recorded for a View.
15947     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
15948     */
15949    void setDisplayListProperties(RenderNode renderNode) {
15950        if (renderNode != null) {
15951            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
15952            renderNode.setClipToBounds(mParent instanceof ViewGroup
15953                    && ((ViewGroup) mParent).getClipChildren());
15954
15955            float alpha = 1;
15956            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
15957                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15958                ViewGroup parentVG = (ViewGroup) mParent;
15959                final Transformation t = parentVG.getChildTransformation();
15960                if (parentVG.getChildStaticTransformation(this, t)) {
15961                    final int transformType = t.getTransformationType();
15962                    if (transformType != Transformation.TYPE_IDENTITY) {
15963                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
15964                            alpha = t.getAlpha();
15965                        }
15966                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
15967                            renderNode.setStaticMatrix(t.getMatrix());
15968                        }
15969                    }
15970                }
15971            }
15972            if (mTransformationInfo != null) {
15973                alpha *= getFinalAlpha();
15974                if (alpha < 1) {
15975                    final int multipliedAlpha = (int) (255 * alpha);
15976                    if (onSetAlpha(multipliedAlpha)) {
15977                        alpha = 1;
15978                    }
15979                }
15980                renderNode.setAlpha(alpha);
15981            } else if (alpha < 1) {
15982                renderNode.setAlpha(alpha);
15983            }
15984        }
15985    }
15986
15987    /**
15988     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
15989     *
15990     * This is where the View specializes rendering behavior based on layer type,
15991     * and hardware acceleration.
15992     */
15993    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
15994        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
15995        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
15996         *
15997         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
15998         * HW accelerated, it can't handle drawing RenderNodes.
15999         */
16000        boolean drawingWithRenderNode = mAttachInfo != null
16001                && mAttachInfo.mHardwareAccelerated
16002                && hardwareAcceleratedCanvas;
16003
16004        boolean more = false;
16005        final boolean childHasIdentityMatrix = hasIdentityMatrix();
16006        final int parentFlags = parent.mGroupFlags;
16007
16008        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16009            parent.getChildTransformation().clear();
16010            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16011        }
16012
16013        Transformation transformToApply = null;
16014        boolean concatMatrix = false;
16015        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16016        final Animation a = getAnimation();
16017        if (a != null) {
16018            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16019            concatMatrix = a.willChangeTransformationMatrix();
16020            if (concatMatrix) {
16021                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16022            }
16023            transformToApply = parent.getChildTransformation();
16024        } else {
16025            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16026                // No longer animating: clear out old animation matrix
16027                mRenderNode.setAnimationMatrix(null);
16028                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16029            }
16030            if (!drawingWithRenderNode
16031                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16032                final Transformation t = parent.getChildTransformation();
16033                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16034                if (hasTransform) {
16035                    final int transformType = t.getTransformationType();
16036                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16037                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16038                }
16039            }
16040        }
16041
16042        concatMatrix |= !childHasIdentityMatrix;
16043
16044        // Sets the flag as early as possible to allow draw() implementations
16045        // to call invalidate() successfully when doing animations
16046        mPrivateFlags |= PFLAG_DRAWN;
16047
16048        if (!concatMatrix &&
16049                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16050                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16051                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16052                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16053            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16054            return more;
16055        }
16056        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16057
16058        if (hardwareAcceleratedCanvas) {
16059            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16060            // retain the flag's value temporarily in the mRecreateDisplayList flag
16061            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16062            mPrivateFlags &= ~PFLAG_INVALIDATED;
16063        }
16064
16065        RenderNode renderNode = null;
16066        Bitmap cache = null;
16067        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16068        if (layerType == LAYER_TYPE_SOFTWARE
16069                || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
16070            // If not drawing with RenderNode, treat HW layers as SW
16071            layerType = LAYER_TYPE_SOFTWARE;
16072            buildDrawingCache(true);
16073            cache = getDrawingCache(true);
16074        }
16075
16076        if (drawingWithRenderNode) {
16077            // Delay getting the display list until animation-driven alpha values are
16078            // set up and possibly passed on to the view
16079            renderNode = updateDisplayListIfDirty();
16080            if (!renderNode.isValid()) {
16081                // Uncommon, but possible. If a view is removed from the hierarchy during the call
16082                // to getDisplayList(), the display list will be marked invalid and we should not
16083                // try to use it again.
16084                renderNode = null;
16085                drawingWithRenderNode = false;
16086            }
16087        }
16088
16089        int sx = 0;
16090        int sy = 0;
16091        if (!drawingWithRenderNode) {
16092            computeScroll();
16093            sx = mScrollX;
16094            sy = mScrollY;
16095        }
16096
16097        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16098        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16099
16100        int restoreTo = -1;
16101        if (!drawingWithRenderNode || transformToApply != null) {
16102            restoreTo = canvas.save();
16103        }
16104        if (offsetForScroll) {
16105            canvas.translate(mLeft - sx, mTop - sy);
16106        } else {
16107            if (!drawingWithRenderNode) {
16108                canvas.translate(mLeft, mTop);
16109            }
16110            if (scalingRequired) {
16111                if (drawingWithRenderNode) {
16112                    // TODO: Might not need this if we put everything inside the DL
16113                    restoreTo = canvas.save();
16114                }
16115                // mAttachInfo cannot be null, otherwise scalingRequired == false
16116                final float scale = 1.0f / mAttachInfo.mApplicationScale;
16117                canvas.scale(scale, scale);
16118            }
16119        }
16120
16121        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16122        if (transformToApply != null
16123                || alpha < 1
16124                || !hasIdentityMatrix()
16125                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16126            if (transformToApply != null || !childHasIdentityMatrix) {
16127                int transX = 0;
16128                int transY = 0;
16129
16130                if (offsetForScroll) {
16131                    transX = -sx;
16132                    transY = -sy;
16133                }
16134
16135                if (transformToApply != null) {
16136                    if (concatMatrix) {
16137                        if (drawingWithRenderNode) {
16138                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
16139                        } else {
16140                            // Undo the scroll translation, apply the transformation matrix,
16141                            // then redo the scroll translate to get the correct result.
16142                            canvas.translate(-transX, -transY);
16143                            canvas.concat(transformToApply.getMatrix());
16144                            canvas.translate(transX, transY);
16145                        }
16146                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16147                    }
16148
16149                    float transformAlpha = transformToApply.getAlpha();
16150                    if (transformAlpha < 1) {
16151                        alpha *= transformAlpha;
16152                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16153                    }
16154                }
16155
16156                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
16157                    canvas.translate(-transX, -transY);
16158                    canvas.concat(getMatrix());
16159                    canvas.translate(transX, transY);
16160                }
16161            }
16162
16163            // Deal with alpha if it is or used to be <1
16164            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16165                if (alpha < 1) {
16166                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16167                } else {
16168                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16169                }
16170                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16171                if (!drawingWithDrawingCache) {
16172                    final int multipliedAlpha = (int) (255 * alpha);
16173                    if (!onSetAlpha(multipliedAlpha)) {
16174                        if (drawingWithRenderNode) {
16175                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
16176                        } else if (layerType == LAYER_TYPE_NONE) {
16177                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
16178                                    multipliedAlpha);
16179                        }
16180                    } else {
16181                        // Alpha is handled by the child directly, clobber the layer's alpha
16182                        mPrivateFlags |= PFLAG_ALPHA_SET;
16183                    }
16184                }
16185            }
16186        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16187            onSetAlpha(255);
16188            mPrivateFlags &= ~PFLAG_ALPHA_SET;
16189        }
16190
16191        if (!drawingWithRenderNode) {
16192            // apply clips directly, since RenderNode won't do it for this draw
16193            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
16194                if (offsetForScroll) {
16195                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
16196                } else {
16197                    if (!scalingRequired || cache == null) {
16198                        canvas.clipRect(0, 0, getWidth(), getHeight());
16199                    } else {
16200                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
16201                    }
16202                }
16203            }
16204
16205            if (mClipBounds != null) {
16206                // clip bounds ignore scroll
16207                canvas.clipRect(mClipBounds);
16208            }
16209        }
16210
16211        if (!drawingWithDrawingCache) {
16212            if (drawingWithRenderNode) {
16213                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16214                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16215            } else {
16216                // Fast path for layouts with no backgrounds
16217                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16218                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16219                    dispatchDraw(canvas);
16220                } else {
16221                    draw(canvas);
16222                }
16223            }
16224        } else if (cache != null) {
16225            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16226            if (layerType == LAYER_TYPE_NONE) {
16227                // no layer paint, use temporary paint to draw bitmap
16228                Paint cachePaint = parent.mCachePaint;
16229                if (cachePaint == null) {
16230                    cachePaint = new Paint();
16231                    cachePaint.setDither(false);
16232                    parent.mCachePaint = cachePaint;
16233                }
16234                cachePaint.setAlpha((int) (alpha * 255));
16235                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
16236            } else {
16237                // use layer paint to draw the bitmap, merging the two alphas, but also restore
16238                int layerPaintAlpha = mLayerPaint.getAlpha();
16239                mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
16240                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
16241                mLayerPaint.setAlpha(layerPaintAlpha);
16242            }
16243        }
16244
16245        if (restoreTo >= 0) {
16246            canvas.restoreToCount(restoreTo);
16247        }
16248
16249        if (a != null && !more) {
16250            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
16251                onSetAlpha(255);
16252            }
16253            parent.finishAnimatingView(this, a);
16254        }
16255
16256        if (more && hardwareAcceleratedCanvas) {
16257            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16258                // alpha animations should cause the child to recreate its display list
16259                invalidate(true);
16260            }
16261        }
16262
16263        mRecreateDisplayList = false;
16264
16265        return more;
16266    }
16267
16268    /**
16269     * Manually render this view (and all of its children) to the given Canvas.
16270     * The view must have already done a full layout before this function is
16271     * called.  When implementing a view, implement
16272     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
16273     * If you do need to override this method, call the superclass version.
16274     *
16275     * @param canvas The Canvas to which the View is rendered.
16276     */
16277    @CallSuper
16278    public void draw(Canvas canvas) {
16279        final int privateFlags = mPrivateFlags;
16280        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
16281                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
16282        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
16283
16284        /*
16285         * Draw traversal performs several drawing steps which must be executed
16286         * in the appropriate order:
16287         *
16288         *      1. Draw the background
16289         *      2. If necessary, save the canvas' layers to prepare for fading
16290         *      3. Draw view's content
16291         *      4. Draw children
16292         *      5. If necessary, draw the fading edges and restore layers
16293         *      6. Draw decorations (scrollbars for instance)
16294         */
16295
16296        // Step 1, draw the background, if needed
16297        int saveCount;
16298
16299        if (!dirtyOpaque) {
16300            drawBackground(canvas);
16301        }
16302
16303        // skip step 2 & 5 if possible (common case)
16304        final int viewFlags = mViewFlags;
16305        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
16306        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
16307        if (!verticalEdges && !horizontalEdges) {
16308            // Step 3, draw the content
16309            if (!dirtyOpaque) onDraw(canvas);
16310
16311            // Step 4, draw the children
16312            dispatchDraw(canvas);
16313
16314            // Overlay is part of the content and draws beneath Foreground
16315            if (mOverlay != null && !mOverlay.isEmpty()) {
16316                mOverlay.getOverlayView().dispatchDraw(canvas);
16317            }
16318
16319            // Step 6, draw decorations (foreground, scrollbars)
16320            onDrawForeground(canvas);
16321
16322            // we're done...
16323            return;
16324        }
16325
16326        /*
16327         * Here we do the full fledged routine...
16328         * (this is an uncommon case where speed matters less,
16329         * this is why we repeat some of the tests that have been
16330         * done above)
16331         */
16332
16333        boolean drawTop = false;
16334        boolean drawBottom = false;
16335        boolean drawLeft = false;
16336        boolean drawRight = false;
16337
16338        float topFadeStrength = 0.0f;
16339        float bottomFadeStrength = 0.0f;
16340        float leftFadeStrength = 0.0f;
16341        float rightFadeStrength = 0.0f;
16342
16343        // Step 2, save the canvas' layers
16344        int paddingLeft = mPaddingLeft;
16345
16346        final boolean offsetRequired = isPaddingOffsetRequired();
16347        if (offsetRequired) {
16348            paddingLeft += getLeftPaddingOffset();
16349        }
16350
16351        int left = mScrollX + paddingLeft;
16352        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
16353        int top = mScrollY + getFadeTop(offsetRequired);
16354        int bottom = top + getFadeHeight(offsetRequired);
16355
16356        if (offsetRequired) {
16357            right += getRightPaddingOffset();
16358            bottom += getBottomPaddingOffset();
16359        }
16360
16361        final ScrollabilityCache scrollabilityCache = mScrollCache;
16362        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
16363        int length = (int) fadeHeight;
16364
16365        // clip the fade length if top and bottom fades overlap
16366        // overlapping fades produce odd-looking artifacts
16367        if (verticalEdges && (top + length > bottom - length)) {
16368            length = (bottom - top) / 2;
16369        }
16370
16371        // also clip horizontal fades if necessary
16372        if (horizontalEdges && (left + length > right - length)) {
16373            length = (right - left) / 2;
16374        }
16375
16376        if (verticalEdges) {
16377            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
16378            drawTop = topFadeStrength * fadeHeight > 1.0f;
16379            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
16380            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
16381        }
16382
16383        if (horizontalEdges) {
16384            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
16385            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
16386            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
16387            drawRight = rightFadeStrength * fadeHeight > 1.0f;
16388        }
16389
16390        saveCount = canvas.getSaveCount();
16391
16392        int solidColor = getSolidColor();
16393        if (solidColor == 0) {
16394            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
16395
16396            if (drawTop) {
16397                canvas.saveLayer(left, top, right, top + length, null, flags);
16398            }
16399
16400            if (drawBottom) {
16401                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
16402            }
16403
16404            if (drawLeft) {
16405                canvas.saveLayer(left, top, left + length, bottom, null, flags);
16406            }
16407
16408            if (drawRight) {
16409                canvas.saveLayer(right - length, top, right, bottom, null, flags);
16410            }
16411        } else {
16412            scrollabilityCache.setFadeColor(solidColor);
16413        }
16414
16415        // Step 3, draw the content
16416        if (!dirtyOpaque) onDraw(canvas);
16417
16418        // Step 4, draw the children
16419        dispatchDraw(canvas);
16420
16421        // Step 5, draw the fade effect and restore layers
16422        final Paint p = scrollabilityCache.paint;
16423        final Matrix matrix = scrollabilityCache.matrix;
16424        final Shader fade = scrollabilityCache.shader;
16425
16426        if (drawTop) {
16427            matrix.setScale(1, fadeHeight * topFadeStrength);
16428            matrix.postTranslate(left, top);
16429            fade.setLocalMatrix(matrix);
16430            p.setShader(fade);
16431            canvas.drawRect(left, top, right, top + length, p);
16432        }
16433
16434        if (drawBottom) {
16435            matrix.setScale(1, fadeHeight * bottomFadeStrength);
16436            matrix.postRotate(180);
16437            matrix.postTranslate(left, bottom);
16438            fade.setLocalMatrix(matrix);
16439            p.setShader(fade);
16440            canvas.drawRect(left, bottom - length, right, bottom, p);
16441        }
16442
16443        if (drawLeft) {
16444            matrix.setScale(1, fadeHeight * leftFadeStrength);
16445            matrix.postRotate(-90);
16446            matrix.postTranslate(left, top);
16447            fade.setLocalMatrix(matrix);
16448            p.setShader(fade);
16449            canvas.drawRect(left, top, left + length, bottom, p);
16450        }
16451
16452        if (drawRight) {
16453            matrix.setScale(1, fadeHeight * rightFadeStrength);
16454            matrix.postRotate(90);
16455            matrix.postTranslate(right, top);
16456            fade.setLocalMatrix(matrix);
16457            p.setShader(fade);
16458            canvas.drawRect(right - length, top, right, bottom, p);
16459        }
16460
16461        canvas.restoreToCount(saveCount);
16462
16463        // Overlay is part of the content and draws beneath Foreground
16464        if (mOverlay != null && !mOverlay.isEmpty()) {
16465            mOverlay.getOverlayView().dispatchDraw(canvas);
16466        }
16467
16468        // Step 6, draw decorations (foreground, scrollbars)
16469        onDrawForeground(canvas);
16470    }
16471
16472    /**
16473     * Draws the background onto the specified canvas.
16474     *
16475     * @param canvas Canvas on which to draw the background
16476     */
16477    private void drawBackground(Canvas canvas) {
16478        final Drawable background = mBackground;
16479        if (background == null) {
16480            return;
16481        }
16482
16483        setBackgroundBounds();
16484
16485        // Attempt to use a display list if requested.
16486        if (canvas.isHardwareAccelerated() && mAttachInfo != null
16487                && mAttachInfo.mHardwareRenderer != null) {
16488            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
16489
16490            final RenderNode renderNode = mBackgroundRenderNode;
16491            if (renderNode != null && renderNode.isValid()) {
16492                setBackgroundRenderNodeProperties(renderNode);
16493                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16494                return;
16495            }
16496        }
16497
16498        final int scrollX = mScrollX;
16499        final int scrollY = mScrollY;
16500        if ((scrollX | scrollY) == 0) {
16501            background.draw(canvas);
16502        } else {
16503            canvas.translate(scrollX, scrollY);
16504            background.draw(canvas);
16505            canvas.translate(-scrollX, -scrollY);
16506        }
16507    }
16508
16509    /**
16510     * Sets the correct background bounds and rebuilds the outline, if needed.
16511     * <p/>
16512     * This is called by LayoutLib.
16513     */
16514    void setBackgroundBounds() {
16515        if (mBackgroundSizeChanged && mBackground != null) {
16516            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
16517            mBackgroundSizeChanged = false;
16518            rebuildOutline();
16519        }
16520    }
16521
16522    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
16523        renderNode.setTranslationX(mScrollX);
16524        renderNode.setTranslationY(mScrollY);
16525    }
16526
16527    /**
16528     * Creates a new display list or updates the existing display list for the
16529     * specified Drawable.
16530     *
16531     * @param drawable Drawable for which to create a display list
16532     * @param renderNode Existing RenderNode, or {@code null}
16533     * @return A valid display list for the specified drawable
16534     */
16535    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
16536        if (renderNode == null) {
16537            renderNode = RenderNode.create(drawable.getClass().getName(), this);
16538        }
16539
16540        final Rect bounds = drawable.getBounds();
16541        final int width = bounds.width();
16542        final int height = bounds.height();
16543        final DisplayListCanvas canvas = renderNode.start(width, height);
16544
16545        // Reverse left/top translation done by drawable canvas, which will
16546        // instead be applied by rendernode's LTRB bounds below. This way, the
16547        // drawable's bounds match with its rendernode bounds and its content
16548        // will lie within those bounds in the rendernode tree.
16549        canvas.translate(-bounds.left, -bounds.top);
16550
16551        try {
16552            drawable.draw(canvas);
16553        } finally {
16554            renderNode.end(canvas);
16555        }
16556
16557        // Set up drawable properties that are view-independent.
16558        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
16559        renderNode.setProjectBackwards(drawable.isProjected());
16560        renderNode.setProjectionReceiver(true);
16561        renderNode.setClipToBounds(false);
16562        return renderNode;
16563    }
16564
16565    /**
16566     * Returns the overlay for this view, creating it if it does not yet exist.
16567     * Adding drawables to the overlay will cause them to be displayed whenever
16568     * the view itself is redrawn. Objects in the overlay should be actively
16569     * managed: remove them when they should not be displayed anymore. The
16570     * overlay will always have the same size as its host view.
16571     *
16572     * <p>Note: Overlays do not currently work correctly with {@link
16573     * SurfaceView} or {@link TextureView}; contents in overlays for these
16574     * types of views may not display correctly.</p>
16575     *
16576     * @return The ViewOverlay object for this view.
16577     * @see ViewOverlay
16578     */
16579    public ViewOverlay getOverlay() {
16580        if (mOverlay == null) {
16581            mOverlay = new ViewOverlay(mContext, this);
16582        }
16583        return mOverlay;
16584    }
16585
16586    /**
16587     * Override this if your view is known to always be drawn on top of a solid color background,
16588     * and needs to draw fading edges. Returning a non-zero color enables the view system to
16589     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
16590     * should be set to 0xFF.
16591     *
16592     * @see #setVerticalFadingEdgeEnabled(boolean)
16593     * @see #setHorizontalFadingEdgeEnabled(boolean)
16594     *
16595     * @return The known solid color background for this view, or 0 if the color may vary
16596     */
16597    @ViewDebug.ExportedProperty(category = "drawing")
16598    @ColorInt
16599    public int getSolidColor() {
16600        return 0;
16601    }
16602
16603    /**
16604     * Build a human readable string representation of the specified view flags.
16605     *
16606     * @param flags the view flags to convert to a string
16607     * @return a String representing the supplied flags
16608     */
16609    private static String printFlags(int flags) {
16610        String output = "";
16611        int numFlags = 0;
16612        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
16613            output += "TAKES_FOCUS";
16614            numFlags++;
16615        }
16616
16617        switch (flags & VISIBILITY_MASK) {
16618        case INVISIBLE:
16619            if (numFlags > 0) {
16620                output += " ";
16621            }
16622            output += "INVISIBLE";
16623            // USELESS HERE numFlags++;
16624            break;
16625        case GONE:
16626            if (numFlags > 0) {
16627                output += " ";
16628            }
16629            output += "GONE";
16630            // USELESS HERE numFlags++;
16631            break;
16632        default:
16633            break;
16634        }
16635        return output;
16636    }
16637
16638    /**
16639     * Build a human readable string representation of the specified private
16640     * view flags.
16641     *
16642     * @param privateFlags the private view flags to convert to a string
16643     * @return a String representing the supplied flags
16644     */
16645    private static String printPrivateFlags(int privateFlags) {
16646        String output = "";
16647        int numFlags = 0;
16648
16649        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
16650            output += "WANTS_FOCUS";
16651            numFlags++;
16652        }
16653
16654        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
16655            if (numFlags > 0) {
16656                output += " ";
16657            }
16658            output += "FOCUSED";
16659            numFlags++;
16660        }
16661
16662        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
16663            if (numFlags > 0) {
16664                output += " ";
16665            }
16666            output += "SELECTED";
16667            numFlags++;
16668        }
16669
16670        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
16671            if (numFlags > 0) {
16672                output += " ";
16673            }
16674            output += "IS_ROOT_NAMESPACE";
16675            numFlags++;
16676        }
16677
16678        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
16679            if (numFlags > 0) {
16680                output += " ";
16681            }
16682            output += "HAS_BOUNDS";
16683            numFlags++;
16684        }
16685
16686        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
16687            if (numFlags > 0) {
16688                output += " ";
16689            }
16690            output += "DRAWN";
16691            // USELESS HERE numFlags++;
16692        }
16693        return output;
16694    }
16695
16696    /**
16697     * <p>Indicates whether or not this view's layout will be requested during
16698     * the next hierarchy layout pass.</p>
16699     *
16700     * @return true if the layout will be forced during next layout pass
16701     */
16702    public boolean isLayoutRequested() {
16703        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16704    }
16705
16706    /**
16707     * Return true if o is a ViewGroup that is laying out using optical bounds.
16708     * @hide
16709     */
16710    public static boolean isLayoutModeOptical(Object o) {
16711        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16712    }
16713
16714    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16715        Insets parentInsets = mParent instanceof View ?
16716                ((View) mParent).getOpticalInsets() : Insets.NONE;
16717        Insets childInsets = getOpticalInsets();
16718        return setFrame(
16719                left   + parentInsets.left - childInsets.left,
16720                top    + parentInsets.top  - childInsets.top,
16721                right  + parentInsets.left + childInsets.right,
16722                bottom + parentInsets.top  + childInsets.bottom);
16723    }
16724
16725    /**
16726     * Assign a size and position to a view and all of its
16727     * descendants
16728     *
16729     * <p>This is the second phase of the layout mechanism.
16730     * (The first is measuring). In this phase, each parent calls
16731     * layout on all of its children to position them.
16732     * This is typically done using the child measurements
16733     * that were stored in the measure pass().</p>
16734     *
16735     * <p>Derived classes should not override this method.
16736     * Derived classes with children should override
16737     * onLayout. In that method, they should
16738     * call layout on each of their children.</p>
16739     *
16740     * @param l Left position, relative to parent
16741     * @param t Top position, relative to parent
16742     * @param r Right position, relative to parent
16743     * @param b Bottom position, relative to parent
16744     */
16745    @SuppressWarnings({"unchecked"})
16746    public void layout(int l, int t, int r, int b) {
16747        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16748            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16749            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16750        }
16751
16752        int oldL = mLeft;
16753        int oldT = mTop;
16754        int oldB = mBottom;
16755        int oldR = mRight;
16756
16757        boolean changed = isLayoutModeOptical(mParent) ?
16758                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16759
16760        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
16761            onLayout(changed, l, t, r, b);
16762            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
16763
16764            ListenerInfo li = mListenerInfo;
16765            if (li != null && li.mOnLayoutChangeListeners != null) {
16766                ArrayList<OnLayoutChangeListener> listenersCopy =
16767                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
16768                int numListeners = listenersCopy.size();
16769                for (int i = 0; i < numListeners; ++i) {
16770                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
16771                }
16772            }
16773        }
16774
16775        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
16776        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
16777    }
16778
16779    /**
16780     * Called from layout when this view should
16781     * assign a size and position to each of its children.
16782     *
16783     * Derived classes with children should override
16784     * this method and call layout on each of
16785     * their children.
16786     * @param changed This is a new size or position for this view
16787     * @param left Left position, relative to parent
16788     * @param top Top position, relative to parent
16789     * @param right Right position, relative to parent
16790     * @param bottom Bottom position, relative to parent
16791     */
16792    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
16793    }
16794
16795    /**
16796     * Assign a size and position to this view.
16797     *
16798     * This is called from layout.
16799     *
16800     * @param left Left position, relative to parent
16801     * @param top Top position, relative to parent
16802     * @param right Right position, relative to parent
16803     * @param bottom Bottom position, relative to parent
16804     * @return true if the new size and position are different than the
16805     *         previous ones
16806     * {@hide}
16807     */
16808    protected boolean setFrame(int left, int top, int right, int bottom) {
16809        boolean changed = false;
16810
16811        if (DBG) {
16812            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16813                    + right + "," + bottom + ")");
16814        }
16815
16816        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16817            changed = true;
16818
16819            // Remember our drawn bit
16820            int drawn = mPrivateFlags & PFLAG_DRAWN;
16821
16822            int oldWidth = mRight - mLeft;
16823            int oldHeight = mBottom - mTop;
16824            int newWidth = right - left;
16825            int newHeight = bottom - top;
16826            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16827
16828            // Invalidate our old position
16829            invalidate(sizeChanged);
16830
16831            mLeft = left;
16832            mTop = top;
16833            mRight = right;
16834            mBottom = bottom;
16835            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16836
16837            mPrivateFlags |= PFLAG_HAS_BOUNDS;
16838
16839
16840            if (sizeChanged) {
16841                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16842            }
16843
16844            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16845                // If we are visible, force the DRAWN bit to on so that
16846                // this invalidate will go through (at least to our parent).
16847                // This is because someone may have invalidated this view
16848                // before this call to setFrame came in, thereby clearing
16849                // the DRAWN bit.
16850                mPrivateFlags |= PFLAG_DRAWN;
16851                invalidate(sizeChanged);
16852                // parent display list may need to be recreated based on a change in the bounds
16853                // of any child
16854                invalidateParentCaches();
16855            }
16856
16857            // Reset drawn bit to original value (invalidate turns it off)
16858            mPrivateFlags |= drawn;
16859
16860            mBackgroundSizeChanged = true;
16861            if (mForegroundInfo != null) {
16862                mForegroundInfo.mBoundsChanged = true;
16863            }
16864
16865            notifySubtreeAccessibilityStateChangedIfNeeded();
16866        }
16867        return changed;
16868    }
16869
16870    /**
16871     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
16872     * @hide
16873     */
16874    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
16875        setFrame(left, top, right, bottom);
16876    }
16877
16878    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
16879        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
16880        if (mOverlay != null) {
16881            mOverlay.getOverlayView().setRight(newWidth);
16882            mOverlay.getOverlayView().setBottom(newHeight);
16883        }
16884        rebuildOutline();
16885    }
16886
16887    /**
16888     * Finalize inflating a view from XML.  This is called as the last phase
16889     * of inflation, after all child views have been added.
16890     *
16891     * <p>Even if the subclass overrides onFinishInflate, they should always be
16892     * sure to call the super method, so that we get called.
16893     */
16894    @CallSuper
16895    protected void onFinishInflate() {
16896    }
16897
16898    /**
16899     * Returns the resources associated with this view.
16900     *
16901     * @return Resources object.
16902     */
16903    public Resources getResources() {
16904        return mResources;
16905    }
16906
16907    /**
16908     * Invalidates the specified Drawable.
16909     *
16910     * @param drawable the drawable to invalidate
16911     */
16912    @Override
16913    public void invalidateDrawable(@NonNull Drawable drawable) {
16914        if (verifyDrawable(drawable)) {
16915            final Rect dirty = drawable.getDirtyBounds();
16916            final int scrollX = mScrollX;
16917            final int scrollY = mScrollY;
16918
16919            invalidate(dirty.left + scrollX, dirty.top + scrollY,
16920                    dirty.right + scrollX, dirty.bottom + scrollY);
16921            rebuildOutline();
16922        }
16923    }
16924
16925    /**
16926     * Schedules an action on a drawable to occur at a specified time.
16927     *
16928     * @param who the recipient of the action
16929     * @param what the action to run on the drawable
16930     * @param when the time at which the action must occur. Uses the
16931     *        {@link SystemClock#uptimeMillis} timebase.
16932     */
16933    @Override
16934    public void scheduleDrawable(Drawable who, Runnable what, long when) {
16935        if (verifyDrawable(who) && what != null) {
16936            final long delay = when - SystemClock.uptimeMillis();
16937            if (mAttachInfo != null) {
16938                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
16939                        Choreographer.CALLBACK_ANIMATION, what, who,
16940                        Choreographer.subtractFrameDelay(delay));
16941            } else {
16942                // Postpone the runnable until we know
16943                // on which thread it needs to run.
16944                getRunQueue().postDelayed(what, delay);
16945            }
16946        }
16947    }
16948
16949    /**
16950     * Cancels a scheduled action on a drawable.
16951     *
16952     * @param who the recipient of the action
16953     * @param what the action to cancel
16954     */
16955    @Override
16956    public void unscheduleDrawable(Drawable who, Runnable what) {
16957        if (verifyDrawable(who) && what != null) {
16958            if (mAttachInfo != null) {
16959                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16960                        Choreographer.CALLBACK_ANIMATION, what, who);
16961            }
16962            getRunQueue().removeCallbacks(what);
16963        }
16964    }
16965
16966    /**
16967     * Unschedule any events associated with the given Drawable.  This can be
16968     * used when selecting a new Drawable into a view, so that the previous
16969     * one is completely unscheduled.
16970     *
16971     * @param who The Drawable to unschedule.
16972     *
16973     * @see #drawableStateChanged
16974     */
16975    public void unscheduleDrawable(Drawable who) {
16976        if (mAttachInfo != null && who != null) {
16977            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16978                    Choreographer.CALLBACK_ANIMATION, null, who);
16979        }
16980    }
16981
16982    /**
16983     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
16984     * that the View directionality can and will be resolved before its Drawables.
16985     *
16986     * Will call {@link View#onResolveDrawables} when resolution is done.
16987     *
16988     * @hide
16989     */
16990    protected void resolveDrawables() {
16991        // Drawables resolution may need to happen before resolving the layout direction (which is
16992        // done only during the measure() call).
16993        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
16994        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
16995        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
16996        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
16997        // direction to be resolved as its resolved value will be the same as its raw value.
16998        if (!isLayoutDirectionResolved() &&
16999                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17000            return;
17001        }
17002
17003        final int layoutDirection = isLayoutDirectionResolved() ?
17004                getLayoutDirection() : getRawLayoutDirection();
17005
17006        if (mBackground != null) {
17007            mBackground.setLayoutDirection(layoutDirection);
17008        }
17009        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17010            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17011        }
17012        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17013        onResolveDrawables(layoutDirection);
17014    }
17015
17016    boolean areDrawablesResolved() {
17017        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17018    }
17019
17020    /**
17021     * Called when layout direction has been resolved.
17022     *
17023     * The default implementation does nothing.
17024     *
17025     * @param layoutDirection The resolved layout direction.
17026     *
17027     * @see #LAYOUT_DIRECTION_LTR
17028     * @see #LAYOUT_DIRECTION_RTL
17029     *
17030     * @hide
17031     */
17032    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17033    }
17034
17035    /**
17036     * @hide
17037     */
17038    protected void resetResolvedDrawables() {
17039        resetResolvedDrawablesInternal();
17040    }
17041
17042    void resetResolvedDrawablesInternal() {
17043        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17044    }
17045
17046    /**
17047     * If your view subclass is displaying its own Drawable objects, it should
17048     * override this function and return true for any Drawable it is
17049     * displaying.  This allows animations for those drawables to be
17050     * scheduled.
17051     *
17052     * <p>Be sure to call through to the super class when overriding this
17053     * function.
17054     *
17055     * @param who The Drawable to verify.  Return true if it is one you are
17056     *            displaying, else return the result of calling through to the
17057     *            super class.
17058     *
17059     * @return boolean If true than the Drawable is being displayed in the
17060     *         view; else false and it is not allowed to animate.
17061     *
17062     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17063     * @see #drawableStateChanged()
17064     */
17065    @CallSuper
17066    protected boolean verifyDrawable(Drawable who) {
17067        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
17068                || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17069    }
17070
17071    /**
17072     * This function is called whenever the state of the view changes in such
17073     * a way that it impacts the state of drawables being shown.
17074     * <p>
17075     * If the View has a StateListAnimator, it will also be called to run necessary state
17076     * change animations.
17077     * <p>
17078     * Be sure to call through to the superclass when overriding this function.
17079     *
17080     * @see Drawable#setState(int[])
17081     */
17082    @CallSuper
17083    protected void drawableStateChanged() {
17084        final int[] state = getDrawableState();
17085        boolean changed = false;
17086
17087        final Drawable bg = mBackground;
17088        if (bg != null && bg.isStateful()) {
17089            changed |= bg.setState(state);
17090        }
17091
17092        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17093        if (fg != null && fg.isStateful()) {
17094            changed |= fg.setState(state);
17095        }
17096
17097        if (mScrollCache != null) {
17098            final Drawable scrollBar = mScrollCache.scrollBar;
17099            if (scrollBar != null && scrollBar.isStateful()) {
17100                changed |= scrollBar.setState(state)
17101                        && mScrollCache.state != ScrollabilityCache.OFF;
17102            }
17103        }
17104
17105        if (mStateListAnimator != null) {
17106            mStateListAnimator.setState(state);
17107        }
17108
17109        if (changed) {
17110            invalidate();
17111        }
17112    }
17113
17114    /**
17115     * This function is called whenever the view hotspot changes and needs to
17116     * be propagated to drawables or child views managed by the view.
17117     * <p>
17118     * Dispatching to child views is handled by
17119     * {@link #dispatchDrawableHotspotChanged(float, float)}.
17120     * <p>
17121     * Be sure to call through to the superclass when overriding this function.
17122     *
17123     * @param x hotspot x coordinate
17124     * @param y hotspot y coordinate
17125     */
17126    @CallSuper
17127    public void drawableHotspotChanged(float x, float y) {
17128        if (mBackground != null) {
17129            mBackground.setHotspot(x, y);
17130        }
17131        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17132            mForegroundInfo.mDrawable.setHotspot(x, y);
17133        }
17134
17135        dispatchDrawableHotspotChanged(x, y);
17136    }
17137
17138    /**
17139     * Dispatches drawableHotspotChanged to all of this View's children.
17140     *
17141     * @param x hotspot x coordinate
17142     * @param y hotspot y coordinate
17143     * @see #drawableHotspotChanged(float, float)
17144     */
17145    public void dispatchDrawableHotspotChanged(float x, float y) {
17146    }
17147
17148    /**
17149     * Call this to force a view to update its drawable state. This will cause
17150     * drawableStateChanged to be called on this view. Views that are interested
17151     * in the new state should call getDrawableState.
17152     *
17153     * @see #drawableStateChanged
17154     * @see #getDrawableState
17155     */
17156    public void refreshDrawableState() {
17157        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17158        drawableStateChanged();
17159
17160        ViewParent parent = mParent;
17161        if (parent != null) {
17162            parent.childDrawableStateChanged(this);
17163        }
17164    }
17165
17166    /**
17167     * Return an array of resource IDs of the drawable states representing the
17168     * current state of the view.
17169     *
17170     * @return The current drawable state
17171     *
17172     * @see Drawable#setState(int[])
17173     * @see #drawableStateChanged()
17174     * @see #onCreateDrawableState(int)
17175     */
17176    public final int[] getDrawableState() {
17177        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
17178            return mDrawableState;
17179        } else {
17180            mDrawableState = onCreateDrawableState(0);
17181            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
17182            return mDrawableState;
17183        }
17184    }
17185
17186    /**
17187     * Generate the new {@link android.graphics.drawable.Drawable} state for
17188     * this view. This is called by the view
17189     * system when the cached Drawable state is determined to be invalid.  To
17190     * retrieve the current state, you should use {@link #getDrawableState}.
17191     *
17192     * @param extraSpace if non-zero, this is the number of extra entries you
17193     * would like in the returned array in which you can place your own
17194     * states.
17195     *
17196     * @return Returns an array holding the current {@link Drawable} state of
17197     * the view.
17198     *
17199     * @see #mergeDrawableStates(int[], int[])
17200     */
17201    protected int[] onCreateDrawableState(int extraSpace) {
17202        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
17203                mParent instanceof View) {
17204            return ((View) mParent).onCreateDrawableState(extraSpace);
17205        }
17206
17207        int[] drawableState;
17208
17209        int privateFlags = mPrivateFlags;
17210
17211        int viewStateIndex = 0;
17212        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
17213        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
17214        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
17215        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
17216        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
17217        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
17218        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
17219                HardwareRenderer.isAvailable()) {
17220            // This is set if HW acceleration is requested, even if the current
17221            // process doesn't allow it.  This is just to allow app preview
17222            // windows to better match their app.
17223            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
17224        }
17225        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
17226
17227        final int privateFlags2 = mPrivateFlags2;
17228        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
17229            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
17230        }
17231        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
17232            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
17233        }
17234
17235        drawableState = StateSet.get(viewStateIndex);
17236
17237        //noinspection ConstantIfStatement
17238        if (false) {
17239            Log.i("View", "drawableStateIndex=" + viewStateIndex);
17240            Log.i("View", toString()
17241                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
17242                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
17243                    + " fo=" + hasFocus()
17244                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
17245                    + " wf=" + hasWindowFocus()
17246                    + ": " + Arrays.toString(drawableState));
17247        }
17248
17249        if (extraSpace == 0) {
17250            return drawableState;
17251        }
17252
17253        final int[] fullState;
17254        if (drawableState != null) {
17255            fullState = new int[drawableState.length + extraSpace];
17256            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
17257        } else {
17258            fullState = new int[extraSpace];
17259        }
17260
17261        return fullState;
17262    }
17263
17264    /**
17265     * Merge your own state values in <var>additionalState</var> into the base
17266     * state values <var>baseState</var> that were returned by
17267     * {@link #onCreateDrawableState(int)}.
17268     *
17269     * @param baseState The base state values returned by
17270     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
17271     * own additional state values.
17272     *
17273     * @param additionalState The additional state values you would like
17274     * added to <var>baseState</var>; this array is not modified.
17275     *
17276     * @return As a convenience, the <var>baseState</var> array you originally
17277     * passed into the function is returned.
17278     *
17279     * @see #onCreateDrawableState(int)
17280     */
17281    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
17282        final int N = baseState.length;
17283        int i = N - 1;
17284        while (i >= 0 && baseState[i] == 0) {
17285            i--;
17286        }
17287        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
17288        return baseState;
17289    }
17290
17291    /**
17292     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
17293     * on all Drawable objects associated with this view.
17294     * <p>
17295     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
17296     * attached to this view.
17297     */
17298    @CallSuper
17299    public void jumpDrawablesToCurrentState() {
17300        if (mBackground != null) {
17301            mBackground.jumpToCurrentState();
17302        }
17303        if (mStateListAnimator != null) {
17304            mStateListAnimator.jumpToCurrentState();
17305        }
17306        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17307            mForegroundInfo.mDrawable.jumpToCurrentState();
17308        }
17309    }
17310
17311    /**
17312     * Sets the background color for this view.
17313     * @param color the color of the background
17314     */
17315    @RemotableViewMethod
17316    public void setBackgroundColor(@ColorInt int color) {
17317        if (mBackground instanceof ColorDrawable) {
17318            ((ColorDrawable) mBackground.mutate()).setColor(color);
17319            computeOpaqueFlags();
17320            mBackgroundResource = 0;
17321        } else {
17322            setBackground(new ColorDrawable(color));
17323        }
17324    }
17325
17326    /**
17327     * Set the background to a given resource. The resource should refer to
17328     * a Drawable object or 0 to remove the background.
17329     * @param resid The identifier of the resource.
17330     *
17331     * @attr ref android.R.styleable#View_background
17332     */
17333    @RemotableViewMethod
17334    public void setBackgroundResource(@DrawableRes int resid) {
17335        if (resid != 0 && resid == mBackgroundResource) {
17336            return;
17337        }
17338
17339        Drawable d = null;
17340        if (resid != 0) {
17341            d = mContext.getDrawable(resid);
17342        }
17343        setBackground(d);
17344
17345        mBackgroundResource = resid;
17346    }
17347
17348    /**
17349     * Set the background to a given Drawable, or remove the background. If the
17350     * background has padding, this View's padding is set to the background's
17351     * padding. However, when a background is removed, this View's padding isn't
17352     * touched. If setting the padding is desired, please use
17353     * {@link #setPadding(int, int, int, int)}.
17354     *
17355     * @param background The Drawable to use as the background, or null to remove the
17356     *        background
17357     */
17358    public void setBackground(Drawable background) {
17359        //noinspection deprecation
17360        setBackgroundDrawable(background);
17361    }
17362
17363    /**
17364     * @deprecated use {@link #setBackground(Drawable)} instead
17365     */
17366    @Deprecated
17367    public void setBackgroundDrawable(Drawable background) {
17368        computeOpaqueFlags();
17369
17370        if (background == mBackground) {
17371            return;
17372        }
17373
17374        boolean requestLayout = false;
17375
17376        mBackgroundResource = 0;
17377
17378        /*
17379         * Regardless of whether we're setting a new background or not, we want
17380         * to clear the previous drawable.
17381         */
17382        if (mBackground != null) {
17383            mBackground.setCallback(null);
17384            unscheduleDrawable(mBackground);
17385        }
17386
17387        if (background != null) {
17388            Rect padding = sThreadLocal.get();
17389            if (padding == null) {
17390                padding = new Rect();
17391                sThreadLocal.set(padding);
17392            }
17393            resetResolvedDrawablesInternal();
17394            background.setLayoutDirection(getLayoutDirection());
17395            if (background.getPadding(padding)) {
17396                resetResolvedPaddingInternal();
17397                switch (background.getLayoutDirection()) {
17398                    case LAYOUT_DIRECTION_RTL:
17399                        mUserPaddingLeftInitial = padding.right;
17400                        mUserPaddingRightInitial = padding.left;
17401                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
17402                        break;
17403                    case LAYOUT_DIRECTION_LTR:
17404                    default:
17405                        mUserPaddingLeftInitial = padding.left;
17406                        mUserPaddingRightInitial = padding.right;
17407                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
17408                }
17409                mLeftPaddingDefined = false;
17410                mRightPaddingDefined = false;
17411            }
17412
17413            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
17414            // if it has a different minimum size, we should layout again
17415            if (mBackground == null
17416                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
17417                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
17418                requestLayout = true;
17419            }
17420
17421            background.setCallback(this);
17422            if (background.isStateful()) {
17423                background.setState(getDrawableState());
17424            }
17425            background.setVisible(getVisibility() == VISIBLE, false);
17426            mBackground = background;
17427
17428            applyBackgroundTint();
17429
17430            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17431                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17432                requestLayout = true;
17433            }
17434        } else {
17435            /* Remove the background */
17436            mBackground = null;
17437            if ((mViewFlags & WILL_NOT_DRAW) != 0
17438                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
17439                mPrivateFlags |= PFLAG_SKIP_DRAW;
17440            }
17441
17442            /*
17443             * When the background is set, we try to apply its padding to this
17444             * View. When the background is removed, we don't touch this View's
17445             * padding. This is noted in the Javadocs. Hence, we don't need to
17446             * requestLayout(), the invalidate() below is sufficient.
17447             */
17448
17449            // The old background's minimum size could have affected this
17450            // View's layout, so let's requestLayout
17451            requestLayout = true;
17452        }
17453
17454        computeOpaqueFlags();
17455
17456        if (requestLayout) {
17457            requestLayout();
17458        }
17459
17460        mBackgroundSizeChanged = true;
17461        invalidate(true);
17462    }
17463
17464    /**
17465     * Gets the background drawable
17466     *
17467     * @return The drawable used as the background for this view, if any.
17468     *
17469     * @see #setBackground(Drawable)
17470     *
17471     * @attr ref android.R.styleable#View_background
17472     */
17473    public Drawable getBackground() {
17474        return mBackground;
17475    }
17476
17477    /**
17478     * Applies a tint to the background drawable. Does not modify the current tint
17479     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17480     * <p>
17481     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
17482     * mutate the drawable and apply the specified tint and tint mode using
17483     * {@link Drawable#setTintList(ColorStateList)}.
17484     *
17485     * @param tint the tint to apply, may be {@code null} to clear tint
17486     *
17487     * @attr ref android.R.styleable#View_backgroundTint
17488     * @see #getBackgroundTintList()
17489     * @see Drawable#setTintList(ColorStateList)
17490     */
17491    public void setBackgroundTintList(@Nullable ColorStateList tint) {
17492        if (mBackgroundTint == null) {
17493            mBackgroundTint = new TintInfo();
17494        }
17495        mBackgroundTint.mTintList = tint;
17496        mBackgroundTint.mHasTintList = true;
17497
17498        applyBackgroundTint();
17499    }
17500
17501    /**
17502     * Return the tint applied to the background drawable, if specified.
17503     *
17504     * @return the tint applied to the background drawable
17505     * @attr ref android.R.styleable#View_backgroundTint
17506     * @see #setBackgroundTintList(ColorStateList)
17507     */
17508    @Nullable
17509    public ColorStateList getBackgroundTintList() {
17510        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
17511    }
17512
17513    /**
17514     * Specifies the blending mode used to apply the tint specified by
17515     * {@link #setBackgroundTintList(ColorStateList)}} to the background
17516     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17517     *
17518     * @param tintMode the blending mode used to apply the tint, may be
17519     *                 {@code null} to clear tint
17520     * @attr ref android.R.styleable#View_backgroundTintMode
17521     * @see #getBackgroundTintMode()
17522     * @see Drawable#setTintMode(PorterDuff.Mode)
17523     */
17524    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17525        if (mBackgroundTint == null) {
17526            mBackgroundTint = new TintInfo();
17527        }
17528        mBackgroundTint.mTintMode = tintMode;
17529        mBackgroundTint.mHasTintMode = true;
17530
17531        applyBackgroundTint();
17532    }
17533
17534    /**
17535     * Return the blending mode used to apply the tint to the background
17536     * drawable, if specified.
17537     *
17538     * @return the blending mode used to apply the tint to the background
17539     *         drawable
17540     * @attr ref android.R.styleable#View_backgroundTintMode
17541     * @see #setBackgroundTintMode(PorterDuff.Mode)
17542     */
17543    @Nullable
17544    public PorterDuff.Mode getBackgroundTintMode() {
17545        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
17546    }
17547
17548    private void applyBackgroundTint() {
17549        if (mBackground != null && mBackgroundTint != null) {
17550            final TintInfo tintInfo = mBackgroundTint;
17551            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17552                mBackground = mBackground.mutate();
17553
17554                if (tintInfo.mHasTintList) {
17555                    mBackground.setTintList(tintInfo.mTintList);
17556                }
17557
17558                if (tintInfo.mHasTintMode) {
17559                    mBackground.setTintMode(tintInfo.mTintMode);
17560                }
17561
17562                // The drawable (or one of its children) may not have been
17563                // stateful before applying the tint, so let's try again.
17564                if (mBackground.isStateful()) {
17565                    mBackground.setState(getDrawableState());
17566                }
17567            }
17568        }
17569    }
17570
17571    /**
17572     * Returns the drawable used as the foreground of this View. The
17573     * foreground drawable, if non-null, is always drawn on top of the view's content.
17574     *
17575     * @return a Drawable or null if no foreground was set
17576     *
17577     * @see #onDrawForeground(Canvas)
17578     */
17579    public Drawable getForeground() {
17580        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17581    }
17582
17583    /**
17584     * Supply a Drawable that is to be rendered on top of all of the content in the view.
17585     *
17586     * @param foreground the Drawable to be drawn on top of the children
17587     *
17588     * @attr ref android.R.styleable#View_foreground
17589     */
17590    public void setForeground(Drawable foreground) {
17591        if (mForegroundInfo == null) {
17592            if (foreground == null) {
17593                // Nothing to do.
17594                return;
17595            }
17596            mForegroundInfo = new ForegroundInfo();
17597        }
17598
17599        if (foreground == mForegroundInfo.mDrawable) {
17600            // Nothing to do
17601            return;
17602        }
17603
17604        if (mForegroundInfo.mDrawable != null) {
17605            mForegroundInfo.mDrawable.setCallback(null);
17606            unscheduleDrawable(mForegroundInfo.mDrawable);
17607        }
17608
17609        mForegroundInfo.mDrawable = foreground;
17610        mForegroundInfo.mBoundsChanged = true;
17611        if (foreground != null) {
17612            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17613                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17614            }
17615            foreground.setCallback(this);
17616            foreground.setLayoutDirection(getLayoutDirection());
17617            if (foreground.isStateful()) {
17618                foreground.setState(getDrawableState());
17619            }
17620            applyForegroundTint();
17621        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
17622            mPrivateFlags |= PFLAG_SKIP_DRAW;
17623        }
17624        requestLayout();
17625        invalidate();
17626    }
17627
17628    /**
17629     * Magic bit used to support features of framework-internal window decor implementation details.
17630     * This used to live exclusively in FrameLayout.
17631     *
17632     * @return true if the foreground should draw inside the padding region or false
17633     *         if it should draw inset by the view's padding
17634     * @hide internal use only; only used by FrameLayout and internal screen layouts.
17635     */
17636    public boolean isForegroundInsidePadding() {
17637        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
17638    }
17639
17640    /**
17641     * Describes how the foreground is positioned.
17642     *
17643     * @return foreground gravity.
17644     *
17645     * @see #setForegroundGravity(int)
17646     *
17647     * @attr ref android.R.styleable#View_foregroundGravity
17648     */
17649    public int getForegroundGravity() {
17650        return mForegroundInfo != null ? mForegroundInfo.mGravity
17651                : Gravity.START | Gravity.TOP;
17652    }
17653
17654    /**
17655     * Describes how the foreground is positioned. Defaults to START and TOP.
17656     *
17657     * @param gravity see {@link android.view.Gravity}
17658     *
17659     * @see #getForegroundGravity()
17660     *
17661     * @attr ref android.R.styleable#View_foregroundGravity
17662     */
17663    public void setForegroundGravity(int gravity) {
17664        if (mForegroundInfo == null) {
17665            mForegroundInfo = new ForegroundInfo();
17666        }
17667
17668        if (mForegroundInfo.mGravity != gravity) {
17669            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
17670                gravity |= Gravity.START;
17671            }
17672
17673            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
17674                gravity |= Gravity.TOP;
17675            }
17676
17677            mForegroundInfo.mGravity = gravity;
17678            requestLayout();
17679        }
17680    }
17681
17682    /**
17683     * Applies a tint to the foreground drawable. Does not modify the current tint
17684     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17685     * <p>
17686     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
17687     * mutate the drawable and apply the specified tint and tint mode using
17688     * {@link Drawable#setTintList(ColorStateList)}.
17689     *
17690     * @param tint the tint to apply, may be {@code null} to clear tint
17691     *
17692     * @attr ref android.R.styleable#View_foregroundTint
17693     * @see #getForegroundTintList()
17694     * @see Drawable#setTintList(ColorStateList)
17695     */
17696    public void setForegroundTintList(@Nullable ColorStateList tint) {
17697        if (mForegroundInfo == null) {
17698            mForegroundInfo = new ForegroundInfo();
17699        }
17700        if (mForegroundInfo.mTintInfo == null) {
17701            mForegroundInfo.mTintInfo = new TintInfo();
17702        }
17703        mForegroundInfo.mTintInfo.mTintList = tint;
17704        mForegroundInfo.mTintInfo.mHasTintList = true;
17705
17706        applyForegroundTint();
17707    }
17708
17709    /**
17710     * Return the tint applied to the foreground drawable, if specified.
17711     *
17712     * @return the tint applied to the foreground drawable
17713     * @attr ref android.R.styleable#View_foregroundTint
17714     * @see #setForegroundTintList(ColorStateList)
17715     */
17716    @Nullable
17717    public ColorStateList getForegroundTintList() {
17718        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17719                ? mForegroundInfo.mTintInfo.mTintList : null;
17720    }
17721
17722    /**
17723     * Specifies the blending mode used to apply the tint specified by
17724     * {@link #setForegroundTintList(ColorStateList)}} to the background
17725     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17726     *
17727     * @param tintMode the blending mode used to apply the tint, may be
17728     *                 {@code null} to clear tint
17729     * @attr ref android.R.styleable#View_foregroundTintMode
17730     * @see #getForegroundTintMode()
17731     * @see Drawable#setTintMode(PorterDuff.Mode)
17732     */
17733    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17734        if (mForegroundInfo == null) {
17735            mForegroundInfo = new ForegroundInfo();
17736        }
17737        if (mForegroundInfo.mTintInfo == null) {
17738            mForegroundInfo.mTintInfo = new TintInfo();
17739        }
17740        mForegroundInfo.mTintInfo.mTintMode = tintMode;
17741        mForegroundInfo.mTintInfo.mHasTintMode = true;
17742
17743        applyForegroundTint();
17744    }
17745
17746    /**
17747     * Return the blending mode used to apply the tint to the foreground
17748     * drawable, if specified.
17749     *
17750     * @return the blending mode used to apply the tint to the foreground
17751     *         drawable
17752     * @attr ref android.R.styleable#View_foregroundTintMode
17753     * @see #setForegroundTintMode(PorterDuff.Mode)
17754     */
17755    @Nullable
17756    public PorterDuff.Mode getForegroundTintMode() {
17757        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17758                ? mForegroundInfo.mTintInfo.mTintMode : null;
17759    }
17760
17761    private void applyForegroundTint() {
17762        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
17763                && mForegroundInfo.mTintInfo != null) {
17764            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
17765            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17766                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
17767
17768                if (tintInfo.mHasTintList) {
17769                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
17770                }
17771
17772                if (tintInfo.mHasTintMode) {
17773                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
17774                }
17775
17776                // The drawable (or one of its children) may not have been
17777                // stateful before applying the tint, so let's try again.
17778                if (mForegroundInfo.mDrawable.isStateful()) {
17779                    mForegroundInfo.mDrawable.setState(getDrawableState());
17780                }
17781            }
17782        }
17783    }
17784
17785    /**
17786     * Draw any foreground content for this view.
17787     *
17788     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
17789     * drawable or other view-specific decorations. The foreground is drawn on top of the
17790     * primary view content.</p>
17791     *
17792     * @param canvas canvas to draw into
17793     */
17794    public void onDrawForeground(Canvas canvas) {
17795        onDrawScrollIndicators(canvas);
17796        onDrawScrollBars(canvas);
17797
17798        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17799        if (foreground != null) {
17800            if (mForegroundInfo.mBoundsChanged) {
17801                mForegroundInfo.mBoundsChanged = false;
17802                final Rect selfBounds = mForegroundInfo.mSelfBounds;
17803                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17804
17805                if (mForegroundInfo.mInsidePadding) {
17806                    selfBounds.set(0, 0, getWidth(), getHeight());
17807                } else {
17808                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
17809                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17810                }
17811
17812                final int ld = getLayoutDirection();
17813                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17814                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17815                foreground.setBounds(overlayBounds);
17816            }
17817
17818            foreground.draw(canvas);
17819        }
17820    }
17821
17822    /**
17823     * Sets the padding. The view may add on the space required to display
17824     * the scrollbars, depending on the style and visibility of the scrollbars.
17825     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17826     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17827     * from the values set in this call.
17828     *
17829     * @attr ref android.R.styleable#View_padding
17830     * @attr ref android.R.styleable#View_paddingBottom
17831     * @attr ref android.R.styleable#View_paddingLeft
17832     * @attr ref android.R.styleable#View_paddingRight
17833     * @attr ref android.R.styleable#View_paddingTop
17834     * @param left the left padding in pixels
17835     * @param top the top padding in pixels
17836     * @param right the right padding in pixels
17837     * @param bottom the bottom padding in pixels
17838     */
17839    public void setPadding(int left, int top, int right, int bottom) {
17840        resetResolvedPaddingInternal();
17841
17842        mUserPaddingStart = UNDEFINED_PADDING;
17843        mUserPaddingEnd = UNDEFINED_PADDING;
17844
17845        mUserPaddingLeftInitial = left;
17846        mUserPaddingRightInitial = right;
17847
17848        mLeftPaddingDefined = true;
17849        mRightPaddingDefined = true;
17850
17851        internalSetPadding(left, top, right, bottom);
17852    }
17853
17854    /**
17855     * @hide
17856     */
17857    protected void internalSetPadding(int left, int top, int right, int bottom) {
17858        mUserPaddingLeft = left;
17859        mUserPaddingRight = right;
17860        mUserPaddingBottom = bottom;
17861
17862        final int viewFlags = mViewFlags;
17863        boolean changed = false;
17864
17865        // Common case is there are no scroll bars.
17866        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
17867            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
17868                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
17869                        ? 0 : getVerticalScrollbarWidth();
17870                switch (mVerticalScrollbarPosition) {
17871                    case SCROLLBAR_POSITION_DEFAULT:
17872                        if (isLayoutRtl()) {
17873                            left += offset;
17874                        } else {
17875                            right += offset;
17876                        }
17877                        break;
17878                    case SCROLLBAR_POSITION_RIGHT:
17879                        right += offset;
17880                        break;
17881                    case SCROLLBAR_POSITION_LEFT:
17882                        left += offset;
17883                        break;
17884                }
17885            }
17886            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
17887                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
17888                        ? 0 : getHorizontalScrollbarHeight();
17889            }
17890        }
17891
17892        if (mPaddingLeft != left) {
17893            changed = true;
17894            mPaddingLeft = left;
17895        }
17896        if (mPaddingTop != top) {
17897            changed = true;
17898            mPaddingTop = top;
17899        }
17900        if (mPaddingRight != right) {
17901            changed = true;
17902            mPaddingRight = right;
17903        }
17904        if (mPaddingBottom != bottom) {
17905            changed = true;
17906            mPaddingBottom = bottom;
17907        }
17908
17909        if (changed) {
17910            requestLayout();
17911            invalidateOutline();
17912        }
17913    }
17914
17915    /**
17916     * Sets the relative padding. The view may add on the space required to display
17917     * the scrollbars, depending on the style and visibility of the scrollbars.
17918     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
17919     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
17920     * from the values set in this call.
17921     *
17922     * @attr ref android.R.styleable#View_padding
17923     * @attr ref android.R.styleable#View_paddingBottom
17924     * @attr ref android.R.styleable#View_paddingStart
17925     * @attr ref android.R.styleable#View_paddingEnd
17926     * @attr ref android.R.styleable#View_paddingTop
17927     * @param start the start padding in pixels
17928     * @param top the top padding in pixels
17929     * @param end the end padding in pixels
17930     * @param bottom the bottom padding in pixels
17931     */
17932    public void setPaddingRelative(int start, int top, int end, int bottom) {
17933        resetResolvedPaddingInternal();
17934
17935        mUserPaddingStart = start;
17936        mUserPaddingEnd = end;
17937        mLeftPaddingDefined = true;
17938        mRightPaddingDefined = true;
17939
17940        switch(getLayoutDirection()) {
17941            case LAYOUT_DIRECTION_RTL:
17942                mUserPaddingLeftInitial = end;
17943                mUserPaddingRightInitial = start;
17944                internalSetPadding(end, top, start, bottom);
17945                break;
17946            case LAYOUT_DIRECTION_LTR:
17947            default:
17948                mUserPaddingLeftInitial = start;
17949                mUserPaddingRightInitial = end;
17950                internalSetPadding(start, top, end, bottom);
17951        }
17952    }
17953
17954    /**
17955     * Returns the top padding of this view.
17956     *
17957     * @return the top padding in pixels
17958     */
17959    public int getPaddingTop() {
17960        return mPaddingTop;
17961    }
17962
17963    /**
17964     * Returns the bottom padding of this view. If there are inset and enabled
17965     * scrollbars, this value may include the space required to display the
17966     * scrollbars as well.
17967     *
17968     * @return the bottom padding in pixels
17969     */
17970    public int getPaddingBottom() {
17971        return mPaddingBottom;
17972    }
17973
17974    /**
17975     * Returns the left padding of this view. If there are inset and enabled
17976     * scrollbars, this value may include the space required to display the
17977     * scrollbars as well.
17978     *
17979     * @return the left padding in pixels
17980     */
17981    public int getPaddingLeft() {
17982        if (!isPaddingResolved()) {
17983            resolvePadding();
17984        }
17985        return mPaddingLeft;
17986    }
17987
17988    /**
17989     * Returns the start padding of this view depending on its resolved layout direction.
17990     * If there are inset and enabled scrollbars, this value may include the space
17991     * required to display the scrollbars as well.
17992     *
17993     * @return the start padding in pixels
17994     */
17995    public int getPaddingStart() {
17996        if (!isPaddingResolved()) {
17997            resolvePadding();
17998        }
17999        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18000                mPaddingRight : mPaddingLeft;
18001    }
18002
18003    /**
18004     * Returns the right padding of this view. If there are inset and enabled
18005     * scrollbars, this value may include the space required to display the
18006     * scrollbars as well.
18007     *
18008     * @return the right padding in pixels
18009     */
18010    public int getPaddingRight() {
18011        if (!isPaddingResolved()) {
18012            resolvePadding();
18013        }
18014        return mPaddingRight;
18015    }
18016
18017    /**
18018     * Returns the end padding of this view depending on its resolved layout direction.
18019     * If there are inset and enabled scrollbars, this value may include the space
18020     * required to display the scrollbars as well.
18021     *
18022     * @return the end padding in pixels
18023     */
18024    public int getPaddingEnd() {
18025        if (!isPaddingResolved()) {
18026            resolvePadding();
18027        }
18028        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18029                mPaddingLeft : mPaddingRight;
18030    }
18031
18032    /**
18033     * Return if the padding has been set through relative values
18034     * {@link #setPaddingRelative(int, int, int, int)} or through
18035     * @attr ref android.R.styleable#View_paddingStart or
18036     * @attr ref android.R.styleable#View_paddingEnd
18037     *
18038     * @return true if the padding is relative or false if it is not.
18039     */
18040    public boolean isPaddingRelative() {
18041        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18042    }
18043
18044    Insets computeOpticalInsets() {
18045        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18046    }
18047
18048    /**
18049     * @hide
18050     */
18051    public void resetPaddingToInitialValues() {
18052        if (isRtlCompatibilityMode()) {
18053            mPaddingLeft = mUserPaddingLeftInitial;
18054            mPaddingRight = mUserPaddingRightInitial;
18055            return;
18056        }
18057        if (isLayoutRtl()) {
18058            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18059            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18060        } else {
18061            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18062            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18063        }
18064    }
18065
18066    /**
18067     * @hide
18068     */
18069    public Insets getOpticalInsets() {
18070        if (mLayoutInsets == null) {
18071            mLayoutInsets = computeOpticalInsets();
18072        }
18073        return mLayoutInsets;
18074    }
18075
18076    /**
18077     * Set this view's optical insets.
18078     *
18079     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
18080     * property. Views that compute their own optical insets should call it as part of measurement.
18081     * This method does not request layout. If you are setting optical insets outside of
18082     * measure/layout itself you will want to call requestLayout() yourself.
18083     * </p>
18084     * @hide
18085     */
18086    public void setOpticalInsets(Insets insets) {
18087        mLayoutInsets = insets;
18088    }
18089
18090    /**
18091     * Changes the selection state of this view. A view can be selected or not.
18092     * Note that selection is not the same as focus. Views are typically
18093     * selected in the context of an AdapterView like ListView or GridView;
18094     * the selected view is the view that is highlighted.
18095     *
18096     * @param selected true if the view must be selected, false otherwise
18097     */
18098    public void setSelected(boolean selected) {
18099        //noinspection DoubleNegation
18100        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
18101            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
18102            if (!selected) resetPressedState();
18103            invalidate(true);
18104            refreshDrawableState();
18105            dispatchSetSelected(selected);
18106            if (selected) {
18107                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
18108            } else {
18109                notifyViewAccessibilityStateChangedIfNeeded(
18110                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
18111            }
18112        }
18113    }
18114
18115    /**
18116     * Dispatch setSelected to all of this View's children.
18117     *
18118     * @see #setSelected(boolean)
18119     *
18120     * @param selected The new selected state
18121     */
18122    protected void dispatchSetSelected(boolean selected) {
18123    }
18124
18125    /**
18126     * Indicates the selection state of this view.
18127     *
18128     * @return true if the view is selected, false otherwise
18129     */
18130    @ViewDebug.ExportedProperty
18131    public boolean isSelected() {
18132        return (mPrivateFlags & PFLAG_SELECTED) != 0;
18133    }
18134
18135    /**
18136     * Changes the activated state of this view. A view can be activated or not.
18137     * Note that activation is not the same as selection.  Selection is
18138     * a transient property, representing the view (hierarchy) the user is
18139     * currently interacting with.  Activation is a longer-term state that the
18140     * user can move views in and out of.  For example, in a list view with
18141     * single or multiple selection enabled, the views in the current selection
18142     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
18143     * here.)  The activated state is propagated down to children of the view it
18144     * is set on.
18145     *
18146     * @param activated true if the view must be activated, false otherwise
18147     */
18148    public void setActivated(boolean activated) {
18149        //noinspection DoubleNegation
18150        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
18151            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
18152            invalidate(true);
18153            refreshDrawableState();
18154            dispatchSetActivated(activated);
18155        }
18156    }
18157
18158    /**
18159     * Dispatch setActivated to all of this View's children.
18160     *
18161     * @see #setActivated(boolean)
18162     *
18163     * @param activated The new activated state
18164     */
18165    protected void dispatchSetActivated(boolean activated) {
18166    }
18167
18168    /**
18169     * Indicates the activation state of this view.
18170     *
18171     * @return true if the view is activated, false otherwise
18172     */
18173    @ViewDebug.ExportedProperty
18174    public boolean isActivated() {
18175        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
18176    }
18177
18178    /**
18179     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
18180     * observer can be used to get notifications when global events, like
18181     * layout, happen.
18182     *
18183     * The returned ViewTreeObserver observer is not guaranteed to remain
18184     * valid for the lifetime of this View. If the caller of this method keeps
18185     * a long-lived reference to ViewTreeObserver, it should always check for
18186     * the return value of {@link ViewTreeObserver#isAlive()}.
18187     *
18188     * @return The ViewTreeObserver for this view's hierarchy.
18189     */
18190    public ViewTreeObserver getViewTreeObserver() {
18191        if (mAttachInfo != null) {
18192            return mAttachInfo.mTreeObserver;
18193        }
18194        if (mFloatingTreeObserver == null) {
18195            mFloatingTreeObserver = new ViewTreeObserver();
18196        }
18197        return mFloatingTreeObserver;
18198    }
18199
18200    /**
18201     * <p>Finds the topmost view in the current view hierarchy.</p>
18202     *
18203     * @return the topmost view containing this view
18204     */
18205    public View getRootView() {
18206        if (mAttachInfo != null) {
18207            final View v = mAttachInfo.mRootView;
18208            if (v != null) {
18209                return v;
18210            }
18211        }
18212
18213        View parent = this;
18214
18215        while (parent.mParent != null && parent.mParent instanceof View) {
18216            parent = (View) parent.mParent;
18217        }
18218
18219        return parent;
18220    }
18221
18222    /**
18223     * Transforms a motion event from view-local coordinates to on-screen
18224     * coordinates.
18225     *
18226     * @param ev the view-local motion event
18227     * @return false if the transformation could not be applied
18228     * @hide
18229     */
18230    public boolean toGlobalMotionEvent(MotionEvent ev) {
18231        final AttachInfo info = mAttachInfo;
18232        if (info == null) {
18233            return false;
18234        }
18235
18236        final Matrix m = info.mTmpMatrix;
18237        m.set(Matrix.IDENTITY_MATRIX);
18238        transformMatrixToGlobal(m);
18239        ev.transform(m);
18240        return true;
18241    }
18242
18243    /**
18244     * Transforms a motion event from on-screen coordinates to view-local
18245     * coordinates.
18246     *
18247     * @param ev the on-screen motion event
18248     * @return false if the transformation could not be applied
18249     * @hide
18250     */
18251    public boolean toLocalMotionEvent(MotionEvent ev) {
18252        final AttachInfo info = mAttachInfo;
18253        if (info == null) {
18254            return false;
18255        }
18256
18257        final Matrix m = info.mTmpMatrix;
18258        m.set(Matrix.IDENTITY_MATRIX);
18259        transformMatrixToLocal(m);
18260        ev.transform(m);
18261        return true;
18262    }
18263
18264    /**
18265     * Modifies the input matrix such that it maps view-local coordinates to
18266     * on-screen coordinates.
18267     *
18268     * @param m input matrix to modify
18269     * @hide
18270     */
18271    public void transformMatrixToGlobal(Matrix m) {
18272        final ViewParent parent = mParent;
18273        if (parent instanceof View) {
18274            final View vp = (View) parent;
18275            vp.transformMatrixToGlobal(m);
18276            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
18277        } else if (parent instanceof ViewRootImpl) {
18278            final ViewRootImpl vr = (ViewRootImpl) parent;
18279            vr.transformMatrixToGlobal(m);
18280            m.preTranslate(0, -vr.mCurScrollY);
18281        }
18282
18283        m.preTranslate(mLeft, mTop);
18284
18285        if (!hasIdentityMatrix()) {
18286            m.preConcat(getMatrix());
18287        }
18288    }
18289
18290    /**
18291     * Modifies the input matrix such that it maps on-screen coordinates to
18292     * view-local coordinates.
18293     *
18294     * @param m input matrix to modify
18295     * @hide
18296     */
18297    public void transformMatrixToLocal(Matrix m) {
18298        final ViewParent parent = mParent;
18299        if (parent instanceof View) {
18300            final View vp = (View) parent;
18301            vp.transformMatrixToLocal(m);
18302            m.postTranslate(vp.mScrollX, vp.mScrollY);
18303        } else if (parent instanceof ViewRootImpl) {
18304            final ViewRootImpl vr = (ViewRootImpl) parent;
18305            vr.transformMatrixToLocal(m);
18306            m.postTranslate(0, vr.mCurScrollY);
18307        }
18308
18309        m.postTranslate(-mLeft, -mTop);
18310
18311        if (!hasIdentityMatrix()) {
18312            m.postConcat(getInverseMatrix());
18313        }
18314    }
18315
18316    /**
18317     * @hide
18318     */
18319    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
18320            @ViewDebug.IntToString(from = 0, to = "x"),
18321            @ViewDebug.IntToString(from = 1, to = "y")
18322    })
18323    public int[] getLocationOnScreen() {
18324        int[] location = new int[2];
18325        getLocationOnScreen(location);
18326        return location;
18327    }
18328
18329    /**
18330     * <p>Computes the coordinates of this view on the screen. The argument
18331     * must be an array of two integers. After the method returns, the array
18332     * contains the x and y location in that order.</p>
18333     *
18334     * @param location an array of two integers in which to hold the coordinates
18335     */
18336    public void getLocationOnScreen(@Size(2) int[] location) {
18337        getLocationInWindow(location);
18338
18339        final AttachInfo info = mAttachInfo;
18340        if (info != null) {
18341            location[0] += info.mWindowLeft;
18342            location[1] += info.mWindowTop;
18343        }
18344    }
18345
18346    /**
18347     * <p>Computes the coordinates of this view in its window. The argument
18348     * must be an array of two integers. After the method returns, the array
18349     * contains the x and y location in that order.</p>
18350     *
18351     * @param location an array of two integers in which to hold the coordinates
18352     */
18353    public void getLocationInWindow(@Size(2) int[] location) {
18354        if (location == null || location.length < 2) {
18355            throw new IllegalArgumentException("location must be an array of two integers");
18356        }
18357
18358        if (mAttachInfo == null) {
18359            // When the view is not attached to a window, this method does not make sense
18360            location[0] = location[1] = 0;
18361            return;
18362        }
18363
18364        float[] position = mAttachInfo.mTmpTransformLocation;
18365        position[0] = position[1] = 0.0f;
18366
18367        if (!hasIdentityMatrix()) {
18368            getMatrix().mapPoints(position);
18369        }
18370
18371        position[0] += mLeft;
18372        position[1] += mTop;
18373
18374        ViewParent viewParent = mParent;
18375        while (viewParent instanceof View) {
18376            final View view = (View) viewParent;
18377
18378            position[0] -= view.mScrollX;
18379            position[1] -= view.mScrollY;
18380
18381            if (!view.hasIdentityMatrix()) {
18382                view.getMatrix().mapPoints(position);
18383            }
18384
18385            position[0] += view.mLeft;
18386            position[1] += view.mTop;
18387
18388            viewParent = view.mParent;
18389         }
18390
18391        if (viewParent instanceof ViewRootImpl) {
18392            // *cough*
18393            final ViewRootImpl vr = (ViewRootImpl) viewParent;
18394            position[1] -= vr.mCurScrollY;
18395        }
18396
18397        location[0] = (int) (position[0] + 0.5f);
18398        location[1] = (int) (position[1] + 0.5f);
18399    }
18400
18401    /**
18402     * {@hide}
18403     * @param id the id of the view to be found
18404     * @return the view of the specified id, null if cannot be found
18405     */
18406    protected View findViewTraversal(@IdRes int id) {
18407        if (id == mID) {
18408            return this;
18409        }
18410        return null;
18411    }
18412
18413    /**
18414     * {@hide}
18415     * @param tag the tag of the view to be found
18416     * @return the view of specified tag, null if cannot be found
18417     */
18418    protected View findViewWithTagTraversal(Object tag) {
18419        if (tag != null && tag.equals(mTag)) {
18420            return this;
18421        }
18422        return null;
18423    }
18424
18425    /**
18426     * {@hide}
18427     * @param predicate The predicate to evaluate.
18428     * @param childToSkip If not null, ignores this child during the recursive traversal.
18429     * @return The first view that matches the predicate or null.
18430     */
18431    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
18432        if (predicate.apply(this)) {
18433            return this;
18434        }
18435        return null;
18436    }
18437
18438    /**
18439     * Look for a child view with the given id.  If this view has the given
18440     * id, return this view.
18441     *
18442     * @param id The id to search for.
18443     * @return The view that has the given id in the hierarchy or null
18444     */
18445    @Nullable
18446    public final View findViewById(@IdRes int id) {
18447        if (id < 0) {
18448            return null;
18449        }
18450        return findViewTraversal(id);
18451    }
18452
18453    /**
18454     * Finds a view by its unuque and stable accessibility id.
18455     *
18456     * @param accessibilityId The searched accessibility id.
18457     * @return The found view.
18458     */
18459    final View findViewByAccessibilityId(int accessibilityId) {
18460        if (accessibilityId < 0) {
18461            return null;
18462        }
18463        View view = findViewByAccessibilityIdTraversal(accessibilityId);
18464        if (view != null) {
18465            return view.includeForAccessibility() ? view : null;
18466        }
18467        return null;
18468    }
18469
18470    /**
18471     * Performs the traversal to find a view by its unuque and stable accessibility id.
18472     *
18473     * <strong>Note:</strong>This method does not stop at the root namespace
18474     * boundary since the user can touch the screen at an arbitrary location
18475     * potentially crossing the root namespace bounday which will send an
18476     * accessibility event to accessibility services and they should be able
18477     * to obtain the event source. Also accessibility ids are guaranteed to be
18478     * unique in the window.
18479     *
18480     * @param accessibilityId The accessibility id.
18481     * @return The found view.
18482     *
18483     * @hide
18484     */
18485    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
18486        if (getAccessibilityViewId() == accessibilityId) {
18487            return this;
18488        }
18489        return null;
18490    }
18491
18492    /**
18493     * Look for a child view with the given tag.  If this view has the given
18494     * tag, return this view.
18495     *
18496     * @param tag The tag to search for, using "tag.equals(getTag())".
18497     * @return The View that has the given tag in the hierarchy or null
18498     */
18499    public final View findViewWithTag(Object tag) {
18500        if (tag == null) {
18501            return null;
18502        }
18503        return findViewWithTagTraversal(tag);
18504    }
18505
18506    /**
18507     * {@hide}
18508     * Look for a child view that matches the specified predicate.
18509     * If this view matches the predicate, return this view.
18510     *
18511     * @param predicate The predicate to evaluate.
18512     * @return The first view that matches the predicate or null.
18513     */
18514    public final View findViewByPredicate(Predicate<View> predicate) {
18515        return findViewByPredicateTraversal(predicate, null);
18516    }
18517
18518    /**
18519     * {@hide}
18520     * Look for a child view that matches the specified predicate,
18521     * starting with the specified view and its descendents and then
18522     * recusively searching the ancestors and siblings of that view
18523     * until this view is reached.
18524     *
18525     * This method is useful in cases where the predicate does not match
18526     * a single unique view (perhaps multiple views use the same id)
18527     * and we are trying to find the view that is "closest" in scope to the
18528     * starting view.
18529     *
18530     * @param start The view to start from.
18531     * @param predicate The predicate to evaluate.
18532     * @return The first view that matches the predicate or null.
18533     */
18534    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
18535        View childToSkip = null;
18536        for (;;) {
18537            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
18538            if (view != null || start == this) {
18539                return view;
18540            }
18541
18542            ViewParent parent = start.getParent();
18543            if (parent == null || !(parent instanceof View)) {
18544                return null;
18545            }
18546
18547            childToSkip = start;
18548            start = (View) parent;
18549        }
18550    }
18551
18552    /**
18553     * Sets the identifier for this view. The identifier does not have to be
18554     * unique in this view's hierarchy. The identifier should be a positive
18555     * number.
18556     *
18557     * @see #NO_ID
18558     * @see #getId()
18559     * @see #findViewById(int)
18560     *
18561     * @param id a number used to identify the view
18562     *
18563     * @attr ref android.R.styleable#View_id
18564     */
18565    public void setId(@IdRes int id) {
18566        mID = id;
18567        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
18568            mID = generateViewId();
18569        }
18570    }
18571
18572    /**
18573     * {@hide}
18574     *
18575     * @param isRoot true if the view belongs to the root namespace, false
18576     *        otherwise
18577     */
18578    public void setIsRootNamespace(boolean isRoot) {
18579        if (isRoot) {
18580            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
18581        } else {
18582            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
18583        }
18584    }
18585
18586    /**
18587     * {@hide}
18588     *
18589     * @return true if the view belongs to the root namespace, false otherwise
18590     */
18591    public boolean isRootNamespace() {
18592        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
18593    }
18594
18595    /**
18596     * Returns this view's identifier.
18597     *
18598     * @return a positive integer used to identify the view or {@link #NO_ID}
18599     *         if the view has no ID
18600     *
18601     * @see #setId(int)
18602     * @see #findViewById(int)
18603     * @attr ref android.R.styleable#View_id
18604     */
18605    @IdRes
18606    @ViewDebug.CapturedViewProperty
18607    public int getId() {
18608        return mID;
18609    }
18610
18611    /**
18612     * Returns this view's tag.
18613     *
18614     * @return the Object stored in this view as a tag, or {@code null} if not
18615     *         set
18616     *
18617     * @see #setTag(Object)
18618     * @see #getTag(int)
18619     */
18620    @ViewDebug.ExportedProperty
18621    public Object getTag() {
18622        return mTag;
18623    }
18624
18625    /**
18626     * Sets the tag associated with this view. A tag can be used to mark
18627     * a view in its hierarchy and does not have to be unique within the
18628     * hierarchy. Tags can also be used to store data within a view without
18629     * resorting to another data structure.
18630     *
18631     * @param tag an Object to tag the view with
18632     *
18633     * @see #getTag()
18634     * @see #setTag(int, Object)
18635     */
18636    public void setTag(final Object tag) {
18637        mTag = tag;
18638    }
18639
18640    /**
18641     * Returns the tag associated with this view and the specified key.
18642     *
18643     * @param key The key identifying the tag
18644     *
18645     * @return the Object stored in this view as a tag, or {@code null} if not
18646     *         set
18647     *
18648     * @see #setTag(int, Object)
18649     * @see #getTag()
18650     */
18651    public Object getTag(int key) {
18652        if (mKeyedTags != null) return mKeyedTags.get(key);
18653        return null;
18654    }
18655
18656    /**
18657     * Sets a tag associated with this view and a key. A tag can be used
18658     * to mark a view in its hierarchy and does not have to be unique within
18659     * the hierarchy. Tags can also be used to store data within a view
18660     * without resorting to another data structure.
18661     *
18662     * The specified key should be an id declared in the resources of the
18663     * application to ensure it is unique (see the <a
18664     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
18665     * Keys identified as belonging to
18666     * the Android framework or not associated with any package will cause
18667     * an {@link IllegalArgumentException} to be thrown.
18668     *
18669     * @param key The key identifying the tag
18670     * @param tag An Object to tag the view with
18671     *
18672     * @throws IllegalArgumentException If they specified key is not valid
18673     *
18674     * @see #setTag(Object)
18675     * @see #getTag(int)
18676     */
18677    public void setTag(int key, final Object tag) {
18678        // If the package id is 0x00 or 0x01, it's either an undefined package
18679        // or a framework id
18680        if ((key >>> 24) < 2) {
18681            throw new IllegalArgumentException("The key must be an application-specific "
18682                    + "resource id.");
18683        }
18684
18685        setKeyedTag(key, tag);
18686    }
18687
18688    /**
18689     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
18690     * framework id.
18691     *
18692     * @hide
18693     */
18694    public void setTagInternal(int key, Object tag) {
18695        if ((key >>> 24) != 0x1) {
18696            throw new IllegalArgumentException("The key must be a framework-specific "
18697                    + "resource id.");
18698        }
18699
18700        setKeyedTag(key, tag);
18701    }
18702
18703    private void setKeyedTag(int key, Object tag) {
18704        if (mKeyedTags == null) {
18705            mKeyedTags = new SparseArray<Object>(2);
18706        }
18707
18708        mKeyedTags.put(key, tag);
18709    }
18710
18711    /**
18712     * Prints information about this view in the log output, with the tag
18713     * {@link #VIEW_LOG_TAG}.
18714     *
18715     * @hide
18716     */
18717    public void debug() {
18718        debug(0);
18719    }
18720
18721    /**
18722     * Prints information about this view in the log output, with the tag
18723     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18724     * indentation defined by the <code>depth</code>.
18725     *
18726     * @param depth the indentation level
18727     *
18728     * @hide
18729     */
18730    protected void debug(int depth) {
18731        String output = debugIndent(depth - 1);
18732
18733        output += "+ " + this;
18734        int id = getId();
18735        if (id != -1) {
18736            output += " (id=" + id + ")";
18737        }
18738        Object tag = getTag();
18739        if (tag != null) {
18740            output += " (tag=" + tag + ")";
18741        }
18742        Log.d(VIEW_LOG_TAG, output);
18743
18744        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18745            output = debugIndent(depth) + " FOCUSED";
18746            Log.d(VIEW_LOG_TAG, output);
18747        }
18748
18749        output = debugIndent(depth);
18750        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
18751                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
18752                + "} ";
18753        Log.d(VIEW_LOG_TAG, output);
18754
18755        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
18756                || mPaddingBottom != 0) {
18757            output = debugIndent(depth);
18758            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
18759                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
18760            Log.d(VIEW_LOG_TAG, output);
18761        }
18762
18763        output = debugIndent(depth);
18764        output += "mMeasureWidth=" + mMeasuredWidth +
18765                " mMeasureHeight=" + mMeasuredHeight;
18766        Log.d(VIEW_LOG_TAG, output);
18767
18768        output = debugIndent(depth);
18769        if (mLayoutParams == null) {
18770            output += "BAD! no layout params";
18771        } else {
18772            output = mLayoutParams.debug(output);
18773        }
18774        Log.d(VIEW_LOG_TAG, output);
18775
18776        output = debugIndent(depth);
18777        output += "flags={";
18778        output += View.printFlags(mViewFlags);
18779        output += "}";
18780        Log.d(VIEW_LOG_TAG, output);
18781
18782        output = debugIndent(depth);
18783        output += "privateFlags={";
18784        output += View.printPrivateFlags(mPrivateFlags);
18785        output += "}";
18786        Log.d(VIEW_LOG_TAG, output);
18787    }
18788
18789    /**
18790     * Creates a string of whitespaces used for indentation.
18791     *
18792     * @param depth the indentation level
18793     * @return a String containing (depth * 2 + 3) * 2 white spaces
18794     *
18795     * @hide
18796     */
18797    protected static String debugIndent(int depth) {
18798        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
18799        for (int i = 0; i < (depth * 2) + 3; i++) {
18800            spaces.append(' ').append(' ');
18801        }
18802        return spaces.toString();
18803    }
18804
18805    /**
18806     * <p>Return the offset of the widget's text baseline from the widget's top
18807     * boundary. If this widget does not support baseline alignment, this
18808     * method returns -1. </p>
18809     *
18810     * @return the offset of the baseline within the widget's bounds or -1
18811     *         if baseline alignment is not supported
18812     */
18813    @ViewDebug.ExportedProperty(category = "layout")
18814    public int getBaseline() {
18815        return -1;
18816    }
18817
18818    /**
18819     * Returns whether the view hierarchy is currently undergoing a layout pass. This
18820     * information is useful to avoid situations such as calling {@link #requestLayout()} during
18821     * a layout pass.
18822     *
18823     * @return whether the view hierarchy is currently undergoing a layout pass
18824     */
18825    public boolean isInLayout() {
18826        ViewRootImpl viewRoot = getViewRootImpl();
18827        return (viewRoot != null && viewRoot.isInLayout());
18828    }
18829
18830    /**
18831     * Call this when something has changed which has invalidated the
18832     * layout of this view. This will schedule a layout pass of the view
18833     * tree. This should not be called while the view hierarchy is currently in a layout
18834     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18835     * end of the current layout pass (and then layout will run again) or after the current
18836     * frame is drawn and the next layout occurs.
18837     *
18838     * <p>Subclasses which override this method should call the superclass method to
18839     * handle possible request-during-layout errors correctly.</p>
18840     */
18841    @CallSuper
18842    public void requestLayout() {
18843        if (mMeasureCache != null) mMeasureCache.clear();
18844
18845        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
18846            // Only trigger request-during-layout logic if this is the view requesting it,
18847            // not the views in its parent hierarchy
18848            ViewRootImpl viewRoot = getViewRootImpl();
18849            if (viewRoot != null && viewRoot.isInLayout()) {
18850                if (!viewRoot.requestLayoutDuringLayout(this)) {
18851                    return;
18852                }
18853            }
18854            mAttachInfo.mViewRequestingLayout = this;
18855        }
18856
18857        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18858        mPrivateFlags |= PFLAG_INVALIDATED;
18859
18860        if (mParent != null && !mParent.isLayoutRequested()) {
18861            mParent.requestLayout();
18862        }
18863        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
18864            mAttachInfo.mViewRequestingLayout = null;
18865        }
18866    }
18867
18868    /**
18869     * Forces this view to be laid out during the next layout pass.
18870     * This method does not call requestLayout() or forceLayout()
18871     * on the parent.
18872     */
18873    public void forceLayout() {
18874        if (mMeasureCache != null) mMeasureCache.clear();
18875
18876        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18877        mPrivateFlags |= PFLAG_INVALIDATED;
18878    }
18879
18880    /**
18881     * <p>
18882     * This is called to find out how big a view should be. The parent
18883     * supplies constraint information in the width and height parameters.
18884     * </p>
18885     *
18886     * <p>
18887     * The actual measurement work of a view is performed in
18888     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
18889     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
18890     * </p>
18891     *
18892     *
18893     * @param widthMeasureSpec Horizontal space requirements as imposed by the
18894     *        parent
18895     * @param heightMeasureSpec Vertical space requirements as imposed by the
18896     *        parent
18897     *
18898     * @see #onMeasure(int, int)
18899     */
18900    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
18901        boolean optical = isLayoutModeOptical(this);
18902        if (optical != isLayoutModeOptical(mParent)) {
18903            Insets insets = getOpticalInsets();
18904            int oWidth  = insets.left + insets.right;
18905            int oHeight = insets.top  + insets.bottom;
18906            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
18907            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
18908        }
18909
18910        // Suppress sign extension for the low bytes
18911        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
18912        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
18913
18914        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
18915
18916        // Optimize layout by avoiding an extra EXACTLY pass when the view is
18917        // already measured as the correct size. In API 23 and below, this
18918        // extra pass is required to make LinearLayout re-distribute weight.
18919        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
18920                || heightMeasureSpec != mOldHeightMeasureSpec;
18921        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
18922                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
18923        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
18924                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
18925        final boolean needsLayout = specChanged
18926                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
18927
18928        if (forceLayout || needsLayout) {
18929            // first clears the measured dimension flag
18930            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
18931
18932            resolveRtlPropertiesIfNeeded();
18933
18934            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
18935            if (cacheIndex < 0 || sIgnoreMeasureCache) {
18936                // measure ourselves, this should set the measured dimension flag back
18937                onMeasure(widthMeasureSpec, heightMeasureSpec);
18938                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18939            } else {
18940                long value = mMeasureCache.valueAt(cacheIndex);
18941                // Casting a long to int drops the high 32 bits, no mask needed
18942                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
18943                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18944            }
18945
18946            // flag not set, setMeasuredDimension() was not invoked, we raise
18947            // an exception to warn the developer
18948            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
18949                throw new IllegalStateException("View with id " + getId() + ": "
18950                        + getClass().getName() + "#onMeasure() did not set the"
18951                        + " measured dimension by calling"
18952                        + " setMeasuredDimension()");
18953            }
18954
18955            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
18956        }
18957
18958        mOldWidthMeasureSpec = widthMeasureSpec;
18959        mOldHeightMeasureSpec = heightMeasureSpec;
18960
18961        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
18962                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
18963    }
18964
18965    /**
18966     * <p>
18967     * Measure the view and its content to determine the measured width and the
18968     * measured height. This method is invoked by {@link #measure(int, int)} and
18969     * should be overridden by subclasses to provide accurate and efficient
18970     * measurement of their contents.
18971     * </p>
18972     *
18973     * <p>
18974     * <strong>CONTRACT:</strong> When overriding this method, you
18975     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
18976     * measured width and height of this view. Failure to do so will trigger an
18977     * <code>IllegalStateException</code>, thrown by
18978     * {@link #measure(int, int)}. Calling the superclass'
18979     * {@link #onMeasure(int, int)} is a valid use.
18980     * </p>
18981     *
18982     * <p>
18983     * The base class implementation of measure defaults to the background size,
18984     * unless a larger size is allowed by the MeasureSpec. Subclasses should
18985     * override {@link #onMeasure(int, int)} to provide better measurements of
18986     * their content.
18987     * </p>
18988     *
18989     * <p>
18990     * If this method is overridden, it is the subclass's responsibility to make
18991     * sure the measured height and width are at least the view's minimum height
18992     * and width ({@link #getSuggestedMinimumHeight()} and
18993     * {@link #getSuggestedMinimumWidth()}).
18994     * </p>
18995     *
18996     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
18997     *                         The requirements are encoded with
18998     *                         {@link android.view.View.MeasureSpec}.
18999     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19000     *                         The requirements are encoded with
19001     *                         {@link android.view.View.MeasureSpec}.
19002     *
19003     * @see #getMeasuredWidth()
19004     * @see #getMeasuredHeight()
19005     * @see #setMeasuredDimension(int, int)
19006     * @see #getSuggestedMinimumHeight()
19007     * @see #getSuggestedMinimumWidth()
19008     * @see android.view.View.MeasureSpec#getMode(int)
19009     * @see android.view.View.MeasureSpec#getSize(int)
19010     */
19011    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19012        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19013                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19014    }
19015
19016    /**
19017     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19018     * measured width and measured height. Failing to do so will trigger an
19019     * exception at measurement time.</p>
19020     *
19021     * @param measuredWidth The measured width of this view.  May be a complex
19022     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19023     * {@link #MEASURED_STATE_TOO_SMALL}.
19024     * @param measuredHeight The measured height of this view.  May be a complex
19025     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19026     * {@link #MEASURED_STATE_TOO_SMALL}.
19027     */
19028    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19029        boolean optical = isLayoutModeOptical(this);
19030        if (optical != isLayoutModeOptical(mParent)) {
19031            Insets insets = getOpticalInsets();
19032            int opticalWidth  = insets.left + insets.right;
19033            int opticalHeight = insets.top  + insets.bottom;
19034
19035            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
19036            measuredHeight += optical ? opticalHeight : -opticalHeight;
19037        }
19038        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19039    }
19040
19041    /**
19042     * Sets the measured dimension without extra processing for things like optical bounds.
19043     * Useful for reapplying consistent values that have already been cooked with adjustments
19044     * for optical bounds, etc. such as those from the measurement cache.
19045     *
19046     * @param measuredWidth The measured width of this view.  May be a complex
19047     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19048     * {@link #MEASURED_STATE_TOO_SMALL}.
19049     * @param measuredHeight The measured height of this view.  May be a complex
19050     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19051     * {@link #MEASURED_STATE_TOO_SMALL}.
19052     */
19053    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19054        mMeasuredWidth = measuredWidth;
19055        mMeasuredHeight = measuredHeight;
19056
19057        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19058    }
19059
19060    /**
19061     * Merge two states as returned by {@link #getMeasuredState()}.
19062     * @param curState The current state as returned from a view or the result
19063     * of combining multiple views.
19064     * @param newState The new view state to combine.
19065     * @return Returns a new integer reflecting the combination of the two
19066     * states.
19067     */
19068    public static int combineMeasuredStates(int curState, int newState) {
19069        return curState | newState;
19070    }
19071
19072    /**
19073     * Version of {@link #resolveSizeAndState(int, int, int)}
19074     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
19075     */
19076    public static int resolveSize(int size, int measureSpec) {
19077        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
19078    }
19079
19080    /**
19081     * Utility to reconcile a desired size and state, with constraints imposed
19082     * by a MeasureSpec. Will take the desired size, unless a different size
19083     * is imposed by the constraints. The returned value is a compound integer,
19084     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
19085     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
19086     * resulting size is smaller than the size the view wants to be.
19087     *
19088     * @param size How big the view wants to be.
19089     * @param measureSpec Constraints imposed by the parent.
19090     * @param childMeasuredState Size information bit mask for the view's
19091     *                           children.
19092     * @return Size information bit mask as defined by
19093     *         {@link #MEASURED_SIZE_MASK} and
19094     *         {@link #MEASURED_STATE_TOO_SMALL}.
19095     */
19096    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
19097        final int specMode = MeasureSpec.getMode(measureSpec);
19098        final int specSize = MeasureSpec.getSize(measureSpec);
19099        final int result;
19100        switch (specMode) {
19101            case MeasureSpec.AT_MOST:
19102                if (specSize < size) {
19103                    result = specSize | MEASURED_STATE_TOO_SMALL;
19104                } else {
19105                    result = size;
19106                }
19107                break;
19108            case MeasureSpec.EXACTLY:
19109                result = specSize;
19110                break;
19111            case MeasureSpec.UNSPECIFIED:
19112            default:
19113                result = size;
19114        }
19115        return result | (childMeasuredState & MEASURED_STATE_MASK);
19116    }
19117
19118    /**
19119     * Utility to return a default size. Uses the supplied size if the
19120     * MeasureSpec imposed no constraints. Will get larger if allowed
19121     * by the MeasureSpec.
19122     *
19123     * @param size Default size for this view
19124     * @param measureSpec Constraints imposed by the parent
19125     * @return The size this view should be.
19126     */
19127    public static int getDefaultSize(int size, int measureSpec) {
19128        int result = size;
19129        int specMode = MeasureSpec.getMode(measureSpec);
19130        int specSize = MeasureSpec.getSize(measureSpec);
19131
19132        switch (specMode) {
19133        case MeasureSpec.UNSPECIFIED:
19134            result = size;
19135            break;
19136        case MeasureSpec.AT_MOST:
19137        case MeasureSpec.EXACTLY:
19138            result = specSize;
19139            break;
19140        }
19141        return result;
19142    }
19143
19144    /**
19145     * Returns the suggested minimum height that the view should use. This
19146     * returns the maximum of the view's minimum height
19147     * and the background's minimum height
19148     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
19149     * <p>
19150     * When being used in {@link #onMeasure(int, int)}, the caller should still
19151     * ensure the returned height is within the requirements of the parent.
19152     *
19153     * @return The suggested minimum height of the view.
19154     */
19155    protected int getSuggestedMinimumHeight() {
19156        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
19157
19158    }
19159
19160    /**
19161     * Returns the suggested minimum width that the view should use. This
19162     * returns the maximum of the view's minimum width
19163     * and the background's minimum width
19164     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
19165     * <p>
19166     * When being used in {@link #onMeasure(int, int)}, the caller should still
19167     * ensure the returned width is within the requirements of the parent.
19168     *
19169     * @return The suggested minimum width of the view.
19170     */
19171    protected int getSuggestedMinimumWidth() {
19172        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
19173    }
19174
19175    /**
19176     * Returns the minimum height of the view.
19177     *
19178     * @return the minimum height the view will try to be.
19179     *
19180     * @see #setMinimumHeight(int)
19181     *
19182     * @attr ref android.R.styleable#View_minHeight
19183     */
19184    public int getMinimumHeight() {
19185        return mMinHeight;
19186    }
19187
19188    /**
19189     * Sets the minimum height of the view. It is not guaranteed the view will
19190     * be able to achieve this minimum height (for example, if its parent layout
19191     * constrains it with less available height).
19192     *
19193     * @param minHeight The minimum height the view will try to be.
19194     *
19195     * @see #getMinimumHeight()
19196     *
19197     * @attr ref android.R.styleable#View_minHeight
19198     */
19199    public void setMinimumHeight(int minHeight) {
19200        mMinHeight = minHeight;
19201        requestLayout();
19202    }
19203
19204    /**
19205     * Returns the minimum width of the view.
19206     *
19207     * @return the minimum width the view will try to be.
19208     *
19209     * @see #setMinimumWidth(int)
19210     *
19211     * @attr ref android.R.styleable#View_minWidth
19212     */
19213    public int getMinimumWidth() {
19214        return mMinWidth;
19215    }
19216
19217    /**
19218     * Sets the minimum width of the view. It is not guaranteed the view will
19219     * be able to achieve this minimum width (for example, if its parent layout
19220     * constrains it with less available width).
19221     *
19222     * @param minWidth The minimum width the view will try to be.
19223     *
19224     * @see #getMinimumWidth()
19225     *
19226     * @attr ref android.R.styleable#View_minWidth
19227     */
19228    public void setMinimumWidth(int minWidth) {
19229        mMinWidth = minWidth;
19230        requestLayout();
19231
19232    }
19233
19234    /**
19235     * Get the animation currently associated with this view.
19236     *
19237     * @return The animation that is currently playing or
19238     *         scheduled to play for this view.
19239     */
19240    public Animation getAnimation() {
19241        return mCurrentAnimation;
19242    }
19243
19244    /**
19245     * Start the specified animation now.
19246     *
19247     * @param animation the animation to start now
19248     */
19249    public void startAnimation(Animation animation) {
19250        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
19251        setAnimation(animation);
19252        invalidateParentCaches();
19253        invalidate(true);
19254    }
19255
19256    /**
19257     * Cancels any animations for this view.
19258     */
19259    public void clearAnimation() {
19260        if (mCurrentAnimation != null) {
19261            mCurrentAnimation.detach();
19262        }
19263        mCurrentAnimation = null;
19264        invalidateParentIfNeeded();
19265    }
19266
19267    /**
19268     * Sets the next animation to play for this view.
19269     * If you want the animation to play immediately, use
19270     * {@link #startAnimation(android.view.animation.Animation)} instead.
19271     * This method provides allows fine-grained
19272     * control over the start time and invalidation, but you
19273     * must make sure that 1) the animation has a start time set, and
19274     * 2) the view's parent (which controls animations on its children)
19275     * will be invalidated when the animation is supposed to
19276     * start.
19277     *
19278     * @param animation The next animation, or null.
19279     */
19280    public void setAnimation(Animation animation) {
19281        mCurrentAnimation = animation;
19282
19283        if (animation != null) {
19284            // If the screen is off assume the animation start time is now instead of
19285            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
19286            // would cause the animation to start when the screen turns back on
19287            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
19288                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
19289                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
19290            }
19291            animation.reset();
19292        }
19293    }
19294
19295    /**
19296     * Invoked by a parent ViewGroup to notify the start of the animation
19297     * currently associated with this view. If you override this method,
19298     * always call super.onAnimationStart();
19299     *
19300     * @see #setAnimation(android.view.animation.Animation)
19301     * @see #getAnimation()
19302     */
19303    @CallSuper
19304    protected void onAnimationStart() {
19305        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
19306    }
19307
19308    /**
19309     * Invoked by a parent ViewGroup to notify the end of the animation
19310     * currently associated with this view. If you override this method,
19311     * always call super.onAnimationEnd();
19312     *
19313     * @see #setAnimation(android.view.animation.Animation)
19314     * @see #getAnimation()
19315     */
19316    @CallSuper
19317    protected void onAnimationEnd() {
19318        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
19319    }
19320
19321    /**
19322     * Invoked if there is a Transform that involves alpha. Subclass that can
19323     * draw themselves with the specified alpha should return true, and then
19324     * respect that alpha when their onDraw() is called. If this returns false
19325     * then the view may be redirected to draw into an offscreen buffer to
19326     * fulfill the request, which will look fine, but may be slower than if the
19327     * subclass handles it internally. The default implementation returns false.
19328     *
19329     * @param alpha The alpha (0..255) to apply to the view's drawing
19330     * @return true if the view can draw with the specified alpha.
19331     */
19332    protected boolean onSetAlpha(int alpha) {
19333        return false;
19334    }
19335
19336    /**
19337     * This is used by the RootView to perform an optimization when
19338     * the view hierarchy contains one or several SurfaceView.
19339     * SurfaceView is always considered transparent, but its children are not,
19340     * therefore all View objects remove themselves from the global transparent
19341     * region (passed as a parameter to this function).
19342     *
19343     * @param region The transparent region for this ViewAncestor (window).
19344     *
19345     * @return Returns true if the effective visibility of the view at this
19346     * point is opaque, regardless of the transparent region; returns false
19347     * if it is possible for underlying windows to be seen behind the view.
19348     *
19349     * {@hide}
19350     */
19351    public boolean gatherTransparentRegion(Region region) {
19352        final AttachInfo attachInfo = mAttachInfo;
19353        if (region != null && attachInfo != null) {
19354            final int pflags = mPrivateFlags;
19355            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
19356                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
19357                // remove it from the transparent region.
19358                final int[] location = attachInfo.mTransparentLocation;
19359                getLocationInWindow(location);
19360                region.op(location[0], location[1], location[0] + mRight - mLeft,
19361                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
19362            } else {
19363                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
19364                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
19365                    // the background drawable's non-transparent parts from this transparent region.
19366                    applyDrawableToTransparentRegion(mBackground, region);
19367                }
19368                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19369                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
19370                    // Similarly, we remove the foreground drawable's non-transparent parts.
19371                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
19372                }
19373            }
19374        }
19375        return true;
19376    }
19377
19378    /**
19379     * Play a sound effect for this view.
19380     *
19381     * <p>The framework will play sound effects for some built in actions, such as
19382     * clicking, but you may wish to play these effects in your widget,
19383     * for instance, for internal navigation.
19384     *
19385     * <p>The sound effect will only be played if sound effects are enabled by the user, and
19386     * {@link #isSoundEffectsEnabled()} is true.
19387     *
19388     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
19389     */
19390    public void playSoundEffect(int soundConstant) {
19391        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
19392            return;
19393        }
19394        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
19395    }
19396
19397    /**
19398     * BZZZTT!!1!
19399     *
19400     * <p>Provide haptic feedback to the user for this view.
19401     *
19402     * <p>The framework will provide haptic feedback for some built in actions,
19403     * such as long presses, but you may wish to provide feedback for your
19404     * own widget.
19405     *
19406     * <p>The feedback will only be performed if
19407     * {@link #isHapticFeedbackEnabled()} is true.
19408     *
19409     * @param feedbackConstant One of the constants defined in
19410     * {@link HapticFeedbackConstants}
19411     */
19412    public boolean performHapticFeedback(int feedbackConstant) {
19413        return performHapticFeedback(feedbackConstant, 0);
19414    }
19415
19416    /**
19417     * BZZZTT!!1!
19418     *
19419     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
19420     *
19421     * @param feedbackConstant One of the constants defined in
19422     * {@link HapticFeedbackConstants}
19423     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
19424     */
19425    public boolean performHapticFeedback(int feedbackConstant, int flags) {
19426        if (mAttachInfo == null) {
19427            return false;
19428        }
19429        //noinspection SimplifiableIfStatement
19430        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
19431                && !isHapticFeedbackEnabled()) {
19432            return false;
19433        }
19434        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
19435                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
19436    }
19437
19438    /**
19439     * Request that the visibility of the status bar or other screen/window
19440     * decorations be changed.
19441     *
19442     * <p>This method is used to put the over device UI into temporary modes
19443     * where the user's attention is focused more on the application content,
19444     * by dimming or hiding surrounding system affordances.  This is typically
19445     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
19446     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
19447     * to be placed behind the action bar (and with these flags other system
19448     * affordances) so that smooth transitions between hiding and showing them
19449     * can be done.
19450     *
19451     * <p>Two representative examples of the use of system UI visibility is
19452     * implementing a content browsing application (like a magazine reader)
19453     * and a video playing application.
19454     *
19455     * <p>The first code shows a typical implementation of a View in a content
19456     * browsing application.  In this implementation, the application goes
19457     * into a content-oriented mode by hiding the status bar and action bar,
19458     * and putting the navigation elements into lights out mode.  The user can
19459     * then interact with content while in this mode.  Such an application should
19460     * provide an easy way for the user to toggle out of the mode (such as to
19461     * check information in the status bar or access notifications).  In the
19462     * implementation here, this is done simply by tapping on the content.
19463     *
19464     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
19465     *      content}
19466     *
19467     * <p>This second code sample shows a typical implementation of a View
19468     * in a video playing application.  In this situation, while the video is
19469     * playing the application would like to go into a complete full-screen mode,
19470     * to use as much of the display as possible for the video.  When in this state
19471     * the user can not interact with the application; the system intercepts
19472     * touching on the screen to pop the UI out of full screen mode.  See
19473     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
19474     *
19475     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
19476     *      content}
19477     *
19478     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19479     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19480     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19481     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19482     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19483     */
19484    public void setSystemUiVisibility(int visibility) {
19485        if (visibility != mSystemUiVisibility) {
19486            mSystemUiVisibility = visibility;
19487            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19488                mParent.recomputeViewAttributes(this);
19489            }
19490        }
19491    }
19492
19493    /**
19494     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
19495     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19496     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19497     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19498     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19499     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19500     */
19501    public int getSystemUiVisibility() {
19502        return mSystemUiVisibility;
19503    }
19504
19505    /**
19506     * Returns the current system UI visibility that is currently set for
19507     * the entire window.  This is the combination of the
19508     * {@link #setSystemUiVisibility(int)} values supplied by all of the
19509     * views in the window.
19510     */
19511    public int getWindowSystemUiVisibility() {
19512        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
19513    }
19514
19515    /**
19516     * Override to find out when the window's requested system UI visibility
19517     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
19518     * This is different from the callbacks received through
19519     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
19520     * in that this is only telling you about the local request of the window,
19521     * not the actual values applied by the system.
19522     */
19523    public void onWindowSystemUiVisibilityChanged(int visible) {
19524    }
19525
19526    /**
19527     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
19528     * the view hierarchy.
19529     */
19530    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
19531        onWindowSystemUiVisibilityChanged(visible);
19532    }
19533
19534    /**
19535     * Set a listener to receive callbacks when the visibility of the system bar changes.
19536     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
19537     */
19538    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
19539        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
19540        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19541            mParent.recomputeViewAttributes(this);
19542        }
19543    }
19544
19545    /**
19546     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
19547     * the view hierarchy.
19548     */
19549    public void dispatchSystemUiVisibilityChanged(int visibility) {
19550        ListenerInfo li = mListenerInfo;
19551        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
19552            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
19553                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
19554        }
19555    }
19556
19557    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
19558        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
19559        if (val != mSystemUiVisibility) {
19560            setSystemUiVisibility(val);
19561            return true;
19562        }
19563        return false;
19564    }
19565
19566    /** @hide */
19567    public void setDisabledSystemUiVisibility(int flags) {
19568        if (mAttachInfo != null) {
19569            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
19570                mAttachInfo.mDisabledSystemUiVisibility = flags;
19571                if (mParent != null) {
19572                    mParent.recomputeViewAttributes(this);
19573                }
19574            }
19575        }
19576    }
19577
19578    /**
19579     * Creates an image that the system displays during the drag and drop
19580     * operation. This is called a &quot;drag shadow&quot;. The default implementation
19581     * for a DragShadowBuilder based on a View returns an image that has exactly the same
19582     * appearance as the given View. The default also positions the center of the drag shadow
19583     * directly under the touch point. If no View is provided (the constructor with no parameters
19584     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
19585     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
19586     * default is an invisible drag shadow.
19587     * <p>
19588     * You are not required to use the View you provide to the constructor as the basis of the
19589     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
19590     * anything you want as the drag shadow.
19591     * </p>
19592     * <p>
19593     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
19594     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
19595     *  size and position of the drag shadow. It uses this data to construct a
19596     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
19597     *  so that your application can draw the shadow image in the Canvas.
19598     * </p>
19599     *
19600     * <div class="special reference">
19601     * <h3>Developer Guides</h3>
19602     * <p>For a guide to implementing drag and drop features, read the
19603     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19604     * </div>
19605     */
19606    public static class DragShadowBuilder {
19607        private final WeakReference<View> mView;
19608
19609        /**
19610         * Constructs a shadow image builder based on a View. By default, the resulting drag
19611         * shadow will have the same appearance and dimensions as the View, with the touch point
19612         * over the center of the View.
19613         * @param view A View. Any View in scope can be used.
19614         */
19615        public DragShadowBuilder(View view) {
19616            mView = new WeakReference<View>(view);
19617        }
19618
19619        /**
19620         * Construct a shadow builder object with no associated View.  This
19621         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
19622         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
19623         * to supply the drag shadow's dimensions and appearance without
19624         * reference to any View object. If they are not overridden, then the result is an
19625         * invisible drag shadow.
19626         */
19627        public DragShadowBuilder() {
19628            mView = new WeakReference<View>(null);
19629        }
19630
19631        /**
19632         * Returns the View object that had been passed to the
19633         * {@link #View.DragShadowBuilder(View)}
19634         * constructor.  If that View parameter was {@code null} or if the
19635         * {@link #View.DragShadowBuilder()}
19636         * constructor was used to instantiate the builder object, this method will return
19637         * null.
19638         *
19639         * @return The View object associate with this builder object.
19640         */
19641        @SuppressWarnings({"JavadocReference"})
19642        final public View getView() {
19643            return mView.get();
19644        }
19645
19646        /**
19647         * Provides the metrics for the shadow image. These include the dimensions of
19648         * the shadow image, and the point within that shadow that should
19649         * be centered under the touch location while dragging.
19650         * <p>
19651         * The default implementation sets the dimensions of the shadow to be the
19652         * same as the dimensions of the View itself and centers the shadow under
19653         * the touch point.
19654         * </p>
19655         *
19656         * @param shadowSize A {@link android.graphics.Point} containing the width and height
19657         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
19658         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
19659         * image.
19660         *
19661         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
19662         * shadow image that should be underneath the touch point during the drag and drop
19663         * operation. Your application must set {@link android.graphics.Point#x} to the
19664         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
19665         */
19666        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
19667            final View view = mView.get();
19668            if (view != null) {
19669                shadowSize.set(view.getWidth(), view.getHeight());
19670                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
19671            } else {
19672                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
19673            }
19674        }
19675
19676        /**
19677         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
19678         * based on the dimensions it received from the
19679         * {@link #onProvideShadowMetrics(Point, Point)} callback.
19680         *
19681         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
19682         */
19683        public void onDrawShadow(Canvas canvas) {
19684            final View view = mView.get();
19685            if (view != null) {
19686                view.draw(canvas);
19687            } else {
19688                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
19689            }
19690        }
19691    }
19692
19693    /**
19694     * Starts a drag and drop operation. When your application calls this method, it passes a
19695     * {@link android.view.View.DragShadowBuilder} object to the system. The
19696     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
19697     * to get metrics for the drag shadow, and then calls the object's
19698     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
19699     * <p>
19700     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
19701     *  drag events to all the View objects in your application that are currently visible. It does
19702     *  this either by calling the View object's drag listener (an implementation of
19703     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
19704     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
19705     *  Both are passed a {@link android.view.DragEvent} object that has a
19706     *  {@link android.view.DragEvent#getAction()} value of
19707     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19708     * </p>
19709     * <p>
19710     * Your application can invoke startDrag() on any attached View object. The View object does not
19711     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
19712     * be related to the View the user selected for dragging.
19713     * </p>
19714     * @param data A {@link android.content.ClipData} object pointing to the data to be
19715     * transferred by the drag and drop operation.
19716     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19717     * drag shadow.
19718     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19719     * drop operation. This Object is put into every DragEvent object sent by the system during the
19720     * current drag.
19721     * <p>
19722     * myLocalState is a lightweight mechanism for the sending information from the dragged View
19723     * to the target Views. For example, it can contain flags that differentiate between a
19724     * a copy operation and a move operation.
19725     * </p>
19726     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19727     * so the parameter should be set to 0.
19728     * @return {@code true} if the method completes successfully, or
19729     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19730     * do a drag, and so no drag operation is in progress.
19731     */
19732    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19733            Object myLocalState, int flags) {
19734        if (ViewDebug.DEBUG_DRAG) {
19735            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
19736        }
19737        boolean okay = false;
19738
19739        Point shadowSize = new Point();
19740        Point shadowTouchPoint = new Point();
19741        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
19742
19743        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
19744                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
19745            throw new IllegalStateException("Drag shadow dimensions must not be negative");
19746        }
19747
19748        if (ViewDebug.DEBUG_DRAG) {
19749            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
19750                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
19751        }
19752        Surface surface = new Surface();
19753        try {
19754            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
19755                    flags, shadowSize.x, shadowSize.y, surface);
19756            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
19757                    + " surface=" + surface);
19758            if (token != null) {
19759                Canvas canvas = surface.lockCanvas(null);
19760                try {
19761                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
19762                    shadowBuilder.onDrawShadow(canvas);
19763                } finally {
19764                    surface.unlockCanvasAndPost(canvas);
19765                }
19766
19767                final ViewRootImpl root = getViewRootImpl();
19768
19769                // Cache the local state object for delivery with DragEvents
19770                root.setLocalDragState(myLocalState);
19771
19772                // repurpose 'shadowSize' for the last touch point
19773                root.getLastTouchPoint(shadowSize);
19774
19775                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
19776                        shadowSize.x, shadowSize.y,
19777                        shadowTouchPoint.x, shadowTouchPoint.y, data);
19778                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
19779
19780                // Off and running!  Release our local surface instance; the drag
19781                // shadow surface is now managed by the system process.
19782                surface.release();
19783            }
19784        } catch (Exception e) {
19785            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
19786            surface.destroy();
19787        }
19788
19789        return okay;
19790    }
19791
19792    /**
19793     * Starts a move from {startX, startY}, the amount of the movement will be the offset
19794     * between {startX, startY} and the new cursor positon.
19795     * @param startX horizontal coordinate where the move started.
19796     * @param startY vertical coordinate where the move started.
19797     * @return whether moving was started successfully.
19798     * @hide
19799     */
19800    public final boolean startMovingTask(float startX, float startY) {
19801        if (ViewDebug.DEBUG_POSITIONING) {
19802            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
19803        }
19804        try {
19805            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
19806        } catch (RemoteException e) {
19807            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
19808        }
19809        return false;
19810    }
19811
19812    /**
19813     * Handles drag events sent by the system following a call to
19814     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
19815     *<p>
19816     * When the system calls this method, it passes a
19817     * {@link android.view.DragEvent} object. A call to
19818     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
19819     * in DragEvent. The method uses these to determine what is happening in the drag and drop
19820     * operation.
19821     * @param event The {@link android.view.DragEvent} sent by the system.
19822     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
19823     * in DragEvent, indicating the type of drag event represented by this object.
19824     * @return {@code true} if the method was successful, otherwise {@code false}.
19825     * <p>
19826     *  The method should return {@code true} in response to an action type of
19827     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
19828     *  operation.
19829     * </p>
19830     * <p>
19831     *  The method should also return {@code true} in response to an action type of
19832     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19833     *  {@code false} if it didn't.
19834     * </p>
19835     */
19836    public boolean onDragEvent(DragEvent event) {
19837        return false;
19838    }
19839
19840    /**
19841     * Detects if this View is enabled and has a drag event listener.
19842     * If both are true, then it calls the drag event listener with the
19843     * {@link android.view.DragEvent} it received. If the drag event listener returns
19844     * {@code true}, then dispatchDragEvent() returns {@code true}.
19845     * <p>
19846     * For all other cases, the method calls the
19847     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
19848     * method and returns its result.
19849     * </p>
19850     * <p>
19851     * This ensures that a drag event is always consumed, even if the View does not have a drag
19852     * event listener. However, if the View has a listener and the listener returns true, then
19853     * onDragEvent() is not called.
19854     * </p>
19855     */
19856    public boolean dispatchDragEvent(DragEvent event) {
19857        ListenerInfo li = mListenerInfo;
19858        //noinspection SimplifiableIfStatement
19859        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
19860                && li.mOnDragListener.onDrag(this, event)) {
19861            return true;
19862        }
19863        return onDragEvent(event);
19864    }
19865
19866    boolean canAcceptDrag() {
19867        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
19868    }
19869
19870    /**
19871     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
19872     * it is ever exposed at all.
19873     * @hide
19874     */
19875    public void onCloseSystemDialogs(String reason) {
19876    }
19877
19878    /**
19879     * Given a Drawable whose bounds have been set to draw into this view,
19880     * update a Region being computed for
19881     * {@link #gatherTransparentRegion(android.graphics.Region)} so
19882     * that any non-transparent parts of the Drawable are removed from the
19883     * given transparent region.
19884     *
19885     * @param dr The Drawable whose transparency is to be applied to the region.
19886     * @param region A Region holding the current transparency information,
19887     * where any parts of the region that are set are considered to be
19888     * transparent.  On return, this region will be modified to have the
19889     * transparency information reduced by the corresponding parts of the
19890     * Drawable that are not transparent.
19891     * {@hide}
19892     */
19893    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
19894        if (DBG) {
19895            Log.i("View", "Getting transparent region for: " + this);
19896        }
19897        final Region r = dr.getTransparentRegion();
19898        final Rect db = dr.getBounds();
19899        final AttachInfo attachInfo = mAttachInfo;
19900        if (r != null && attachInfo != null) {
19901            final int w = getRight()-getLeft();
19902            final int h = getBottom()-getTop();
19903            if (db.left > 0) {
19904                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
19905                r.op(0, 0, db.left, h, Region.Op.UNION);
19906            }
19907            if (db.right < w) {
19908                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
19909                r.op(db.right, 0, w, h, Region.Op.UNION);
19910            }
19911            if (db.top > 0) {
19912                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
19913                r.op(0, 0, w, db.top, Region.Op.UNION);
19914            }
19915            if (db.bottom < h) {
19916                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
19917                r.op(0, db.bottom, w, h, Region.Op.UNION);
19918            }
19919            final int[] location = attachInfo.mTransparentLocation;
19920            getLocationInWindow(location);
19921            r.translate(location[0], location[1]);
19922            region.op(r, Region.Op.INTERSECT);
19923        } else {
19924            region.op(db, Region.Op.DIFFERENCE);
19925        }
19926    }
19927
19928    private void checkForLongClick(int delayOffset) {
19929        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
19930            mHasPerformedLongPress = false;
19931
19932            if (mPendingCheckForLongPress == null) {
19933                mPendingCheckForLongPress = new CheckForLongPress();
19934            }
19935            mPendingCheckForLongPress.rememberWindowAttachCount();
19936            postDelayed(mPendingCheckForLongPress,
19937                    ViewConfiguration.getLongPressTimeout() - delayOffset);
19938        }
19939    }
19940
19941    /**
19942     * Inflate a view from an XML resource.  This convenience method wraps the {@link
19943     * LayoutInflater} class, which provides a full range of options for view inflation.
19944     *
19945     * @param context The Context object for your activity or application.
19946     * @param resource The resource ID to inflate
19947     * @param root A view group that will be the parent.  Used to properly inflate the
19948     * layout_* parameters.
19949     * @see LayoutInflater
19950     */
19951    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
19952        LayoutInflater factory = LayoutInflater.from(context);
19953        return factory.inflate(resource, root);
19954    }
19955
19956    /**
19957     * Scroll the view with standard behavior for scrolling beyond the normal
19958     * content boundaries. Views that call this method should override
19959     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
19960     * results of an over-scroll operation.
19961     *
19962     * Views can use this method to handle any touch or fling-based scrolling.
19963     *
19964     * @param deltaX Change in X in pixels
19965     * @param deltaY Change in Y in pixels
19966     * @param scrollX Current X scroll value in pixels before applying deltaX
19967     * @param scrollY Current Y scroll value in pixels before applying deltaY
19968     * @param scrollRangeX Maximum content scroll range along the X axis
19969     * @param scrollRangeY Maximum content scroll range along the Y axis
19970     * @param maxOverScrollX Number of pixels to overscroll by in either direction
19971     *          along the X axis.
19972     * @param maxOverScrollY Number of pixels to overscroll by in either direction
19973     *          along the Y axis.
19974     * @param isTouchEvent true if this scroll operation is the result of a touch event.
19975     * @return true if scrolling was clamped to an over-scroll boundary along either
19976     *          axis, false otherwise.
19977     */
19978    @SuppressWarnings({"UnusedParameters"})
19979    protected boolean overScrollBy(int deltaX, int deltaY,
19980            int scrollX, int scrollY,
19981            int scrollRangeX, int scrollRangeY,
19982            int maxOverScrollX, int maxOverScrollY,
19983            boolean isTouchEvent) {
19984        final int overScrollMode = mOverScrollMode;
19985        final boolean canScrollHorizontal =
19986                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
19987        final boolean canScrollVertical =
19988                computeVerticalScrollRange() > computeVerticalScrollExtent();
19989        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
19990                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
19991        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
19992                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
19993
19994        int newScrollX = scrollX + deltaX;
19995        if (!overScrollHorizontal) {
19996            maxOverScrollX = 0;
19997        }
19998
19999        int newScrollY = scrollY + deltaY;
20000        if (!overScrollVertical) {
20001            maxOverScrollY = 0;
20002        }
20003
20004        // Clamp values if at the limits and record
20005        final int left = -maxOverScrollX;
20006        final int right = maxOverScrollX + scrollRangeX;
20007        final int top = -maxOverScrollY;
20008        final int bottom = maxOverScrollY + scrollRangeY;
20009
20010        boolean clampedX = false;
20011        if (newScrollX > right) {
20012            newScrollX = right;
20013            clampedX = true;
20014        } else if (newScrollX < left) {
20015            newScrollX = left;
20016            clampedX = true;
20017        }
20018
20019        boolean clampedY = false;
20020        if (newScrollY > bottom) {
20021            newScrollY = bottom;
20022            clampedY = true;
20023        } else if (newScrollY < top) {
20024            newScrollY = top;
20025            clampedY = true;
20026        }
20027
20028        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
20029
20030        return clampedX || clampedY;
20031    }
20032
20033    /**
20034     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
20035     * respond to the results of an over-scroll operation.
20036     *
20037     * @param scrollX New X scroll value in pixels
20038     * @param scrollY New Y scroll value in pixels
20039     * @param clampedX True if scrollX was clamped to an over-scroll boundary
20040     * @param clampedY True if scrollY was clamped to an over-scroll boundary
20041     */
20042    protected void onOverScrolled(int scrollX, int scrollY,
20043            boolean clampedX, boolean clampedY) {
20044        // Intentionally empty.
20045    }
20046
20047    /**
20048     * Returns the over-scroll mode for this view. The result will be
20049     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
20050     * (allow over-scrolling only if the view content is larger than the container),
20051     * or {@link #OVER_SCROLL_NEVER}.
20052     *
20053     * @return This view's over-scroll mode.
20054     */
20055    public int getOverScrollMode() {
20056        return mOverScrollMode;
20057    }
20058
20059    /**
20060     * Set the over-scroll mode for this view. Valid over-scroll modes are
20061     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
20062     * (allow over-scrolling only if the view content is larger than the container),
20063     * or {@link #OVER_SCROLL_NEVER}.
20064     *
20065     * Setting the over-scroll mode of a view will have an effect only if the
20066     * view is capable of scrolling.
20067     *
20068     * @param overScrollMode The new over-scroll mode for this view.
20069     */
20070    public void setOverScrollMode(int overScrollMode) {
20071        if (overScrollMode != OVER_SCROLL_ALWAYS &&
20072                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
20073                overScrollMode != OVER_SCROLL_NEVER) {
20074            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
20075        }
20076        mOverScrollMode = overScrollMode;
20077    }
20078
20079    /**
20080     * Enable or disable nested scrolling for this view.
20081     *
20082     * <p>If this property is set to true the view will be permitted to initiate nested
20083     * scrolling operations with a compatible parent view in the current hierarchy. If this
20084     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
20085     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
20086     * the nested scroll.</p>
20087     *
20088     * @param enabled true to enable nested scrolling, false to disable
20089     *
20090     * @see #isNestedScrollingEnabled()
20091     */
20092    public void setNestedScrollingEnabled(boolean enabled) {
20093        if (enabled) {
20094            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
20095        } else {
20096            stopNestedScroll();
20097            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
20098        }
20099    }
20100
20101    /**
20102     * Returns true if nested scrolling is enabled for this view.
20103     *
20104     * <p>If nested scrolling is enabled and this View class implementation supports it,
20105     * this view will act as a nested scrolling child view when applicable, forwarding data
20106     * about the scroll operation in progress to a compatible and cooperating nested scrolling
20107     * parent.</p>
20108     *
20109     * @return true if nested scrolling is enabled
20110     *
20111     * @see #setNestedScrollingEnabled(boolean)
20112     */
20113    public boolean isNestedScrollingEnabled() {
20114        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
20115                PFLAG3_NESTED_SCROLLING_ENABLED;
20116    }
20117
20118    /**
20119     * Begin a nestable scroll operation along the given axes.
20120     *
20121     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
20122     *
20123     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
20124     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
20125     * In the case of touch scrolling the nested scroll will be terminated automatically in
20126     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
20127     * In the event of programmatic scrolling the caller must explicitly call
20128     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
20129     *
20130     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
20131     * If it returns false the caller may ignore the rest of this contract until the next scroll.
20132     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
20133     *
20134     * <p>At each incremental step of the scroll the caller should invoke
20135     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
20136     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
20137     * parent at least partially consumed the scroll and the caller should adjust the amount it
20138     * scrolls by.</p>
20139     *
20140     * <p>After applying the remainder of the scroll delta the caller should invoke
20141     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
20142     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
20143     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
20144     * </p>
20145     *
20146     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
20147     *             {@link #SCROLL_AXIS_VERTICAL}.
20148     * @return true if a cooperative parent was found and nested scrolling has been enabled for
20149     *         the current gesture.
20150     *
20151     * @see #stopNestedScroll()
20152     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20153     * @see #dispatchNestedScroll(int, int, int, int, int[])
20154     */
20155    public boolean startNestedScroll(int axes) {
20156        if (hasNestedScrollingParent()) {
20157            // Already in progress
20158            return true;
20159        }
20160        if (isNestedScrollingEnabled()) {
20161            ViewParent p = getParent();
20162            View child = this;
20163            while (p != null) {
20164                try {
20165                    if (p.onStartNestedScroll(child, this, axes)) {
20166                        mNestedScrollingParent = p;
20167                        p.onNestedScrollAccepted(child, this, axes);
20168                        return true;
20169                    }
20170                } catch (AbstractMethodError e) {
20171                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
20172                            "method onStartNestedScroll", e);
20173                    // Allow the search upward to continue
20174                }
20175                if (p instanceof View) {
20176                    child = (View) p;
20177                }
20178                p = p.getParent();
20179            }
20180        }
20181        return false;
20182    }
20183
20184    /**
20185     * Stop a nested scroll in progress.
20186     *
20187     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
20188     *
20189     * @see #startNestedScroll(int)
20190     */
20191    public void stopNestedScroll() {
20192        if (mNestedScrollingParent != null) {
20193            mNestedScrollingParent.onStopNestedScroll(this);
20194            mNestedScrollingParent = null;
20195        }
20196    }
20197
20198    /**
20199     * Returns true if this view has a nested scrolling parent.
20200     *
20201     * <p>The presence of a nested scrolling parent indicates that this view has initiated
20202     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
20203     *
20204     * @return whether this view has a nested scrolling parent
20205     */
20206    public boolean hasNestedScrollingParent() {
20207        return mNestedScrollingParent != null;
20208    }
20209
20210    /**
20211     * Dispatch one step of a nested scroll in progress.
20212     *
20213     * <p>Implementations of views that support nested scrolling should call this to report
20214     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
20215     * is not currently in progress or nested scrolling is not
20216     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
20217     *
20218     * <p>Compatible View implementations should also call
20219     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
20220     * consuming a component of the scroll event themselves.</p>
20221     *
20222     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
20223     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
20224     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
20225     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
20226     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20227     *                       in local view coordinates of this view from before this operation
20228     *                       to after it completes. View implementations may use this to adjust
20229     *                       expected input coordinate tracking.
20230     * @return true if the event was dispatched, false if it could not be dispatched.
20231     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20232     */
20233    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
20234            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
20235        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20236            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
20237                int startX = 0;
20238                int startY = 0;
20239                if (offsetInWindow != null) {
20240                    getLocationInWindow(offsetInWindow);
20241                    startX = offsetInWindow[0];
20242                    startY = offsetInWindow[1];
20243                }
20244
20245                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
20246                        dxUnconsumed, dyUnconsumed);
20247
20248                if (offsetInWindow != null) {
20249                    getLocationInWindow(offsetInWindow);
20250                    offsetInWindow[0] -= startX;
20251                    offsetInWindow[1] -= startY;
20252                }
20253                return true;
20254            } else if (offsetInWindow != null) {
20255                // No motion, no dispatch. Keep offsetInWindow up to date.
20256                offsetInWindow[0] = 0;
20257                offsetInWindow[1] = 0;
20258            }
20259        }
20260        return false;
20261    }
20262
20263    /**
20264     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
20265     *
20266     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
20267     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
20268     * scrolling operation to consume some or all of the scroll operation before the child view
20269     * consumes it.</p>
20270     *
20271     * @param dx Horizontal scroll distance in pixels
20272     * @param dy Vertical scroll distance in pixels
20273     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
20274     *                 and consumed[1] the consumed dy.
20275     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20276     *                       in local view coordinates of this view from before this operation
20277     *                       to after it completes. View implementations may use this to adjust
20278     *                       expected input coordinate tracking.
20279     * @return true if the parent consumed some or all of the scroll delta
20280     * @see #dispatchNestedScroll(int, int, int, int, int[])
20281     */
20282    public boolean dispatchNestedPreScroll(int dx, int dy,
20283            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
20284        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20285            if (dx != 0 || dy != 0) {
20286                int startX = 0;
20287                int startY = 0;
20288                if (offsetInWindow != null) {
20289                    getLocationInWindow(offsetInWindow);
20290                    startX = offsetInWindow[0];
20291                    startY = offsetInWindow[1];
20292                }
20293
20294                if (consumed == null) {
20295                    if (mTempNestedScrollConsumed == null) {
20296                        mTempNestedScrollConsumed = new int[2];
20297                    }
20298                    consumed = mTempNestedScrollConsumed;
20299                }
20300                consumed[0] = 0;
20301                consumed[1] = 0;
20302                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
20303
20304                if (offsetInWindow != null) {
20305                    getLocationInWindow(offsetInWindow);
20306                    offsetInWindow[0] -= startX;
20307                    offsetInWindow[1] -= startY;
20308                }
20309                return consumed[0] != 0 || consumed[1] != 0;
20310            } else if (offsetInWindow != null) {
20311                offsetInWindow[0] = 0;
20312                offsetInWindow[1] = 0;
20313            }
20314        }
20315        return false;
20316    }
20317
20318    /**
20319     * Dispatch a fling to a nested scrolling parent.
20320     *
20321     * <p>This method should be used to indicate that a nested scrolling child has detected
20322     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
20323     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
20324     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
20325     * along a scrollable axis.</p>
20326     *
20327     * <p>If a nested scrolling child view would normally fling but it is at the edge of
20328     * its own content, it can use this method to delegate the fling to its nested scrolling
20329     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
20330     *
20331     * @param velocityX Horizontal fling velocity in pixels per second
20332     * @param velocityY Vertical fling velocity in pixels per second
20333     * @param consumed true if the child consumed the fling, false otherwise
20334     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
20335     */
20336    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
20337        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20338            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
20339        }
20340        return false;
20341    }
20342
20343    /**
20344     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
20345     *
20346     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
20347     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
20348     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
20349     * before the child view consumes it. If this method returns <code>true</code>, a nested
20350     * parent view consumed the fling and this view should not scroll as a result.</p>
20351     *
20352     * <p>For a better user experience, only one view in a nested scrolling chain should consume
20353     * the fling at a time. If a parent view consumed the fling this method will return false.
20354     * Custom view implementations should account for this in two ways:</p>
20355     *
20356     * <ul>
20357     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
20358     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
20359     *     position regardless.</li>
20360     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
20361     *     even to settle back to a valid idle position.</li>
20362     * </ul>
20363     *
20364     * <p>Views should also not offer fling velocities to nested parent views along an axis
20365     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
20366     * should not offer a horizontal fling velocity to its parents since scrolling along that
20367     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
20368     *
20369     * @param velocityX Horizontal fling velocity in pixels per second
20370     * @param velocityY Vertical fling velocity in pixels per second
20371     * @return true if a nested scrolling parent consumed the fling
20372     */
20373    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
20374        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20375            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
20376        }
20377        return false;
20378    }
20379
20380    /**
20381     * Gets a scale factor that determines the distance the view should scroll
20382     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
20383     * @return The vertical scroll scale factor.
20384     * @hide
20385     */
20386    protected float getVerticalScrollFactor() {
20387        if (mVerticalScrollFactor == 0) {
20388            TypedValue outValue = new TypedValue();
20389            if (!mContext.getTheme().resolveAttribute(
20390                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
20391                throw new IllegalStateException(
20392                        "Expected theme to define listPreferredItemHeight.");
20393            }
20394            mVerticalScrollFactor = outValue.getDimension(
20395                    mContext.getResources().getDisplayMetrics());
20396        }
20397        return mVerticalScrollFactor;
20398    }
20399
20400    /**
20401     * Gets a scale factor that determines the distance the view should scroll
20402     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
20403     * @return The horizontal scroll scale factor.
20404     * @hide
20405     */
20406    protected float getHorizontalScrollFactor() {
20407        // TODO: Should use something else.
20408        return getVerticalScrollFactor();
20409    }
20410
20411    /**
20412     * Return the value specifying the text direction or policy that was set with
20413     * {@link #setTextDirection(int)}.
20414     *
20415     * @return the defined text direction. It can be one of:
20416     *
20417     * {@link #TEXT_DIRECTION_INHERIT},
20418     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20419     * {@link #TEXT_DIRECTION_ANY_RTL},
20420     * {@link #TEXT_DIRECTION_LTR},
20421     * {@link #TEXT_DIRECTION_RTL},
20422     * {@link #TEXT_DIRECTION_LOCALE},
20423     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20424     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20425     *
20426     * @attr ref android.R.styleable#View_textDirection
20427     *
20428     * @hide
20429     */
20430    @ViewDebug.ExportedProperty(category = "text", mapping = {
20431            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20432            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20433            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20434            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20435            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20436            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20437            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20438            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20439    })
20440    public int getRawTextDirection() {
20441        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
20442    }
20443
20444    /**
20445     * Set the text direction.
20446     *
20447     * @param textDirection the direction to set. Should be one of:
20448     *
20449     * {@link #TEXT_DIRECTION_INHERIT},
20450     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20451     * {@link #TEXT_DIRECTION_ANY_RTL},
20452     * {@link #TEXT_DIRECTION_LTR},
20453     * {@link #TEXT_DIRECTION_RTL},
20454     * {@link #TEXT_DIRECTION_LOCALE}
20455     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20456     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
20457     *
20458     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
20459     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
20460     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
20461     *
20462     * @attr ref android.R.styleable#View_textDirection
20463     */
20464    public void setTextDirection(int textDirection) {
20465        if (getRawTextDirection() != textDirection) {
20466            // Reset the current text direction and the resolved one
20467            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
20468            resetResolvedTextDirection();
20469            // Set the new text direction
20470            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
20471            // Do resolution
20472            resolveTextDirection();
20473            // Notify change
20474            onRtlPropertiesChanged(getLayoutDirection());
20475            // Refresh
20476            requestLayout();
20477            invalidate(true);
20478        }
20479    }
20480
20481    /**
20482     * Return the resolved text direction.
20483     *
20484     * @return the resolved text direction. Returns one of:
20485     *
20486     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20487     * {@link #TEXT_DIRECTION_ANY_RTL},
20488     * {@link #TEXT_DIRECTION_LTR},
20489     * {@link #TEXT_DIRECTION_RTL},
20490     * {@link #TEXT_DIRECTION_LOCALE},
20491     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20492     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20493     *
20494     * @attr ref android.R.styleable#View_textDirection
20495     */
20496    @ViewDebug.ExportedProperty(category = "text", mapping = {
20497            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20498            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20499            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20500            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20501            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20502            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20503            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20504            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20505    })
20506    public int getTextDirection() {
20507        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
20508    }
20509
20510    /**
20511     * Resolve the text direction.
20512     *
20513     * @return true if resolution has been done, false otherwise.
20514     *
20515     * @hide
20516     */
20517    public boolean resolveTextDirection() {
20518        // Reset any previous text direction resolution
20519        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20520
20521        if (hasRtlSupport()) {
20522            // Set resolved text direction flag depending on text direction flag
20523            final int textDirection = getRawTextDirection();
20524            switch(textDirection) {
20525                case TEXT_DIRECTION_INHERIT:
20526                    if (!canResolveTextDirection()) {
20527                        // We cannot do the resolution if there is no parent, so use the default one
20528                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20529                        // Resolution will need to happen again later
20530                        return false;
20531                    }
20532
20533                    // Parent has not yet resolved, so we still return the default
20534                    try {
20535                        if (!mParent.isTextDirectionResolved()) {
20536                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20537                            // Resolution will need to happen again later
20538                            return false;
20539                        }
20540                    } catch (AbstractMethodError e) {
20541                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20542                                " does not fully implement ViewParent", e);
20543                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
20544                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20545                        return true;
20546                    }
20547
20548                    // Set current resolved direction to the same value as the parent's one
20549                    int parentResolvedDirection;
20550                    try {
20551                        parentResolvedDirection = mParent.getTextDirection();
20552                    } catch (AbstractMethodError e) {
20553                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20554                                " does not fully implement ViewParent", e);
20555                        parentResolvedDirection = TEXT_DIRECTION_LTR;
20556                    }
20557                    switch (parentResolvedDirection) {
20558                        case TEXT_DIRECTION_FIRST_STRONG:
20559                        case TEXT_DIRECTION_ANY_RTL:
20560                        case TEXT_DIRECTION_LTR:
20561                        case TEXT_DIRECTION_RTL:
20562                        case TEXT_DIRECTION_LOCALE:
20563                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
20564                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
20565                            mPrivateFlags2 |=
20566                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20567                            break;
20568                        default:
20569                            // Default resolved direction is "first strong" heuristic
20570                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20571                    }
20572                    break;
20573                case TEXT_DIRECTION_FIRST_STRONG:
20574                case TEXT_DIRECTION_ANY_RTL:
20575                case TEXT_DIRECTION_LTR:
20576                case TEXT_DIRECTION_RTL:
20577                case TEXT_DIRECTION_LOCALE:
20578                case TEXT_DIRECTION_FIRST_STRONG_LTR:
20579                case TEXT_DIRECTION_FIRST_STRONG_RTL:
20580                    // Resolved direction is the same as text direction
20581                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20582                    break;
20583                default:
20584                    // Default resolved direction is "first strong" heuristic
20585                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20586            }
20587        } else {
20588            // Default resolved direction is "first strong" heuristic
20589            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20590        }
20591
20592        // Set to resolved
20593        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
20594        return true;
20595    }
20596
20597    /**
20598     * Check if text direction resolution can be done.
20599     *
20600     * @return true if text direction resolution can be done otherwise return false.
20601     */
20602    public boolean canResolveTextDirection() {
20603        switch (getRawTextDirection()) {
20604            case TEXT_DIRECTION_INHERIT:
20605                if (mParent != null) {
20606                    try {
20607                        return mParent.canResolveTextDirection();
20608                    } catch (AbstractMethodError e) {
20609                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20610                                " does not fully implement ViewParent", e);
20611                    }
20612                }
20613                return false;
20614
20615            default:
20616                return true;
20617        }
20618    }
20619
20620    /**
20621     * Reset resolved text direction. Text direction will be resolved during a call to
20622     * {@link #onMeasure(int, int)}.
20623     *
20624     * @hide
20625     */
20626    public void resetResolvedTextDirection() {
20627        // Reset any previous text direction resolution
20628        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20629        // Set to default value
20630        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20631    }
20632
20633    /**
20634     * @return true if text direction is inherited.
20635     *
20636     * @hide
20637     */
20638    public boolean isTextDirectionInherited() {
20639        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
20640    }
20641
20642    /**
20643     * @return true if text direction is resolved.
20644     */
20645    public boolean isTextDirectionResolved() {
20646        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
20647    }
20648
20649    /**
20650     * Return the value specifying the text alignment or policy that was set with
20651     * {@link #setTextAlignment(int)}.
20652     *
20653     * @return the defined text alignment. It can be one of:
20654     *
20655     * {@link #TEXT_ALIGNMENT_INHERIT},
20656     * {@link #TEXT_ALIGNMENT_GRAVITY},
20657     * {@link #TEXT_ALIGNMENT_CENTER},
20658     * {@link #TEXT_ALIGNMENT_TEXT_START},
20659     * {@link #TEXT_ALIGNMENT_TEXT_END},
20660     * {@link #TEXT_ALIGNMENT_VIEW_START},
20661     * {@link #TEXT_ALIGNMENT_VIEW_END}
20662     *
20663     * @attr ref android.R.styleable#View_textAlignment
20664     *
20665     * @hide
20666     */
20667    @ViewDebug.ExportedProperty(category = "text", mapping = {
20668            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20669            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20670            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20671            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20672            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20673            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20674            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20675    })
20676    @TextAlignment
20677    public int getRawTextAlignment() {
20678        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
20679    }
20680
20681    /**
20682     * Set the text alignment.
20683     *
20684     * @param textAlignment The text alignment to set. Should be one of
20685     *
20686     * {@link #TEXT_ALIGNMENT_INHERIT},
20687     * {@link #TEXT_ALIGNMENT_GRAVITY},
20688     * {@link #TEXT_ALIGNMENT_CENTER},
20689     * {@link #TEXT_ALIGNMENT_TEXT_START},
20690     * {@link #TEXT_ALIGNMENT_TEXT_END},
20691     * {@link #TEXT_ALIGNMENT_VIEW_START},
20692     * {@link #TEXT_ALIGNMENT_VIEW_END}
20693     *
20694     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
20695     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
20696     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
20697     *
20698     * @attr ref android.R.styleable#View_textAlignment
20699     */
20700    public void setTextAlignment(@TextAlignment int textAlignment) {
20701        if (textAlignment != getRawTextAlignment()) {
20702            // Reset the current and resolved text alignment
20703            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
20704            resetResolvedTextAlignment();
20705            // Set the new text alignment
20706            mPrivateFlags2 |=
20707                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
20708            // Do resolution
20709            resolveTextAlignment();
20710            // Notify change
20711            onRtlPropertiesChanged(getLayoutDirection());
20712            // Refresh
20713            requestLayout();
20714            invalidate(true);
20715        }
20716    }
20717
20718    /**
20719     * Return the resolved text alignment.
20720     *
20721     * @return the resolved text alignment. Returns one of:
20722     *
20723     * {@link #TEXT_ALIGNMENT_GRAVITY},
20724     * {@link #TEXT_ALIGNMENT_CENTER},
20725     * {@link #TEXT_ALIGNMENT_TEXT_START},
20726     * {@link #TEXT_ALIGNMENT_TEXT_END},
20727     * {@link #TEXT_ALIGNMENT_VIEW_START},
20728     * {@link #TEXT_ALIGNMENT_VIEW_END}
20729     *
20730     * @attr ref android.R.styleable#View_textAlignment
20731     */
20732    @ViewDebug.ExportedProperty(category = "text", mapping = {
20733            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20734            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20735            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20736            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20737            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20738            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20739            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20740    })
20741    @TextAlignment
20742    public int getTextAlignment() {
20743        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
20744                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
20745    }
20746
20747    /**
20748     * Resolve the text alignment.
20749     *
20750     * @return true if resolution has been done, false otherwise.
20751     *
20752     * @hide
20753     */
20754    public boolean resolveTextAlignment() {
20755        // Reset any previous text alignment resolution
20756        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20757
20758        if (hasRtlSupport()) {
20759            // Set resolved text alignment flag depending on text alignment flag
20760            final int textAlignment = getRawTextAlignment();
20761            switch (textAlignment) {
20762                case TEXT_ALIGNMENT_INHERIT:
20763                    // Check if we can resolve the text alignment
20764                    if (!canResolveTextAlignment()) {
20765                        // We cannot do the resolution if there is no parent so use the default
20766                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20767                        // Resolution will need to happen again later
20768                        return false;
20769                    }
20770
20771                    // Parent has not yet resolved, so we still return the default
20772                    try {
20773                        if (!mParent.isTextAlignmentResolved()) {
20774                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20775                            // Resolution will need to happen again later
20776                            return false;
20777                        }
20778                    } catch (AbstractMethodError e) {
20779                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20780                                " does not fully implement ViewParent", e);
20781                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
20782                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20783                        return true;
20784                    }
20785
20786                    int parentResolvedTextAlignment;
20787                    try {
20788                        parentResolvedTextAlignment = mParent.getTextAlignment();
20789                    } catch (AbstractMethodError e) {
20790                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20791                                " does not fully implement ViewParent", e);
20792                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
20793                    }
20794                    switch (parentResolvedTextAlignment) {
20795                        case TEXT_ALIGNMENT_GRAVITY:
20796                        case TEXT_ALIGNMENT_TEXT_START:
20797                        case TEXT_ALIGNMENT_TEXT_END:
20798                        case TEXT_ALIGNMENT_CENTER:
20799                        case TEXT_ALIGNMENT_VIEW_START:
20800                        case TEXT_ALIGNMENT_VIEW_END:
20801                            // Resolved text alignment is the same as the parent resolved
20802                            // text alignment
20803                            mPrivateFlags2 |=
20804                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20805                            break;
20806                        default:
20807                            // Use default resolved text alignment
20808                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20809                    }
20810                    break;
20811                case TEXT_ALIGNMENT_GRAVITY:
20812                case TEXT_ALIGNMENT_TEXT_START:
20813                case TEXT_ALIGNMENT_TEXT_END:
20814                case TEXT_ALIGNMENT_CENTER:
20815                case TEXT_ALIGNMENT_VIEW_START:
20816                case TEXT_ALIGNMENT_VIEW_END:
20817                    // Resolved text alignment is the same as text alignment
20818                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20819                    break;
20820                default:
20821                    // Use default resolved text alignment
20822                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20823            }
20824        } else {
20825            // Use default resolved text alignment
20826            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20827        }
20828
20829        // Set the resolved
20830        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20831        return true;
20832    }
20833
20834    /**
20835     * Check if text alignment resolution can be done.
20836     *
20837     * @return true if text alignment resolution can be done otherwise return false.
20838     */
20839    public boolean canResolveTextAlignment() {
20840        switch (getRawTextAlignment()) {
20841            case TEXT_DIRECTION_INHERIT:
20842                if (mParent != null) {
20843                    try {
20844                        return mParent.canResolveTextAlignment();
20845                    } catch (AbstractMethodError e) {
20846                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20847                                " does not fully implement ViewParent", e);
20848                    }
20849                }
20850                return false;
20851
20852            default:
20853                return true;
20854        }
20855    }
20856
20857    /**
20858     * Reset resolved text alignment. Text alignment will be resolved during a call to
20859     * {@link #onMeasure(int, int)}.
20860     *
20861     * @hide
20862     */
20863    public void resetResolvedTextAlignment() {
20864        // Reset any previous text alignment resolution
20865        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20866        // Set to default
20867        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20868    }
20869
20870    /**
20871     * @return true if text alignment is inherited.
20872     *
20873     * @hide
20874     */
20875    public boolean isTextAlignmentInherited() {
20876        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
20877    }
20878
20879    /**
20880     * @return true if text alignment is resolved.
20881     */
20882    public boolean isTextAlignmentResolved() {
20883        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20884    }
20885
20886    /**
20887     * Generate a value suitable for use in {@link #setId(int)}.
20888     * This value will not collide with ID values generated at build time by aapt for R.id.
20889     *
20890     * @return a generated ID value
20891     */
20892    public static int generateViewId() {
20893        for (;;) {
20894            final int result = sNextGeneratedId.get();
20895            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
20896            int newValue = result + 1;
20897            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
20898            if (sNextGeneratedId.compareAndSet(result, newValue)) {
20899                return result;
20900            }
20901        }
20902    }
20903
20904    /**
20905     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
20906     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
20907     *                           a normal View or a ViewGroup with
20908     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
20909     * @hide
20910     */
20911    public void captureTransitioningViews(List<View> transitioningViews) {
20912        if (getVisibility() == View.VISIBLE) {
20913            transitioningViews.add(this);
20914        }
20915    }
20916
20917    /**
20918     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
20919     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
20920     * @hide
20921     */
20922    public void findNamedViews(Map<String, View> namedElements) {
20923        if (getVisibility() == VISIBLE || mGhostView != null) {
20924            String transitionName = getTransitionName();
20925            if (transitionName != null) {
20926                namedElements.put(transitionName, this);
20927            }
20928        }
20929    }
20930
20931    //
20932    // Properties
20933    //
20934    /**
20935     * A Property wrapper around the <code>alpha</code> functionality handled by the
20936     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
20937     */
20938    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
20939        @Override
20940        public void setValue(View object, float value) {
20941            object.setAlpha(value);
20942        }
20943
20944        @Override
20945        public Float get(View object) {
20946            return object.getAlpha();
20947        }
20948    };
20949
20950    /**
20951     * A Property wrapper around the <code>translationX</code> functionality handled by the
20952     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
20953     */
20954    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
20955        @Override
20956        public void setValue(View object, float value) {
20957            object.setTranslationX(value);
20958        }
20959
20960                @Override
20961        public Float get(View object) {
20962            return object.getTranslationX();
20963        }
20964    };
20965
20966    /**
20967     * A Property wrapper around the <code>translationY</code> functionality handled by the
20968     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
20969     */
20970    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
20971        @Override
20972        public void setValue(View object, float value) {
20973            object.setTranslationY(value);
20974        }
20975
20976        @Override
20977        public Float get(View object) {
20978            return object.getTranslationY();
20979        }
20980    };
20981
20982    /**
20983     * A Property wrapper around the <code>translationZ</code> functionality handled by the
20984     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
20985     */
20986    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
20987        @Override
20988        public void setValue(View object, float value) {
20989            object.setTranslationZ(value);
20990        }
20991
20992        @Override
20993        public Float get(View object) {
20994            return object.getTranslationZ();
20995        }
20996    };
20997
20998    /**
20999     * A Property wrapper around the <code>x</code> functionality handled by the
21000     * {@link View#setX(float)} and {@link View#getX()} methods.
21001     */
21002    public static final Property<View, Float> X = new FloatProperty<View>("x") {
21003        @Override
21004        public void setValue(View object, float value) {
21005            object.setX(value);
21006        }
21007
21008        @Override
21009        public Float get(View object) {
21010            return object.getX();
21011        }
21012    };
21013
21014    /**
21015     * A Property wrapper around the <code>y</code> functionality handled by the
21016     * {@link View#setY(float)} and {@link View#getY()} methods.
21017     */
21018    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
21019        @Override
21020        public void setValue(View object, float value) {
21021            object.setY(value);
21022        }
21023
21024        @Override
21025        public Float get(View object) {
21026            return object.getY();
21027        }
21028    };
21029
21030    /**
21031     * A Property wrapper around the <code>z</code> functionality handled by the
21032     * {@link View#setZ(float)} and {@link View#getZ()} methods.
21033     */
21034    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
21035        @Override
21036        public void setValue(View object, float value) {
21037            object.setZ(value);
21038        }
21039
21040        @Override
21041        public Float get(View object) {
21042            return object.getZ();
21043        }
21044    };
21045
21046    /**
21047     * A Property wrapper around the <code>rotation</code> functionality handled by the
21048     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
21049     */
21050    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
21051        @Override
21052        public void setValue(View object, float value) {
21053            object.setRotation(value);
21054        }
21055
21056        @Override
21057        public Float get(View object) {
21058            return object.getRotation();
21059        }
21060    };
21061
21062    /**
21063     * A Property wrapper around the <code>rotationX</code> functionality handled by the
21064     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
21065     */
21066    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
21067        @Override
21068        public void setValue(View object, float value) {
21069            object.setRotationX(value);
21070        }
21071
21072        @Override
21073        public Float get(View object) {
21074            return object.getRotationX();
21075        }
21076    };
21077
21078    /**
21079     * A Property wrapper around the <code>rotationY</code> functionality handled by the
21080     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
21081     */
21082    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
21083        @Override
21084        public void setValue(View object, float value) {
21085            object.setRotationY(value);
21086        }
21087
21088        @Override
21089        public Float get(View object) {
21090            return object.getRotationY();
21091        }
21092    };
21093
21094    /**
21095     * A Property wrapper around the <code>scaleX</code> functionality handled by the
21096     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
21097     */
21098    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
21099        @Override
21100        public void setValue(View object, float value) {
21101            object.setScaleX(value);
21102        }
21103
21104        @Override
21105        public Float get(View object) {
21106            return object.getScaleX();
21107        }
21108    };
21109
21110    /**
21111     * A Property wrapper around the <code>scaleY</code> functionality handled by the
21112     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
21113     */
21114    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
21115        @Override
21116        public void setValue(View object, float value) {
21117            object.setScaleY(value);
21118        }
21119
21120        @Override
21121        public Float get(View object) {
21122            return object.getScaleY();
21123        }
21124    };
21125
21126    /**
21127     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
21128     * Each MeasureSpec represents a requirement for either the width or the height.
21129     * A MeasureSpec is comprised of a size and a mode. There are three possible
21130     * modes:
21131     * <dl>
21132     * <dt>UNSPECIFIED</dt>
21133     * <dd>
21134     * The parent has not imposed any constraint on the child. It can be whatever size
21135     * it wants.
21136     * </dd>
21137     *
21138     * <dt>EXACTLY</dt>
21139     * <dd>
21140     * The parent has determined an exact size for the child. The child is going to be
21141     * given those bounds regardless of how big it wants to be.
21142     * </dd>
21143     *
21144     * <dt>AT_MOST</dt>
21145     * <dd>
21146     * The child can be as large as it wants up to the specified size.
21147     * </dd>
21148     * </dl>
21149     *
21150     * MeasureSpecs are implemented as ints to reduce object allocation. This class
21151     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
21152     */
21153    public static class MeasureSpec {
21154        private static final int MODE_SHIFT = 30;
21155        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
21156
21157        /**
21158         * Measure specification mode: The parent has not imposed any constraint
21159         * on the child. It can be whatever size it wants.
21160         */
21161        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
21162
21163        /**
21164         * Measure specification mode: The parent has determined an exact size
21165         * for the child. The child is going to be given those bounds regardless
21166         * of how big it wants to be.
21167         */
21168        public static final int EXACTLY     = 1 << MODE_SHIFT;
21169
21170        /**
21171         * Measure specification mode: The child can be as large as it wants up
21172         * to the specified size.
21173         */
21174        public static final int AT_MOST     = 2 << MODE_SHIFT;
21175
21176        /**
21177         * Creates a measure specification based on the supplied size and mode.
21178         *
21179         * The mode must always be one of the following:
21180         * <ul>
21181         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
21182         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
21183         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
21184         * </ul>
21185         *
21186         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
21187         * implementation was such that the order of arguments did not matter
21188         * and overflow in either value could impact the resulting MeasureSpec.
21189         * {@link android.widget.RelativeLayout} was affected by this bug.
21190         * Apps targeting API levels greater than 17 will get the fixed, more strict
21191         * behavior.</p>
21192         *
21193         * @param size the size of the measure specification
21194         * @param mode the mode of the measure specification
21195         * @return the measure specification based on size and mode
21196         */
21197        public static int makeMeasureSpec(int size, int mode) {
21198            if (sUseBrokenMakeMeasureSpec) {
21199                return size + mode;
21200            } else {
21201                return (size & ~MODE_MASK) | (mode & MODE_MASK);
21202            }
21203        }
21204
21205        /**
21206         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
21207         * will automatically get a size of 0. Older apps expect this.
21208         *
21209         * @hide internal use only for compatibility with system widgets and older apps
21210         */
21211        public static int makeSafeMeasureSpec(int size, int mode) {
21212            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
21213                return 0;
21214            }
21215            return makeMeasureSpec(size, mode);
21216        }
21217
21218        /**
21219         * Extracts the mode from the supplied measure specification.
21220         *
21221         * @param measureSpec the measure specification to extract the mode from
21222         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
21223         *         {@link android.view.View.MeasureSpec#AT_MOST} or
21224         *         {@link android.view.View.MeasureSpec#EXACTLY}
21225         */
21226        public static int getMode(int measureSpec) {
21227            return (measureSpec & MODE_MASK);
21228        }
21229
21230        /**
21231         * Extracts the size from the supplied measure specification.
21232         *
21233         * @param measureSpec the measure specification to extract the size from
21234         * @return the size in pixels defined in the supplied measure specification
21235         */
21236        public static int getSize(int measureSpec) {
21237            return (measureSpec & ~MODE_MASK);
21238        }
21239
21240        static int adjust(int measureSpec, int delta) {
21241            final int mode = getMode(measureSpec);
21242            int size = getSize(measureSpec);
21243            if (mode == UNSPECIFIED) {
21244                // No need to adjust size for UNSPECIFIED mode.
21245                return makeMeasureSpec(size, UNSPECIFIED);
21246            }
21247            size += delta;
21248            if (size < 0) {
21249                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
21250                        ") spec: " + toString(measureSpec) + " delta: " + delta);
21251                size = 0;
21252            }
21253            return makeMeasureSpec(size, mode);
21254        }
21255
21256        /**
21257         * Returns a String representation of the specified measure
21258         * specification.
21259         *
21260         * @param measureSpec the measure specification to convert to a String
21261         * @return a String with the following format: "MeasureSpec: MODE SIZE"
21262         */
21263        public static String toString(int measureSpec) {
21264            int mode = getMode(measureSpec);
21265            int size = getSize(measureSpec);
21266
21267            StringBuilder sb = new StringBuilder("MeasureSpec: ");
21268
21269            if (mode == UNSPECIFIED)
21270                sb.append("UNSPECIFIED ");
21271            else if (mode == EXACTLY)
21272                sb.append("EXACTLY ");
21273            else if (mode == AT_MOST)
21274                sb.append("AT_MOST ");
21275            else
21276                sb.append(mode).append(" ");
21277
21278            sb.append(size);
21279            return sb.toString();
21280        }
21281    }
21282
21283    private final class CheckForLongPress implements Runnable {
21284        private int mOriginalWindowAttachCount;
21285
21286        @Override
21287        public void run() {
21288            if (isPressed() && (mParent != null)
21289                    && mOriginalWindowAttachCount == mWindowAttachCount) {
21290                if (performLongClick()) {
21291                    mHasPerformedLongPress = true;
21292                }
21293            }
21294        }
21295
21296        public void rememberWindowAttachCount() {
21297            mOriginalWindowAttachCount = mWindowAttachCount;
21298        }
21299    }
21300
21301    private final class CheckForTap implements Runnable {
21302        public float x;
21303        public float y;
21304
21305        @Override
21306        public void run() {
21307            mPrivateFlags &= ~PFLAG_PREPRESSED;
21308            setPressed(true, x, y);
21309            checkForLongClick(ViewConfiguration.getTapTimeout());
21310        }
21311    }
21312
21313    private final class PerformClick implements Runnable {
21314        @Override
21315        public void run() {
21316            performClick();
21317        }
21318    }
21319
21320    /**
21321     * This method returns a ViewPropertyAnimator object, which can be used to animate
21322     * specific properties on this View.
21323     *
21324     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
21325     */
21326    public ViewPropertyAnimator animate() {
21327        if (mAnimator == null) {
21328            mAnimator = new ViewPropertyAnimator(this);
21329        }
21330        return mAnimator;
21331    }
21332
21333    /**
21334     * Sets the name of the View to be used to identify Views in Transitions.
21335     * Names should be unique in the View hierarchy.
21336     *
21337     * @param transitionName The name of the View to uniquely identify it for Transitions.
21338     */
21339    public final void setTransitionName(String transitionName) {
21340        mTransitionName = transitionName;
21341    }
21342
21343    /**
21344     * Returns the name of the View to be used to identify Views in Transitions.
21345     * Names should be unique in the View hierarchy.
21346     *
21347     * <p>This returns null if the View has not been given a name.</p>
21348     *
21349     * @return The name used of the View to be used to identify Views in Transitions or null
21350     * if no name has been given.
21351     */
21352    @ViewDebug.ExportedProperty
21353    public String getTransitionName() {
21354        return mTransitionName;
21355    }
21356
21357    /**
21358     * Interface definition for a callback to be invoked when a hardware key event is
21359     * dispatched to this view. The callback will be invoked before the key event is
21360     * given to the view. This is only useful for hardware keyboards; a software input
21361     * method has no obligation to trigger this listener.
21362     */
21363    public interface OnKeyListener {
21364        /**
21365         * Called when a hardware key is dispatched to a view. This allows listeners to
21366         * get a chance to respond before the target view.
21367         * <p>Key presses in software keyboards will generally NOT trigger this method,
21368         * although some may elect to do so in some situations. Do not assume a
21369         * software input method has to be key-based; even if it is, it may use key presses
21370         * in a different way than you expect, so there is no way to reliably catch soft
21371         * input key presses.
21372         *
21373         * @param v The view the key has been dispatched to.
21374         * @param keyCode The code for the physical key that was pressed
21375         * @param event The KeyEvent object containing full information about
21376         *        the event.
21377         * @return True if the listener has consumed the event, false otherwise.
21378         */
21379        boolean onKey(View v, int keyCode, KeyEvent event);
21380    }
21381
21382    /**
21383     * Interface definition for a callback to be invoked when a touch event is
21384     * dispatched to this view. The callback will be invoked before the touch
21385     * event is given to the view.
21386     */
21387    public interface OnTouchListener {
21388        /**
21389         * Called when a touch event is dispatched to a view. This allows listeners to
21390         * get a chance to respond before the target view.
21391         *
21392         * @param v The view the touch event has been dispatched to.
21393         * @param event The MotionEvent object containing full information about
21394         *        the event.
21395         * @return True if the listener has consumed the event, false otherwise.
21396         */
21397        boolean onTouch(View v, MotionEvent event);
21398    }
21399
21400    /**
21401     * Interface definition for a callback to be invoked when a hover event is
21402     * dispatched to this view. The callback will be invoked before the hover
21403     * event is given to the view.
21404     */
21405    public interface OnHoverListener {
21406        /**
21407         * Called when a hover event is dispatched to a view. This allows listeners to
21408         * get a chance to respond before the target view.
21409         *
21410         * @param v The view the hover event has been dispatched to.
21411         * @param event The MotionEvent object containing full information about
21412         *        the event.
21413         * @return True if the listener has consumed the event, false otherwise.
21414         */
21415        boolean onHover(View v, MotionEvent event);
21416    }
21417
21418    /**
21419     * Interface definition for a callback to be invoked when a generic motion event is
21420     * dispatched to this view. The callback will be invoked before the generic motion
21421     * event is given to the view.
21422     */
21423    public interface OnGenericMotionListener {
21424        /**
21425         * Called when a generic motion event is dispatched to a view. This allows listeners to
21426         * get a chance to respond before the target view.
21427         *
21428         * @param v The view the generic motion event has been dispatched to.
21429         * @param event The MotionEvent object containing full information about
21430         *        the event.
21431         * @return True if the listener has consumed the event, false otherwise.
21432         */
21433        boolean onGenericMotion(View v, MotionEvent event);
21434    }
21435
21436    /**
21437     * Interface definition for a callback to be invoked when a view has been clicked and held.
21438     */
21439    public interface OnLongClickListener {
21440        /**
21441         * Called when a view has been clicked and held.
21442         *
21443         * @param v The view that was clicked and held.
21444         *
21445         * @return true if the callback consumed the long click, false otherwise.
21446         */
21447        boolean onLongClick(View v);
21448    }
21449
21450    /**
21451     * Interface definition for a callback to be invoked when a drag is being dispatched
21452     * to this view.  The callback will be invoked before the hosting view's own
21453     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
21454     * onDrag(event) behavior, it should return 'false' from this callback.
21455     *
21456     * <div class="special reference">
21457     * <h3>Developer Guides</h3>
21458     * <p>For a guide to implementing drag and drop features, read the
21459     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21460     * </div>
21461     */
21462    public interface OnDragListener {
21463        /**
21464         * Called when a drag event is dispatched to a view. This allows listeners
21465         * to get a chance to override base View behavior.
21466         *
21467         * @param v The View that received the drag event.
21468         * @param event The {@link android.view.DragEvent} object for the drag event.
21469         * @return {@code true} if the drag event was handled successfully, or {@code false}
21470         * if the drag event was not handled. Note that {@code false} will trigger the View
21471         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
21472         */
21473        boolean onDrag(View v, DragEvent event);
21474    }
21475
21476    /**
21477     * Interface definition for a callback to be invoked when the focus state of
21478     * a view changed.
21479     */
21480    public interface OnFocusChangeListener {
21481        /**
21482         * Called when the focus state of a view has changed.
21483         *
21484         * @param v The view whose state has changed.
21485         * @param hasFocus The new focus state of v.
21486         */
21487        void onFocusChange(View v, boolean hasFocus);
21488    }
21489
21490    /**
21491     * Interface definition for a callback to be invoked when a view is clicked.
21492     */
21493    public interface OnClickListener {
21494        /**
21495         * Called when a view has been clicked.
21496         *
21497         * @param v The view that was clicked.
21498         */
21499        void onClick(View v);
21500    }
21501
21502    /**
21503     * Interface definition for a callback to be invoked when a view is context clicked.
21504     */
21505    public interface OnContextClickListener {
21506        /**
21507         * Called when a view is context clicked.
21508         *
21509         * @param v The view that has been context clicked.
21510         * @return true if the callback consumed the context click, false otherwise.
21511         */
21512        boolean onContextClick(View v);
21513    }
21514
21515    /**
21516     * Interface definition for a callback to be invoked when the context menu
21517     * for this view is being built.
21518     */
21519    public interface OnCreateContextMenuListener {
21520        /**
21521         * Called when the context menu for this view is being built. It is not
21522         * safe to hold onto the menu after this method returns.
21523         *
21524         * @param menu The context menu that is being built
21525         * @param v The view for which the context menu is being built
21526         * @param menuInfo Extra information about the item for which the
21527         *            context menu should be shown. This information will vary
21528         *            depending on the class of v.
21529         */
21530        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
21531    }
21532
21533    /**
21534     * Interface definition for a callback to be invoked when the status bar changes
21535     * visibility.  This reports <strong>global</strong> changes to the system UI
21536     * state, not what the application is requesting.
21537     *
21538     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
21539     */
21540    public interface OnSystemUiVisibilityChangeListener {
21541        /**
21542         * Called when the status bar changes visibility because of a call to
21543         * {@link View#setSystemUiVisibility(int)}.
21544         *
21545         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21546         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
21547         * This tells you the <strong>global</strong> state of these UI visibility
21548         * flags, not what your app is currently applying.
21549         */
21550        public void onSystemUiVisibilityChange(int visibility);
21551    }
21552
21553    /**
21554     * Interface definition for a callback to be invoked when this view is attached
21555     * or detached from its window.
21556     */
21557    public interface OnAttachStateChangeListener {
21558        /**
21559         * Called when the view is attached to a window.
21560         * @param v The view that was attached
21561         */
21562        public void onViewAttachedToWindow(View v);
21563        /**
21564         * Called when the view is detached from a window.
21565         * @param v The view that was detached
21566         */
21567        public void onViewDetachedFromWindow(View v);
21568    }
21569
21570    /**
21571     * Listener for applying window insets on a view in a custom way.
21572     *
21573     * <p>Apps may choose to implement this interface if they want to apply custom policy
21574     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
21575     * is set, its
21576     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
21577     * method will be called instead of the View's own
21578     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
21579     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
21580     * the View's normal behavior as part of its own.</p>
21581     */
21582    public interface OnApplyWindowInsetsListener {
21583        /**
21584         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
21585         * on a View, this listener method will be called instead of the view's own
21586         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
21587         *
21588         * @param v The view applying window insets
21589         * @param insets The insets to apply
21590         * @return The insets supplied, minus any insets that were consumed
21591         */
21592        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
21593    }
21594
21595    private final class UnsetPressedState implements Runnable {
21596        @Override
21597        public void run() {
21598            setPressed(false);
21599        }
21600    }
21601
21602    /**
21603     * Base class for derived classes that want to save and restore their own
21604     * state in {@link android.view.View#onSaveInstanceState()}.
21605     */
21606    public static class BaseSavedState extends AbsSavedState {
21607        String mStartActivityRequestWhoSaved;
21608
21609        /**
21610         * Constructor used when reading from a parcel. Reads the state of the superclass.
21611         *
21612         * @param source
21613         */
21614        public BaseSavedState(Parcel source) {
21615            super(source);
21616            mStartActivityRequestWhoSaved = source.readString();
21617        }
21618
21619        /**
21620         * Constructor called by derived classes when creating their SavedState objects
21621         *
21622         * @param superState The state of the superclass of this view
21623         */
21624        public BaseSavedState(Parcelable superState) {
21625            super(superState);
21626        }
21627
21628        @Override
21629        public void writeToParcel(Parcel out, int flags) {
21630            super.writeToParcel(out, flags);
21631            out.writeString(mStartActivityRequestWhoSaved);
21632        }
21633
21634        public static final Parcelable.Creator<BaseSavedState> CREATOR =
21635                new Parcelable.Creator<BaseSavedState>() {
21636            public BaseSavedState createFromParcel(Parcel in) {
21637                return new BaseSavedState(in);
21638            }
21639
21640            public BaseSavedState[] newArray(int size) {
21641                return new BaseSavedState[size];
21642            }
21643        };
21644    }
21645
21646    /**
21647     * A set of information given to a view when it is attached to its parent
21648     * window.
21649     */
21650    final static class AttachInfo {
21651        interface Callbacks {
21652            void playSoundEffect(int effectId);
21653            boolean performHapticFeedback(int effectId, boolean always);
21654        }
21655
21656        /**
21657         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
21658         * to a Handler. This class contains the target (View) to invalidate and
21659         * the coordinates of the dirty rectangle.
21660         *
21661         * For performance purposes, this class also implements a pool of up to
21662         * POOL_LIMIT objects that get reused. This reduces memory allocations
21663         * whenever possible.
21664         */
21665        static class InvalidateInfo {
21666            private static final int POOL_LIMIT = 10;
21667
21668            private static final SynchronizedPool<InvalidateInfo> sPool =
21669                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
21670
21671            View target;
21672
21673            int left;
21674            int top;
21675            int right;
21676            int bottom;
21677
21678            public static InvalidateInfo obtain() {
21679                InvalidateInfo instance = sPool.acquire();
21680                return (instance != null) ? instance : new InvalidateInfo();
21681            }
21682
21683            public void recycle() {
21684                target = null;
21685                sPool.release(this);
21686            }
21687        }
21688
21689        final IWindowSession mSession;
21690
21691        final IWindow mWindow;
21692
21693        final IBinder mWindowToken;
21694
21695        final Display mDisplay;
21696
21697        final Callbacks mRootCallbacks;
21698
21699        IWindowId mIWindowId;
21700        WindowId mWindowId;
21701
21702        /**
21703         * The top view of the hierarchy.
21704         */
21705        View mRootView;
21706
21707        IBinder mPanelParentWindowToken;
21708
21709        boolean mHardwareAccelerated;
21710        boolean mHardwareAccelerationRequested;
21711        HardwareRenderer mHardwareRenderer;
21712        List<RenderNode> mPendingAnimatingRenderNodes;
21713
21714        /**
21715         * The state of the display to which the window is attached, as reported
21716         * by {@link Display#getState()}.  Note that the display state constants
21717         * declared by {@link Display} do not exactly line up with the screen state
21718         * constants declared by {@link View} (there are more display states than
21719         * screen states).
21720         */
21721        int mDisplayState = Display.STATE_UNKNOWN;
21722
21723        /**
21724         * Scale factor used by the compatibility mode
21725         */
21726        float mApplicationScale;
21727
21728        /**
21729         * Indicates whether the application is in compatibility mode
21730         */
21731        boolean mScalingRequired;
21732
21733        /**
21734         * Left position of this view's window
21735         */
21736        int mWindowLeft;
21737
21738        /**
21739         * Top position of this view's window
21740         */
21741        int mWindowTop;
21742
21743        /**
21744         * Indicates whether views need to use 32-bit drawing caches
21745         */
21746        boolean mUse32BitDrawingCache;
21747
21748        /**
21749         * For windows that are full-screen but using insets to layout inside
21750         * of the screen areas, these are the current insets to appear inside
21751         * the overscan area of the display.
21752         */
21753        final Rect mOverscanInsets = new Rect();
21754
21755        /**
21756         * For windows that are full-screen but using insets to layout inside
21757         * of the screen decorations, these are the current insets for the
21758         * content of the window.
21759         */
21760        final Rect mContentInsets = new Rect();
21761
21762        /**
21763         * For windows that are full-screen but using insets to layout inside
21764         * of the screen decorations, these are the current insets for the
21765         * actual visible parts of the window.
21766         */
21767        final Rect mVisibleInsets = new Rect();
21768
21769        /**
21770         * For windows that are full-screen but using insets to layout inside
21771         * of the screen decorations, these are the current insets for the
21772         * stable system windows.
21773         */
21774        final Rect mStableInsets = new Rect();
21775
21776        /**
21777         * For windows that include areas that are not covered by real surface these are the outsets
21778         * for real surface.
21779         */
21780        final Rect mOutsets = new Rect();
21781
21782        /**
21783         * The internal insets given by this window.  This value is
21784         * supplied by the client (through
21785         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
21786         * be given to the window manager when changed to be used in laying
21787         * out windows behind it.
21788         */
21789        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
21790                = new ViewTreeObserver.InternalInsetsInfo();
21791
21792        /**
21793         * Set to true when mGivenInternalInsets is non-empty.
21794         */
21795        boolean mHasNonEmptyGivenInternalInsets;
21796
21797        /**
21798         * All views in the window's hierarchy that serve as scroll containers,
21799         * used to determine if the window can be resized or must be panned
21800         * to adjust for a soft input area.
21801         */
21802        final ArrayList<View> mScrollContainers = new ArrayList<View>();
21803
21804        final KeyEvent.DispatcherState mKeyDispatchState
21805                = new KeyEvent.DispatcherState();
21806
21807        /**
21808         * Indicates whether the view's window currently has the focus.
21809         */
21810        boolean mHasWindowFocus;
21811
21812        /**
21813         * The current visibility of the window.
21814         */
21815        int mWindowVisibility;
21816
21817        /**
21818         * Indicates the time at which drawing started to occur.
21819         */
21820        long mDrawingTime;
21821
21822        /**
21823         * Indicates whether or not ignoring the DIRTY_MASK flags.
21824         */
21825        boolean mIgnoreDirtyState;
21826
21827        /**
21828         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
21829         * to avoid clearing that flag prematurely.
21830         */
21831        boolean mSetIgnoreDirtyState = false;
21832
21833        /**
21834         * Indicates whether the view's window is currently in touch mode.
21835         */
21836        boolean mInTouchMode;
21837
21838        /**
21839         * Indicates whether the view has requested unbuffered input dispatching for the current
21840         * event stream.
21841         */
21842        boolean mUnbufferedDispatchRequested;
21843
21844        /**
21845         * Indicates that ViewAncestor should trigger a global layout change
21846         * the next time it performs a traversal
21847         */
21848        boolean mRecomputeGlobalAttributes;
21849
21850        /**
21851         * Always report new attributes at next traversal.
21852         */
21853        boolean mForceReportNewAttributes;
21854
21855        /**
21856         * Set during a traveral if any views want to keep the screen on.
21857         */
21858        boolean mKeepScreenOn;
21859
21860        /**
21861         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
21862         */
21863        int mSystemUiVisibility;
21864
21865        /**
21866         * Hack to force certain system UI visibility flags to be cleared.
21867         */
21868        int mDisabledSystemUiVisibility;
21869
21870        /**
21871         * Last global system UI visibility reported by the window manager.
21872         */
21873        int mGlobalSystemUiVisibility;
21874
21875        /**
21876         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
21877         * attached.
21878         */
21879        boolean mHasSystemUiListeners;
21880
21881        /**
21882         * Set if the window has requested to extend into the overscan region
21883         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
21884         */
21885        boolean mOverscanRequested;
21886
21887        /**
21888         * Set if the visibility of any views has changed.
21889         */
21890        boolean mViewVisibilityChanged;
21891
21892        /**
21893         * Set to true if a view has been scrolled.
21894         */
21895        boolean mViewScrollChanged;
21896
21897        /**
21898         * Set to true if high contrast mode enabled
21899         */
21900        boolean mHighContrastText;
21901
21902        /**
21903         * Global to the view hierarchy used as a temporary for dealing with
21904         * x/y points in the transparent region computations.
21905         */
21906        final int[] mTransparentLocation = new int[2];
21907
21908        /**
21909         * Global to the view hierarchy used as a temporary for dealing with
21910         * x/y points in the ViewGroup.invalidateChild implementation.
21911         */
21912        final int[] mInvalidateChildLocation = new int[2];
21913
21914        /**
21915         * Global to the view hierarchy used as a temporary for dealng with
21916         * computing absolute on-screen location.
21917         */
21918        final int[] mTmpLocation = new int[2];
21919
21920        /**
21921         * Global to the view hierarchy used as a temporary for dealing with
21922         * x/y location when view is transformed.
21923         */
21924        final float[] mTmpTransformLocation = new float[2];
21925
21926        /**
21927         * The view tree observer used to dispatch global events like
21928         * layout, pre-draw, touch mode change, etc.
21929         */
21930        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
21931
21932        /**
21933         * A Canvas used by the view hierarchy to perform bitmap caching.
21934         */
21935        Canvas mCanvas;
21936
21937        /**
21938         * The view root impl.
21939         */
21940        final ViewRootImpl mViewRootImpl;
21941
21942        /**
21943         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
21944         * handler can be used to pump events in the UI events queue.
21945         */
21946        final Handler mHandler;
21947
21948        /**
21949         * Temporary for use in computing invalidate rectangles while
21950         * calling up the hierarchy.
21951         */
21952        final Rect mTmpInvalRect = new Rect();
21953
21954        /**
21955         * Temporary for use in computing hit areas with transformed views
21956         */
21957        final RectF mTmpTransformRect = new RectF();
21958
21959        /**
21960         * Temporary for use in computing hit areas with transformed views
21961         */
21962        final RectF mTmpTransformRect1 = new RectF();
21963
21964        /**
21965         * Temporary list of rectanges.
21966         */
21967        final List<RectF> mTmpRectList = new ArrayList<>();
21968
21969        /**
21970         * Temporary for use in transforming invalidation rect
21971         */
21972        final Matrix mTmpMatrix = new Matrix();
21973
21974        /**
21975         * Temporary for use in transforming invalidation rect
21976         */
21977        final Transformation mTmpTransformation = new Transformation();
21978
21979        /**
21980         * Temporary for use in querying outlines from OutlineProviders
21981         */
21982        final Outline mTmpOutline = new Outline();
21983
21984        /**
21985         * Temporary list for use in collecting focusable descendents of a view.
21986         */
21987        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
21988
21989        /**
21990         * The id of the window for accessibility purposes.
21991         */
21992        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
21993
21994        /**
21995         * Flags related to accessibility processing.
21996         *
21997         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
21998         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
21999         */
22000        int mAccessibilityFetchFlags;
22001
22002        /**
22003         * The drawable for highlighting accessibility focus.
22004         */
22005        Drawable mAccessibilityFocusDrawable;
22006
22007        /**
22008         * Show where the margins, bounds and layout bounds are for each view.
22009         */
22010        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
22011
22012        /**
22013         * Point used to compute visible regions.
22014         */
22015        final Point mPoint = new Point();
22016
22017        /**
22018         * Used to track which View originated a requestLayout() call, used when
22019         * requestLayout() is called during layout.
22020         */
22021        View mViewRequestingLayout;
22022
22023        /**
22024         * Creates a new set of attachment information with the specified
22025         * events handler and thread.
22026         *
22027         * @param handler the events handler the view must use
22028         */
22029        AttachInfo(IWindowSession session, IWindow window, Display display,
22030                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
22031            mSession = session;
22032            mWindow = window;
22033            mWindowToken = window.asBinder();
22034            mDisplay = display;
22035            mViewRootImpl = viewRootImpl;
22036            mHandler = handler;
22037            mRootCallbacks = effectPlayer;
22038        }
22039    }
22040
22041    /**
22042     * <p>ScrollabilityCache holds various fields used by a View when scrolling
22043     * is supported. This avoids keeping too many unused fields in most
22044     * instances of View.</p>
22045     */
22046    private static class ScrollabilityCache implements Runnable {
22047
22048        /**
22049         * Scrollbars are not visible
22050         */
22051        public static final int OFF = 0;
22052
22053        /**
22054         * Scrollbars are visible
22055         */
22056        public static final int ON = 1;
22057
22058        /**
22059         * Scrollbars are fading away
22060         */
22061        public static final int FADING = 2;
22062
22063        public boolean fadeScrollBars;
22064
22065        public int fadingEdgeLength;
22066        public int scrollBarDefaultDelayBeforeFade;
22067        public int scrollBarFadeDuration;
22068
22069        public int scrollBarSize;
22070        public ScrollBarDrawable scrollBar;
22071        public float[] interpolatorValues;
22072        public View host;
22073
22074        public final Paint paint;
22075        public final Matrix matrix;
22076        public Shader shader;
22077
22078        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
22079
22080        private static final float[] OPAQUE = { 255 };
22081        private static final float[] TRANSPARENT = { 0.0f };
22082
22083        /**
22084         * When fading should start. This time moves into the future every time
22085         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
22086         */
22087        public long fadeStartTime;
22088
22089
22090        /**
22091         * The current state of the scrollbars: ON, OFF, or FADING
22092         */
22093        public int state = OFF;
22094
22095        private int mLastColor;
22096
22097        public ScrollabilityCache(ViewConfiguration configuration, View host) {
22098            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
22099            scrollBarSize = configuration.getScaledScrollBarSize();
22100            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
22101            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
22102
22103            paint = new Paint();
22104            matrix = new Matrix();
22105            // use use a height of 1, and then wack the matrix each time we
22106            // actually use it.
22107            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
22108            paint.setShader(shader);
22109            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
22110
22111            this.host = host;
22112        }
22113
22114        public void setFadeColor(int color) {
22115            if (color != mLastColor) {
22116                mLastColor = color;
22117
22118                if (color != 0) {
22119                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
22120                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
22121                    paint.setShader(shader);
22122                    // Restore the default transfer mode (src_over)
22123                    paint.setXfermode(null);
22124                } else {
22125                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
22126                    paint.setShader(shader);
22127                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
22128                }
22129            }
22130        }
22131
22132        public void run() {
22133            long now = AnimationUtils.currentAnimationTimeMillis();
22134            if (now >= fadeStartTime) {
22135
22136                // the animation fades the scrollbars out by changing
22137                // the opacity (alpha) from fully opaque to fully
22138                // transparent
22139                int nextFrame = (int) now;
22140                int framesCount = 0;
22141
22142                Interpolator interpolator = scrollBarInterpolator;
22143
22144                // Start opaque
22145                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
22146
22147                // End transparent
22148                nextFrame += scrollBarFadeDuration;
22149                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
22150
22151                state = FADING;
22152
22153                // Kick off the fade animation
22154                host.invalidate(true);
22155            }
22156        }
22157    }
22158
22159    /**
22160     * Resuable callback for sending
22161     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
22162     */
22163    private class SendViewScrolledAccessibilityEvent implements Runnable {
22164        public volatile boolean mIsPending;
22165
22166        public void run() {
22167            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
22168            mIsPending = false;
22169        }
22170    }
22171
22172    /**
22173     * <p>
22174     * This class represents a delegate that can be registered in a {@link View}
22175     * to enhance accessibility support via composition rather via inheritance.
22176     * It is specifically targeted to widget developers that extend basic View
22177     * classes i.e. classes in package android.view, that would like their
22178     * applications to be backwards compatible.
22179     * </p>
22180     * <div class="special reference">
22181     * <h3>Developer Guides</h3>
22182     * <p>For more information about making applications accessible, read the
22183     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
22184     * developer guide.</p>
22185     * </div>
22186     * <p>
22187     * A scenario in which a developer would like to use an accessibility delegate
22188     * is overriding a method introduced in a later API version then the minimal API
22189     * version supported by the application. For example, the method
22190     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
22191     * in API version 4 when the accessibility APIs were first introduced. If a
22192     * developer would like his application to run on API version 4 devices (assuming
22193     * all other APIs used by the application are version 4 or lower) and take advantage
22194     * of this method, instead of overriding the method which would break the application's
22195     * backwards compatibility, he can override the corresponding method in this
22196     * delegate and register the delegate in the target View if the API version of
22197     * the system is high enough i.e. the API version is same or higher to the API
22198     * version that introduced
22199     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
22200     * </p>
22201     * <p>
22202     * Here is an example implementation:
22203     * </p>
22204     * <code><pre><p>
22205     * if (Build.VERSION.SDK_INT >= 14) {
22206     *     // If the API version is equal of higher than the version in
22207     *     // which onInitializeAccessibilityNodeInfo was introduced we
22208     *     // register a delegate with a customized implementation.
22209     *     View view = findViewById(R.id.view_id);
22210     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
22211     *         public void onInitializeAccessibilityNodeInfo(View host,
22212     *                 AccessibilityNodeInfo info) {
22213     *             // Let the default implementation populate the info.
22214     *             super.onInitializeAccessibilityNodeInfo(host, info);
22215     *             // Set some other information.
22216     *             info.setEnabled(host.isEnabled());
22217     *         }
22218     *     });
22219     * }
22220     * </code></pre></p>
22221     * <p>
22222     * This delegate contains methods that correspond to the accessibility methods
22223     * in View. If a delegate has been specified the implementation in View hands
22224     * off handling to the corresponding method in this delegate. The default
22225     * implementation the delegate methods behaves exactly as the corresponding
22226     * method in View for the case of no accessibility delegate been set. Hence,
22227     * to customize the behavior of a View method, clients can override only the
22228     * corresponding delegate method without altering the behavior of the rest
22229     * accessibility related methods of the host view.
22230     * </p>
22231     */
22232    public static class AccessibilityDelegate {
22233
22234        /**
22235         * Sends an accessibility event of the given type. If accessibility is not
22236         * enabled this method has no effect.
22237         * <p>
22238         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
22239         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
22240         * been set.
22241         * </p>
22242         *
22243         * @param host The View hosting the delegate.
22244         * @param eventType The type of the event to send.
22245         *
22246         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
22247         */
22248        public void sendAccessibilityEvent(View host, int eventType) {
22249            host.sendAccessibilityEventInternal(eventType);
22250        }
22251
22252        /**
22253         * Performs the specified accessibility action on the view. For
22254         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
22255         * <p>
22256         * The default implementation behaves as
22257         * {@link View#performAccessibilityAction(int, Bundle)
22258         *  View#performAccessibilityAction(int, Bundle)} for the case of
22259         *  no accessibility delegate been set.
22260         * </p>
22261         *
22262         * @param action The action to perform.
22263         * @return Whether the action was performed.
22264         *
22265         * @see View#performAccessibilityAction(int, Bundle)
22266         *      View#performAccessibilityAction(int, Bundle)
22267         */
22268        public boolean performAccessibilityAction(View host, int action, Bundle args) {
22269            return host.performAccessibilityActionInternal(action, args);
22270        }
22271
22272        /**
22273         * Sends an accessibility event. This method behaves exactly as
22274         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
22275         * empty {@link AccessibilityEvent} and does not perform a check whether
22276         * accessibility is enabled.
22277         * <p>
22278         * The default implementation behaves as
22279         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22280         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
22281         * the case of no accessibility delegate been set.
22282         * </p>
22283         *
22284         * @param host The View hosting the delegate.
22285         * @param event The event to send.
22286         *
22287         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22288         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22289         */
22290        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
22291            host.sendAccessibilityEventUncheckedInternal(event);
22292        }
22293
22294        /**
22295         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
22296         * to its children for adding their text content to the event.
22297         * <p>
22298         * The default implementation behaves as
22299         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22300         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
22301         * the case of no accessibility delegate been set.
22302         * </p>
22303         *
22304         * @param host The View hosting the delegate.
22305         * @param event The event.
22306         * @return True if the event population was completed.
22307         *
22308         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22309         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22310         */
22311        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22312            return host.dispatchPopulateAccessibilityEventInternal(event);
22313        }
22314
22315        /**
22316         * Gives a chance to the host View to populate the accessibility event with its
22317         * text content.
22318         * <p>
22319         * The default implementation behaves as
22320         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
22321         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
22322         * the case of no accessibility delegate been set.
22323         * </p>
22324         *
22325         * @param host The View hosting the delegate.
22326         * @param event The accessibility event which to populate.
22327         *
22328         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
22329         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
22330         */
22331        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22332            host.onPopulateAccessibilityEventInternal(event);
22333        }
22334
22335        /**
22336         * Initializes an {@link AccessibilityEvent} with information about the
22337         * the host View which is the event source.
22338         * <p>
22339         * The default implementation behaves as
22340         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
22341         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
22342         * the case of no accessibility delegate been set.
22343         * </p>
22344         *
22345         * @param host The View hosting the delegate.
22346         * @param event The event to initialize.
22347         *
22348         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
22349         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
22350         */
22351        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
22352            host.onInitializeAccessibilityEventInternal(event);
22353        }
22354
22355        /**
22356         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
22357         * <p>
22358         * The default implementation behaves as
22359         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22360         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
22361         * the case of no accessibility delegate been set.
22362         * </p>
22363         *
22364         * @param host The View hosting the delegate.
22365         * @param info The instance to initialize.
22366         *
22367         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22368         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22369         */
22370        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
22371            host.onInitializeAccessibilityNodeInfoInternal(info);
22372        }
22373
22374        /**
22375         * Called when a child of the host View has requested sending an
22376         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
22377         * to augment the event.
22378         * <p>
22379         * The default implementation behaves as
22380         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22381         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
22382         * the case of no accessibility delegate been set.
22383         * </p>
22384         *
22385         * @param host The View hosting the delegate.
22386         * @param child The child which requests sending the event.
22387         * @param event The event to be sent.
22388         * @return True if the event should be sent
22389         *
22390         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22391         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22392         */
22393        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
22394                AccessibilityEvent event) {
22395            return host.onRequestSendAccessibilityEventInternal(child, event);
22396        }
22397
22398        /**
22399         * Gets the provider for managing a virtual view hierarchy rooted at this View
22400         * and reported to {@link android.accessibilityservice.AccessibilityService}s
22401         * that explore the window content.
22402         * <p>
22403         * The default implementation behaves as
22404         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
22405         * the case of no accessibility delegate been set.
22406         * </p>
22407         *
22408         * @return The provider.
22409         *
22410         * @see AccessibilityNodeProvider
22411         */
22412        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
22413            return null;
22414        }
22415
22416        /**
22417         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
22418         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
22419         * This method is responsible for obtaining an accessibility node info from a
22420         * pool of reusable instances and calling
22421         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
22422         * view to initialize the former.
22423         * <p>
22424         * <strong>Note:</strong> The client is responsible for recycling the obtained
22425         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
22426         * creation.
22427         * </p>
22428         * <p>
22429         * The default implementation behaves as
22430         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
22431         * the case of no accessibility delegate been set.
22432         * </p>
22433         * @return A populated {@link AccessibilityNodeInfo}.
22434         *
22435         * @see AccessibilityNodeInfo
22436         *
22437         * @hide
22438         */
22439        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
22440            return host.createAccessibilityNodeInfoInternal();
22441        }
22442    }
22443
22444    private class MatchIdPredicate implements Predicate<View> {
22445        public int mId;
22446
22447        @Override
22448        public boolean apply(View view) {
22449            return (view.mID == mId);
22450        }
22451    }
22452
22453    private class MatchLabelForPredicate implements Predicate<View> {
22454        private int mLabeledId;
22455
22456        @Override
22457        public boolean apply(View view) {
22458            return (view.mLabelForId == mLabeledId);
22459        }
22460    }
22461
22462    private class SendViewStateChangedAccessibilityEvent implements Runnable {
22463        private int mChangeTypes = 0;
22464        private boolean mPosted;
22465        private boolean mPostedWithDelay;
22466        private long mLastEventTimeMillis;
22467
22468        @Override
22469        public void run() {
22470            mPosted = false;
22471            mPostedWithDelay = false;
22472            mLastEventTimeMillis = SystemClock.uptimeMillis();
22473            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
22474                final AccessibilityEvent event = AccessibilityEvent.obtain();
22475                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
22476                event.setContentChangeTypes(mChangeTypes);
22477                sendAccessibilityEventUnchecked(event);
22478            }
22479            mChangeTypes = 0;
22480        }
22481
22482        public void runOrPost(int changeType) {
22483            mChangeTypes |= changeType;
22484
22485            // If this is a live region or the child of a live region, collect
22486            // all events from this frame and send them on the next frame.
22487            if (inLiveRegion()) {
22488                // If we're already posted with a delay, remove that.
22489                if (mPostedWithDelay) {
22490                    removeCallbacks(this);
22491                    mPostedWithDelay = false;
22492                }
22493                // Only post if we're not already posted.
22494                if (!mPosted) {
22495                    post(this);
22496                    mPosted = true;
22497                }
22498                return;
22499            }
22500
22501            if (mPosted) {
22502                return;
22503            }
22504
22505            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
22506            final long minEventIntevalMillis =
22507                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
22508            if (timeSinceLastMillis >= minEventIntevalMillis) {
22509                removeCallbacks(this);
22510                run();
22511            } else {
22512                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
22513                mPostedWithDelay = true;
22514            }
22515        }
22516    }
22517
22518    private boolean inLiveRegion() {
22519        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22520            return true;
22521        }
22522
22523        ViewParent parent = getParent();
22524        while (parent instanceof View) {
22525            if (((View) parent).getAccessibilityLiveRegion()
22526                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22527                return true;
22528            }
22529            parent = parent.getParent();
22530        }
22531
22532        return false;
22533    }
22534
22535    /**
22536     * Dump all private flags in readable format, useful for documentation and
22537     * sanity checking.
22538     */
22539    private static void dumpFlags() {
22540        final HashMap<String, String> found = Maps.newHashMap();
22541        try {
22542            for (Field field : View.class.getDeclaredFields()) {
22543                final int modifiers = field.getModifiers();
22544                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
22545                    if (field.getType().equals(int.class)) {
22546                        final int value = field.getInt(null);
22547                        dumpFlag(found, field.getName(), value);
22548                    } else if (field.getType().equals(int[].class)) {
22549                        final int[] values = (int[]) field.get(null);
22550                        for (int i = 0; i < values.length; i++) {
22551                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
22552                        }
22553                    }
22554                }
22555            }
22556        } catch (IllegalAccessException e) {
22557            throw new RuntimeException(e);
22558        }
22559
22560        final ArrayList<String> keys = Lists.newArrayList();
22561        keys.addAll(found.keySet());
22562        Collections.sort(keys);
22563        for (String key : keys) {
22564            Log.d(VIEW_LOG_TAG, found.get(key));
22565        }
22566    }
22567
22568    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
22569        // Sort flags by prefix, then by bits, always keeping unique keys
22570        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
22571        final int prefix = name.indexOf('_');
22572        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
22573        final String output = bits + " " + name;
22574        found.put(key, output);
22575    }
22576
22577    /** {@hide} */
22578    public void encode(@NonNull ViewHierarchyEncoder stream) {
22579        stream.beginObject(this);
22580        encodeProperties(stream);
22581        stream.endObject();
22582    }
22583
22584    /** {@hide} */
22585    @CallSuper
22586    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
22587        Object resolveId = ViewDebug.resolveId(getContext(), mID);
22588        if (resolveId instanceof String) {
22589            stream.addProperty("id", (String) resolveId);
22590        } else {
22591            stream.addProperty("id", mID);
22592        }
22593
22594        stream.addProperty("misc:transformation.alpha",
22595                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
22596        stream.addProperty("misc:transitionName", getTransitionName());
22597
22598        // layout
22599        stream.addProperty("layout:left", mLeft);
22600        stream.addProperty("layout:right", mRight);
22601        stream.addProperty("layout:top", mTop);
22602        stream.addProperty("layout:bottom", mBottom);
22603        stream.addProperty("layout:width", getWidth());
22604        stream.addProperty("layout:height", getHeight());
22605        stream.addProperty("layout:layoutDirection", getLayoutDirection());
22606        stream.addProperty("layout:layoutRtl", isLayoutRtl());
22607        stream.addProperty("layout:hasTransientState", hasTransientState());
22608        stream.addProperty("layout:baseline", getBaseline());
22609
22610        // layout params
22611        ViewGroup.LayoutParams layoutParams = getLayoutParams();
22612        if (layoutParams != null) {
22613            stream.addPropertyKey("layoutParams");
22614            layoutParams.encode(stream);
22615        }
22616
22617        // scrolling
22618        stream.addProperty("scrolling:scrollX", mScrollX);
22619        stream.addProperty("scrolling:scrollY", mScrollY);
22620
22621        // padding
22622        stream.addProperty("padding:paddingLeft", mPaddingLeft);
22623        stream.addProperty("padding:paddingRight", mPaddingRight);
22624        stream.addProperty("padding:paddingTop", mPaddingTop);
22625        stream.addProperty("padding:paddingBottom", mPaddingBottom);
22626        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
22627        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
22628        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
22629        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
22630        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
22631
22632        // measurement
22633        stream.addProperty("measurement:minHeight", mMinHeight);
22634        stream.addProperty("measurement:minWidth", mMinWidth);
22635        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
22636        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
22637
22638        // drawing
22639        stream.addProperty("drawing:elevation", getElevation());
22640        stream.addProperty("drawing:translationX", getTranslationX());
22641        stream.addProperty("drawing:translationY", getTranslationY());
22642        stream.addProperty("drawing:translationZ", getTranslationZ());
22643        stream.addProperty("drawing:rotation", getRotation());
22644        stream.addProperty("drawing:rotationX", getRotationX());
22645        stream.addProperty("drawing:rotationY", getRotationY());
22646        stream.addProperty("drawing:scaleX", getScaleX());
22647        stream.addProperty("drawing:scaleY", getScaleY());
22648        stream.addProperty("drawing:pivotX", getPivotX());
22649        stream.addProperty("drawing:pivotY", getPivotY());
22650        stream.addProperty("drawing:opaque", isOpaque());
22651        stream.addProperty("drawing:alpha", getAlpha());
22652        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
22653        stream.addProperty("drawing:shadow", hasShadow());
22654        stream.addProperty("drawing:solidColor", getSolidColor());
22655        stream.addProperty("drawing:layerType", mLayerType);
22656        stream.addProperty("drawing:willNotDraw", willNotDraw());
22657        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
22658        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
22659        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
22660        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
22661
22662        // focus
22663        stream.addProperty("focus:hasFocus", hasFocus());
22664        stream.addProperty("focus:isFocused", isFocused());
22665        stream.addProperty("focus:isFocusable", isFocusable());
22666        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
22667
22668        stream.addProperty("misc:clickable", isClickable());
22669        stream.addProperty("misc:pressed", isPressed());
22670        stream.addProperty("misc:selected", isSelected());
22671        stream.addProperty("misc:touchMode", isInTouchMode());
22672        stream.addProperty("misc:hovered", isHovered());
22673        stream.addProperty("misc:activated", isActivated());
22674
22675        stream.addProperty("misc:visibility", getVisibility());
22676        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
22677        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
22678
22679        stream.addProperty("misc:enabled", isEnabled());
22680        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
22681        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
22682
22683        // theme attributes
22684        Resources.Theme theme = getContext().getTheme();
22685        if (theme != null) {
22686            stream.addPropertyKey("theme");
22687            theme.encode(stream);
22688        }
22689
22690        // view attribute information
22691        int n = mAttributes != null ? mAttributes.length : 0;
22692        stream.addProperty("meta:__attrCount__", n/2);
22693        for (int i = 0; i < n; i += 2) {
22694            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
22695        }
22696
22697        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
22698
22699        // text
22700        stream.addProperty("text:textDirection", getTextDirection());
22701        stream.addProperty("text:textAlignment", getTextAlignment());
22702
22703        // accessibility
22704        CharSequence contentDescription = getContentDescription();
22705        stream.addProperty("accessibility:contentDescription",
22706                contentDescription == null ? "" : contentDescription.toString());
22707        stream.addProperty("accessibility:labelFor", getLabelFor());
22708        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
22709    }
22710}
22711